From dc7dfafe548f321f38f84c1ae18cad97a833d721 Mon Sep 17 00:00:00 2001 From: AlumiuN <> Date: Mon, 12 Oct 2015 14:16:37 +1300 Subject: [PATCH 01/46] Added Infiltrate, Teferi's Response, Surestrike Trident, Chaoslace, Deathlace, Lifelace, Purelace, Thoughlace and Moonlace. --- .../src/mage/sets/coldsnap/BraidOfFire.java | 97 +++++++++ .../sets/darksteel/SurestrikeTrident.java | 139 ++++++++++++ .../mage/sets/fourthedition/Chaoslace.java | 63 ++++++ .../mage/sets/fourthedition/Deathlace.java | 52 +++++ .../src/mage/sets/fourthedition/Lifelace.java | 52 +++++ .../src/mage/sets/fourthedition/Purelace.java | 52 +++++ .../mage/sets/fourthedition/Thoughtlace.java | 52 +++++ .../mage/sets/invasion/TeferisResponse.java | 198 ++++++++++++++++++ .../src/mage/sets/limitedalpha/Chaoslace.java | 52 +++++ .../src/mage/sets/limitedalpha/Deathlace.java | 52 +++++ .../src/mage/sets/limitedalpha/Lifelace.java | 62 ++++++ .../src/mage/sets/limitedalpha/Purelace.java | 52 +++++ .../mage/sets/limitedalpha/Thoughtlace.java | 52 +++++ .../src/mage/sets/limitedbeta/Chaoslace.java | 52 +++++ .../src/mage/sets/limitedbeta/Deathlace.java | 62 ++++++ .../src/mage/sets/limitedbeta/Lifelace.java | 52 +++++ .../src/mage/sets/limitedbeta/Purelace.java | 52 +++++ .../mage/sets/limitedbeta/Thoughtlace.java | 62 ++++++ .../src/mage/sets/nemesis/Infiltrate.java | 60 ++++++ .../mage/sets/revisededition/Chaoslace.java | 52 +++++ .../mage/sets/revisededition/Deathlace.java | 52 +++++ .../mage/sets/revisededition/Lifelace.java | 52 +++++ .../mage/sets/revisededition/Purelace.java | 52 +++++ .../mage/sets/revisededition/Thoughtlace.java | 52 +++++ .../src/mage/sets/timespiral/Moonlace.java | 62 ++++++ .../mage/sets/unlimitededition/Chaoslace.java | 52 +++++ .../mage/sets/unlimitededition/Deathlace.java | 52 +++++ .../mage/sets/unlimitededition/Lifelace.java | 52 +++++ .../mage/sets/unlimitededition/Purelace.java | 62 ++++++ .../sets/unlimitededition/Thoughtlace.java | 52 +++++ 30 files changed, 1907 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/coldsnap/BraidOfFire.java create mode 100644 Mage.Sets/src/mage/sets/darksteel/SurestrikeTrident.java create mode 100644 Mage.Sets/src/mage/sets/fourthedition/Chaoslace.java create mode 100644 Mage.Sets/src/mage/sets/fourthedition/Deathlace.java create mode 100644 Mage.Sets/src/mage/sets/fourthedition/Lifelace.java create mode 100644 Mage.Sets/src/mage/sets/fourthedition/Purelace.java create mode 100644 Mage.Sets/src/mage/sets/fourthedition/Thoughtlace.java create mode 100644 Mage.Sets/src/mage/sets/invasion/TeferisResponse.java create mode 100644 Mage.Sets/src/mage/sets/limitedalpha/Chaoslace.java create mode 100644 Mage.Sets/src/mage/sets/limitedalpha/Deathlace.java create mode 100644 Mage.Sets/src/mage/sets/limitedalpha/Lifelace.java create mode 100644 Mage.Sets/src/mage/sets/limitedalpha/Purelace.java create mode 100644 Mage.Sets/src/mage/sets/limitedalpha/Thoughtlace.java create mode 100644 Mage.Sets/src/mage/sets/limitedbeta/Chaoslace.java create mode 100644 Mage.Sets/src/mage/sets/limitedbeta/Deathlace.java create mode 100644 Mage.Sets/src/mage/sets/limitedbeta/Lifelace.java create mode 100644 Mage.Sets/src/mage/sets/limitedbeta/Purelace.java create mode 100644 Mage.Sets/src/mage/sets/limitedbeta/Thoughtlace.java create mode 100644 Mage.Sets/src/mage/sets/nemesis/Infiltrate.java create mode 100644 Mage.Sets/src/mage/sets/revisededition/Chaoslace.java create mode 100644 Mage.Sets/src/mage/sets/revisededition/Deathlace.java create mode 100644 Mage.Sets/src/mage/sets/revisededition/Lifelace.java create mode 100644 Mage.Sets/src/mage/sets/revisededition/Purelace.java create mode 100644 Mage.Sets/src/mage/sets/revisededition/Thoughtlace.java create mode 100644 Mage.Sets/src/mage/sets/timespiral/Moonlace.java create mode 100644 Mage.Sets/src/mage/sets/unlimitededition/Chaoslace.java create mode 100644 Mage.Sets/src/mage/sets/unlimitededition/Deathlace.java create mode 100644 Mage.Sets/src/mage/sets/unlimitededition/Lifelace.java create mode 100644 Mage.Sets/src/mage/sets/unlimitededition/Purelace.java create mode 100644 Mage.Sets/src/mage/sets/unlimitededition/Thoughtlace.java diff --git a/Mage.Sets/src/mage/sets/coldsnap/BraidOfFire.java b/Mage.Sets/src/mage/sets/coldsnap/BraidOfFire.java new file mode 100644 index 0000000000..7cb6a49452 --- /dev/null +++ b/Mage.Sets/src/mage/sets/coldsnap/BraidOfFire.java @@ -0,0 +1,97 @@ +/* + * 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.coldsnap; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.costs.CostImpl; +import mage.abilities.keyword.CumulativeUpkeepAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author AlumiuN + */ +public class BraidOfFire extends CardImpl { + + public BraidOfFire(UUID ownerId) { + super(ownerId, 78, "Braid of Fire", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}"); + this.expansionSetCode = "CSP"; + + // Cumulative upkeep-Add {R} to your mana pool. + this.addAbility(new CumulativeUpkeepAbility(new BraidOfFireCost())); + } + + public BraidOfFire(final BraidOfFire card) { + super(card); + } + + @Override + public BraidOfFire copy() { + return new BraidOfFire(this); + } +} + +class BraidOfFireCost extends CostImpl { + + public BraidOfFireCost() { + this.text = "Add {R} to your mana pool"; + } + + public BraidOfFireCost(BraidOfFireCost cost) { + super(cost); + } + + @Override + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { + Player player = game.getPlayer(controllerId); + player.getManaPool().addMana(Mana.RedMana, game, ability); + paid = true; + return true; + } + + @Override + public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { + Player player = game.getPlayer(controllerId); + if (player != null) { + return true; + } + return false; + } + + @Override + public BraidOfFireCost copy() { + return new BraidOfFireCost(this); + } + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/darksteel/SurestrikeTrident.java b/Mage.Sets/src/mage/sets/darksteel/SurestrikeTrident.java new file mode 100644 index 0000000000..761ed72d84 --- /dev/null +++ b/Mage.Sets/src/mage/sets/darksteel/SurestrikeTrident.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.darksteel; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.CostImpl; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.SourcePermanentPowerCount; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.EquipAbility; +import mage.abilities.keyword.FirstStrikeAbility; +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.abilities.effects.Effect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.TargetPlayer; + +/** + * + * @author AlumiuN + */ +public class SurestrikeTrident extends CardImpl { + + public SurestrikeTrident(UUID ownerId) { + super(ownerId, 147, "Surestrike Trident", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT}, "{2}"); + this.expansionSetCode = "DST"; + this.subtype.add("Equipment"); + + // Equipped creature has first strike and "{tap}, Unattach Surestrike Trident: This creature deals damage equal to its power to target player." + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(FirstStrikeAbility.getInstance(), AttachmentType.EQUIPMENT))); + + DynamicValue xValue = new SourcePermanentPowerCount(); + Effect effect = new DamageTargetEffect(xValue); + effect.setText("This creature deals damage equal to its power to target player"); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new TapSourceCost()); + ability.addTarget(new TargetPlayer()); + ability.addCost(new SurestrikeTridentUnattachCost()); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(ability, AttachmentType.EQUIPMENT, Duration.WhileOnBattlefield))); + + // Equip {4} + this.addAbility(new EquipAbility(Outcome.Benefit, new GenericManaCost(4))); + } + + public SurestrikeTrident(final SurestrikeTrident card) { + super(card); + } + + @Override + public SurestrikeTrident copy() { + return new SurestrikeTrident(this); + } +} + +class SurestrikeTridentUnattachCost extends CostImpl { + + public SurestrikeTridentUnattachCost() { + this.text = "Unattach Surestrike Trident"; + } + + public SurestrikeTridentUnattachCost(final SurestrikeTridentUnattachCost cost) { + super(cost); + } + + @Override + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { + Permanent permanent = game.getPermanent(sourceId); + if (permanent != null) { + for (UUID attachmentId :permanent.getAttachments()) { + Permanent attachment = game.getPermanent(attachmentId); + if (attachment != null && attachment.getName().equals("Surestrike Trident")) { + paid = permanent.removeAttachment(attachmentId, game); + if (paid) { + break; + } + } + } + + } + return paid; + } + + @Override + public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { + Permanent permanent = game.getPermanent(sourceId); + if (permanent != null) { + for (UUID attachmentId :permanent.getAttachments()) { + Permanent attachment = game.getPermanent(attachmentId); + if (attachment != null && attachment.getName().equals("Surestrike Trident") ) { + return true; + } + } + + } + return false; + } + + @Override + public SurestrikeTridentUnattachCost copy() { + return new SurestrikeTridentUnattachCost(this); + } + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/fourthedition/Chaoslace.java b/Mage.Sets/src/mage/sets/fourthedition/Chaoslace.java new file mode 100644 index 0000000000..74d149d3ed --- /dev/null +++ b/Mage.Sets/src/mage/sets/fourthedition/Chaoslace.java @@ -0,0 +1,63 @@ +/* + * 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.fourthedition; + +import java.util.UUID; +import mage.abilities.effects.common.continuous.BecomesColorTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.ObjectColor; +import mage.target.common.TargetSpellOrPermanent; + + +/** + * + * @author AlumiuN + */ +public class Chaoslace extends CardImpl { + + public Chaoslace(UUID ownerId) { + super(ownerId, 200, "Chaoslace", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{R}"); + this.expansionSetCode = "4ED"; + + // Target spell or permanent becomes red. + this.getSpellAbility().addTarget(new TargetSpellOrPermanent()); + this.getSpellAbility().addEffect(new BecomesColorTargetEffect(ObjectColor.RED, Duration.Custom)); + } + + public Chaoslace(final Chaoslace card) { + super(card); + } + + @Override + public Chaoslace copy() { + return new Chaoslace(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/fourthedition/Deathlace.java b/Mage.Sets/src/mage/sets/fourthedition/Deathlace.java new file mode 100644 index 0000000000..a6d66e70d7 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fourthedition/Deathlace.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.fourthedition; + +import java.util.UUID; + +/** + * + * @author AlumiuN + */ +public class Deathlace extends mage.sets.limitedbeta.Deathlace { + + public Deathlace(UUID ownerId) { + super(ownerId); + this.cardNumber = 15; + this.expansionSetCode = "4ED"; + } + + public Deathlace(final Deathlace card) { + super(card); + } + + @Override + public Deathlace copy() { + return new Deathlace(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fourthedition/Lifelace.java b/Mage.Sets/src/mage/sets/fourthedition/Lifelace.java new file mode 100644 index 0000000000..2b9c81b10e --- /dev/null +++ b/Mage.Sets/src/mage/sets/fourthedition/Lifelace.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.fourthedition; + +import java.util.UUID; + +/** + * + * @author AlumiuN + */ +public class Lifelace extends mage.sets.limitedalpha.Lifelace { + + public Lifelace(UUID ownerId) { + super(ownerId); + this.cardNumber = 142; + this.expansionSetCode = "4ED"; + } + + public Lifelace(final Lifelace card) { + super(card); + } + + @Override + public Lifelace copy() { + return new Lifelace(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fourthedition/Purelace.java b/Mage.Sets/src/mage/sets/fourthedition/Purelace.java new file mode 100644 index 0000000000..a25d9f92c2 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fourthedition/Purelace.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.fourthedition; + +import java.util.UUID; + +/** + * + * @author AlumiuN + */ +public class Purelace extends mage.sets.unlimitededition.Purelace { + + public Purelace(UUID ownerId) { + super(ownerId); + this.cardNumber = 293; + this.expansionSetCode = "4ED"; + } + + public Purelace(final Purelace card) { + super(card); + } + + @Override + public Purelace copy() { + return new Purelace(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fourthedition/Thoughtlace.java b/Mage.Sets/src/mage/sets/fourthedition/Thoughtlace.java new file mode 100644 index 0000000000..19f9d3bcc3 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fourthedition/Thoughtlace.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.fourthedition; + +import java.util.UUID; + +/** + * + * @author AlumiuN + */ +public class Thoughtlace extends mage.sets.limitedbeta.Thoughtlace { + + public Thoughtlace(UUID ownerId) { + super(ownerId); + this.cardNumber = 107; + this.expansionSetCode = "4ED"; + } + + public Thoughtlace(final Thoughtlace card) { + super(card); + } + + @Override + public Thoughtlace copy() { + return new Thoughtlace(this); + } +} diff --git a/Mage.Sets/src/mage/sets/invasion/TeferisResponse.java b/Mage.Sets/src/mage/sets/invasion/TeferisResponse.java new file mode 100644 index 0000000000..f61b1d22bd --- /dev/null +++ b/Mage.Sets/src/mage/sets/invasion/TeferisResponse.java @@ -0,0 +1,198 @@ +/* + * 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.invasion; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.Filter; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.stack.Spell; +import mage.game.stack.StackAbility; +import mage.game.stack.StackObject; +import mage.target.Target; +import mage.target.TargetObject; +import mage.target.Targets; + +/** + * + * @author AlumiuN + */ +public class TeferisResponse extends CardImpl { + + public TeferisResponse(UUID ownerId) { + super(ownerId, 78, "Teferi's Response", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{1}{U}"); + this.expansionSetCode = "INV"; + + // Counter target spell or ability an opponent controls that targets a land you control. If a permanent's ability is countered this way, destroy that permanent. + this.getSpellAbility().addEffect(new TeferisResponseEffect()); + this.getSpellAbility().addTarget(new TargetStackObjectTargetingControlledLand()); + + // Draw two cards. + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(2)); + } + + public TeferisResponse(final TeferisResponse card) { + super(card); + } + + @Override + public TeferisResponse copy() { + return new TeferisResponse(this); + } +} + +class TargetStackObjectTargetingControlledLand extends TargetObject { + + public TargetStackObjectTargetingControlledLand() { + this.minNumberOfTargets = 1; + this.maxNumberOfTargets = 1; + this.zone = Zone.STACK; + this.targetName = "spell or ability an opponent controls that targets a land you control"; + } + + public TargetStackObjectTargetingControlledLand(final TargetStackObjectTargetingControlledLand target) { + super(target); + } + + @Override + public Filter getFilter() { + throw new UnsupportedOperationException("Not supported."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + public boolean canTarget(UUID id, Ability source, Game game) { + StackObject stackObject = game.getStack().getStackObject(id); + if ((stackObject instanceof Spell) || (stackObject instanceof StackAbility)) { + return true; + } + return false; + } + + @Override + public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { + return canChoose(sourceControllerId, game); + } + + @Override + public boolean canChoose(UUID sourceControllerId, Game game) { + for (StackObject stackObject : game.getStack()) { + if (((stackObject instanceof Spell) || (stackObject instanceof StackAbility)) && stackObject.getControllerId() != sourceControllerId) { + Targets objectTargets = stackObject.getStackAbility().getTargets(); + if(!objectTargets.isEmpty()) { + for (Target target : objectTargets) { + for (UUID targetId : target.getTargets()) { + Permanent targetedPermanent = game.getPermanentOrLKIBattlefield(targetId); + if (targetedPermanent != null && targetedPermanent.getCardType().contains(CardType.LAND) && targetedPermanent.getControllerId().equals(sourceControllerId)) { + return true; + } + } + } + } + } + } + return false; + } + + @Override + public Set possibleTargets(UUID sourceId, UUID sourceControllerId, + Game game) { + return possibleTargets(sourceControllerId, game); + } + + @Override + public Set possibleTargets(UUID sourceControllerId, Game game) { + Set possibleTargets = new HashSet<>(); + for (StackObject stackObject : game.getStack()) { + if (((stackObject instanceof Spell) || (stackObject instanceof StackAbility)) && stackObject.getControllerId() != sourceControllerId) { + Targets objectTargets = stackObject.getStackAbility().getTargets(); + if(!objectTargets.isEmpty()) { + for (Target target : objectTargets) { + for (UUID targetId : target.getTargets()) { + Permanent targetedPermanent = game.getPermanentOrLKIBattlefield(targetId); + if (targetedPermanent != null && targetedPermanent.getCardType().contains(CardType.LAND) && targetedPermanent.getControllerId().equals(sourceControllerId)) { + possibleTargets.add(stackObject.getId()); + } + } + } + } + } + } + return possibleTargets; + } + + @Override + public TargetStackObjectTargetingControlledLand copy() { + return new TargetStackObjectTargetingControlledLand(this); + } + +} + +class TeferisResponseEffect extends OneShotEffect { + + public TeferisResponseEffect() { + super(Outcome.Detriment); + this.staticText = "Counter target spell or ability an opponent controls that targets a land you control. If a permanent's ability is countered this way, destroy that permanent"; + } + + public TeferisResponseEffect(final TeferisResponseEffect effect) { + super(effect); + } + + @Override + public TeferisResponseEffect copy() { + return new TeferisResponseEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + UUID targetId = source.getFirstTarget(); + StackObject stackObject = game.getStack().getStackObject(targetId); + if (targetId != null && game.getStack().counter(targetId, source.getSourceId(), game)) { + UUID permanentId = stackObject.getSourceId(); + if (permanentId != null) { + Permanent usedPermanent = game.getPermanent(permanentId); + if (usedPermanent != null) { + usedPermanent.destroy(source.getSourceId(), game, false); + } + } + return true; + } + + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/limitedalpha/Chaoslace.java b/Mage.Sets/src/mage/sets/limitedalpha/Chaoslace.java new file mode 100644 index 0000000000..0c9258bab6 --- /dev/null +++ b/Mage.Sets/src/mage/sets/limitedalpha/Chaoslace.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.limitedalpha; + +import java.util.UUID; + +/** + * + * @author AlumiuN + */ +public class Chaoslace extends mage.sets.fourthedition.Chaoslace { + + public Chaoslace(UUID ownerId) { + super(ownerId); + this.cardNumber = 140; + this.expansionSetCode = "LEA"; + } + + public Chaoslace(final Chaoslace card) { + super(card); + } + + @Override + public Chaoslace copy() { + return new Chaoslace(this); + } +} diff --git a/Mage.Sets/src/mage/sets/limitedalpha/Deathlace.java b/Mage.Sets/src/mage/sets/limitedalpha/Deathlace.java new file mode 100644 index 0000000000..15a9f29743 --- /dev/null +++ b/Mage.Sets/src/mage/sets/limitedalpha/Deathlace.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.limitedalpha; + +import java.util.UUID; + +/** + * + * @author AlumiuN + */ +public class Deathlace extends mage.sets.limitedbeta.Deathlace { + + public Deathlace(UUID ownerId) { + super(ownerId); + this.cardNumber = 10; + this.expansionSetCode = "LEA"; + } + + public Deathlace(final Deathlace card) { + super(card); + } + + @Override + public Deathlace copy() { + return new Deathlace(this); + } +} diff --git a/Mage.Sets/src/mage/sets/limitedalpha/Lifelace.java b/Mage.Sets/src/mage/sets/limitedalpha/Lifelace.java new file mode 100644 index 0000000000..f01f6e6ae9 --- /dev/null +++ b/Mage.Sets/src/mage/sets/limitedalpha/Lifelace.java @@ -0,0 +1,62 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE 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.limitedalpha; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.effects.common.continuous.BecomesColorTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.target.common.TargetSpellOrPermanent; + +/** + * + * @author AlumiuN + */ +public class Lifelace extends CardImpl { + + public Lifelace(UUID ownerId) { + super(ownerId, 116, "Lifelace", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{G}"); + this.expansionSetCode = "LEA"; + + // Target spell or permanent becomes green. + this.getSpellAbility().addTarget(new TargetSpellOrPermanent()); + this.getSpellAbility().addEffect(new BecomesColorTargetEffect(ObjectColor.GREEN, Duration.Custom)); + } + + public Lifelace(final Lifelace card) { + super(card); + } + + @Override + public Lifelace copy() { + return new Lifelace(this); + } +} diff --git a/Mage.Sets/src/mage/sets/limitedalpha/Purelace.java b/Mage.Sets/src/mage/sets/limitedalpha/Purelace.java new file mode 100644 index 0000000000..3651a9766c --- /dev/null +++ b/Mage.Sets/src/mage/sets/limitedalpha/Purelace.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.limitedalpha; + +import java.util.UUID; + +/** + * + * @author AlumiuN + */ +public class Purelace extends mage.sets.unlimitededition.Purelace { + + public Purelace(UUID ownerId) { + super(ownerId); + this.cardNumber = 216; + this.expansionSetCode = "LEA"; + } + + public Purelace(final Purelace card) { + super(card); + } + + @Override + public Purelace copy() { + return new Purelace(this); + } +} diff --git a/Mage.Sets/src/mage/sets/limitedalpha/Thoughtlace.java b/Mage.Sets/src/mage/sets/limitedalpha/Thoughtlace.java new file mode 100644 index 0000000000..e426d3ec9f --- /dev/null +++ b/Mage.Sets/src/mage/sets/limitedalpha/Thoughtlace.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.limitedalpha; + +import java.util.UUID; + +/** + * + * @author AlumiuN + */ +public class Thoughtlace extends mage.sets.limitedbeta.Thoughtlace { + + public Thoughtlace(UUID ownerId) { + super(ownerId); + this.cardNumber = 83; + this.expansionSetCode = "LEA"; + } + + public Thoughtlace(final Thoughtlace card) { + super(card); + } + + @Override + public Thoughtlace copy() { + return new Thoughtlace(this); + } +} diff --git a/Mage.Sets/src/mage/sets/limitedbeta/Chaoslace.java b/Mage.Sets/src/mage/sets/limitedbeta/Chaoslace.java new file mode 100644 index 0000000000..5dd7ab9c79 --- /dev/null +++ b/Mage.Sets/src/mage/sets/limitedbeta/Chaoslace.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.limitedbeta; + +import java.util.UUID; + +/** + * + * @author AlumiuN + */ +public class Chaoslace extends mage.sets.fourthedition.Chaoslace { + + public Chaoslace(UUID ownerId) { + super(ownerId); + this.cardNumber = 141; + this.expansionSetCode = "LEB"; + } + + public Chaoslace(final Chaoslace card) { + super(card); + } + + @Override + public Chaoslace copy() { + return new Chaoslace(this); + } +} diff --git a/Mage.Sets/src/mage/sets/limitedbeta/Deathlace.java b/Mage.Sets/src/mage/sets/limitedbeta/Deathlace.java new file mode 100644 index 0000000000..568c464156 --- /dev/null +++ b/Mage.Sets/src/mage/sets/limitedbeta/Deathlace.java @@ -0,0 +1,62 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE 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.limitedbeta; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.effects.common.continuous.BecomesColorTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.target.common.TargetSpellOrPermanent; + +/** + * + * @author AlumiuN + */ +public class Deathlace extends CardImpl { + + public Deathlace(UUID ownerId) { + super(ownerId, 10, "Deathlace", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{B}"); + this.expansionSetCode = "LEB"; + + // Target spell or permanent becomes black. + this.getSpellAbility().addTarget(new TargetSpellOrPermanent()); + this.getSpellAbility().addEffect(new BecomesColorTargetEffect(ObjectColor.BLACK, Duration.Custom)); + } + + public Deathlace(final Deathlace card) { + super(card); + } + + @Override + public Deathlace copy() { + return new Deathlace(this); + } +} diff --git a/Mage.Sets/src/mage/sets/limitedbeta/Lifelace.java b/Mage.Sets/src/mage/sets/limitedbeta/Lifelace.java new file mode 100644 index 0000000000..e19cd0970d --- /dev/null +++ b/Mage.Sets/src/mage/sets/limitedbeta/Lifelace.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.limitedbeta; + +import java.util.UUID; + +/** + * + * @author AlumiuN + */ +public class Lifelace extends mage.sets.limitedalpha.Lifelace { + + public Lifelace(UUID ownerId) { + super(ownerId); + this.cardNumber = 116; + this.expansionSetCode = "LEB"; + } + + public Lifelace(final Lifelace card) { + super(card); + } + + @Override + public Lifelace copy() { + return new Lifelace(this); + } +} diff --git a/Mage.Sets/src/mage/sets/limitedbeta/Purelace.java b/Mage.Sets/src/mage/sets/limitedbeta/Purelace.java new file mode 100644 index 0000000000..bc81190443 --- /dev/null +++ b/Mage.Sets/src/mage/sets/limitedbeta/Purelace.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.limitedbeta; + +import java.util.UUID; + +/** + * + * @author AlumiuN + */ +public class Purelace extends mage.sets.unlimitededition.Purelace { + + public Purelace(UUID ownerId) { + super(ownerId); + this.cardNumber = 218; + this.expansionSetCode = "LEB"; + } + + public Purelace(final Purelace card) { + super(card); + } + + @Override + public Purelace copy() { + return new Purelace(this); + } +} diff --git a/Mage.Sets/src/mage/sets/limitedbeta/Thoughtlace.java b/Mage.Sets/src/mage/sets/limitedbeta/Thoughtlace.java new file mode 100644 index 0000000000..0b91774b4d --- /dev/null +++ b/Mage.Sets/src/mage/sets/limitedbeta/Thoughtlace.java @@ -0,0 +1,62 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE 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.limitedbeta; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.effects.common.continuous.BecomesColorTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.target.common.TargetSpellOrPermanent; + +/** + * + * @author AlumiuN + */ +public class Thoughtlace extends CardImpl { + + public Thoughtlace(UUID ownerId) { + super(ownerId, 83, "Thoughtlace", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{U}"); + this.expansionSetCode = "LEB"; + + // Target spell or permanent becomes blue. + this.getSpellAbility().addTarget(new TargetSpellOrPermanent()); + this.getSpellAbility().addEffect(new BecomesColorTargetEffect(ObjectColor.BLUE, Duration.Custom)); + } + + public Thoughtlace(final Thoughtlace card) { + super(card); + } + + @Override + public Thoughtlace copy() { + return new Thoughtlace(this); + } +} diff --git a/Mage.Sets/src/mage/sets/nemesis/Infiltrate.java b/Mage.Sets/src/mage/sets/nemesis/Infiltrate.java new file mode 100644 index 0000000000..cb8f7fbc9e --- /dev/null +++ b/Mage.Sets/src/mage/sets/nemesis/Infiltrate.java @@ -0,0 +1,60 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.nemesis; + +import java.util.UUID; +import mage.abilities.effects.common.combat.CantBeBlockedTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author AlumiuN + */ +public class Infiltrate extends CardImpl { + + public Infiltrate(UUID ownerId) { + super(ownerId, 33, "Infiltrate", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{U}"); + this.expansionSetCode = "NMS"; + + // Target creature is unblockable this turn. + this.getSpellAbility().addEffect(new CantBeBlockedTargetEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + public Infiltrate(final Infiltrate card) { + super(card); + } + + @Override + public Infiltrate copy() { + return new Infiltrate(this); + } +} diff --git a/Mage.Sets/src/mage/sets/revisededition/Chaoslace.java b/Mage.Sets/src/mage/sets/revisededition/Chaoslace.java new file mode 100644 index 0000000000..247ae5fe06 --- /dev/null +++ b/Mage.Sets/src/mage/sets/revisededition/Chaoslace.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.revisededition; + +import java.util.UUID; + +/** + * + * @author AlumiuN + */ +public class Chaoslace extends mage.sets.fourthedition.Chaoslace { + + public Chaoslace(UUID ownerId) { + super(ownerId); + this.cardNumber = 140; + this.expansionSetCode = "3ED"; + } + + public Chaoslace(final Chaoslace card) { + super(card); + } + + @Override + public Chaoslace copy() { + return new Chaoslace(this); + } +} diff --git a/Mage.Sets/src/mage/sets/revisededition/Deathlace.java b/Mage.Sets/src/mage/sets/revisededition/Deathlace.java new file mode 100644 index 0000000000..55e0d3a6a9 --- /dev/null +++ b/Mage.Sets/src/mage/sets/revisededition/Deathlace.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.revisededition; + +import java.util.UUID; + +/** + * + * @author AlumiuN + */ +public class Deathlace extends mage.sets.limitedbeta.Deathlace { + + public Deathlace(UUID ownerId) { + super(ownerId); + this.cardNumber = 10; + this.expansionSetCode = "3ED"; + } + + public Deathlace(final Deathlace card) { + super(card); + } + + @Override + public Deathlace copy() { + return new Deathlace(this); + } +} diff --git a/Mage.Sets/src/mage/sets/revisededition/Lifelace.java b/Mage.Sets/src/mage/sets/revisededition/Lifelace.java new file mode 100644 index 0000000000..3012b263eb --- /dev/null +++ b/Mage.Sets/src/mage/sets/revisededition/Lifelace.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.revisededition; + +import java.util.UUID; + +/** + * + * @author AlumiuN + */ +public class Lifelace extends mage.sets.limitedalpha.Lifelace { + + public Lifelace(UUID ownerId) { + super(ownerId); + this.cardNumber = 115; + this.expansionSetCode = "3ED"; + } + + public Lifelace(final Lifelace card) { + super(card); + } + + @Override + public Lifelace copy() { + return new Lifelace(this); + } +} diff --git a/Mage.Sets/src/mage/sets/revisededition/Purelace.java b/Mage.Sets/src/mage/sets/revisededition/Purelace.java new file mode 100644 index 0000000000..35bf375c63 --- /dev/null +++ b/Mage.Sets/src/mage/sets/revisededition/Purelace.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.revisededition; + +import java.util.UUID; + +/** + * + * @author AlumiuN + */ +public class Purelace extends mage.sets.unlimitededition.Purelace { + + public Purelace(UUID ownerId) { + super(ownerId); + this.cardNumber = 216; + this.expansionSetCode = "3ED"; + } + + public Purelace(final Purelace card) { + super(card); + } + + @Override + public Purelace copy() { + return new Purelace(this); + } +} diff --git a/Mage.Sets/src/mage/sets/revisededition/Thoughtlace.java b/Mage.Sets/src/mage/sets/revisededition/Thoughtlace.java new file mode 100644 index 0000000000..a0415d3b7e --- /dev/null +++ b/Mage.Sets/src/mage/sets/revisededition/Thoughtlace.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.revisededition; + +import java.util.UUID; + +/** + * + * @author AlumiuN + */ +public class Thoughtlace extends mage.sets.limitedbeta.Thoughtlace { + + public Thoughtlace(UUID ownerId) { + super(ownerId); + this.cardNumber = 85; + this.expansionSetCode = "3ED"; + } + + public Thoughtlace(final Thoughtlace card) { + super(card); + } + + @Override + public Thoughtlace copy() { + return new Thoughtlace(this); + } +} diff --git a/Mage.Sets/src/mage/sets/timespiral/Moonlace.java b/Mage.Sets/src/mage/sets/timespiral/Moonlace.java new file mode 100644 index 0000000000..8babbebfc6 --- /dev/null +++ b/Mage.Sets/src/mage/sets/timespiral/Moonlace.java @@ -0,0 +1,62 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.timespiral; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.effects.common.continuous.BecomesColorTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.target.common.TargetSpellOrPermanent; + +/** + * + * @author AlumiuN + */ +public class Moonlace extends CardImpl { + + public Moonlace(UUID ownerId) { + super(ownerId, 68, "Moonlace", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{U}"); + this.expansionSetCode = "TSP"; + + // Target spell or permanent becomes colorless. + this.getSpellAbility().addTarget(new TargetSpellOrPermanent()); + this.getSpellAbility().addEffect(new BecomesColorTargetEffect(new ObjectColor(), Duration.Custom)); + } + + public Moonlace(final Moonlace card) { + super(card); + } + + @Override + public Moonlace copy() { + return new Moonlace(this); + } +} diff --git a/Mage.Sets/src/mage/sets/unlimitededition/Chaoslace.java b/Mage.Sets/src/mage/sets/unlimitededition/Chaoslace.java new file mode 100644 index 0000000000..b42abd03c4 --- /dev/null +++ b/Mage.Sets/src/mage/sets/unlimitededition/Chaoslace.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.unlimitededition; + +import java.util.UUID; + +/** + * + * @author AlumiuN + */ +public class Chaoslace extends mage.sets.fourthedition.Chaoslace { + + public Chaoslace(UUID ownerId) { + super(ownerId); + this.cardNumber = 140; + this.expansionSetCode = "2ED"; + } + + public Chaoslace(final Chaoslace card) { + super(card); + } + + @Override + public Chaoslace copy() { + return new Chaoslace(this); + } +} diff --git a/Mage.Sets/src/mage/sets/unlimitededition/Deathlace.java b/Mage.Sets/src/mage/sets/unlimitededition/Deathlace.java new file mode 100644 index 0000000000..6dd2d54e01 --- /dev/null +++ b/Mage.Sets/src/mage/sets/unlimitededition/Deathlace.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.unlimitededition; + +import java.util.UUID; + +/** + * + * @author AlumiuN + */ +public class Deathlace extends mage.sets.limitedbeta.Deathlace { + + public Deathlace(UUID ownerId) { + super(ownerId); + this.cardNumber = 10; + this.expansionSetCode = "2ED"; + } + + public Deathlace(final Deathlace card) { + super(card); + } + + @Override + public Deathlace copy() { + return new Deathlace(this); + } +} diff --git a/Mage.Sets/src/mage/sets/unlimitededition/Lifelace.java b/Mage.Sets/src/mage/sets/unlimitededition/Lifelace.java new file mode 100644 index 0000000000..d96ebdbe10 --- /dev/null +++ b/Mage.Sets/src/mage/sets/unlimitededition/Lifelace.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.unlimitededition; + +import java.util.UUID; + +/** + * + * @author AlumiuN + */ +public class Lifelace extends mage.sets.limitedalpha.Lifelace { + + public Lifelace(UUID ownerId) { + super(ownerId); + this.cardNumber = 116; + this.expansionSetCode = "2ED"; + } + + public Lifelace(final Lifelace card) { + super(card); + } + + @Override + public Lifelace copy() { + return new Lifelace(this); + } +} diff --git a/Mage.Sets/src/mage/sets/unlimitededition/Purelace.java b/Mage.Sets/src/mage/sets/unlimitededition/Purelace.java new file mode 100644 index 0000000000..d7fb351bf0 --- /dev/null +++ b/Mage.Sets/src/mage/sets/unlimitededition/Purelace.java @@ -0,0 +1,62 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE 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.unlimitededition; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.effects.common.continuous.BecomesColorTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.target.common.TargetSpellOrPermanent; + +/** + * + * @author AlumiuN + */ +public class Purelace extends CardImpl { + + public Purelace(UUID ownerId) { + super(ownerId, 217, "Purelace", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{W}"); + this.expansionSetCode = "2ED"; + + // Target spell or permanent becomes white. + this.getSpellAbility().addTarget(new TargetSpellOrPermanent()); + this.getSpellAbility().addEffect(new BecomesColorTargetEffect(ObjectColor.WHITE, Duration.Custom)); + } + + public Purelace(final Purelace card) { + super(card); + } + + @Override + public Purelace copy() { + return new Purelace(this); + } +} diff --git a/Mage.Sets/src/mage/sets/unlimitededition/Thoughtlace.java b/Mage.Sets/src/mage/sets/unlimitededition/Thoughtlace.java new file mode 100644 index 0000000000..e7fb6d3908 --- /dev/null +++ b/Mage.Sets/src/mage/sets/unlimitededition/Thoughtlace.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.unlimitededition; + +import java.util.UUID; + +/** + * + * @author AlumiuN + */ +public class Thoughtlace extends mage.sets.limitedbeta.Thoughtlace { + + public Thoughtlace(UUID ownerId) { + super(ownerId); + this.cardNumber = 83; + this.expansionSetCode = "2ED"; + } + + public Thoughtlace(final Thoughtlace card) { + super(card); + } + + @Override + public Thoughtlace copy() { + return new Thoughtlace(this); + } +} From bc06e83ce17027a0413730194199162d55c6a4c3 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 9 Oct 2015 14:55:39 +0200 Subject: [PATCH 02/46] * Nissa, Sage Animist - Added test for +1 ability. --- .../sets/magicorigins/NissaSageAnimist.java | 14 ++++++------- .../abilities/keywords/TransformTest.java | 20 +++++++++++++++---- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/Mage.Sets/src/mage/sets/magicorigins/NissaSageAnimist.java b/Mage.Sets/src/mage/sets/magicorigins/NissaSageAnimist.java index 7959cf7f6b..d3a209c463 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/NissaSageAnimist.java +++ b/Mage.Sets/src/mage/sets/magicorigins/NissaSageAnimist.java @@ -28,6 +28,7 @@ package mage.sets.magicorigins; import java.util.UUID; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; import mage.abilities.common.EntersBattlefieldAbility; @@ -112,19 +113,18 @@ class NissaSageAnimistPlusOneEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null && controller.getLibrary().size() > 0) { + MageObject sourceObject = game.getObject(source.getSourceId()); + if (sourceObject != null && controller != null && controller.getLibrary().size() > 0) { Card card = controller.getLibrary().getFromTop(game); if (card == null) { return false; } - CardsImpl cards = new CardsImpl(); - cards.add(card); - controller.revealCards("Nissa, Sage Animist", cards, game); + controller.revealCards(sourceObject.getIdName(), new CardsImpl(card), game); + Zone targetZone = Zone.HAND; if (card.getCardType().contains(CardType.LAND)) { - return controller.putOntoBattlefieldWithInfo(card, game, Zone.LIBRARY, source.getSourceId()); - } else { - return controller.moveCards(card, Zone.LIBRARY, Zone.HAND, source, game); + targetZone = Zone.BATTLEFIELD; } + return controller.moveCards(card, null, targetZone, source, game); } return true; } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/TransformTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/TransformTest.java index 14e6c0db6a..d37249116c 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/TransformTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/TransformTest.java @@ -44,23 +44,35 @@ public class TransformTest extends CardTestPlayerBase { addCard(Zone.LIBRARY, playerA, "Forest"); - addCard(Zone.BATTLEFIELD, playerA, "Forest", 6); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 5); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1); // When Nissa, Vastwood Seer enters the battlefield, you may search your library for a basic Forest card, reveal it, put it into your hand, then shuffle your library. // Whenever a land enters the battlefield under your control, if you control seven or more lands, exile Nissa, then return her to the battlefield transformed under her owner's control. addCard(Zone.HAND, playerA, "Nissa, Vastwood Seer"); + addCard(Zone.BATTLEFIELD, playerB, "Forest", 2); + // {G}{G}, Sacrifice Rootrunner: Put target land on top of its owner's library. + addCard(Zone.BATTLEFIELD, playerB, "Rootrunner"); // {2}{G}{G} + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Nissa, Vastwood Seer"); playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Forest"); - setStopAt(1, PhaseStep.BEGIN_COMBAT); + activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "{G}{G}", "Swamp"); + activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "+1: Reveal"); + + setStopAt(1, PhaseStep.END_TURN); execute(); - assertPermanentCount(playerA, "Forest", 7); + assertGraveyardCount(playerB, "Rootrunner", 1); assertPermanentCount(playerA, "Nissa, Vastwood Seer", 0); assertPermanentCount(playerA, "Nissa, Sage Animist", 1); - assertCounterCount("Nissa, Sage Animist", CounterType.LOYALTY, 3); + + assertCounterCount("Nissa, Sage Animist", CounterType.LOYALTY, 4); + assertPermanentCount(playerA, "Forest", 6); + assertPermanentCount(playerA, "Swamp", 1); + } @Test From 0d127ae2e03154f03c8cecc81674481dcdcff954 Mon Sep 17 00:00:00 2001 From: LoneFox Date: Sun, 11 Oct 2015 11:33:59 +0300 Subject: [PATCH 03/46] Implement cards: Armor Thrull, Dwarven Armorer, Dwarven Lieutenant, and Elven Lyre --- .../mage/sets/fallenempires/ArmorThrull1.java | 52 +++++++ .../mage/sets/fallenempires/ArmorThrull2.java | 52 +++++++ .../mage/sets/fallenempires/ArmorThrull3.java | 52 +++++++ .../mage/sets/fallenempires/ArmorThrull4.java | 52 +++++++ .../sets/fallenempires/DwarvenArmorer.java | 128 ++++++++++++++++++ .../sets/fallenempires/DwarvenLieutenant.java | 79 +++++++++++ .../mage/sets/fallenempires/ElvenLyre.java | 54 ++++++++ .../sets/masterseditionii/ArmorThrull.java | 72 ++++++++++ .../mage/sets/masterseditionii/ElvenLyre.java | 71 ++++++++++ Mage/src/mage/counters/CounterType.java | 6 + 10 files changed, 618 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/fallenempires/ArmorThrull1.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/ArmorThrull2.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/ArmorThrull3.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/ArmorThrull4.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/DwarvenArmorer.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/DwarvenLieutenant.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/ElvenLyre.java create mode 100644 Mage.Sets/src/mage/sets/masterseditionii/ArmorThrull.java create mode 100644 Mage.Sets/src/mage/sets/masterseditionii/ElvenLyre.java diff --git a/Mage.Sets/src/mage/sets/fallenempires/ArmorThrull1.java b/Mage.Sets/src/mage/sets/fallenempires/ArmorThrull1.java new file mode 100644 index 0000000000..e543304cf0 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/ArmorThrull1.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 LoneFox + */ +public class ArmorThrull1 extends mage.sets.masterseditionii.ArmorThrull { + + public ArmorThrull1(UUID ownerId) { + super(ownerId); + this.cardNumber = 1; + this.expansionSetCode = "FEM"; + } + + public ArmorThrull1(final ArmorThrull1 card) { + super(card); + } + + @Override + public ArmorThrull1 copy() { + return new ArmorThrull1(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/ArmorThrull2.java b/Mage.Sets/src/mage/sets/fallenempires/ArmorThrull2.java new file mode 100644 index 0000000000..c39b457788 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/ArmorThrull2.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 LoneFox + */ +public class ArmorThrull2 extends mage.sets.masterseditionii.ArmorThrull { + + public ArmorThrull2(UUID ownerId) { + super(ownerId); + this.cardNumber = 2; + this.expansionSetCode = "FEM"; + } + + public ArmorThrull2(final ArmorThrull2 card) { + super(card); + } + + @Override + public ArmorThrull2 copy() { + return new ArmorThrull2(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/ArmorThrull3.java b/Mage.Sets/src/mage/sets/fallenempires/ArmorThrull3.java new file mode 100644 index 0000000000..2a16cd7b3f --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/ArmorThrull3.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 LoneFox + */ +public class ArmorThrull3 extends mage.sets.masterseditionii.ArmorThrull { + + public ArmorThrull3(UUID ownerId) { + super(ownerId); + this.cardNumber = 3; + this.expansionSetCode = "FEM"; + } + + public ArmorThrull3(final ArmorThrull3 card) { + super(card); + } + + @Override + public ArmorThrull3 copy() { + return new ArmorThrull3(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/ArmorThrull4.java b/Mage.Sets/src/mage/sets/fallenempires/ArmorThrull4.java new file mode 100644 index 0000000000..97d46f8898 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/ArmorThrull4.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 LoneFox + */ +public class ArmorThrull4 extends mage.sets.masterseditionii.ArmorThrull { + + public ArmorThrull4(UUID ownerId) { + super(ownerId); + this.cardNumber = 4; + this.expansionSetCode = "FEM"; + } + + public ArmorThrull4(final ArmorThrull4 card) { + super(card); + } + + @Override + public ArmorThrull4 copy() { + return new ArmorThrull4(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/DwarvenArmorer.java b/Mage.Sets/src/mage/sets/fallenempires/DwarvenArmorer.java new file mode 100644 index 0000000000..b98704b1ec --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/DwarvenArmorer.java @@ -0,0 +1,128 @@ +/* + * 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.HashSet; +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.DiscardCardCost; +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.counter.AddCountersTargetEffect; +import mage.cards.CardImpl; +import mage.choices.Choice; +import mage.choices.ChoiceImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.counters.Counter; +import mage.counters.CounterType; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author LoneFox + */ +public class DwarvenArmorer extends CardImpl { + + public DwarvenArmorer(UUID ownerId) { + super(ownerId, 104, "Dwarven Armorer", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{R}"); + this.expansionSetCode = "FEM"; + this.subtype.add("Dwarf"); + this.power = new MageInt(0); + this.toughness = new MageInt(2); + + // {R}, {tap}, Discard a card: Put a +0/+1 counter or a +1/+0 counter on target creature. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DwarvenArmorerEffect(), new ManaCostsImpl("{R}")); + ability.addCost(new TapSourceCost()); + ability.addCost(new DiscardCardCost()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public DwarvenArmorer(final DwarvenArmorer card) { + super(card); + } + + @Override + public DwarvenArmorer copy() { + return new DwarvenArmorer(this); + } +} + +class DwarvenArmorerEffect extends OneShotEffect { + + private static final HashSet choices = new HashSet<>(); + + static { + choices.add("+0/+1"); + choices.add("+1/+0"); + } + + public DwarvenArmorerEffect() { + super(Outcome.Benefit); + staticText = "Put a +0/+1 counter or a +1/+0 counter on target creature."; + } + + public DwarvenArmorerEffect(final DwarvenArmorerEffect effect) { + super(effect); + } + + @java.lang.Override + public DwarvenArmorerEffect copy() { + return new DwarvenArmorerEffect(this); + } + + @java.lang.Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if(controller != null) { + Choice choice = new ChoiceImpl(true); + choice.setMessage("Choose type of counter to add"); + choice.setChoices(choices); + while(!controller.choose(outcome, choice, game)) { + if(controller.canRespond()) { + return false; + } + } + Counter counter = choice.getChoice().equals("+0/+1") ? CounterType.P0P1.createInstance() : CounterType.P1P0.createInstance(); + Effect effect = new AddCountersTargetEffect(counter); + effect.setTargetPointer(new FixedTarget(this.getTargetPointer().getFirst(game, source))); + return effect.apply(game, source); + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/DwarvenLieutenant.java b/Mage.Sets/src/mage/sets/fallenempires/DwarvenLieutenant.java new file mode 100644 index 0000000000..2cc864b9fc --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/DwarvenLieutenant.java @@ -0,0 +1,79 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.fallenempires; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + */ +public class DwarvenLieutenant extends CardImpl { + + static FilterCreaturePermanent filter = new FilterCreaturePermanent("Dwarf creature"); + + static { + filter.add(new SubtypePredicate("Dwarf")); + } + + public DwarvenLieutenant(UUID ownerId) { + super(ownerId, 106, "Dwarven Lieutenant", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{R}{R}"); + this.expansionSetCode = "FEM"; + this.subtype.add("Dwarf"); + this.subtype.add("Soldier"); + this.power = new MageInt(1); + this.toughness = new MageInt(2); + + // {1}{R}: Target Dwarf creature gets +1/+0 until end of turn. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(1, 0, Duration.EndOfTurn), new ManaCostsImpl("{1}{R}")); + ability.addTarget(new TargetCreaturePermanent(filter)); + this.addAbility(ability); + } + + public DwarvenLieutenant(final DwarvenLieutenant card) { + super(card); + } + + @Override + public DwarvenLieutenant copy() { + return new DwarvenLieutenant(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/ElvenLyre.java b/Mage.Sets/src/mage/sets/fallenempires/ElvenLyre.java new file mode 100644 index 0000000000..8657136f09 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/ElvenLyre.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 LoneFox + */ +public class ElvenLyre extends mage.sets.masterseditionii.ElvenLyre { + + public ElvenLyre(UUID ownerId) { + super(ownerId); + this.cardNumber = 172; + this.expansionSetCode = "FEM"; + this.rarity = Rarity.RARE; + } + + public ElvenLyre(final ElvenLyre card) { + super(card); + } + + @Override + public ElvenLyre copy() { + return new ElvenLyre(this); + } +} diff --git a/Mage.Sets/src/mage/sets/masterseditionii/ArmorThrull.java b/Mage.Sets/src/mage/sets/masterseditionii/ArmorThrull.java new file mode 100644 index 0000000000..dbd058685b --- /dev/null +++ b/Mage.Sets/src/mage/sets/masterseditionii/ArmorThrull.java @@ -0,0 +1,72 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.masterseditionii; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + */ +public class ArmorThrull extends CardImpl { + + public ArmorThrull(UUID ownerId) { + super(ownerId, 77, "Armor Thrull", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{B}"); + this.expansionSetCode = "ME2"; + this.subtype.add("Thrull"); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // {T}, Sacrifice Armor Thrull: Put a +1/+2 counter on target creature. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersTargetEffect(CounterType.P1P2.createInstance()), new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public ArmorThrull(final ArmorThrull card) { + super(card); + } + + @Override + public ArmorThrull copy() { + return new ArmorThrull(this); + } +} diff --git a/Mage.Sets/src/mage/sets/masterseditionii/ElvenLyre.java b/Mage.Sets/src/mage/sets/masterseditionii/ElvenLyre.java new file mode 100644 index 0000000000..5fd78b1f65 --- /dev/null +++ b/Mage.Sets/src/mage/sets/masterseditionii/ElvenLyre.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.masterseditionii; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + */ +public class ElvenLyre extends CardImpl { + + public ElvenLyre(UUID ownerId) { + super(ownerId, 208, "Elven Lyre", Rarity.COMMON, new CardType[]{CardType.ARTIFACT}, "{2}"); + this.expansionSetCode = "ME2"; + + // {1}, {tap}, Sacrifice Elven Lyre: Target creature gets +2/+2 until end of turn. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(2, 2, Duration.EndOfTurn), new ManaCostsImpl("{1}")); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + + } + + public ElvenLyre(final ElvenLyre card) { + super(card); + } + + @Override + public ElvenLyre copy() { + return new ElvenLyre(this); + } +} diff --git a/Mage/src/mage/counters/CounterType.java b/Mage/src/mage/counters/CounterType.java index eaf7bde19e..da70425325 100644 --- a/Mage/src/mage/counters/CounterType.java +++ b/Mage/src/mage/counters/CounterType.java @@ -75,8 +75,10 @@ public enum CounterType { M2M2(new BoostCounter(-2, -2).name), MINING("mining"), MUSTER("muster"), + P0P1(new BoostCounter(0, 1).name), P1P0(new BoostCounter(1, 0).name), P1P1(new BoostCounter(1, 1).name), + P1P2(new BoostCounter(1, 2).name), P2P2(new BoostCounter(2, 2).name), PAGE("page"), PAIN("pain"), @@ -134,10 +136,14 @@ public enum CounterType { */ public Counter createInstance(int amount) { switch (this) { + case P0P1: + return new BoostCounter(0, 1, amount); case P1P0: return new BoostCounter(1, 0, amount); case P1P1: return new BoostCounter(1, 1, amount); + case P1P2: + return new BoostCounter(1, 2, amount); case P2P2: return new BoostCounter(2, 2, amount); case M1M1: From 1227d8fc6fb23d4ecc783f533ec259ec95aaaac9 Mon Sep 17 00:00:00 2001 From: LoneFox Date: Sun, 11 Oct 2015 12:28:24 +0300 Subject: [PATCH 04/46] Fix Bloodied Ghost's tooltip text --- Mage.Sets/src/mage/sets/eventide/BloodiedGhost.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Mage.Sets/src/mage/sets/eventide/BloodiedGhost.java b/Mage.Sets/src/mage/sets/eventide/BloodiedGhost.java index 2d046b50df..dd8ae7ec4b 100644 --- a/Mage.Sets/src/mage/sets/eventide/BloodiedGhost.java +++ b/Mage.Sets/src/mage/sets/eventide/BloodiedGhost.java @@ -29,13 +29,13 @@ package mage.sets.eventide; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Rarity; import mage.MageInt; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; import mage.counters.CounterType; /** @@ -48,12 +48,15 @@ public class BloodiedGhost extends CardImpl { super(ownerId, 83, "Bloodied Ghost", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{W/B}{W/B}"); this.expansionSetCode = "EVE"; this.subtype.add("Spirit"); - - this.power = new MageInt(3); this.toughness = new MageInt(3); + + // Flying this.addAbility(FlyingAbility.getInstance()); - this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.M1M1.createInstance()), "Bloodied Ghost gets a -1/-1 counter")); + + // Bloodied Ghost enters the battlefield with a -1/-1 counter on it. + this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.M1M1.createInstance()), + "with a -1/-1 counter on it.")); } public BloodiedGhost (final BloodiedGhost card) { From f81605847b5e9a8ce682af68c1db1a5a32fdcaae Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 12 Oct 2015 17:35:04 +0200 Subject: [PATCH 05/46] * Paradox Haze - Fixed that check if a step is the first upkeep step of a turn did not work always correctly (fixes #1313). --- .../src/mage/sets/tempest/VerdantForce.java | 7 +- .../src/mage/sets/timespiral/ParadoxHaze.java | 39 ++++---- .../cards/enchantments/ParadoxHazeTest.java | 88 +++++++++++++++++++ .../watchers/common/FirstTimeStepWatcher.java | 72 +++++++++++++++ 4 files changed, 183 insertions(+), 23 deletions(-) create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/enchantments/ParadoxHazeTest.java create mode 100644 Mage/src/mage/watchers/common/FirstTimeStepWatcher.java diff --git a/Mage.Sets/src/mage/sets/tempest/VerdantForce.java b/Mage.Sets/src/mage/sets/tempest/VerdantForce.java index 4377abe9c5..b383f7df44 100644 --- a/Mage.Sets/src/mage/sets/tempest/VerdantForce.java +++ b/Mage.Sets/src/mage/sets/tempest/VerdantForce.java @@ -28,13 +28,12 @@ package mage.sets.tempest; import java.util.UUID; - -import mage.constants.CardType; -import mage.constants.Rarity; import mage.MageInt; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; import mage.constants.TargetController; import mage.game.permanent.token.SaprolingToken; @@ -51,6 +50,8 @@ public class VerdantForce extends CardImpl { this.power = new MageInt(7); this.toughness = new MageInt(7); + + // At the beginning of each upkeep, put a 1/1 green Saproling creature token onto the battlefield. this.addAbility(new BeginningOfUpkeepTriggeredAbility(new CreateTokenEffect(new SaprolingToken()), TargetController.ANY, false)); } diff --git a/Mage.Sets/src/mage/sets/timespiral/ParadoxHaze.java b/Mage.Sets/src/mage/sets/timespiral/ParadoxHaze.java index 40c612225b..76b84e06c3 100644 --- a/Mage.Sets/src/mage/sets/timespiral/ParadoxHaze.java +++ b/Mage.Sets/src/mage/sets/timespiral/ParadoxHaze.java @@ -47,6 +47,7 @@ import mage.game.turn.UpkeepStep; import mage.players.Player; import mage.target.TargetPlayer; import mage.target.targetpointer.FixedTarget; +import mage.watchers.common.FirstTimeStepWatcher; /** * @@ -59,15 +60,14 @@ public class ParadoxHaze extends CardImpl { this.expansionSetCode = "TSP"; this.subtype.add("Aura"); - // Enchant player TargetPlayer auraTarget = new TargetPlayer(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.Neutral)); this.addAbility(new EnchantAbility(auraTarget.getTargetName())); - + // At the beginning of enchanted player's first upkeep each turn, that player gets an additional upkeep step after this step. - this.addAbility(new ParadoxHazeTriggeredAbility()); + this.addAbility(new ParadoxHazeTriggeredAbility(), new FirstTimeStepWatcher(EventType.UPKEEP_STEP_POST)); } public ParadoxHaze(final ParadoxHaze card) { @@ -81,18 +81,15 @@ public class ParadoxHaze extends CardImpl { } class ParadoxHazeTriggeredAbility extends TriggeredAbilityImpl { - - protected int lastTriggerTurnNumber; - + ParadoxHazeTriggeredAbility() { super(Zone.BATTLEFIELD, new ParadoxHazeEffect(), false); } - + ParadoxHazeTriggeredAbility(final ParadoxHazeTriggeredAbility ability) { super(ability); - lastTriggerTurnNumber = ability.lastTriggerTurnNumber; } - + @Override public ParadoxHazeTriggeredAbility copy() { return new ParadoxHazeTriggeredAbility(this); @@ -102,21 +99,23 @@ class ParadoxHazeTriggeredAbility extends TriggeredAbilityImpl { public boolean checkEventType(GameEvent event, Game game) { return event.getType() == EventType.UPKEEP_STEP_PRE; } - + @Override public boolean checkTrigger(GameEvent event, Game game) { - Permanent permanent = game.getPermanent(this.sourceId); + Permanent permanent = game.getPermanent(getSourceId()); if (permanent != null) { Player player = game.getPlayer(permanent.getAttachedTo()); - if (player != null && game.getActivePlayerId().equals(player.getId()) && lastTriggerTurnNumber != game.getTurnNum()) { - lastTriggerTurnNumber = game.getTurnNum(); - this.getEffects().get(0).setTargetPointer(new FixedTarget(player.getId())); - return true; + if (player != null && game.getActivePlayerId().equals(player.getId())) { + FirstTimeStepWatcher watcher = (FirstTimeStepWatcher) game.getState().getWatchers().get(EventType.UPKEEP_STEP_POST.toString() + FirstTimeStepWatcher.class.getName()); + if (watcher != null && !watcher.conditionMet()) { + this.getEffects().get(0).setTargetPointer(new FixedTarget(player.getId())); + return true; + } } } return false; } - + @Override public String getRule() { return "At the beginning of enchanted player's first upkeep each turn, that player gets an additional upkeep step after this step."; @@ -124,21 +123,21 @@ class ParadoxHazeTriggeredAbility extends TriggeredAbilityImpl { } class ParadoxHazeEffect extends OneShotEffect { - + ParadoxHazeEffect() { super(Outcome.Benefit); this.staticText = "that player gets an additional upkeep step after this step"; } - + ParadoxHazeEffect(final ParadoxHazeEffect effect) { super(effect); } - + @Override public ParadoxHazeEffect copy() { return new ParadoxHazeEffect(this); } - + @Override public boolean apply(Game game, Ability source) { game.getState().getTurnMods().add(new TurnMod(this.getTargetPointer().getFirst(game, source), new UpkeepStep(), null)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/ParadoxHazeTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/ParadoxHazeTest.java new file mode 100644 index 0000000000..917e25519d --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/ParadoxHazeTest.java @@ -0,0 +1,88 @@ +/* + * 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.enchantments; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class ParadoxHazeTest extends CardTestPlayerBase { + + @Test + public void testNormal() { + addCard(Zone.BATTLEFIELD, playerA, "Island", 3); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 8); + // Enchant player + // At the beginning of enchanted player's first upkeep each turn, that player gets an additional upkeep step after this step. + addCard(Zone.HAND, playerA, "Paradox Haze", 1); // {2}{U} + // At the beginning of each upkeep, put a 1/1 green Saproling creature token onto the battlefield. + addCard(Zone.HAND, playerA, "Verdant Force", 1); // {5}{G}{G}{G} + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Paradox Haze", playerA); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Verdant Force"); + + setStopAt(3, PhaseStep.PRECOMBAT_MAIN); + execute(); + + assertPermanentCount(playerA, "Paradox Haze", 1); + assertPermanentCount(playerA, "Verdant Force", 1); + assertPermanentCount(playerA, "Saproling", 3);// 1 from turn 2 and 2 from turn 3 + } + + @Test + public void testCopied() { + addCard(Zone.BATTLEFIELD, playerA, "Island", 6); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 8); + // Enchant player + // At the beginning of enchanted player's first upkeep each turn, that player gets an additional upkeep step after this step. + addCard(Zone.HAND, playerA, "Paradox Haze", 1); // {2}{U} + + // You may have Copy Enchantment enter the battlefield as a copy of any enchantment on the battlefield. + addCard(Zone.HAND, playerA, "Copy Enchantment", 1); // {2}{U} + + // At the beginning of each upkeep, put a 1/1 green Saproling creature token onto the battlefield. + addCard(Zone.HAND, playerA, "Verdant Force", 1); // {5}{G}{G}{G} + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Paradox Haze", playerA); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Copy Enchantment"); + setChoice(playerA, "Paradox Haze"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Verdant Force"); + + setStopAt(3, PhaseStep.PRECOMBAT_MAIN); + execute(); + + assertPermanentCount(playerA, "Paradox Haze", 2); + assertPermanentCount(playerA, "Verdant Force", 1); + assertPermanentCount(playerA, "Saproling", 4); // 1 from turn 2 and 3 from turn 3 + } +} diff --git a/Mage/src/mage/watchers/common/FirstTimeStepWatcher.java b/Mage/src/mage/watchers/common/FirstTimeStepWatcher.java new file mode 100644 index 0000000000..911a3ecf93 --- /dev/null +++ b/Mage/src/mage/watchers/common/FirstTimeStepWatcher.java @@ -0,0 +1,72 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.watchers.common; + +import mage.constants.WatcherScope; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.watchers.Watcher; + +/** + * The wachter checks if a specific phase event has already happened during the + * current turn. If not it returns false, otheriwsed true. + * + * @author LevelX2 + */ +public class FirstTimeStepWatcher extends Watcher { + + private final EventType eventType; + + public FirstTimeStepWatcher(EventType eventType) { + super(eventType.toString() + FirstTimeStepWatcher.class.getName(), WatcherScope.GAME); + this.eventType = eventType; + } + + public FirstTimeStepWatcher(final FirstTimeStepWatcher watcher) { + super(watcher); + this.eventType = watcher.eventType; + } + + @Override + public FirstTimeStepWatcher copy() { + return new FirstTimeStepWatcher(this); + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() == eventType) { + condition = true; + } + } + + @Override + public void reset() { + super.reset(); + } +} From ccf33f15ca7bd30f79a05f50551f01f9443969f8 Mon Sep 17 00:00:00 2001 From: LoneFox Date: Mon, 12 Oct 2015 19:18:58 +0300 Subject: [PATCH 06/46] Add RemoveAllCountersSourceEffect and use it for Witherscale Wurm. Implement cards: Homarid and Tidal Influence TODO: The tooltip text of Tidal Infuence's first ability is wrong. The idea is copied from Feast of Blood, which also has the same problem. --- .../src/mage/sets/fallenempires/Homarid1.java | 120 +++++++++++++ .../src/mage/sets/fallenempires/Homarid2.java | 51 ++++++ .../src/mage/sets/fallenempires/Homarid3.java | 51 ++++++ .../src/mage/sets/fallenempires/Homarid4.java | 51 ++++++ .../sets/fallenempires/TidalInfluence.java | 167 ++++++++++++++++++ .../mage/sets/shadowmoor/WitherscaleWurm.java | 37 +--- .../common/RemoveAllCountersSourceEffect.java | 73 ++++++++ Mage/src/mage/counters/CounterType.java | 1 + 8 files changed, 516 insertions(+), 35 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/fallenempires/Homarid1.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/Homarid2.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/Homarid3.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/Homarid4.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/TidalInfluence.java create mode 100644 Mage/src/mage/abilities/effects/common/RemoveAllCountersSourceEffect.java diff --git a/Mage.Sets/src/mage/sets/fallenempires/Homarid1.java b/Mage.Sets/src/mage/sets/fallenempires/Homarid1.java new file mode 100644 index 0000000000..a69771b105 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/Homarid1.java @@ -0,0 +1,120 @@ +/* + * 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.StateTriggeredAbility; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.SourceHasCounterCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.RemoveAllCountersSourceEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.events.GameEvent; + +/** + * + * @author LoneFox + */ +public class Homarid1 extends CardImpl { + + public Homarid1(UUID ownerId) { + super(ownerId, 38, "Homarid", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{U}"); + this.expansionSetCode = "FEM"; + this.subtype.add("Homarid"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Homarid enters the battlefield with a tide counter on it. + this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.TIDE.createInstance()), + "with a tide counter on it.")); + // At the beginning of your upkeep, put a tide counter on Homarid. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.TIDE.createInstance()), + TargetController.YOU, false)); + // As long as there is exactly one tide counter on Homarid, it gets -1/-1. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect( + new BoostSourceEffect(-1, -1, Duration.WhileOnBattlefield), new SourceHasCounterCondition(CounterType.TIDE, 1, 1), + "As long as there is exactly one tide counter on {this}, it gets -1/-1."))); + // As long as there are exactly three tide counters on Homarid, it gets +1/+1. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect( + new BoostSourceEffect(1, 1, Duration.WhileOnBattlefield), new SourceHasCounterCondition(CounterType.TIDE, 3, 3), + "As long as there are exactly three tide counter on {this}, it gets +1/+1."))); + // Whenever there are four tide counters on Homarid, remove all tide counters from it. + this.addAbility(new HomaridTriggeredAbility(new RemoveAllCountersSourceEffect(CounterType.TIDE))); + } + + public Homarid1(final Homarid1 card) { + super(card); + } + + @Override + public Homarid1 copy() { + return new Homarid1(this); + } +} + +class HomaridTriggeredAbility extends StateTriggeredAbility { + + public HomaridTriggeredAbility(Effect effect) { + super(Zone.BATTLEFIELD, effect); + } + + public HomaridTriggeredAbility(final HomaridTriggeredAbility ability) { + super(ability); + } + + @Override + public HomaridTriggeredAbility copy() { + return new HomaridTriggeredAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return new CountersCount(CounterType.TIDE).calculate(game, this, null) == 4; + } + + @Override + public String getRule() { + return "Whenever there are four tide counters on {this}, " + super.getRule(); + } + +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/Homarid2.java b/Mage.Sets/src/mage/sets/fallenempires/Homarid2.java new file mode 100644 index 0000000000..51d33e80bb --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/Homarid2.java @@ -0,0 +1,51 @@ +/* + * 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 LoneFox + */ +public class Homarid2 extends Homarid1 { + + public Homarid2(UUID ownerId) { + super(ownerId); + this.cardNumber = 39; + } + + public Homarid2(final Homarid2 card) { + super(card); + } + + @Override + public Homarid2 copy() { + return new Homarid2(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/Homarid3.java b/Mage.Sets/src/mage/sets/fallenempires/Homarid3.java new file mode 100644 index 0000000000..f42970458e --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/Homarid3.java @@ -0,0 +1,51 @@ +/* + * 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 LoneFox + */ +public class Homarid3 extends Homarid1 { + + public Homarid3(UUID ownerId) { + super(ownerId); + this.cardNumber = 40; + } + + public Homarid3(final Homarid3 card) { + super(card); + } + + @Override + public Homarid3 copy() { + return new Homarid3(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/Homarid4.java b/Mage.Sets/src/mage/sets/fallenempires/Homarid4.java new file mode 100644 index 0000000000..4ae2066c64 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/Homarid4.java @@ -0,0 +1,51 @@ +/* + * 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 LoneFox + */ +public class Homarid4 extends Homarid1 { + + public Homarid4(UUID ownerId) { + super(ownerId); + this.cardNumber = 41; + } + + public Homarid4(final Homarid4 card) { + super(card); + } + + @Override + public Homarid4 copy() { + return new Homarid4(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/TidalInfluence.java b/Mage.Sets/src/mage/sets/fallenempires/TidalInfluence.java new file mode 100644 index 0000000000..5de52d6b93 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/TidalInfluence.java @@ -0,0 +1,167 @@ +/* + * 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.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.StateTriggeredAbility; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.SourceHasCounterCondition; +import mage.abilities.costs.CostImpl; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.dynamicvalue.common.CountersCount; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.RemoveAllCountersSourceEffect; +import mage.abilities.effects.common.continuous.BoostAllEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.filter.predicate.mageobject.NamePredicate; +import mage.game.Game; +import mage.game.events.GameEvent; + +/** + * + * @author LoneFox + */ +public class TidalInfluence extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("blue creatures"); + + static { + filter.add(new ColorPredicate(ObjectColor.BLUE)); + } + + public TidalInfluence(UUID ownerId) { + super(ownerId, 57, "Tidal Influence", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); + this.expansionSetCode = "FEM"; + + // Cast Tidal Influence only if no permanents named Tidal Influence are on the battlefield. + this.getSpellAbility().addCost(new TidalInfluenceCost()); + // Tidal Influence enters the battlefield with a tide counter on it. + this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.TIDE.createInstance()), + "with a tide counter on it.")); + // At the beginning of your upkeep, put a tide counter on Tidal Influence. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.TIDE.createInstance()), + TargetController.YOU, false)); + // As long as there is exactly one tide counter on Tidal Influence, all blue creatures get -2/-0. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect( + new BoostAllEffect(-2, -0, Duration.WhileOnBattlefield, filter, false), + new SourceHasCounterCondition(CounterType.TIDE, 1, 1), + "As long as there is exactly one tide counter on {this}, all blue creatures get -2/-0."))); + // As long as there are exactly three tide counters on Tidal Influence, all blue creatures get +2/+0. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect( + new BoostAllEffect(2, -0, Duration.WhileOnBattlefield, filter, false), + new SourceHasCounterCondition(CounterType.TIDE, 3, 3), + "As long as there are exactly three tide counter on {this}, all blue creatures get +2/-0."))); + // Whenever there are four tide counters on Tidal Influence, remove all tide counters from it. + this.addAbility(new TidalInfluenceTriggeredAbility(new RemoveAllCountersSourceEffect(CounterType.TIDE))); + } + + public TidalInfluence(final TidalInfluence card) { + super(card); + } + + @Override + public TidalInfluence copy() { + return new TidalInfluence(this); + } +} + + +class TidalInfluenceCost extends CostImpl { + + private static final FilterPermanent filter = new FilterPermanent(); + + static { + filter.add(new NamePredicate("Tidal Influence")); + } + + public TidalInfluenceCost() { + this.text = "Cast Tidal Influence only if no permanents named Tidal Influence are on the battlefield"; + } + + public TidalInfluenceCost(final TidalInfluenceCost cost) { + super(cost); + } + + @Override + public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { + return !game.getBattlefield().contains(filter, 1, game); + } + + @Override + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { + this.paid = true; + return paid; + } + + @Override + public TidalInfluenceCost copy() { + return new TidalInfluenceCost(this); + } +} + + +class TidalInfluenceTriggeredAbility extends StateTriggeredAbility { + + public TidalInfluenceTriggeredAbility(Effect effect) { + super(Zone.BATTLEFIELD, effect); + } + + public TidalInfluenceTriggeredAbility(final TidalInfluenceTriggeredAbility ability) { + super(ability); + } + + @Override + public TidalInfluenceTriggeredAbility copy() { + return new TidalInfluenceTriggeredAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return new CountersCount(CounterType.TIDE).calculate(game, this, null) == 4; + } + + @Override + public String getRule() { + return "Whenever there are four tide counters on {this}, " + super.getRule(); + } + +} diff --git a/Mage.Sets/src/mage/sets/shadowmoor/WitherscaleWurm.java b/Mage.Sets/src/mage/sets/shadowmoor/WitherscaleWurm.java index bc3e1f3d06..9f8ba6c97d 100644 --- a/Mage.Sets/src/mage/sets/shadowmoor/WitherscaleWurm.java +++ b/Mage.Sets/src/mage/sets/shadowmoor/WitherscaleWurm.java @@ -29,21 +29,17 @@ package mage.sets.shadowmoor; import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.BlocksOrBecomesBlockedByCreatureTriggeredAbility; import mage.abilities.common.DealsDamageToOpponentTriggeredAbility; import mage.abilities.effects.Effect; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.RemoveAllCountersSourceEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.keyword.WitherAbility; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Duration; -import mage.constants.Outcome; import mage.constants.Rarity; import mage.counters.CounterType; -import mage.game.Game; -import mage.game.permanent.Permanent; /** * @@ -65,7 +61,7 @@ public class WitherscaleWurm extends CardImpl { this.addAbility(new BlocksOrBecomesBlockedByCreatureTriggeredAbility(effect, false)); // Whenever Witherscale Wurm deals damage to an opponent, remove all -1/-1 counters from it. - this.addAbility(new DealsDamageToOpponentTriggeredAbility(new WitherscaleWurmEffect(), false)); + this.addAbility(new DealsDamageToOpponentTriggeredAbility(new RemoveAllCountersSourceEffect(CounterType.M1M1), false)); } @@ -78,32 +74,3 @@ public class WitherscaleWurm extends CardImpl { return new WitherscaleWurm(this); } } - -class WitherscaleWurmEffect extends OneShotEffect { - - public WitherscaleWurmEffect() { - super(Outcome.Benefit); - staticText = "remove all -1/-1 counters from it"; - } - - public WitherscaleWurmEffect(WitherscaleWurmEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent witherscaleWurm = game.getPermanent(source.getSourceId()); - if (witherscaleWurm != null - && witherscaleWurm.getCounters().containsKey(CounterType.M1M1)) { - int M1M1Counters = witherscaleWurm.getCounters().getCount(CounterType.M1M1); - witherscaleWurm.getCounters().removeCounter(CounterType.M1M1, M1M1Counters); - return true; - } - return false; - } - - @Override - public WitherscaleWurmEffect copy() { - return new WitherscaleWurmEffect(this); - } -} diff --git a/Mage/src/mage/abilities/effects/common/RemoveAllCountersSourceEffect.java b/Mage/src/mage/abilities/effects/common/RemoveAllCountersSourceEffect.java new file mode 100644 index 0000000000..abc70475f4 --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/RemoveAllCountersSourceEffect.java @@ -0,0 +1,73 @@ +/* + * 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.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author LoneFox + */ +public class RemoveAllCountersSourceEffect extends OneShotEffect { + + private final CounterType counterType; + + public RemoveAllCountersSourceEffect(CounterType counterType) { + super(Outcome.Neutral); + this.counterType = counterType; + staticText = "remove all " + counterType.getName() + " counters from it."; + } + + public RemoveAllCountersSourceEffect(final RemoveAllCountersSourceEffect effect) { + super(effect); + this.counterType = effect.counterType; + } + + @Override + public RemoveAllCountersSourceEffect copy() { + return new RemoveAllCountersSourceEffect(this); + } + + @java.lang.Override + public boolean apply(Game game, Ability source) { + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); + if(sourcePermanent != null) { + int count = sourcePermanent.getCounters().getCount(counterType); + sourcePermanent.getCounters().removeCounter(counterType, count); + return true; + } + return false; + } +} + diff --git a/Mage/src/mage/counters/CounterType.java b/Mage/src/mage/counters/CounterType.java index da70425325..f753763875 100644 --- a/Mage/src/mage/counters/CounterType.java +++ b/Mage/src/mage/counters/CounterType.java @@ -96,6 +96,7 @@ public enum CounterType { STRIFE("strife"), STUDY("study"), THEFT("theft"), + TIDE("tide"), TIME("time"), TOWER("tower"), VELOCITY("velocity"), From b8c96fda2d442d52185e49010aa9d7cce012381b Mon Sep 17 00:00:00 2001 From: LoneFox Date: Mon, 12 Oct 2015 20:47:43 +0300 Subject: [PATCH 07/46] Implement cards: Deep Spawn, Homarid Shaman, Homarid Warrior, and Vodalian Mage --- .../mage/sets/fallenempires/DeepSpawn.java | 88 +++++++++++++++++++ .../sets/fallenempires/HomaridShaman.java | 79 +++++++++++++++++ .../sets/fallenempires/HomaridWarrior1.java | 78 ++++++++++++++++ .../sets/fallenempires/HomaridWarrior2.java | 51 +++++++++++ .../sets/fallenempires/HomaridWarrior3.java | 51 +++++++++++ .../sets/fallenempires/VodalianMage1.java | 73 +++++++++++++++ .../sets/fallenempires/VodalianMage2.java | 51 +++++++++++ .../sets/fallenempires/VodalianMage3.java | 51 +++++++++++ .../sets/fifthedition/HomaridWarrior.java | 52 +++++++++++ .../mage/sets/masterseditionii/DeepSpawn.java | 54 ++++++++++++ 10 files changed, 628 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/fallenempires/DeepSpawn.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/HomaridShaman.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/HomaridWarrior1.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/HomaridWarrior2.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/HomaridWarrior3.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/VodalianMage1.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/VodalianMage2.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/VodalianMage3.java create mode 100644 Mage.Sets/src/mage/sets/fifthedition/HomaridWarrior.java create mode 100644 Mage.Sets/src/mage/sets/masterseditionii/DeepSpawn.java diff --git a/Mage.Sets/src/mage/sets/fallenempires/DeepSpawn.java b/Mage.Sets/src/mage/sets/fallenempires/DeepSpawn.java new file mode 100644 index 0000000000..129e152a1c --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/DeepSpawn.java @@ -0,0 +1,88 @@ +/* + * 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.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.PutTopCardOfYourLibraryToGraveyardCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DontUntapInControllersNextUntapStepSourceEffect; +import mage.abilities.effects.common.SacrificeSourceUnlessPaysEffect; +import mage.abilities.effects.common.TapSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.ShroudAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; + +/** + * + * @author LoneFox + */ +public class DeepSpawn extends CardImpl { + + public DeepSpawn(UUID ownerId) { + super(ownerId, 34, "Deep Spawn", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{5}{U}{U}{U}"); + this.expansionSetCode = "FEM"; + this.subtype.add("Homarid"); + this.power = new MageInt(6); + this.toughness = new MageInt(6); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + // At the beginning of your upkeep, sacrifice Deep Spawn unless you put the top two cards of your library into your graveyard. + Effect effect = new SacrificeSourceUnlessPaysEffect(new PutTopCardOfYourLibraryToGraveyardCost(2)); + effect.setText("sacrifice {this} unless you put the top two cards of your library into your graveyard"); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(effect, TargetController.YOU, false)); + // {U}: Deep Spawn gains shroud until end of turn and doesn't untap during your next untap step. Tap Deep Spawn. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilitySourceEffect( + ShroudAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl("{U}")); + effect = new DontUntapInControllersNextUntapStepSourceEffect(); + effect.setText("and doesn't untap during your next untap step"); + ability.addEffect(effect); + ability.addEffect(new TapSourceEffect()); + this.addAbility(ability); + } + + public DeepSpawn(final DeepSpawn card) { + super(card); + } + + @Override + public DeepSpawn copy() { + return new DeepSpawn(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/HomaridShaman.java b/Mage.Sets/src/mage/sets/fallenempires/HomaridShaman.java new file mode 100644 index 0000000000..e092c8daa7 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/HomaridShaman.java @@ -0,0 +1,79 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.fallenempires; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.TapTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + */ +public class HomaridShaman extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("green creature"); + + static { + filter.add(new ColorPredicate(ObjectColor.GREEN)); + } + + public HomaridShaman(UUID ownerId) { + super(ownerId, 42, "Homarid Shaman", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{U}{U}"); + this.expansionSetCode = "FEM"; + this.subtype.add("Homarid"); + this.subtype.add("Shaman"); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // {U}: Tap target green creature. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(), new ManaCostsImpl("{U}")); + ability.addTarget(new TargetCreaturePermanent(filter)); + this.addAbility(ability); + } + + public HomaridShaman(final HomaridShaman card) { + super(card); + } + + @Override + public HomaridShaman copy() { + return new HomaridShaman(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/HomaridWarrior1.java b/Mage.Sets/src/mage/sets/fallenempires/HomaridWarrior1.java new file mode 100644 index 0000000000..2411486926 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/HomaridWarrior1.java @@ -0,0 +1,78 @@ +/* + * 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.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DontUntapInControllersNextUntapStepSourceEffect; +import mage.abilities.effects.common.TapSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.ShroudAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author LoneFox + */ +public class HomaridWarrior1 extends CardImpl { + + public HomaridWarrior1(UUID ownerId) { + super(ownerId, 44, "Homarid Warrior", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{4}{U}"); + this.expansionSetCode = "FEM"; + this.subtype.add("Homarid"); + this.subtype.add("Warrior"); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // {U}: Homarid Warrior gains shroud until end of turn and doesn't untap during your next untap step. Tap Homarid Warrior. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilitySourceEffect( + ShroudAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl("{U}")); + Effect effect = new DontUntapInControllersNextUntapStepSourceEffect(); + effect.setText("and doesn't untap during your next untap step"); + ability.addEffect(effect); + ability.addEffect(new TapSourceEffect()); + this.addAbility(ability); + } + + public HomaridWarrior1(final HomaridWarrior1 card) { + super(card); + } + + @Override + public HomaridWarrior1 copy() { + return new HomaridWarrior1(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/HomaridWarrior2.java b/Mage.Sets/src/mage/sets/fallenempires/HomaridWarrior2.java new file mode 100644 index 0000000000..f927b68c66 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/HomaridWarrior2.java @@ -0,0 +1,51 @@ +/* + * 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 LoneFox + */ +public class HomaridWarrior2 extends HomaridWarrior1 { + + public HomaridWarrior2(UUID ownerId) { + super(ownerId); + this.cardNumber = 45; + } + + public HomaridWarrior2(final HomaridWarrior2 card) { + super(card); + } + + @Override + public HomaridWarrior2 copy() { + return new HomaridWarrior2(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/HomaridWarrior3.java b/Mage.Sets/src/mage/sets/fallenempires/HomaridWarrior3.java new file mode 100644 index 0000000000..92ba080f52 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/HomaridWarrior3.java @@ -0,0 +1,51 @@ +/* + * 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 LoneFox + */ +public class HomaridWarrior3 extends HomaridWarrior1 { + + public HomaridWarrior3(UUID ownerId) { + super(ownerId); + this.cardNumber = 46; + } + + public HomaridWarrior3(final HomaridWarrior3 card) { + super(card); + } + + @Override + public HomaridWarrior3 copy() { + return new HomaridWarrior3(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/VodalianMage1.java b/Mage.Sets/src/mage/sets/fallenempires/VodalianMage1.java new file mode 100644 index 0000000000..ec3c12ddde --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/VodalianMage1.java @@ -0,0 +1,73 @@ +/* + * 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.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.CounterUnlessPaysEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.TargetSpell; + +/** + * + * @author LoneFox + */ +public class VodalianMage1 extends CardImpl { + + public VodalianMage1(UUID ownerId) { + super(ownerId, 59, "Vodalian Mage", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{U}"); + this.expansionSetCode = "FEM"; + this.subtype.add("Merfolk"); + this.subtype.add("Wizard"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // {U}, {tap}: Counter target spell unless its controller pays {1}. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CounterUnlessPaysEffect(new ManaCostsImpl("{1}")), + new ManaCostsImpl("{U}")); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetSpell()); + this.addAbility(ability); + } + + public VodalianMage1(final VodalianMage1 card) { + super(card); + } + + @Override + public VodalianMage1 copy() { + return new VodalianMage1(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/VodalianMage2.java b/Mage.Sets/src/mage/sets/fallenempires/VodalianMage2.java new file mode 100644 index 0000000000..c1d98f2207 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/VodalianMage2.java @@ -0,0 +1,51 @@ +/* + * 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 LoneFox + */ +public class VodalianMage2 extends VodalianMage1 { + + public VodalianMage2(UUID ownerId) { + super(ownerId); + this.cardNumber = 60; + } + + public VodalianMage2(final VodalianMage2 card) { + super(card); + } + + @Override + public VodalianMage2 copy() { + return new VodalianMage2(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/VodalianMage3.java b/Mage.Sets/src/mage/sets/fallenempires/VodalianMage3.java new file mode 100644 index 0000000000..c7d1789e17 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/VodalianMage3.java @@ -0,0 +1,51 @@ +/* + * 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 LoneFox + */ +public class VodalianMage3 extends VodalianMage1 { + + public VodalianMage3(UUID ownerId) { + super(ownerId); + this.cardNumber = 61; + } + + public VodalianMage3(final VodalianMage3 card) { + super(card); + } + + @Override + public VodalianMage3 copy() { + return new VodalianMage3(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fifthedition/HomaridWarrior.java b/Mage.Sets/src/mage/sets/fifthedition/HomaridWarrior.java new file mode 100644 index 0000000000..a5498872d0 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fifthedition/HomaridWarrior.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 LoneFox + */ +public class HomaridWarrior extends mage.sets.fallenempires.HomaridWarrior1 { + + public HomaridWarrior(UUID ownerId) { + super(ownerId); + this.cardNumber = 92; + this.expansionSetCode = "5ED"; + } + + public HomaridWarrior(final HomaridWarrior card) { + super(card); + } + + @Override + public HomaridWarrior copy() { + return new HomaridWarrior(this); + } +} diff --git a/Mage.Sets/src/mage/sets/masterseditionii/DeepSpawn.java b/Mage.Sets/src/mage/sets/masterseditionii/DeepSpawn.java new file mode 100644 index 0000000000..f990a1afa1 --- /dev/null +++ b/Mage.Sets/src/mage/sets/masterseditionii/DeepSpawn.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.masterseditionii; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LoneFox + */ +public class DeepSpawn extends mage.sets.fallenempires.DeepSpawn { + + public DeepSpawn(UUID ownerId) { + super(ownerId); + this.cardNumber = 45; + this.expansionSetCode = "ME2"; + this.rarity = Rarity.RARE; + } + + public DeepSpawn(final DeepSpawn card) { + super(card); + } + + @Override + public DeepSpawn copy() { + return new DeepSpawn(this); + } +} From 68c354086336678a42d9eff9e2460601b397196e Mon Sep 17 00:00:00 2001 From: LoneFox Date: Mon, 12 Oct 2015 21:42:42 +0300 Subject: [PATCH 08/46] Implement cards: Basal Thrull, Combat Medic, Elven Fortress, and Ring of Renewal --- .../mage/sets/fallenempires/BasalThrull1.java | 70 ++++++++++++++++++ .../mage/sets/fallenempires/BasalThrull2.java | 51 +++++++++++++ .../mage/sets/fallenempires/BasalThrull3.java | 51 +++++++++++++ .../mage/sets/fallenempires/BasalThrull4.java | 51 +++++++++++++ .../mage/sets/fallenempires/CombatMedic1.java | 52 ++++++++++++++ .../mage/sets/fallenempires/CombatMedic2.java | 52 ++++++++++++++ .../mage/sets/fallenempires/CombatMedic3.java | 52 ++++++++++++++ .../mage/sets/fallenempires/CombatMedic4.java | 52 ++++++++++++++ .../sets/fallenempires/ElvenFortress1.java | 67 +++++++++++++++++ .../sets/fallenempires/ElvenFortress2.java | 51 +++++++++++++ .../sets/fallenempires/ElvenFortress3.java | 51 +++++++++++++ .../sets/fallenempires/ElvenFortress4.java | 51 +++++++++++++ .../sets/fallenempires/RingOfRenewal.java | 52 ++++++++++++++ .../mage/sets/mastersedition/BasalThrull.java | 52 ++++++++++++++ .../sets/masterseditionii/CombatMedic.java | 72 +++++++++++++++++++ .../sets/masterseditioniv/RingOfRenewal.java | 70 ++++++++++++++++++ 16 files changed, 897 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/fallenempires/BasalThrull1.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/BasalThrull2.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/BasalThrull3.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/BasalThrull4.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/CombatMedic1.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/CombatMedic2.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/CombatMedic3.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/CombatMedic4.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/ElvenFortress1.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/ElvenFortress2.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/ElvenFortress3.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/ElvenFortress4.java create mode 100644 Mage.Sets/src/mage/sets/fallenempires/RingOfRenewal.java create mode 100644 Mage.Sets/src/mage/sets/mastersedition/BasalThrull.java create mode 100644 Mage.Sets/src/mage/sets/masterseditionii/CombatMedic.java create mode 100644 Mage.Sets/src/mage/sets/masterseditioniv/RingOfRenewal.java diff --git a/Mage.Sets/src/mage/sets/fallenempires/BasalThrull1.java b/Mage.Sets/src/mage/sets/fallenempires/BasalThrull1.java new file mode 100644 index 0000000000..efef91c76a --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/BasalThrull1.java @@ -0,0 +1,70 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.fallenempires; + +import java.util.UUID; +import mage.MageInt; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.BasicManaEffect; +import mage.abilities.mana.SimpleManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author LoneFox + */ +public class BasalThrull1 extends CardImpl { + + public BasalThrull1(UUID ownerId) { + super(ownerId, 5, "Basal Thrull", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{B}{B}"); + this.expansionSetCode = "FEM"; + this.subtype.add("Thrull"); + this.power = new MageInt(1); + this.toughness = new MageInt(2); + + // {T}, Sacrifice Basal Thrull: Add {B}{B} to your mana pool. + Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, new BasicManaEffect(new Mana(0, 0, 0, 0, 2, 0, 0)), new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + this.addAbility(ability); + } + + public BasalThrull1(final BasalThrull1 card) { + super(card); + } + + @Override + public BasalThrull1 copy() { + return new BasalThrull1(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/BasalThrull2.java b/Mage.Sets/src/mage/sets/fallenempires/BasalThrull2.java new file mode 100644 index 0000000000..93ab2baea7 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/BasalThrull2.java @@ -0,0 +1,51 @@ +/* + * 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 LoneFox + */ +public class BasalThrull2 extends BasalThrull1 { + + public BasalThrull2(UUID ownerId) { + super(ownerId); + this.cardNumber = 6; + } + + public BasalThrull2(final BasalThrull2 card) { + super(card); + } + + @Override + public BasalThrull2 copy() { + return new BasalThrull2(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/BasalThrull3.java b/Mage.Sets/src/mage/sets/fallenempires/BasalThrull3.java new file mode 100644 index 0000000000..27a36274d8 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/BasalThrull3.java @@ -0,0 +1,51 @@ +/* + * 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 LoneFox + */ +public class BasalThrull3 extends BasalThrull1 { + + public BasalThrull3(UUID ownerId) { + super(ownerId); + this.cardNumber = 7; + } + + public BasalThrull3(final BasalThrull3 card) { + super(card); + } + + @Override + public BasalThrull3 copy() { + return new BasalThrull3(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/BasalThrull4.java b/Mage.Sets/src/mage/sets/fallenempires/BasalThrull4.java new file mode 100644 index 0000000000..d2441b5dc5 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/BasalThrull4.java @@ -0,0 +1,51 @@ +/* + * 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 LoneFox + */ +public class BasalThrull4 extends BasalThrull1 { + + public BasalThrull4(UUID ownerId) { + super(ownerId); + this.cardNumber = 8; + } + + public BasalThrull4(final BasalThrull4 card) { + super(card); + } + + @Override + public BasalThrull4 copy() { + return new BasalThrull4(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/CombatMedic1.java b/Mage.Sets/src/mage/sets/fallenempires/CombatMedic1.java new file mode 100644 index 0000000000..c564b342fa --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/CombatMedic1.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 LoneFox + */ +public class CombatMedic1 extends mage.sets.masterseditionii.CombatMedic { + + public CombatMedic1(UUID ownerId) { + super(ownerId); + this.cardNumber = 133; + this.expansionSetCode = "FEM"; + } + + public CombatMedic1(final CombatMedic1 card) { + super(card); + } + + @Override + public CombatMedic1 copy() { + return new CombatMedic1(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/CombatMedic2.java b/Mage.Sets/src/mage/sets/fallenempires/CombatMedic2.java new file mode 100644 index 0000000000..9234cc1951 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/CombatMedic2.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 LoneFox + */ +public class CombatMedic2 extends mage.sets.masterseditionii.CombatMedic { + + public CombatMedic2(UUID ownerId) { + super(ownerId); + this.cardNumber = 134; + this.expansionSetCode = "FEM"; + } + + public CombatMedic2(final CombatMedic2 card) { + super(card); + } + + @Override + public CombatMedic2 copy() { + return new CombatMedic2(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/CombatMedic3.java b/Mage.Sets/src/mage/sets/fallenempires/CombatMedic3.java new file mode 100644 index 0000000000..d6efe570e6 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/CombatMedic3.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 LoneFox + */ +public class CombatMedic3 extends mage.sets.masterseditionii.CombatMedic { + + public CombatMedic3(UUID ownerId) { + super(ownerId); + this.cardNumber = 135; + this.expansionSetCode = "FEM"; + } + + public CombatMedic3(final CombatMedic3 card) { + super(card); + } + + @Override + public CombatMedic3 copy() { + return new CombatMedic3(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/CombatMedic4.java b/Mage.Sets/src/mage/sets/fallenempires/CombatMedic4.java new file mode 100644 index 0000000000..33028ae3b5 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/CombatMedic4.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 LoneFox + */ +public class CombatMedic4 extends mage.sets.masterseditionii.CombatMedic { + + public CombatMedic4(UUID ownerId) { + super(ownerId); + this.cardNumber = 136; + this.expansionSetCode = "FEM"; + } + + public CombatMedic4(final CombatMedic4 card) { + super(card); + } + + @Override + public CombatMedic4 copy() { + return new CombatMedic4(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/ElvenFortress1.java b/Mage.Sets/src/mage/sets/fallenempires/ElvenFortress1.java new file mode 100644 index 0000000000..2e5618016c --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/ElvenFortress1.java @@ -0,0 +1,67 @@ +/* + * 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.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterBlockingCreature; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + */ +public class ElvenFortress1 extends CardImpl { + + public ElvenFortress1(UUID ownerId) { + super(ownerId, 67, "Elven Fortress", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{G}"); + this.expansionSetCode = "FEM"; + + // {1}{G}: Target blocking creature gets +0/+1 until end of turn. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(0, 1, Duration.EndOfTurn), new ManaCostsImpl("{1}{G}")); + ability.addTarget(new TargetCreaturePermanent(new FilterBlockingCreature())); + this.addAbility(ability); + } + + public ElvenFortress1(final ElvenFortress1 card) { + super(card); + } + + @Override + public ElvenFortress1 copy() { + return new ElvenFortress1(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/ElvenFortress2.java b/Mage.Sets/src/mage/sets/fallenempires/ElvenFortress2.java new file mode 100644 index 0000000000..c454d76e92 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/ElvenFortress2.java @@ -0,0 +1,51 @@ +/* + * 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 LoneFox + */ +public class ElvenFortress2 extends ElvenFortress1 { + + public ElvenFortress2(UUID ownerId) { + super(ownerId); + this.cardNumber = 68; + } + + public ElvenFortress2(final ElvenFortress2 card) { + super(card); + } + + @Override + public ElvenFortress2 copy() { + return new ElvenFortress2(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/ElvenFortress3.java b/Mage.Sets/src/mage/sets/fallenempires/ElvenFortress3.java new file mode 100644 index 0000000000..2af6a0b26a --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/ElvenFortress3.java @@ -0,0 +1,51 @@ +/* + * 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 LoneFox + */ +public class ElvenFortress3 extends ElvenFortress1 { + + public ElvenFortress3(UUID ownerId) { + super(ownerId); + this.cardNumber = 69; + } + + public ElvenFortress3(final ElvenFortress3 card) { + super(card); + } + + @Override + public ElvenFortress3 copy() { + return new ElvenFortress3(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/ElvenFortress4.java b/Mage.Sets/src/mage/sets/fallenempires/ElvenFortress4.java new file mode 100644 index 0000000000..70e5a5e6ac --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/ElvenFortress4.java @@ -0,0 +1,51 @@ +/* + * 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 LoneFox + */ +public class ElvenFortress4 extends ElvenFortress1 { + + public ElvenFortress4(UUID ownerId) { + super(ownerId); + this.cardNumber = 70; + } + + public ElvenFortress4(final ElvenFortress4 card) { + super(card); + } + + @Override + public ElvenFortress4 copy() { + return new ElvenFortress4(this); + } +} diff --git a/Mage.Sets/src/mage/sets/fallenempires/RingOfRenewal.java b/Mage.Sets/src/mage/sets/fallenempires/RingOfRenewal.java new file mode 100644 index 0000000000..4d9b13c818 --- /dev/null +++ b/Mage.Sets/src/mage/sets/fallenempires/RingOfRenewal.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 LoneFox + */ +public class RingOfRenewal extends mage.sets.masterseditioniv.RingOfRenewal { + + public RingOfRenewal(UUID ownerId) { + super(ownerId); + this.cardNumber = 174; + this.expansionSetCode = "FEM"; + } + + public RingOfRenewal(final RingOfRenewal card) { + super(card); + } + + @Override + public RingOfRenewal copy() { + return new RingOfRenewal(this); + } +} diff --git a/Mage.Sets/src/mage/sets/mastersedition/BasalThrull.java b/Mage.Sets/src/mage/sets/mastersedition/BasalThrull.java new file mode 100644 index 0000000000..a2cc39602c --- /dev/null +++ b/Mage.Sets/src/mage/sets/mastersedition/BasalThrull.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 LoneFox + */ +public class BasalThrull extends mage.sets.fallenempires.BasalThrull1 { + + public BasalThrull(UUID ownerId) { + super(ownerId); + this.cardNumber = 59; + this.expansionSetCode = "MED"; + } + + public BasalThrull(final BasalThrull card) { + super(card); + } + + @Override + public BasalThrull copy() { + return new BasalThrull(this); + } +} diff --git a/Mage.Sets/src/mage/sets/masterseditionii/CombatMedic.java b/Mage.Sets/src/mage/sets/masterseditionii/CombatMedic.java new file mode 100644 index 0000000000..6708aa9d2c --- /dev/null +++ b/Mage.Sets/src/mage/sets/masterseditionii/CombatMedic.java @@ -0,0 +1,72 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.masterseditionii; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.PreventDamageToTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetCreatureOrPlayer; + +/** + * + * @author LoneFox + */ +public class CombatMedic extends CardImpl { + + public CombatMedic(UUID ownerId) { + super(ownerId, 9, "Combat Medic", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{W}"); + this.expansionSetCode = "ME2"; + this.subtype.add("Human"); + this.subtype.add("Cleric"); + this.subtype.add("Soldier"); + this.power = new MageInt(0); + this.toughness = new MageInt(2); + + // {1}{W}: Prevent the next 1 damage that would be dealt to target creature or player this turn. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PreventDamageToTargetEffect(Duration.EndOfTurn, 1), new ManaCostsImpl("{1}{W}")); + ability.addTarget(new TargetCreatureOrPlayer()); + this.addAbility(ability); + } + + public CombatMedic(final CombatMedic card) { + super(card); + } + + @Override + public CombatMedic copy() { + return new CombatMedic(this); + } +} diff --git a/Mage.Sets/src/mage/sets/masterseditioniv/RingOfRenewal.java b/Mage.Sets/src/mage/sets/masterseditioniv/RingOfRenewal.java new file mode 100644 index 0000000000..61ac07d129 --- /dev/null +++ b/Mage.Sets/src/mage/sets/masterseditioniv/RingOfRenewal.java @@ -0,0 +1,70 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.masterseditioniv; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.discard.DiscardControllerEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author LoneFox + */ +public class RingOfRenewal extends CardImpl { + + public RingOfRenewal(UUID ownerId) { + super(ownerId, 224, "Ring of Renewal", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{5}"); + this.expansionSetCode = "ME4"; + + // {5}, {tap}: Discard a card at random, then draw two cards. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DiscardControllerEffect(1, true), new ManaCostsImpl("{5}")); + ability.addCost(new TapSourceCost()); + Effect effect = new DrawCardSourceControllerEffect(2); + effect.setText(", then draw two cards"); + ability.addEffect(effect); + this.addAbility(ability); + } + + public RingOfRenewal(final RingOfRenewal card) { + super(card); + } + + @Override + public RingOfRenewal copy() { + return new RingOfRenewal(this); + } +} From fd7bf5d7900f84a6ee36682b3900c0cb39e3f568 Mon Sep 17 00:00:00 2001 From: LoneFox Date: Mon, 12 Oct 2015 22:19:13 +0300 Subject: [PATCH 09/46] Kill a few DamageTargetControllerEffect implementations --- .../riseoftheeldrazi/GrotagSiegeRunner.java | 47 +++------------- .../sets/scarsofmirrodin/MeltTerrain.java | 52 +++--------------- .../mage/sets/shadowmoor/PoisonTheWell.java | 45 +++------------ .../sets/shadowmoor/SmashToSmithereens.java | 51 +++-------------- .../src/mage/sets/tenthedition/Cryoclasm.java | 55 +++---------------- .../src/mage/sets/theros/PeakEruption.java | 53 +++--------------- 6 files changed, 47 insertions(+), 256 deletions(-) diff --git a/Mage.Sets/src/mage/sets/riseoftheeldrazi/GrotagSiegeRunner.java b/Mage.Sets/src/mage/sets/riseoftheeldrazi/GrotagSiegeRunner.java index 4c8578d609..e3407fb0de 100644 --- a/Mage.Sets/src/mage/sets/riseoftheeldrazi/GrotagSiegeRunner.java +++ b/Mage.Sets/src/mage/sets/riseoftheeldrazi/GrotagSiegeRunner.java @@ -28,24 +28,21 @@ package mage.sets.riseoftheeldrazi; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DamageTargetControllerEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.DefenderAbility; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.common.TargetCreaturePermanent; /** @@ -70,10 +67,12 @@ public class GrotagSiegeRunner extends CardImpl { this.toughness = new MageInt(1); // {R}, Sacrifice Grotag Siege-Runner: Destroy target creature with defender. Grotag Siege-Runner deals 2 damage to that creature's controller. - SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new ManaCostsImpl("{R}")); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new ManaCostsImpl("{R}")); ability.addCost(new SacrificeSourceCost()); + Effect effect = new DamageTargetControllerEffect(2); + effect.setText("{this} deals 2 damage to that creature's controller"); + ability.addEffect(effect); ability.addTarget(new TargetCreaturePermanent(filter)); - ability.addEffect(new GrotageSiegeRunnerEffect()); this.addAbility(ability); } @@ -86,31 +85,3 @@ public class GrotagSiegeRunner extends CardImpl { return new GrotagSiegeRunner(this); } } - -class GrotageSiegeRunnerEffect extends OneShotEffect { - - public GrotageSiegeRunnerEffect() { - super(Outcome.Damage); - this.staticText = "{this} deals 2 damage to that creature's controller"; - } - - public GrotageSiegeRunnerEffect(final GrotageSiegeRunnerEffect effect) { - super(effect); - } - - @Override - public GrotageSiegeRunnerEffect copy() { - return new GrotageSiegeRunnerEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = (Permanent) game.getLastKnownInformation(source.getFirstTarget(), Zone.BATTLEFIELD); - if (permanent != null) { - Player controller = game.getPlayer(permanent.getControllerId()); - controller.damage(2, source.getSourceId(), game, false, true); - return true; - } - return false; - } -} diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/MeltTerrain.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/MeltTerrain.java index 8c95d5de0b..0524d95acd 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/MeltTerrain.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/MeltTerrain.java @@ -29,18 +29,12 @@ package mage.sets.scarsofmirrodin; import java.util.UUID; - -import mage.constants.CardType; -import mage.constants.Rarity; -import mage.constants.Zone; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DamageTargetControllerEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; -import mage.constants.Outcome; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; +import mage.constants.CardType; +import mage.constants.Rarity; import mage.target.common.TargetLandPermanent; /** @@ -53,8 +47,11 @@ public class MeltTerrain extends CardImpl { super(ownerId, 97, "Melt Terrain", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{2}{R}{R}"); this.expansionSetCode = "SOM"; + // Destroy target land. Melt Terrain deals 2 damage to that land's controller. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addEffect(new MeltTerrainEffect()); + Effect effect = new DamageTargetControllerEffect(2); + effect.setText("{this} deals 2 damage to that land's controller"); + this.getSpellAbility().addEffect(effect); this.getSpellAbility().addTarget(new TargetLandPermanent()); } @@ -66,37 +63,4 @@ public class MeltTerrain extends CardImpl { public MeltTerrain copy() { return new MeltTerrain(this); } - } - -class MeltTerrainEffect extends OneShotEffect { - MeltTerrainEffect() { - super(Outcome.Damage); - staticText = "{this} deals 2 damage to that land's controller"; - } - - MeltTerrainEffect(final MeltTerrainEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent p = game.getBattlefield().getPermanent(source.getFirstTarget()); - if (p == null) { - p = (Permanent) game.getLastKnownInformation(source.getFirstTarget(), Zone.BATTLEFIELD); - } - if (p != null) { - Player player = game.getPlayer(p.getControllerId()); - if (player != null) { - player.damage(2, source.getSourceId(), game, false, true); - } - } - return false; - } - - @Override - public MeltTerrainEffect copy() { - return new MeltTerrainEffect(this); - } - -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/shadowmoor/PoisonTheWell.java b/Mage.Sets/src/mage/sets/shadowmoor/PoisonTheWell.java index cb515b6669..1b8d897cfe 100644 --- a/Mage.Sets/src/mage/sets/shadowmoor/PoisonTheWell.java +++ b/Mage.Sets/src/mage/sets/shadowmoor/PoisonTheWell.java @@ -28,15 +28,12 @@ package mage.sets.shadowmoor; import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DamageTargetControllerEffect; +import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.Rarity; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.common.TargetLandPermanent; /** @@ -50,7 +47,10 @@ public class PoisonTheWell extends CardImpl { this.expansionSetCode = "SHM"; // Destroy target land. Poison the Well deals 2 damage to that land's controller. - this.getSpellAbility().addEffect(new PoisonTheWellEffect()); + this.getSpellAbility().addEffect(new DestroyTargetEffect()); + Effect effect = new DamageTargetControllerEffect(2); + effect.setText("{this} deals 2 damage to that land's controller"); + this.getSpellAbility().addEffect(effect); this.getSpellAbility().addTarget(new TargetLandPermanent()); } @@ -63,34 +63,3 @@ public class PoisonTheWell extends CardImpl { return new PoisonTheWell(this); } } - -class PoisonTheWellEffect extends OneShotEffect { - - public PoisonTheWellEffect() { - super(Outcome.DestroyPermanent); - this.staticText = "Destroy target land. {this} deals 2 damage to that land's controller"; - } - - public PoisonTheWellEffect(final PoisonTheWellEffect effect) { - super(effect); - } - - @Override - public PoisonTheWellEffect copy() { - return new PoisonTheWellEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent targetedLand = game.getPermanent(source.getFirstTarget()); - if (targetedLand != null) { - targetedLand.destroy(source.getSourceId(), game, true); - Player controller = game.getPlayer(targetedLand.getControllerId()); - if (controller != null) { - controller.damage(2, source.getSourceId(), game, false, true); - } - return true; - } - return false; - } -} diff --git a/Mage.Sets/src/mage/sets/shadowmoor/SmashToSmithereens.java b/Mage.Sets/src/mage/sets/shadowmoor/SmashToSmithereens.java index 98ff75dc2b..113b83d9f7 100644 --- a/Mage.Sets/src/mage/sets/shadowmoor/SmashToSmithereens.java +++ b/Mage.Sets/src/mage/sets/shadowmoor/SmashToSmithereens.java @@ -28,17 +28,12 @@ package mage.sets.shadowmoor; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.constants.Zone; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DamageTargetControllerEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; +import mage.constants.CardType; +import mage.constants.Rarity; import mage.target.common.TargetArtifactPermanent; /** @@ -52,9 +47,11 @@ public class SmashToSmithereens extends CardImpl { this.expansionSetCode = "SHM"; // Destroy target artifact. Smash to Smithereens deals 3 damage to that artifact's controller. - this.getSpellAbility().addTarget(new TargetArtifactPermanent()); this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addEffect(new SmashToSmithereensEffect()); + Effect effect = new DamageTargetControllerEffect(3); + effect.setText("{this} deals 3 damage to that artifact's controller"); + this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addTarget(new TargetArtifactPermanent()); } public SmashToSmithereens(final SmashToSmithereens card) { @@ -66,35 +63,3 @@ public class SmashToSmithereens extends CardImpl { return new SmashToSmithereens(this); } } - -class SmashToSmithereensEffect extends OneShotEffect { - - SmashToSmithereensEffect() { - super(Outcome.Damage); - staticText = "{this} deals 3 damage to that artifact's controller"; - } - - SmashToSmithereensEffect(final SmashToSmithereensEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getBattlefield().getPermanent(source.getFirstTarget()); - if (permanent == null) { - permanent = (Permanent) game.getLastKnownInformation(source.getFirstTarget(), Zone.BATTLEFIELD); - } - if (permanent != null) { - Player player = game.getPlayer(permanent.getControllerId()); - if (player != null) { - player.damage(3, source.getSourceId(), game, false, true); - } - } - return false; - } - - @Override - public SmashToSmithereensEffect copy() { - return new SmashToSmithereensEffect(this); - } -} diff --git a/Mage.Sets/src/mage/sets/tenthedition/Cryoclasm.java b/Mage.Sets/src/mage/sets/tenthedition/Cryoclasm.java index f76c044baa..c9c1cff99b 100644 --- a/Mage.Sets/src/mage/sets/tenthedition/Cryoclasm.java +++ b/Mage.Sets/src/mage/sets/tenthedition/Cryoclasm.java @@ -28,23 +28,15 @@ package mage.sets.tenthedition; import java.util.UUID; - -import mage.MageObject; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DamageTargetControllerEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.Rarity; -import mage.constants.Zone; import mage.filter.common.FilterLandPermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.SubtypePredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.common.TargetLandPermanent; /** @@ -54,20 +46,20 @@ import mage.target.common.TargetLandPermanent; public class Cryoclasm extends CardImpl { private static final FilterLandPermanent filter = new FilterLandPermanent("Plains or Island"); + static { - filter.add(Predicates.or( - new SubtypePredicate("Plains"), - new SubtypePredicate("Island"))); + filter.add(Predicates.or(new SubtypePredicate("Plains"), new SubtypePredicate("Island"))); } public Cryoclasm(UUID ownerId) { super(ownerId, 195, "Cryoclasm", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{2}{R}"); this.expansionSetCode = "10E"; - // Destroy target Plains or Island. Cryoclasm deals 3 damage to that land's controller. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addEffect(new CryoclasmEffect()); + Effect effect = new DamageTargetControllerEffect(3); + effect.setText("{this} deals 3 damage to that land's controller"); + this.getSpellAbility().addEffect(effect); this.getSpellAbility().addTarget(new TargetLandPermanent(filter)); } @@ -81,36 +73,3 @@ public class Cryoclasm extends CardImpl { return new Cryoclasm(this); } } - -class CryoclasmEffect extends OneShotEffect { - - public CryoclasmEffect() { - super(Outcome.Damage); - this.staticText = "{this} deals 3 damage to that land's controller"; - } - - public CryoclasmEffect(final CryoclasmEffect effect) { - super(effect); - } - - @Override - public CryoclasmEffect copy() { - return new CryoclasmEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - UUID targetId = getTargetPointer().getFirst(game, source); - if (targetId != null) { - Permanent permanent = game.getPermanentOrLKIBattlefield(targetId); - if (permanent != null) { - Player controller = game.getPlayer(permanent.getControllerId()); - if (controller != null) { - controller.damage(3, source.getSourceId(), game, false, false); - return true; - } - } - } - return false; - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/theros/PeakEruption.java b/Mage.Sets/src/mage/sets/theros/PeakEruption.java index 4aa27c573a..0b8e9796eb 100644 --- a/Mage.Sets/src/mage/sets/theros/PeakEruption.java +++ b/Mage.Sets/src/mage/sets/theros/PeakEruption.java @@ -28,19 +28,14 @@ package mage.sets.theros; import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DamageTargetControllerEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.Rarity; -import mage.constants.Zone; import mage.filter.common.FilterLandPermanent; import mage.filter.predicate.mageobject.SubtypePredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.common.TargetLandPermanent; /** @@ -50,20 +45,21 @@ import mage.target.common.TargetLandPermanent; public class PeakEruption extends CardImpl { private static final FilterLandPermanent filter = new FilterLandPermanent("Mountain"); + static{ filter.add(new SubtypePredicate(("Mountain"))); } - - + public PeakEruption(UUID ownerId) { super(ownerId, 132, "Peak Eruption", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{2}{R}"); this.expansionSetCode = "THS"; - // Destroy target Mountain. Peak Eruption deals 3 damage to that land's controller. - this.getSpellAbility().addTarget(new TargetLandPermanent(filter)); this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addEffect(new PeakEruptionEffect()); + Effect effect = new DamageTargetControllerEffect(3); + effect.setText("{this} deals 3 damage to that land's controller"); + this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addTarget(new TargetLandPermanent(filter)); } public PeakEruption(final PeakEruption card) { @@ -75,36 +71,3 @@ public class PeakEruption extends CardImpl { return new PeakEruption(this); } } - - -class PeakEruptionEffect extends OneShotEffect { - - PeakEruptionEffect() { - super(Outcome.Damage); - staticText = "{this} deals 3 damage to that land's controller"; - } - - PeakEruptionEffect(final PeakEruptionEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getBattlefield().getPermanent(source.getFirstTarget()); - if (permanent == null) { - permanent = (Permanent) game.getLastKnownInformation(source.getFirstTarget(), Zone.BATTLEFIELD); - } - if (permanent != null) { - Player player = game.getPlayer(permanent.getControllerId()); - if (player != null) { - player.damage(3, source.getSourceId(), game, false, true); - } - } - return false; - } - - @Override - public PeakEruptionEffect copy() { - return new PeakEruptionEffect(this); - } -} From 3076ebd5ad38491ad237bf452cf1d3497ec8936f Mon Sep 17 00:00:00 2001 From: Jeff Date: Mon, 12 Oct 2015 15:15:29 -0500 Subject: [PATCH 10/46] - Simple text fixes. --- Mage/src/mage/abilities/keyword/ConspireAbility.java | 2 +- Mage/src/mage/watchers/common/FirstTimeStepWatcher.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Mage/src/mage/abilities/keyword/ConspireAbility.java b/Mage/src/mage/abilities/keyword/ConspireAbility.java index cef23120fe..a655b31721 100644 --- a/Mage/src/mage/abilities/keyword/ConspireAbility.java +++ b/Mage/src/mage/abilities/keyword/ConspireAbility.java @@ -68,7 +68,7 @@ import mage.target.common.TargetControlledPermanent; * 702.77b If a spell has multiple instances of conspire, each is paid separately and triggers * based on its own payment, not any other instance of conspire. * * - * @author jeffwadsworth heavily based off the replicate keyword by LevelX + * @author LevelX */ public class ConspireAbility extends StaticAbility implements OptionalAdditionalSourceCosts { diff --git a/Mage/src/mage/watchers/common/FirstTimeStepWatcher.java b/Mage/src/mage/watchers/common/FirstTimeStepWatcher.java index 911a3ecf93..028e77e120 100644 --- a/Mage/src/mage/watchers/common/FirstTimeStepWatcher.java +++ b/Mage/src/mage/watchers/common/FirstTimeStepWatcher.java @@ -34,8 +34,8 @@ import mage.game.events.GameEvent.EventType; import mage.watchers.Watcher; /** - * The wachter checks if a specific phase event has already happened during the - * current turn. If not it returns false, otheriwsed true. + * The watcher checks if a specific phase event has already happened during the + * current turn. If not it returns false, otherwise true. * * @author LevelX2 */ From f13ca0c87d4744a98ffaac671c066c3a5122af06 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 12 Oct 2015 23:10:16 +0200 Subject: [PATCH 11/46] * Oath of Lieges - Fixed target handling (fixes #1312). --- .../src/mage/sets/exodus/OathOfLieges.java | 22 ++-- .../cards/enchantments/OathOfLiegesTest.java | 124 ++++++++++++++++++ .../java/org/mage/test/player/TestPlayer.java | 29 +++- Mage/src/mage/game/GameImpl.java | 2 +- 4 files changed, 163 insertions(+), 14 deletions(-) create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/enchantments/OathOfLiegesTest.java diff --git a/Mage.Sets/src/mage/sets/exodus/OathOfLieges.java b/Mage.Sets/src/mage/sets/exodus/OathOfLieges.java index b7a8d63758..f11e6b7823 100644 --- a/Mage.Sets/src/mage/sets/exodus/OathOfLieges.java +++ b/Mage.Sets/src/mage/sets/exodus/OathOfLieges.java @@ -31,7 +31,7 @@ import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.effects.Effect; -import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInPlayTargetPlayerEffect; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Outcome; @@ -46,14 +46,16 @@ import mage.game.Game; import mage.players.Player; import mage.target.TargetPlayer; import mage.target.common.TargetCardInLibrary; +import mage.target.targetpointer.FixedTarget; /** * * @author emerald000 */ public class OathOfLieges extends CardImpl { - - private static final FilterPlayer filter = new FilterPlayer(); + + private static final FilterPlayer filter = new FilterPlayer("player who controls more lands than you do and is his your opponent"); + static { filter.add(new OathOfLiegesPredicate()); } @@ -62,9 +64,8 @@ public class OathOfLieges extends CardImpl { super(ownerId, 11, "Oath of Lieges", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}"); this.expansionSetCode = "EXO"; - // At the beginning of each player's upkeep, that player chooses target player who controls more lands than he or she does and is his or her opponent. The first player may search his or her library for a basic land card, put that card onto the battlefield, then shuffle his or her library. - Effect effect = new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(new FilterBasicLandCard()), false, Outcome.PutLandInPlay); + Effect effect = new SearchLibraryPutInPlayTargetPlayerEffect(new TargetCardInLibrary(new FilterBasicLandCard()), false, Outcome.PutLandInPlay); effect.setText("that player chooses target player who controls more lands than he or she does and is his or her opponent. The first player may search his or her library for a basic land card, put that card onto the battlefield, then shuffle his or her library"); Ability ability = new BeginningOfUpkeepTriggeredAbility(effect, TargetController.ANY, true); ability.addTarget(new TargetPlayer(1, 1, false, filter)); @@ -74,16 +75,21 @@ public class OathOfLieges extends CardImpl { public OathOfLieges(final OathOfLieges card) { super(card); } - + @Override public void adjustTargets(Ability ability, Game game) { if (ability instanceof BeginningOfUpkeepTriggeredAbility) { Player activePlayer = game.getPlayer(game.getActivePlayerId()); if (activePlayer != null) { - ability.setControllerId(activePlayer.getId()); ability.getTargets().clear(); TargetPlayer target = new TargetPlayer(1, 1, false, filter); + target.setTargetController(activePlayer.getId()); ability.getTargets().add(target); + for (Effect effect : ability.getEffects()) { + if (effect instanceof SearchLibraryPutInPlayTargetPlayerEffect) { + effect.setTargetPointer(new FixedTarget(activePlayer.getId())); + } + } } } } @@ -119,4 +125,4 @@ class OathOfLiegesPredicate implements ObjectSourcePlayerPredicate abilities, Game game) { if (!choices.isEmpty()) { @@ -1891,11 +1915,6 @@ public class TestPlayer implements Player { return computerPlayer.choose(outcome, cards, target, game); } - @Override - public boolean chooseTarget(Outcome outcome, Cards cards, TargetCard target, Ability source, Game game) { - return computerPlayer.chooseTarget(outcome, cards, target, source, game); - } - @Override public boolean chooseTargetAmount(Outcome outcome, TargetAmount target, Ability source, Game game) { return computerPlayer.chooseTargetAmount(outcome, target, source, game); diff --git a/Mage/src/mage/game/GameImpl.java b/Mage/src/mage/game/GameImpl.java index 27abfa58db..f67b638743 100644 --- a/Mage/src/mage/game/GameImpl.java +++ b/Mage/src/mage/game/GameImpl.java @@ -1467,7 +1467,7 @@ public abstract class GameImpl implements Game, Serializable { } else { TriggeredAbility newAbility = ability.copy(); newAbility.newId(); - // Too early, becuase no targets set yet !!!!!!!!!!! + // Too early, because no targets set yet !!!!!!!!!!! for (Effect effect : newAbility.getEffects()) { effect.getTargetPointer().init(this, newAbility); } From dc7fee86df8e69fe090f85f2ab73734167ab3599 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 12 Oct 2015 23:50:29 +0200 Subject: [PATCH 12/46] Added test. --- .../sets/avacynrestored/DevastationTide.java | 27 ++++--- .../abilities/other/DevastationTideTest.java | 77 +++++++++++++++++++ 2 files changed, 95 insertions(+), 9 deletions(-) create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/DevastationTideTest.java diff --git a/Mage.Sets/src/mage/sets/avacynrestored/DevastationTide.java b/Mage.Sets/src/mage/sets/avacynrestored/DevastationTide.java index 2a13b1ecf8..126fc303e6 100644 --- a/Mage.Sets/src/mage/sets/avacynrestored/DevastationTide.java +++ b/Mage.Sets/src/mage/sets/avacynrestored/DevastationTide.java @@ -27,20 +27,23 @@ */ package mage.sets.avacynrestored; +import java.util.LinkedHashSet; +import java.util.Set; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.abilities.Ability; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.MiracleAbility; +import mage.cards.Card; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.filter.common.FilterNonlandPermanent; import mage.game.Game; import mage.game.permanent.Permanent; - +import mage.players.Player; /** * @@ -52,7 +55,6 @@ public class DevastationTide extends CardImpl { super(ownerId, 48, "Devastation Tide", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{3}{U}{U}"); this.expansionSetCode = "AVR"; - // Return all nonland permanents to their owners' hands. this.getSpellAbility().addEffect(new DevastationTideEffect()); @@ -83,10 +85,17 @@ class DevastationTideEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - for (Permanent creature : game.getBattlefield().getActivePermanents(new FilterNonlandPermanent(), source.getControllerId(), source.getSourceId(), game)) { - creature.moveToZone(Zone.HAND, source.getSourceId(), game, true); + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Set cardsToHand = new LinkedHashSet<>(); + for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterNonlandPermanent(), source.getControllerId(), source.getSourceId(), game)) { + cardsToHand.add((Card) permanent); + } + controller.moveCards(cardsToHand, null, Zone.HAND, source, game); + return true; + } - return true; + return false; } @Override diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/DevastationTideTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/DevastationTideTest.java new file mode 100644 index 0000000000..e9ddc239d8 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/DevastationTideTest.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 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 DevastationTideTest extends CardTestPlayerBase { + + @Test + public void testReturnNonLandPermanents() { + addCard(Zone.BATTLEFIELD, playerA, "Island", 4); + addCard(Zone.HAND, playerA, "Devastation Tide"); // {3}{U}{U} + + addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); // Creature + addCard(Zone.BATTLEFIELD, playerA, "Vampiric Rites"); // Enchantment + addCard(Zone.BATTLEFIELD, playerA, "Hedron Archive"); // Artifact + addCard(Zone.BATTLEFIELD, playerA, "Karn Liberated"); // Planeswalker + addCard(Zone.BATTLEFIELD, playerA, "Nimbus Maze", 1); // Land + + addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion"); // Creature + addCard(Zone.BATTLEFIELD, playerB, "Vampiric Rites"); // Enchantment + addCard(Zone.BATTLEFIELD, playerB, "Hedron Archive"); // Artifact + addCard(Zone.BATTLEFIELD, playerB, "Karn Liberated"); // Planeswalker + addCard(Zone.BATTLEFIELD, playerB, "Nimbus Maze", 1); // Land + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Devastation Tide"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertHandCount(playerA, "Silvercoat Lion", 1); + assertHandCount(playerA, "Vampiric Rites", 1); + assertHandCount(playerA, "Hedron Archive", 1); + assertHandCount(playerA, "Karn Liberated", 1); + assertHandCount(playerA, "Nimbus Maze", 0); + + assertHandCount(playerB, "Silvercoat Lion", 1); + assertHandCount(playerB, "Vampiric Rites", 1); + assertHandCount(playerB, "Hedron Archive", 1); + assertHandCount(playerB, "Karn Liberated", 1); + assertHandCount(playerB, "Nimbus Maze", 0); + + } + +} From a6014cb4ab148aaa5036c02838cfec851993fb7f Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 13 Oct 2015 00:28:05 +0200 Subject: [PATCH 13/46] Added Hostility card. --- .../anthologyjacevschandra/Hostility.java | 52 +++++++ .../mage/sets/jacevschandra/Hostility.java | 145 ++++++++++++++++++ Mage.Sets/src/mage/sets/lorwyn/Hostility.java | 52 +++++++ 3 files changed, 249 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/anthologyjacevschandra/Hostility.java create mode 100644 Mage.Sets/src/mage/sets/jacevschandra/Hostility.java create mode 100644 Mage.Sets/src/mage/sets/lorwyn/Hostility.java diff --git a/Mage.Sets/src/mage/sets/anthologyjacevschandra/Hostility.java b/Mage.Sets/src/mage/sets/anthologyjacevschandra/Hostility.java new file mode 100644 index 0000000000..3c8621e98e --- /dev/null +++ b/Mage.Sets/src/mage/sets/anthologyjacevschandra/Hostility.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.anthologyjacevschandra; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class Hostility extends mage.sets.jacevschandra.Hostility { + + public Hostility(UUID ownerId) { + super(ownerId); + this.cardNumber = 48; + this.expansionSetCode = "DD3"; + } + + public Hostility(final Hostility card) { + super(card); + } + + @Override + public Hostility copy() { + return new Hostility(this); + } +} diff --git a/Mage.Sets/src/mage/sets/jacevschandra/Hostility.java b/Mage.Sets/src/mage/sets/jacevschandra/Hostility.java new file mode 100644 index 0000000000..a4e6865226 --- /dev/null +++ b/Mage.Sets/src/mage/sets/jacevschandra/Hostility.java @@ -0,0 +1,145 @@ +/* + * 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.jacevschandra; + +import java.util.Arrays; +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.PutIntoGraveFromAnywhereSourceTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.PreventionEffectData; +import mage.abilities.effects.PreventionEffectImpl; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.ShuffleIntoLibrarySourceEffect; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.token.Token; + +/** + * + * @author LevelX2 + */ +public class Hostility extends CardImpl { + + public Hostility(UUID ownerId) { + super(ownerId, 48, "Hostility", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{R}{R}{R}"); + this.expansionSetCode = "DD2"; + this.subtype.add("Elemental"); + this.subtype.add("Incarnation"); + this.power = new MageInt(6); + this.toughness = new MageInt(6); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // If a spell you control would deal damage to an opponent, prevent that damage. + // Put a 3/1 red Elemental Shaman creature token with haste onto the battlefield for each 1 damage prevented this way. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new HostilityEffect())); + + // When Hostility is put into a graveyard from anywhere, shuffle it into its owner's library. + this.addAbility(new PutIntoGraveFromAnywhereSourceTriggeredAbility(new ShuffleIntoLibrarySourceEffect())); + } + + public Hostility(final Hostility card) { + super(card); + } + + @Override + public Hostility copy() { + return new Hostility(this); + } +} + +class HostilityEffect extends PreventionEffectImpl { + + public HostilityEffect() { + super(Duration.WhileOnBattlefield, Integer.MAX_VALUE, false, false); + staticText = "If a spell you control would deal damage to an opponent, prevent that damage. Put a 3/1 red Elemental Shaman creature token with haste onto the battlefield for each 1 damage prevented this way."; + } + + public HostilityEffect(final HostilityEffect effect) { + super(effect); + } + + @Override + public HostilityEffect copy() { + return new HostilityEffect(this); + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + switch (event.getType()) { + case DAMAGE_PLAYER: + return true; + } + return false; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (super.applies(event, source, game)) { + if (game.getOpponents(source.getControllerId()).contains(event.getTargetId())) { + return true; + } + } + return false; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + PreventionEffectData preventionEffectData = preventDamageAction(event, source, game); + if (preventionEffectData.getPreventedDamage() > 0) { + new CreateTokenEffect(new HostilityElementalToken(), preventionEffectData.getPreventedDamage()).apply(game, source); + } + return true; + } +} + +class HostilityElementalToken extends Token { + + public HostilityElementalToken() { + super("Elemental Shaman", "3/1 red Elemental Shaman creature token with haste"); + availableImageSetCodes.addAll(Arrays.asList("LRW", "DD2")); + cardType.add(CardType.CREATURE); + color.setRed(true); + subtype.add("Elemental"); + subtype.add("Shaman"); + power = new MageInt(3); + toughness = new MageInt(1); + + addAbility(HasteAbility.getInstance()); + } + +} diff --git a/Mage.Sets/src/mage/sets/lorwyn/Hostility.java b/Mage.Sets/src/mage/sets/lorwyn/Hostility.java new file mode 100644 index 0000000000..b309e8f73a --- /dev/null +++ b/Mage.Sets/src/mage/sets/lorwyn/Hostility.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.lorwyn; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class Hostility extends mage.sets.jacevschandra.Hostility { + + public Hostility(UUID ownerId) { + super(ownerId); + this.cardNumber = 176; + this.expansionSetCode = "LRW"; + } + + public Hostility(final Hostility card) { + super(card); + } + + @Override + public Hostility copy() { + return new Hostility(this); + } +} From b902a099a130e4abe29638e2fa3a22af406d415d Mon Sep 17 00:00:00 2001 From: LoneFox Date: Tue, 13 Oct 2015 08:03:39 +0300 Subject: [PATCH 14/46] Fix ExileFromZoneTargetEffect text generation --- .../abilities/effects/common/ExileFromZoneTargetEffect.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage/src/mage/abilities/effects/common/ExileFromZoneTargetEffect.java b/Mage/src/mage/abilities/effects/common/ExileFromZoneTargetEffect.java index 028237b01c..654c49ea41 100644 --- a/Mage/src/mage/abilities/effects/common/ExileFromZoneTargetEffect.java +++ b/Mage/src/mage/abilities/effects/common/ExileFromZoneTargetEffect.java @@ -111,6 +111,6 @@ public class ExileFromZoneTargetEffect extends OneShotEffect { } private void setText() { - staticText = "target player exiles " + CardUtil.numberToText(exileName, "a") + filter.getMessage() + " from his or her " + zone.toString().toLowerCase(); + staticText = "target player exiles " + CardUtil.numberToText(amount, "a") + " " + filter.getMessage() + " from his or her " + zone.toString().toLowerCase(); } } From 769f61aa05bdbd79b62fec49e6daae0ac4da63d5 Mon Sep 17 00:00:00 2001 From: LoneFox Date: Tue, 13 Oct 2015 08:03:56 +0300 Subject: [PATCH 15/46] Fix a couple of incorrect set codes --- Mage.Sets/src/mage/sets/anthologyjacevschandra/Hostility.java | 2 +- Mage.Sets/src/mage/sets/anthologyjacevschandra/Ophidian.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/anthologyjacevschandra/Hostility.java b/Mage.Sets/src/mage/sets/anthologyjacevschandra/Hostility.java index 3c8621e98e..4769a6c8b3 100644 --- a/Mage.Sets/src/mage/sets/anthologyjacevschandra/Hostility.java +++ b/Mage.Sets/src/mage/sets/anthologyjacevschandra/Hostility.java @@ -38,7 +38,7 @@ public class Hostility extends mage.sets.jacevschandra.Hostility { public Hostility(UUID ownerId) { super(ownerId); this.cardNumber = 48; - this.expansionSetCode = "DD3"; + this.expansionSetCode = "DD3D"; } public Hostility(final Hostility card) { diff --git a/Mage.Sets/src/mage/sets/anthologyjacevschandra/Ophidian.java b/Mage.Sets/src/mage/sets/anthologyjacevschandra/Ophidian.java index 3816fda1c8..bf51396499 100644 --- a/Mage.Sets/src/mage/sets/anthologyjacevschandra/Ophidian.java +++ b/Mage.Sets/src/mage/sets/anthologyjacevschandra/Ophidian.java @@ -38,7 +38,7 @@ public class Ophidian extends mage.sets.vintagemasters.Ophidian { public Ophidian(UUID ownerId) { super(ownerId); this.cardNumber = 9; - this.expansionSetCode = "DD3"; + this.expansionSetCode = "DD3D"; } public Ophidian(final Ophidian card) { From c1984b15d9ddd8220e6911d905d132c010d0d4ff Mon Sep 17 00:00:00 2001 From: LoneFox Date: Tue, 13 Oct 2015 10:02:42 +0300 Subject: [PATCH 16/46] Implement cards: Quicksilver Wall, Ribbon Snake, Vintara Elephant, and Zerapa Minotaur --- .../mage/sets/prophecy/QuicksilverWall.java | 75 +++++++++++++++++++ .../src/mage/sets/prophecy/RibbonSnake.java | 75 +++++++++++++++++++ .../mage/sets/prophecy/VintaraElephant.java | 75 +++++++++++++++++++ .../mage/sets/prophecy/ZerapaMinotaur.java | 75 +++++++++++++++++++ .../continuous/LoseAbilitySourceEffect.java | 16 ++-- 5 files changed, 308 insertions(+), 8 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/prophecy/QuicksilverWall.java create mode 100644 Mage.Sets/src/mage/sets/prophecy/RibbonSnake.java create mode 100644 Mage.Sets/src/mage/sets/prophecy/VintaraElephant.java create mode 100644 Mage.Sets/src/mage/sets/prophecy/ZerapaMinotaur.java diff --git a/Mage.Sets/src/mage/sets/prophecy/QuicksilverWall.java b/Mage.Sets/src/mage/sets/prophecy/QuicksilverWall.java new file mode 100644 index 0000000000..21a43d9f3c --- /dev/null +++ b/Mage.Sets/src/mage/sets/prophecy/QuicksilverWall.java @@ -0,0 +1,75 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.prophecy; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.InfoEffect; +import mage.abilities.effects.common.ReturnToHandSourceEffect; +import mage.abilities.keyword.DefenderAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; + +/** + * + * @author LoneFox + */ +public class QuicksilverWall extends CardImpl { + + public QuicksilverWall(UUID ownerId) { + super(ownerId, 41, "Quicksilver Wall", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{U}"); + this.expansionSetCode = "PCY"; + this.subtype.add("Wall"); + this.power = new MageInt(1); + this.toughness = new MageInt(6); + + // Defender + this.addAbility(DefenderAbility.getInstance()); + // {4}: Return Quicksilver Wall to its owner's hand. Any player may activate this ability. + SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, + new ReturnToHandSourceEffect(true), new ManaCostsImpl("{4}")); + ability.setMayActivate(TargetController.ANY); + ability.addEffect(new InfoEffect("Any player may activate this ability")); + this.addAbility(ability); + } + + public QuicksilverWall(final QuicksilverWall card) { + super(card); + } + + @Override + public QuicksilverWall copy() { + return new QuicksilverWall(this); + } +} diff --git a/Mage.Sets/src/mage/sets/prophecy/RibbonSnake.java b/Mage.Sets/src/mage/sets/prophecy/RibbonSnake.java new file mode 100644 index 0000000000..4e4829f4dc --- /dev/null +++ b/Mage.Sets/src/mage/sets/prophecy/RibbonSnake.java @@ -0,0 +1,75 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.prophecy; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.InfoEffect; +import mage.abilities.effects.common.continuous.LoseAbilitySourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; + +/** + * + * @author LoneFox + */ +public class RibbonSnake extends CardImpl { + + public RibbonSnake(UUID ownerId) { + super(ownerId, 46, "Ribbon Snake", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{U}{U}"); + this.expansionSetCode = "PCY"; + this.subtype.add("Snake"); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // {2}: Ribbon Snake loses flying until end of turn. Any player may activate this ability. + SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new LoseAbilitySourceEffect( + FlyingAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl("{2}")); + ability.setMayActivate(TargetController.ANY); + ability.addEffect(new InfoEffect("Any player may activate this ability")); + this.addAbility(ability); + } + + public RibbonSnake(final RibbonSnake card) { + super(card); + } + + @Override + public RibbonSnake copy() { + return new RibbonSnake(this); + } +} diff --git a/Mage.Sets/src/mage/sets/prophecy/VintaraElephant.java b/Mage.Sets/src/mage/sets/prophecy/VintaraElephant.java new file mode 100644 index 0000000000..1e70c6836b --- /dev/null +++ b/Mage.Sets/src/mage/sets/prophecy/VintaraElephant.java @@ -0,0 +1,75 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.prophecy; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.InfoEffect; +import mage.abilities.effects.common.continuous.LoseAbilitySourceEffect; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; + +/** + * + * @author LoneFox + */ +public class VintaraElephant extends CardImpl { + + public VintaraElephant(UUID ownerId) { + super(ownerId, 131, "Vintara Elephant", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{4}{G}"); + this.expansionSetCode = "PCY"; + this.subtype.add("Elephant"); + this.power = new MageInt(4); + this.toughness = new MageInt(3); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + // {3}: Vintara Elephant loses trample until end of turn. Any player may activate this ability. + SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new LoseAbilitySourceEffect( + TrampleAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl("{3}")); + ability.setMayActivate(TargetController.ANY); + ability.addEffect(new InfoEffect("Any player may activate this ability")); + this.addAbility(ability); + } + + public VintaraElephant(final VintaraElephant card) { + super(card); + } + + @Override + public VintaraElephant copy() { + return new VintaraElephant(this); + } +} diff --git a/Mage.Sets/src/mage/sets/prophecy/ZerapaMinotaur.java b/Mage.Sets/src/mage/sets/prophecy/ZerapaMinotaur.java new file mode 100644 index 0000000000..6000fde3df --- /dev/null +++ b/Mage.Sets/src/mage/sets/prophecy/ZerapaMinotaur.java @@ -0,0 +1,75 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.prophecy; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.InfoEffect; +import mage.abilities.effects.common.continuous.LoseAbilitySourceEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; + +/** + * + * @author LoneFox + */ +public class ZerapaMinotaur extends CardImpl { + + public ZerapaMinotaur(UUID ownerId) { + super(ownerId, 108, "Zerapa Minotaur", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{R}{R}"); + this.expansionSetCode = "PCY"; + this.subtype.add("Minotaur"); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // First strike + this.addAbility(FirstStrikeAbility.getInstance()); + // {2}: Zerapa Minotaur loses first strike until end of turn. Any player may activate this ability. + SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new LoseAbilitySourceEffect( + FirstStrikeAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl("{2}")); + ability.setMayActivate(TargetController.ANY); + ability.addEffect(new InfoEffect("Any player may activate this ability")); + this.addAbility(ability); + } + + public ZerapaMinotaur(final ZerapaMinotaur card) { + super(card); + } + + @Override + public ZerapaMinotaur copy() { + return new ZerapaMinotaur(this); + } +} diff --git a/Mage/src/mage/abilities/effects/common/continuous/LoseAbilitySourceEffect.java b/Mage/src/mage/abilities/effects/common/continuous/LoseAbilitySourceEffect.java index 2c898399a0..785420e329 100644 --- a/Mage/src/mage/abilities/effects/common/continuous/LoseAbilitySourceEffect.java +++ b/Mage/src/mage/abilities/effects/common/continuous/LoseAbilitySourceEffect.java @@ -17,36 +17,36 @@ import mage.game.permanent.Permanent; * @author Noahsark */ public class LoseAbilitySourceEffect extends ContinuousEffectImpl{ - + protected Ability ability; - + public LoseAbilitySourceEffect(Ability ability){ this(ability, Duration.WhileOnBattlefield); } - + public LoseAbilitySourceEffect(Ability ability, Duration duration){ super(duration, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.LoseAbility); this.ability = ability; - staticText = "{this} loses " + ability.getRule() + duration.toString(); + staticText = "{this} loses " + ability.getRule() + " " + duration.toString(); } - + public LoseAbilitySourceEffect(final LoseAbilitySourceEffect effect){ super(effect); this.ability = effect.ability.copy(); } - + @Override public LoseAbilitySourceEffect copy(){ return new LoseAbilitySourceEffect(this); } - + @Override public boolean apply(Game game, Ability source){ Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null){ // 112.10 while (permanent.getAbilities().remove(ability)) { - + } } return true; From 6dcfa0cee4c63bf5572f702ada84dee584ef99c8 Mon Sep 17 00:00:00 2001 From: LoneFox Date: Tue, 13 Oct 2015 10:29:08 +0300 Subject: [PATCH 17/46] Implement cards: Fen Stalker, Scoria Cat, Spur Grappler, and Vintara Snapper --- .../src/mage/sets/prophecy/FenStalker.java | 81 +++++++++++++++++++ .../src/mage/sets/prophecy/ScoriaCat.java | 80 ++++++++++++++++++ .../src/mage/sets/prophecy/SpurGrappler.java | 80 ++++++++++++++++++ .../mage/sets/prophecy/VintaraSnapper.java | 81 +++++++++++++++++++ 4 files changed, 322 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/prophecy/FenStalker.java create mode 100644 Mage.Sets/src/mage/sets/prophecy/ScoriaCat.java create mode 100644 Mage.Sets/src/mage/sets/prophecy/SpurGrappler.java create mode 100644 Mage.Sets/src/mage/sets/prophecy/VintaraSnapper.java diff --git a/Mage.Sets/src/mage/sets/prophecy/FenStalker.java b/Mage.Sets/src/mage/sets/prophecy/FenStalker.java new file mode 100644 index 0000000000..9a573268b6 --- /dev/null +++ b/Mage.Sets/src/mage/sets/prophecy/FenStalker.java @@ -0,0 +1,81 @@ +/* + * 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.prophecy; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.InvertCondition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.FearAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledLandPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.TappedPredicate; + +/** + * + * @author LoneFox + */ +public class FenStalker extends CardImpl { + + private static final FilterControlledLandPermanent filter = new FilterControlledLandPermanent(); + + static { + filter.add(Predicates.not(new TappedPredicate())); + } + + public FenStalker(UUID ownerId) { + super(ownerId, 64, "Fen Stalker", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{3}{B}"); + this.expansionSetCode = "PCY"; + this.subtype.add("Nightstalker"); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Fen Stalker has fear as long as you control no untapped lands. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, + new ConditionalContinuousEffect(new GainAbilitySourceEffect(FearAbility.getInstance(), + Duration.WhileOnBattlefield), new InvertCondition(new PermanentsOnTheBattlefieldCondition(filter)), + "{this} has fear as long as you control no untapped lands"))); + } + + public FenStalker(final FenStalker card) { + super(card); + } + + @Override + public FenStalker copy() { + return new FenStalker(this); + } +} diff --git a/Mage.Sets/src/mage/sets/prophecy/ScoriaCat.java b/Mage.Sets/src/mage/sets/prophecy/ScoriaCat.java new file mode 100644 index 0000000000..1d7e4438dd --- /dev/null +++ b/Mage.Sets/src/mage/sets/prophecy/ScoriaCat.java @@ -0,0 +1,80 @@ +/* + * 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.prophecy; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.InvertCondition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +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.constants.Zone; +import mage.filter.common.FilterControlledLandPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.TappedPredicate; + +/** + * + * @author LoneFox + */ +public class ScoriaCat extends CardImpl { + + private static final FilterControlledLandPermanent filter = new FilterControlledLandPermanent(); + + static { + filter.add(Predicates.not(new TappedPredicate())); + } + + public ScoriaCat(UUID ownerId) { + super(ownerId, 101, "Scoria Cat", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{3}{R}{R}"); + this.expansionSetCode = "PCY"; + this.subtype.add("Cat"); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Scoria Cat gets +3/+3 as long as you control no untapped lands. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, + new ConditionalContinuousEffect(new BoostSourceEffect(3, 3, Duration.WhileOnBattlefield), + new InvertCondition(new PermanentsOnTheBattlefieldCondition(filter)), + "{this} gets +3/+3 as long as you control no untapped lands"))); + } + + public ScoriaCat(final ScoriaCat card) { + super(card); + } + + @Override + public ScoriaCat copy() { + return new ScoriaCat(this); + } +} diff --git a/Mage.Sets/src/mage/sets/prophecy/SpurGrappler.java b/Mage.Sets/src/mage/sets/prophecy/SpurGrappler.java new file mode 100644 index 0000000000..204a883999 --- /dev/null +++ b/Mage.Sets/src/mage/sets/prophecy/SpurGrappler.java @@ -0,0 +1,80 @@ +/* + * 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.prophecy; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.InvertCondition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +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.constants.Zone; +import mage.filter.common.FilterControlledLandPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.TappedPredicate; + +/** + * + * @author LoneFox + */ +public class SpurGrappler extends CardImpl { + + private static final FilterControlledLandPermanent filter = new FilterControlledLandPermanent(); + + static { + filter.add(Predicates.not(new TappedPredicate())); + } + + public SpurGrappler(UUID ownerId) { + super(ownerId, 104, "Spur Grappler", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{R}"); + this.expansionSetCode = "PCY"; + this.subtype.add("Beast"); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Spur Grappler gets +2/+1 as long as you control no untapped lands. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, + new ConditionalContinuousEffect(new BoostSourceEffect(2, 1, Duration.WhileOnBattlefield), + new InvertCondition(new PermanentsOnTheBattlefieldCondition(filter)), + "{this} gets +2/+1 as long as you control no untapped lands"))); + } + + public SpurGrappler(final SpurGrappler card) { + super(card); + } + + @Override + public SpurGrappler copy() { + return new SpurGrappler(this); + } +} diff --git a/Mage.Sets/src/mage/sets/prophecy/VintaraSnapper.java b/Mage.Sets/src/mage/sets/prophecy/VintaraSnapper.java new file mode 100644 index 0000000000..ba9f95908b --- /dev/null +++ b/Mage.Sets/src/mage/sets/prophecy/VintaraSnapper.java @@ -0,0 +1,81 @@ +/* + * 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.prophecy; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.InvertCondition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.ShroudAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledLandPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.TappedPredicate; + +/** + * + * @author LoneFox + */ +public class VintaraSnapper extends CardImpl { + + private static final FilterControlledLandPermanent filter = new FilterControlledLandPermanent(); + + static { + filter.add(Predicates.not(new TappedPredicate())); + } + + public VintaraSnapper(UUID ownerId) { + super(ownerId, 132, "Vintara Snapper", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{G}{G}"); + this.expansionSetCode = "PCY"; + this.subtype.add("Turtle"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Vintara Snapper has shroud as long as you control no untapped lands. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, + new ConditionalContinuousEffect(new GainAbilitySourceEffect(ShroudAbility.getInstance(), + Duration.WhileOnBattlefield), new InvertCondition(new PermanentsOnTheBattlefieldCondition(filter)), + "{this} has shroud as long as you control no untapped lands"))); + } + + public VintaraSnapper(final VintaraSnapper card) { + super(card); + } + + @Override + public VintaraSnapper copy() { + return new VintaraSnapper(this); + } +} From 321c2e8b295c9310e262ace65c6e0db7daa96292 Mon Sep 17 00:00:00 2001 From: LoneFox Date: Tue, 13 Oct 2015 11:07:23 +0300 Subject: [PATCH 18/46] Implement cards: Devastate, Noxious Field, Silt Crawler, and Troublesome Spirit --- .../src/mage/sets/prophecy/Devastate.java | 62 ++++++++++++++ .../src/mage/sets/prophecy/NoxiousField.java | 82 +++++++++++++++++++ .../src/mage/sets/prophecy/SiltCrawler.java | 64 +++++++++++++++ .../mage/sets/prophecy/TroublesomeSpirit.java | 68 +++++++++++++++ 4 files changed, 276 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/prophecy/Devastate.java create mode 100644 Mage.Sets/src/mage/sets/prophecy/NoxiousField.java create mode 100644 Mage.Sets/src/mage/sets/prophecy/SiltCrawler.java create mode 100644 Mage.Sets/src/mage/sets/prophecy/TroublesomeSpirit.java diff --git a/Mage.Sets/src/mage/sets/prophecy/Devastate.java b/Mage.Sets/src/mage/sets/prophecy/Devastate.java new file mode 100644 index 0000000000..20068f5e1b --- /dev/null +++ b/Mage.Sets/src/mage/sets/prophecy/Devastate.java @@ -0,0 +1,62 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE 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.prophecy; + +import java.util.UUID; +import mage.abilities.effects.common.DamageEverythingEffect; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.target.common.TargetLandPermanent; + +/** + * + * @author LoneFox + */ +public class Devastate extends CardImpl { + + public Devastate(UUID ownerId) { + super(ownerId, 87, "Devastate", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{3}{R}{R}"); + this.expansionSetCode = "PCY"; + + // Destroy target land. Devastate deals 1 damage to each creature and each player. + this.getSpellAbility().addEffect(new DestroyTargetEffect()); + this.getSpellAbility().addEffect(new DamageEverythingEffect(1)); + this.getSpellAbility().addTarget(new TargetLandPermanent()); + } + + public Devastate(final Devastate card) { + super(card); + } + + @Override + public Devastate copy() { + return new Devastate(this); + } +} diff --git a/Mage.Sets/src/mage/sets/prophecy/NoxiousField.java b/Mage.Sets/src/mage/sets/prophecy/NoxiousField.java new file mode 100644 index 0000000000..e3aa9bf82c --- /dev/null +++ b/Mage.Sets/src/mage/sets/prophecy/NoxiousField.java @@ -0,0 +1,82 @@ +/* + * 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.prophecy; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.DamageEverythingEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.TargetPermanent; +import mage.target.common.TargetLandPermanent; + +/** + * + * @author LoneFox + */ +public class NoxiousField extends CardImpl { + + public NoxiousField(UUID ownerId) { + super(ownerId, 70, "Noxious Field", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}{B}"); + this.expansionSetCode = "PCY"; + this.subtype.add("Aura"); + + // Enchant land + TargetPermanent auraTarget = new TargetLandPermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + // Enchanted land has "{tap}: This land deals 1 damage to each creature and each player." + ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageEverythingEffect(1), new TapSourceCost()); + Effect effect = new GainAbilityAttachedEffect(ability, AttachmentType.AURA); + effect.setText("Enchanted land has \"{T}: This land deals 1 damage to each creature and each player.\""); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); + } + + public NoxiousField(final NoxiousField card) { + super(card); + } + + @Override + public NoxiousField copy() { + return new NoxiousField(this); + } +} diff --git a/Mage.Sets/src/mage/sets/prophecy/SiltCrawler.java b/Mage.Sets/src/mage/sets/prophecy/SiltCrawler.java new file mode 100644 index 0000000000..177b90a087 --- /dev/null +++ b/Mage.Sets/src/mage/sets/prophecy/SiltCrawler.java @@ -0,0 +1,64 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.prophecy; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.TapAllEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterControlledLandPermanent; + +/** + * + * @author LoneFox + */ +public class SiltCrawler extends CardImpl { + + public SiltCrawler(UUID ownerId) { + super(ownerId, 123, "Silt Crawler", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{G}"); + this.expansionSetCode = "PCY"; + this.subtype.add("Beast"); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // When Silt Crawler enters the battlefield, tap all lands you control. + this.addAbility(new EntersBattlefieldTriggeredAbility(new TapAllEffect(new FilterControlledLandPermanent("lands you control")), false)); + } + + public SiltCrawler(final SiltCrawler card) { + super(card); + } + + @Override + public SiltCrawler copy() { + return new SiltCrawler(this); + } +} diff --git a/Mage.Sets/src/mage/sets/prophecy/TroublesomeSpirit.java b/Mage.Sets/src/mage/sets/prophecy/TroublesomeSpirit.java new file mode 100644 index 0000000000..f3a6f6c58c --- /dev/null +++ b/Mage.Sets/src/mage/sets/prophecy/TroublesomeSpirit.java @@ -0,0 +1,68 @@ +/* + * 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.prophecy; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.BeginningOfEndStepTriggeredAbility; +import mage.abilities.effects.common.TapAllEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.filter.common.FilterControlledLandPermanent; + +/** + * + * @author LoneFox + */ +public class TroublesomeSpirit extends CardImpl { + + public TroublesomeSpirit(UUID ownerId) { + super(ownerId, 52, "Troublesome Spirit", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{U}{U}"); + this.expansionSetCode = "PCY"; + this.subtype.add("Spirit"); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // At the beginning of your end step, tap all lands you control. + this.addAbility(new BeginningOfEndStepTriggeredAbility(new TapAllEffect(new FilterControlledLandPermanent("lands you control")), TargetController.YOU, false)); + } + + public TroublesomeSpirit(final TroublesomeSpirit card) { + super(card); + } + + @Override + public TroublesomeSpirit copy() { + return new TroublesomeSpirit(this); + } +} From 5f74101fa53d539b65bb3cbb5ce64ca894ec6e66 Mon Sep 17 00:00:00 2001 From: LoneFox Date: Tue, 13 Oct 2015 11:58:12 +0300 Subject: [PATCH 19/46] Implement cards: Mine Bearer, Sunken Field, Well of Discovery, and Well of Life --- .../src/mage/sets/prophecy/MineBearer.java | 72 ++++++++++++++++ .../src/mage/sets/prophecy/SunkenField.java | 85 +++++++++++++++++++ .../mage/sets/prophecy/WellOfDiscovery.java | 75 ++++++++++++++++ .../src/mage/sets/prophecy/WellOfLife.java | 74 ++++++++++++++++ 4 files changed, 306 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/prophecy/MineBearer.java create mode 100644 Mage.Sets/src/mage/sets/prophecy/SunkenField.java create mode 100644 Mage.Sets/src/mage/sets/prophecy/WellOfDiscovery.java create mode 100644 Mage.Sets/src/mage/sets/prophecy/WellOfLife.java diff --git a/Mage.Sets/src/mage/sets/prophecy/MineBearer.java b/Mage.Sets/src/mage/sets/prophecy/MineBearer.java new file mode 100644 index 0000000000..f74f6b1f0b --- /dev/null +++ b/Mage.Sets/src/mage/sets/prophecy/MineBearer.java @@ -0,0 +1,72 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.prophecy; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.common.TargetAttackingCreature; + +/** + * + * @author LoneFox + */ +public class MineBearer extends CardImpl { + + public MineBearer(UUID ownerId) { + super(ownerId, 16, "Mine Bearer", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{W}"); + this.expansionSetCode = "PCY"; + this.subtype.add("Human"); + this.subtype.add("Soldier"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // {tap}, Sacrifice Mine Bearer: Destroy target attacking creature. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new TapSourceCost()); + ability.addCost(new SacrificeSourceCost()); + ability.addTarget(new TargetAttackingCreature()); + this.addAbility(ability); + } + + public MineBearer(final MineBearer card) { + super(card); + } + + @Override + public MineBearer copy() { + return new MineBearer(this); + } +} diff --git a/Mage.Sets/src/mage/sets/prophecy/SunkenField.java b/Mage.Sets/src/mage/sets/prophecy/SunkenField.java new file mode 100644 index 0000000000..fca2a0bc86 --- /dev/null +++ b/Mage.Sets/src/mage/sets/prophecy/SunkenField.java @@ -0,0 +1,85 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.prophecy; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.CounterUnlessPaysEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.TargetPermanent; +import mage.target.TargetSpell; +import mage.target.common.TargetLandPermanent; + +/** + * + * @author LoneFox + */ +public class SunkenField extends CardImpl { + + public SunkenField(UUID ownerId) { + super(ownerId, 51, "Sunken Field", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}"); + this.expansionSetCode = "PCY"; + this.subtype.add("Aura"); + + // Enchant land + TargetPermanent auraTarget = new TargetLandPermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + // Enchanted land has "{T}: Counter target spell unless its controller pays {1}." + ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CounterUnlessPaysEffect(new ManaCostsImpl("{1}")), new TapSourceCost()); + ability.addTarget(new TargetSpell()); + Effect effect = new GainAbilityAttachedEffect(ability, AttachmentType.AURA); + effect.setText("Enchanted land has \"{T}: Counter target spell unless its controller pays {1}.\""); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); + } + + public SunkenField(final SunkenField card) { + super(card); + } + + @Override + public SunkenField copy() { + return new SunkenField(this); + } +} diff --git a/Mage.Sets/src/mage/sets/prophecy/WellOfDiscovery.java b/Mage.Sets/src/mage/sets/prophecy/WellOfDiscovery.java new file mode 100644 index 0000000000..d13f785e99 --- /dev/null +++ b/Mage.Sets/src/mage/sets/prophecy/WellOfDiscovery.java @@ -0,0 +1,75 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.prophecy; + +import java.util.UUID; +import mage.abilities.common.BeginningOfEndStepTriggeredAbility; +import mage.abilities.condition.InvertCondition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.filter.common.FilterControlledLandPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.TappedPredicate; + +/** + * + * @author LoneFox + */ +public class WellOfDiscovery extends CardImpl { + + private static final FilterControlledLandPermanent filter = new FilterControlledLandPermanent(); + + static { + filter.add(Predicates.not(new TappedPredicate())); + } + + public WellOfDiscovery(UUID ownerId) { + super(ownerId, 140, "Well of Discovery", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{6}"); + this.expansionSetCode = "PCY"; + + // At the beginning of your end step, if you control no untapped lands, draw a card. + this.addAbility(new ConditionalTriggeredAbility(new BeginningOfEndStepTriggeredAbility( + new DrawCardSourceControllerEffect(1), TargetController.YOU, false), + new InvertCondition(new PermanentsOnTheBattlefieldCondition(filter)), + "At the beginning of your end step, if you control no untapped lands, draw a card.")); + } + + public WellOfDiscovery(final WellOfDiscovery card) { + super(card); + } + + @Override + public WellOfDiscovery copy() { + return new WellOfDiscovery(this); + } +} diff --git a/Mage.Sets/src/mage/sets/prophecy/WellOfLife.java b/Mage.Sets/src/mage/sets/prophecy/WellOfLife.java new file mode 100644 index 0000000000..82a2e24ad4 --- /dev/null +++ b/Mage.Sets/src/mage/sets/prophecy/WellOfLife.java @@ -0,0 +1,74 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.prophecy; + +import java.util.UUID; +import mage.abilities.common.BeginningOfEndStepTriggeredAbility; +import mage.abilities.condition.InvertCondition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.filter.common.FilterControlledLandPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.TappedPredicate; + +/** + * + * @author LoneFox + */ +public class WellOfLife extends CardImpl { + + private static final FilterControlledLandPermanent filter = new FilterControlledLandPermanent(); + + static { + filter.add(Predicates.not(new TappedPredicate())); + } + + public WellOfLife(UUID ownerId) { + super(ownerId, 141, "Well of Life", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT}, "{4}"); + this.expansionSetCode = "PCY"; + + // At the beginning of your end step, if you control no untapped lands, you gain 2 life. + this.addAbility(new ConditionalTriggeredAbility(new BeginningOfEndStepTriggeredAbility( + new GainLifeEffect(2), TargetController.YOU, false), new InvertCondition(new PermanentsOnTheBattlefieldCondition(filter)), + "At the beginning of your end step, if you control no untapped lands, you gain 2 life.")); + } + + public WellOfLife(final WellOfLife card) { + super(card); + } + + @Override + public WellOfLife copy() { + return new WellOfLife(this); + } +} From cfb10c869e7d6e8395d60d82a0a5ecbd3f142ae9 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 13 Oct 2015 17:11:10 +0200 Subject: [PATCH 20/46] Added 5 older cards. --- .../mage/sets/planarchaos/BrainGorgers.java | 114 ++++++++++++++++ .../src/mage/sets/planarchaos/DashHopes.java | 110 ++++++++++++++++ .../sets/planarchaos/Phantasmagorian.java | 19 +-- .../sets/planarchaos/TemporalExtortion.java | 104 +++++++++++++++ .../src/mage/sets/prophecy/AvatarOfMight.java | 122 ++++++++++++++++++ .../src/mage/sets/prophecy/AvatarOfWill.java | 120 +++++++++++++++++ .../mage/sets/tenthedition/AvatarOfMight.java | 52 ++++++++ 7 files changed, 633 insertions(+), 8 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/planarchaos/BrainGorgers.java create mode 100644 Mage.Sets/src/mage/sets/planarchaos/DashHopes.java create mode 100644 Mage.Sets/src/mage/sets/planarchaos/TemporalExtortion.java create mode 100644 Mage.Sets/src/mage/sets/prophecy/AvatarOfMight.java create mode 100644 Mage.Sets/src/mage/sets/prophecy/AvatarOfWill.java create mode 100644 Mage.Sets/src/mage/sets/tenthedition/AvatarOfMight.java diff --git a/Mage.Sets/src/mage/sets/planarchaos/BrainGorgers.java b/Mage.Sets/src/mage/sets/planarchaos/BrainGorgers.java new file mode 100644 index 0000000000..9ba3c089df --- /dev/null +++ b/Mage.Sets/src/mage/sets/planarchaos/BrainGorgers.java @@ -0,0 +1,114 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.planarchaos; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CastSourceTriggeredAbility; +import mage.abilities.keyword.MadnessAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.game.Game; +import mage.game.stack.Spell; +import mage.players.Player; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author LevelX2 + */ +public class BrainGorgers extends CardImpl { + + public BrainGorgers(UUID ownerId) { + super(ownerId, 65, "Brain Gorgers", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{3}{B}"); + this.expansionSetCode = "PLC"; + this.subtype.add("Zombie"); + this.power = new MageInt(4); + this.toughness = new MageInt(2); + + // When you cast Brain Gorgers, any player may sacrifice a creature. If a player does, counter Brain Gorgers. + this.addAbility(new CastSourceTriggeredAbility(new BrainGorgersCounterSourceEffect())); + + // Madness {1}{B} + this.addAbility(new MadnessAbility(this, new ManaCostsImpl<>("{1}{B}"))); + } + + public BrainGorgers(final BrainGorgers card) { + super(card); + } + + @Override + public BrainGorgers copy() { + return new BrainGorgers(this); + } +} + +class BrainGorgersCounterSourceEffect extends OneShotEffect { + + public BrainGorgersCounterSourceEffect() { + super(Outcome.AIDontUseIt); + staticText = "any player may sacrifice a creature. If a player does, counter {source}"; + } + + public BrainGorgersCounterSourceEffect(final BrainGorgersCounterSourceEffect effect) { + super(effect); + } + + @Override + public BrainGorgersCounterSourceEffect copy() { + return new BrainGorgersCounterSourceEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Spell spell = game.getStack().getSpell(source.getSourceId()); + if (spell != null) { + SacrificeTargetCost cost = new SacrificeTargetCost(new TargetControlledCreaturePermanent()); + for (UUID playerId : game.getState().getPlayerList(source.getControllerId())) { + cost.clearPaid(); + Player player = game.getPlayer(playerId); + if (cost.canPay(source, source.getSourceId(), player.getId(), game) + && player.chooseUse(outcome, "Sacrifice a creature to counter " + spell.getIdName() + "?", source, game)) { + if (cost.pay(source, game, source.getSourceId(), player.getId(), false)) { + game.informPlayers(player.getLogName() + " sacrifices a creature to counter " + spell.getIdName() + "."); + game.getStack().counter(spell.getId(), source.getSourceId(), game); + } + } + } + return true; + } + return false; + } + +} diff --git a/Mage.Sets/src/mage/sets/planarchaos/DashHopes.java b/Mage.Sets/src/mage/sets/planarchaos/DashHopes.java new file mode 100644 index 0000000000..561fbbc9e8 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planarchaos/DashHopes.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.planarchaos; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.costs.common.PayLifeCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CastSourceTriggeredAbility; +import mage.abilities.effects.common.CounterTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.game.Game; +import mage.game.stack.Spell; +import mage.players.Player; +import mage.target.TargetSpell; + +/** + * + * @author LevelX2 + */ +public class DashHopes extends CardImpl { + + public DashHopes(UUID ownerId) { + super(ownerId, 68, "Dash Hopes", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{B}{B}"); + this.expansionSetCode = "PLC"; + + // When you cast Dash Hopes, any player may pay 5 life. If a player does, counter Dash Hopes. + this.addAbility(new CastSourceTriggeredAbility(new DashHopesCounterSourceEffect())); + + // Counter target spell. + this.getSpellAbility().addEffect(new CounterTargetEffect()); + this.getSpellAbility().addTarget(new TargetSpell()); + } + + public DashHopes(final DashHopes card) { + super(card); + } + + @Override + public DashHopes copy() { + return new DashHopes(this); + } +} + +class DashHopesCounterSourceEffect extends OneShotEffect { + + public DashHopesCounterSourceEffect() { + super(Outcome.AIDontUseIt); + staticText = "any player may pay 5 life. If a player does, counter {source}"; + } + + public DashHopesCounterSourceEffect(final DashHopesCounterSourceEffect effect) { + super(effect); + } + + @Override + public DashHopesCounterSourceEffect copy() { + return new DashHopesCounterSourceEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Spell spell = game.getStack().getSpell(source.getSourceId()); + if (spell != null) { + PayLifeCost cost = new PayLifeCost(5); + for (UUID playerId : game.getState().getPlayerList(source.getControllerId())) { + Player player = game.getPlayer(playerId); + cost.clearPaid(); + if (cost.canPay(source, source.getSourceId(), player.getId(), game) + && player.chooseUse(outcome, "Pay 5 life to counter " + spell.getIdName() + "?", source, game)) { + if (cost.pay(source, game, source.getSourceId(), player.getId(), false)) { + game.informPlayers(player.getLogName() + " pays 5 life to counter " + spell.getIdName() + "."); + game.getStack().counter(spell.getId(), source.getSourceId(), game); + } + } + } + return true; + } + return false; + } + +} diff --git a/Mage.Sets/src/mage/sets/planarchaos/Phantasmagorian.java b/Mage.Sets/src/mage/sets/planarchaos/Phantasmagorian.java index e8e99f9eb6..966f1d2a12 100644 --- a/Mage.Sets/src/mage/sets/planarchaos/Phantasmagorian.java +++ b/Mage.Sets/src/mage/sets/planarchaos/Phantasmagorian.java @@ -95,19 +95,22 @@ class CounterSourceEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - + StackObject spell = null; - for(StackObject objet : game.getStack()){ - if(objet instanceof Spell && objet.getSourceId().equals(source.getSourceId())){ + for (StackObject objet : game.getStack()) { + if (objet instanceof Spell && objet.getSourceId().equals(source.getSourceId())) { spell = objet; } } - if(spell != null){ - for(UUID uuid : game.getPlayerList()){ + if (spell != null) { + DiscardTargetCost cost = new DiscardTargetCost(new TargetCardInHand(3, 3, new FilterCard())); + for (UUID uuid : game.getPlayerList()) { Player player = game.getPlayer(uuid); - if(player.chooseUse(Outcome.Detriment, "Discard three cards to counter " + spell.getName() + "?", source, game)){ - DiscardTargetCost cost = new DiscardTargetCost(new TargetCardInHand(3, 3, new FilterCard())); - if(cost.pay(source, game, source.getSourceId(), uuid, false)){ + cost.clearPaid(); + if (cost.canPay(source, source.getSourceId(), player.getId(), game) + && player.chooseUse(Outcome.Detriment, "Discard three cards to counter " + spell.getName() + "?", source, game)) { + + if (cost.pay(source, game, source.getSourceId(), uuid, false)) { game.informPlayers(player.getLogName() + " discards 3 cards to counter " + spell.getName() + "."); game.getStack().counter(spell.getId(), source.getSourceId(), game); return true; diff --git a/Mage.Sets/src/mage/sets/planarchaos/TemporalExtortion.java b/Mage.Sets/src/mage/sets/planarchaos/TemporalExtortion.java new file mode 100644 index 0000000000..ea806b6198 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planarchaos/TemporalExtortion.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.planarchaos; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CastSourceTriggeredAbility; +import mage.abilities.effects.common.turn.AddExtraTurnControllerEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.game.Game; +import mage.game.stack.Spell; +import mage.players.Player; + +/** + * + * @author LevelX2 + */ +public class TemporalExtortion extends CardImpl { + + public TemporalExtortion(UUID ownerId) { + super(ownerId, 81, "Temporal Extortion", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{B}{B}{B}{B}"); + this.expansionSetCode = "PLC"; + + // When you cast Temporal Extortion, any player may pay half his or her life, rounded up. If a player does, counter Temporal Extortion. + this.addAbility(new CastSourceTriggeredAbility(new TemporalExtortionCounterSourceEffect())); + + // Take an extra turn after this one. + this.getSpellAbility().addEffect(new AddExtraTurnControllerEffect()); + } + + public TemporalExtortion(final TemporalExtortion card) { + super(card); + } + + @Override + public TemporalExtortion copy() { + return new TemporalExtortion(this); + } +} + +class TemporalExtortionCounterSourceEffect extends OneShotEffect { + + public TemporalExtortionCounterSourceEffect() { + super(Outcome.AIDontUseIt); + staticText = "any player may pay half his or her life, rounded up. If a player does, counter {source}"; + } + + public TemporalExtortionCounterSourceEffect(final TemporalExtortionCounterSourceEffect effect) { + super(effect); + } + + @Override + public TemporalExtortionCounterSourceEffect copy() { + return new TemporalExtortionCounterSourceEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Spell spell = game.getStack().getSpell(source.getSourceId()); + if (spell != null) { + for (UUID playerId : game.getState().getPlayerList(source.getControllerId())) { + Player player = game.getPlayer(playerId); + if (player.chooseUse(outcome, "Pay half your life, rounded up to counter " + spell.getIdName() + "?", source, game)) { + Integer amount = (int) Math.ceil(player.getLife() / 2f); + player.loseLife(amount, game); + game.informPlayers(player.getLogName() + " pays half his or her life, rounded up to counter " + spell.getIdName() + "."); + game.getStack().counter(spell.getId(), source.getSourceId(), game); + } + } + return true; + } + return false; + } + +} diff --git a/Mage.Sets/src/mage/sets/prophecy/AvatarOfMight.java b/Mage.Sets/src/mage/sets/prophecy/AvatarOfMight.java new file mode 100644 index 0000000000..8008f96f3d --- /dev/null +++ b/Mage.Sets/src/mage/sets/prophecy/AvatarOfMight.java @@ -0,0 +1,122 @@ +/* + * 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.prophecy; + +import java.util.UUID; +import mage.MageInt; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.SpellAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.cost.CostModificationEffectImpl; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.CostModificationType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author LevelX2 + */ +public class AvatarOfMight extends CardImpl { + + public AvatarOfMight(UUID ownerId) { + super(ownerId, 109, "Avatar of Might", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{6}{G}{G}"); + this.expansionSetCode = "PCY"; + this.subtype.add("Avatar"); + this.power = new MageInt(8); + this.toughness = new MageInt(8); + + // If an opponent controls at least four more creatures than you, Avatar of Might costs {6} less to cast. + this.addAbility(new SimpleStaticAbility(Zone.STACK, new AvatarOfMightCostReductionEffect())); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + } + + public AvatarOfMight(final AvatarOfMight card) { + super(card); + } + + @Override + public AvatarOfMight copy() { + return new AvatarOfMight(this); + } +} + +class AvatarOfMightCostReductionEffect extends CostModificationEffectImpl { + + AvatarOfMightCostReductionEffect() { + super(Duration.Custom, Outcome.Benefit, CostModificationType.REDUCE_COST); + staticText = "If an opponent controls at least four more creatures than you, {this} will costs {6} less to cast"; + } + + AvatarOfMightCostReductionEffect(final AvatarOfMightCostReductionEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source, Ability abilityToModify) { + SpellAbility spellAbility = (SpellAbility) abilityToModify; + Mana mana = spellAbility.getManaCostsToPay().getMana(); + if (mana.getColorless() > 0) { + int newCount = mana.getColorless() - 6; + if (newCount < 0) { + newCount = 0; + } + mana.setColorless(newCount); + spellAbility.getManaCostsToPay().load(mana.toString()); + return true; + } + return false; + } + + @Override + public boolean applies(Ability abilityToModify, Ability source, Game game) { + int creatures = game.getBattlefield().countAll(new FilterCreaturePermanent(), source.getControllerId(), game); + for (UUID playerId : game.getOpponents(source.getControllerId())) { + Player opponent = game.getPlayer(playerId); + if (opponent != null && game.getBattlefield().countAll(new FilterCreaturePermanent(), opponent.getId(), game) >= creatures + 4) { + return true; + } + } + return false; + } + + @Override + public AvatarOfMightCostReductionEffect copy() { + return new AvatarOfMightCostReductionEffect(this); + } +} diff --git a/Mage.Sets/src/mage/sets/prophecy/AvatarOfWill.java b/Mage.Sets/src/mage/sets/prophecy/AvatarOfWill.java new file mode 100644 index 0000000000..2dbd76b18b --- /dev/null +++ b/Mage.Sets/src/mage/sets/prophecy/AvatarOfWill.java @@ -0,0 +1,120 @@ +/* + * 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.prophecy; + +import java.util.UUID; +import mage.MageInt; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.SpellAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.cost.CostModificationEffectImpl; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.CostModificationType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author LevelX2 + */ +public class AvatarOfWill extends CardImpl { + + public AvatarOfWill(UUID ownerId) { + super(ownerId, 30, "Avatar of Will", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{6}{U}{U}"); + this.expansionSetCode = "PCY"; + this.subtype.add("Avatar"); + this.power = new MageInt(5); + this.toughness = new MageInt(6); + + // If an opponent has no cards in hand, Avatar of Will costs {6} less to cast. + this.addAbility(new SimpleStaticAbility(Zone.STACK, new AvatarOfWillCostReductionEffect())); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + } + + public AvatarOfWill(final AvatarOfWill card) { + super(card); + } + + @Override + public AvatarOfWill copy() { + return new AvatarOfWill(this); + } +} + +class AvatarOfWillCostReductionEffect extends CostModificationEffectImpl { + + AvatarOfWillCostReductionEffect() { + super(Duration.Custom, Outcome.Benefit, CostModificationType.REDUCE_COST); + staticText = "If an opponent has no cards in hand, {this} will costs {6} less to cast"; + } + + AvatarOfWillCostReductionEffect(final AvatarOfWillCostReductionEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source, Ability abilityToModify) { + SpellAbility spellAbility = (SpellAbility) abilityToModify; + Mana mana = spellAbility.getManaCostsToPay().getMana(); + if (mana.getColorless() > 0) { + int newCount = mana.getColorless() - 6; + if (newCount < 0) { + newCount = 0; + } + mana.setColorless(newCount); + spellAbility.getManaCostsToPay().load(mana.toString()); + return true; + } + return false; + } + + @Override + public boolean applies(Ability abilityToModify, Ability source, Game game) { + for (UUID playerId : game.getOpponents(source.getControllerId())) { + Player opponent = game.getPlayer(playerId); + if (opponent != null && opponent.getHand().isEmpty()) { + return true; + } + } + return false; + } + + @Override + public AvatarOfWillCostReductionEffect copy() { + return new AvatarOfWillCostReductionEffect(this); + } +} diff --git a/Mage.Sets/src/mage/sets/tenthedition/AvatarOfMight.java b/Mage.Sets/src/mage/sets/tenthedition/AvatarOfMight.java new file mode 100644 index 0000000000..3fb391e281 --- /dev/null +++ b/Mage.Sets/src/mage/sets/tenthedition/AvatarOfMight.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.tenthedition; + +import java.util.UUID; + +/** + * + * @author LevelX2 + */ +public class AvatarOfMight extends mage.sets.prophecy.AvatarOfMight { + + public AvatarOfMight(UUID ownerId) { + super(ownerId); + this.cardNumber = 251; + this.expansionSetCode = "10E"; + } + + public AvatarOfMight(final AvatarOfMight card) { + super(card); + } + + @Override + public AvatarOfMight copy() { + return new AvatarOfMight(this); + } +} From 19e231e860685dc620cf5466c0c35987b3e0d0da Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 13 Oct 2015 22:35:50 +0200 Subject: [PATCH 21/46] * Fixed that continuous effects were not yet applied to lands entering the battlefield (preventing Prismatic Omen and Valakut the Molten Pinnacle combo to work). --- .../mage/sets/shadowmoor/PrismaticOmen.java | 21 ++++--- .../enters/ValakutTheMoltenPinnacleTest.java | 56 +++++++++++++------ .../mage/game/permanent/PermanentImpl.java | 6 +- 3 files changed, 51 insertions(+), 32 deletions(-) diff --git a/Mage.Sets/src/mage/sets/shadowmoor/PrismaticOmen.java b/Mage.Sets/src/mage/sets/shadowmoor/PrismaticOmen.java index f3e7e5bc71..73b5b6ee1b 100644 --- a/Mage.Sets/src/mage/sets/shadowmoor/PrismaticOmen.java +++ b/Mage.Sets/src/mage/sets/shadowmoor/PrismaticOmen.java @@ -30,13 +30,6 @@ package mage.sets.shadowmoor; import java.util.ArrayList; import java.util.Arrays; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.constants.SubLayer; -import mage.constants.Zone; import mage.Mana; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; @@ -48,6 +41,13 @@ import mage.abilities.mana.GreenManaAbility; import mage.abilities.mana.RedManaAbility; import mage.abilities.mana.WhiteManaAbility; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Layer; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.SubLayer; +import mage.constants.Zone; import mage.filter.common.FilterLandPermanent; import mage.game.Game; import mage.game.permanent.Permanent; @@ -62,7 +62,6 @@ public class PrismaticOmen extends CardImpl { super(ownerId, 126, "Prismatic Omen", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}"); this.expansionSetCode = "SHM"; - // Lands you control are every basic land type in addition to their other types. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BecomesBasicLandTypeAllEffect("Swamp", "Mountain", "Forest", "Island", "Plains"))); } @@ -109,11 +108,11 @@ class BecomesBasicLandTypeAllEffect extends ContinuousEffectImpl { switch (layer) { case AbilityAddingRemovingEffects_6: Mana mana = new Mana(); - for (Ability ability : land.getAbilities()){ + for (Ability ability : land.getAbilities()) { if (ability instanceof BasicManaAbility) { - for (Mana netMana: ((BasicManaAbility)ability ).getNetMana(game)) { + for (Mana netMana : ((BasicManaAbility) ability).getNetMana(game)) { mana.add(netMana); - } + } } } if (mana.getGreen() == 0 && landTypes.contains("Forest")) { diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/ValakutTheMoltenPinnacleTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/ValakutTheMoltenPinnacleTest.java index c29cd7a736..141e995132 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/ValakutTheMoltenPinnacleTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/ValakutTheMoltenPinnacleTest.java @@ -26,13 +26,10 @@ * 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.enters; import mage.constants.PhaseStep; import mage.constants.Zone; -import mage.game.permanent.Permanent; -import org.junit.Assert; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; @@ -40,17 +37,15 @@ import org.mage.test.serverside.base.CardTestPlayerBase; * * @author LevelX2 */ - public class ValakutTheMoltenPinnacleTest extends CardTestPlayerBase { /** - * Valakut, the Molten Pinnacle - * Land - * Valakut, the Molten Pinnacle enters the battlefield tapped. - * Whenever a Mountain enters the battlefield under your control, if you control at least five other Mountains, you may have Valakut, the Molten Pinnacle deal 3 damage to target creature or player. - * {T}: Add {R} to your mana pool. + * Valakut, the Molten Pinnacle Land Valakut, the Molten Pinnacle enters the + * battlefield tapped. Whenever a Mountain enters the battlefield under your + * control, if you control at least five other Mountains, you may have + * Valakut, the Molten Pinnacle deal 3 damage to target creature or player. + * {T}: Add {R} to your mana pool. */ - @Test public void onlyFourMountainsNoDamage() { @@ -85,13 +80,11 @@ public class ValakutTheMoltenPinnacleTest extends CardTestPlayerBase { assertLife(playerA, 20); assertLife(playerB, 17); - } - // Scapeshift {2}{G}{G} - // Sorcery - // Sacrifice any number of lands. Search your library for that many land cards, put them onto the battlefield tapped, then shuffle your library. - + // Scapeshift {2}{G}{G} + // Sorcery + // Sacrifice any number of lands. Search your library for that many land cards, put them onto the battlefield tapped, then shuffle your library. @Test public void sixEnterWithScapeshiftDamageToPlayerB() { @@ -113,7 +106,6 @@ public class ValakutTheMoltenPinnacleTest extends CardTestPlayerBase { assertLife(playerA, 20); assertLife(playerB, 2); // 6 * 3 damage = 18 - } @Test @@ -166,4 +158,36 @@ public class ValakutTheMoltenPinnacleTest extends CardTestPlayerBase { assertLife(playerB, 2); // 6 * 3 damage = 18 } + + /** + * Some lands aren't triggering Valakut, the Molten Pinnacle with Prismatic + * Omen and 6+ lands in play. So far I've noticed that Misty Rainforest and + * basic Island did not trigger Valakut, but an additional copy of Valakut + * did. + */ + @Test + public void withPrismaticOmen() { + // Valakut, the Molten Pinnacle enters the battlefield tapped. + // Whenever a Mountain enters the battlefield under your control, if you control at least five other Mountains, + // you may have Valakut, the Molten Pinnacle deal 3 damage to target creature or player. + // {T}: Add {R} to your mana pool. + addCard(Zone.BATTLEFIELD, playerA, "Valakut, the Molten Pinnacle"); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 4); + + addCard(Zone.HAND, playerA, "Forest", 1); + + // Lands you control are every basic land type in addition to their other types. + addCard(Zone.BATTLEFIELD, playerA, "Prismatic Omen"); + + playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Forest"); + addTarget(playerA, playerB); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertLife(playerA, 20); + assertLife(playerB, 17); + + } + } diff --git a/Mage/src/mage/game/permanent/PermanentImpl.java b/Mage/src/mage/game/permanent/PermanentImpl.java index f5be69ff35..783801dc7f 100644 --- a/Mage/src/mage/game/permanent/PermanentImpl.java +++ b/Mage/src/mage/game/permanent/PermanentImpl.java @@ -916,11 +916,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { EntersTheBattlefieldEvent event = new EntersTheBattlefieldEvent(this, sourceId, getControllerId(), fromZone); if (!game.replaceEvent(event)) { if (fireEvent) { - if (sourceId == null) { // play lands - game.fireEvent(event); - } else { // from effects - game.addSimultaneousEvent(event); - } + game.addSimultaneousEvent(event); } return true; } From 7e768e787a2d70d0e0734d920d1387d47a4ca7b5 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 13 Oct 2015 23:16:42 +0200 Subject: [PATCH 22/46] * Fixed some handling problems of all players asked to pay a cost to counter the spell with this ability. --- .../mage/sets/planarchaos/BrainGorgers.java | 16 ++++++---- .../src/mage/sets/planarchaos/DashHopes.java | 14 ++++++--- .../sets/planarchaos/Phantasmagorian.java | 31 ++++++++----------- .../sets/planarchaos/TemporalExtortion.java | 14 ++++++--- .../costs/common/DiscardTargetCost.java | 4 ++- 5 files changed, 44 insertions(+), 35 deletions(-) diff --git a/Mage.Sets/src/mage/sets/planarchaos/BrainGorgers.java b/Mage.Sets/src/mage/sets/planarchaos/BrainGorgers.java index 9ba3c089df..53fd0d565b 100644 --- a/Mage.Sets/src/mage/sets/planarchaos/BrainGorgers.java +++ b/Mage.Sets/src/mage/sets/planarchaos/BrainGorgers.java @@ -29,6 +29,7 @@ package mage.sets.planarchaos; import java.util.UUID; import mage.MageInt; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.mana.ManaCostsImpl; @@ -92,23 +93,26 @@ class BrainGorgersCounterSourceEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Spell spell = game.getStack().getSpell(source.getSourceId()); - if (spell != null) { + MageObject sourceObject = source.getSourceObject(game); + if (sourceObject != null) { SacrificeTargetCost cost = new SacrificeTargetCost(new TargetControlledCreaturePermanent()); for (UUID playerId : game.getState().getPlayerList(source.getControllerId())) { cost.clearPaid(); Player player = game.getPlayer(playerId); if (cost.canPay(source, source.getSourceId(), player.getId(), game) - && player.chooseUse(outcome, "Sacrifice a creature to counter " + spell.getIdName() + "?", source, game)) { + && player.chooseUse(outcome, "Sacrifice a creature to counter " + sourceObject.getIdName() + "?", source, game)) { if (cost.pay(source, game, source.getSourceId(), player.getId(), false)) { - game.informPlayers(player.getLogName() + " sacrifices a creature to counter " + spell.getIdName() + "."); - game.getStack().counter(spell.getId(), source.getSourceId(), game); + game.informPlayers(player.getLogName() + " sacrifices a creature to counter " + sourceObject.getIdName() + "."); + Spell spell = game.getStack().getSpell(source.getSourceId()); + if (spell != null) { + game.getStack().counter(spell.getId(), source.getSourceId(), game); + } } } } return true; } return false; - } + } } diff --git a/Mage.Sets/src/mage/sets/planarchaos/DashHopes.java b/Mage.Sets/src/mage/sets/planarchaos/DashHopes.java index 561fbbc9e8..d061e582a9 100644 --- a/Mage.Sets/src/mage/sets/planarchaos/DashHopes.java +++ b/Mage.Sets/src/mage/sets/planarchaos/DashHopes.java @@ -28,6 +28,7 @@ package mage.sets.planarchaos; import java.util.UUID; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.costs.common.PayLifeCost; import mage.abilities.effects.OneShotEffect; @@ -88,17 +89,20 @@ class DashHopesCounterSourceEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Spell spell = game.getStack().getSpell(source.getSourceId()); - if (spell != null) { + MageObject sourceObject = source.getSourceObject(game); + if (sourceObject != null) { PayLifeCost cost = new PayLifeCost(5); for (UUID playerId : game.getState().getPlayerList(source.getControllerId())) { Player player = game.getPlayer(playerId); cost.clearPaid(); if (cost.canPay(source, source.getSourceId(), player.getId(), game) - && player.chooseUse(outcome, "Pay 5 life to counter " + spell.getIdName() + "?", source, game)) { + && player.chooseUse(outcome, "Pay 5 life to counter " + sourceObject.getIdName() + "?", source, game)) { if (cost.pay(source, game, source.getSourceId(), player.getId(), false)) { - game.informPlayers(player.getLogName() + " pays 5 life to counter " + spell.getIdName() + "."); - game.getStack().counter(spell.getId(), source.getSourceId(), game); + game.informPlayers(player.getLogName() + " pays 5 life to counter " + sourceObject.getIdName() + "."); + Spell spell = game.getStack().getSpell(source.getSourceId()); + if (spell != null) { + game.getStack().counter(spell.getId(), source.getSourceId(), game); + } } } } diff --git a/Mage.Sets/src/mage/sets/planarchaos/Phantasmagorian.java b/Mage.Sets/src/mage/sets/planarchaos/Phantasmagorian.java index 966f1d2a12..31778c3669 100644 --- a/Mage.Sets/src/mage/sets/planarchaos/Phantasmagorian.java +++ b/Mage.Sets/src/mage/sets/planarchaos/Phantasmagorian.java @@ -29,6 +29,7 @@ package mage.sets.planarchaos; import java.util.UUID; import mage.MageInt; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.common.SimpleActivatedAbility; @@ -44,7 +45,6 @@ import mage.constants.Zone; import mage.filter.FilterCard; import mage.game.Game; import mage.game.stack.Spell; -import mage.game.stack.StackObject; import mage.players.Player; import mage.target.common.TargetCardInHand; @@ -81,7 +81,7 @@ public class Phantasmagorian extends CardImpl { class CounterSourceEffect extends OneShotEffect { public CounterSourceEffect() { - super(Outcome.Detriment); + super(Outcome.AIDontUseIt); } public CounterSourceEffect(final CounterSourceEffect effect) { @@ -95,25 +95,20 @@ class CounterSourceEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - - StackObject spell = null; - for (StackObject objet : game.getStack()) { - if (objet instanceof Spell && objet.getSourceId().equals(source.getSourceId())) { - spell = objet; - } - } - if (spell != null) { + MageObject sourceObject = source.getSourceObject(game); + if (sourceObject != null) { DiscardTargetCost cost = new DiscardTargetCost(new TargetCardInHand(3, 3, new FilterCard())); - for (UUID uuid : game.getPlayerList()) { - Player player = game.getPlayer(uuid); + for (UUID playerId : game.getState().getPlayerList(source.getControllerId())) { + Player player = game.getPlayer(playerId); cost.clearPaid(); if (cost.canPay(source, source.getSourceId(), player.getId(), game) - && player.chooseUse(Outcome.Detriment, "Discard three cards to counter " + spell.getName() + "?", source, game)) { - - if (cost.pay(source, game, source.getSourceId(), uuid, false)) { - game.informPlayers(player.getLogName() + " discards 3 cards to counter " + spell.getName() + "."); - game.getStack().counter(spell.getId(), source.getSourceId(), game); - return true; + && player.chooseUse(outcome, "Discard three cards to counter " + sourceObject.getIdName() + "?", source, game)) { + if (cost.pay(source, game, source.getSourceId(), playerId, false)) { + game.informPlayers(player.getLogName() + " discards 3 cards to counter " + sourceObject.getIdName() + "."); + Spell spell = game.getStack().getSpell(source.getSourceId()); + if (spell != null) { + game.getStack().counter(spell.getId(), source.getSourceId(), game); + } } } } diff --git a/Mage.Sets/src/mage/sets/planarchaos/TemporalExtortion.java b/Mage.Sets/src/mage/sets/planarchaos/TemporalExtortion.java index ea806b6198..c1a25134a5 100644 --- a/Mage.Sets/src/mage/sets/planarchaos/TemporalExtortion.java +++ b/Mage.Sets/src/mage/sets/planarchaos/TemporalExtortion.java @@ -28,6 +28,7 @@ package mage.sets.planarchaos; import java.util.UUID; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CastSourceTriggeredAbility; @@ -85,15 +86,18 @@ class TemporalExtortionCounterSourceEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Spell spell = game.getStack().getSpell(source.getSourceId()); - if (spell != null) { + MageObject sourceObject = source.getSourceObject(game); + if (sourceObject != null) { for (UUID playerId : game.getState().getPlayerList(source.getControllerId())) { Player player = game.getPlayer(playerId); - if (player.chooseUse(outcome, "Pay half your life, rounded up to counter " + spell.getIdName() + "?", source, game)) { + if (player.chooseUse(outcome, "Pay half your life, rounded up to counter " + sourceObject.getIdName() + "?", source, game)) { Integer amount = (int) Math.ceil(player.getLife() / 2f); player.loseLife(amount, game); - game.informPlayers(player.getLogName() + " pays half his or her life, rounded up to counter " + spell.getIdName() + "."); - game.getStack().counter(spell.getId(), source.getSourceId(), game); + game.informPlayers(player.getLogName() + " pays half his or her life, rounded up to counter " + sourceObject.getIdName() + "."); + Spell spell = game.getStack().getSpell(source.getSourceId()); + if (spell != null) { + game.getStack().counter(spell.getId(), source.getSourceId(), game); + } } } return true; diff --git a/Mage/src/mage/abilities/costs/common/DiscardTargetCost.java b/Mage/src/mage/abilities/costs/common/DiscardTargetCost.java index 3cb460452a..5ba87b8191 100644 --- a/Mage/src/mage/abilities/costs/common/DiscardTargetCost.java +++ b/Mage/src/mage/abilities/costs/common/DiscardTargetCost.java @@ -68,6 +68,7 @@ public class DiscardTargetCost extends CostImpl { @Override public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { this.cards.clear(); + this.targets.clear(); Player player = game.getPlayer(controllerId); if (player == null) { return false; @@ -94,7 +95,8 @@ public class DiscardTargetCost extends CostImpl { @Override public void clearPaid() { super.clearPaid(); - cards.clear(); + this.cards.clear(); + this.targets.clear(); } @Override From 3d66f662ec5db0d64543ef68e16fea4190cec704 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 13 Oct 2015 23:34:03 +0200 Subject: [PATCH 23/46] * Fixed possible null pointer exception of DiesAttachedTriggerAbility. --- .../src/mage/sets/conflux/MartialCoup.java | 71 ++++++++++--------- .../common/DiesAttachedTriggeredAbility.java | 3 +- 2 files changed, 39 insertions(+), 35 deletions(-) diff --git a/Mage.Sets/src/mage/sets/conflux/MartialCoup.java b/Mage.Sets/src/mage/sets/conflux/MartialCoup.java index 3344214c17..2b85632523 100644 --- a/Mage.Sets/src/mage/sets/conflux/MartialCoup.java +++ b/Mage.Sets/src/mage/sets/conflux/MartialCoup.java @@ -1,46 +1,45 @@ /* -* 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. -*/ - + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ package mage.sets.conflux; +import java.util.List; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Rarity; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.token.SoldierToken; - /** * * @author BetaSteward_at_googlemail.com @@ -51,6 +50,7 @@ public class MartialCoup extends CardImpl { super(ownerId, 11, "Martial Coup", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{X}{W}{W}"); this.expansionSetCode = "CON"; + // Put X 1/1 white Soldier creature tokens onto the battlefield. If X is 5 or more, destroy all other creatures. this.getSpellAbility().addEffect(new MartialCoupEffect()); } @@ -85,12 +85,15 @@ class MartialCoupEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { int amount = source.getManaCostsToPay().getX(); + token.putOntoBattlefield(amount, game, source.getSourceId(), source.getControllerId()); + List tokens = token.getLastAddedTokenIds(); if (amount > 4) { - for (Permanent permanent: game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), game)) { - permanent.destroy(source.getSourceId(), game, false); + for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), game)) { + if (!tokens.contains(permanent.getId())) { + permanent.destroy(source.getSourceId(), game, false); + } } } - token.putOntoBattlefield(amount, game, source.getSourceId(), source.getControllerId()); return true; } diff --git a/Mage/src/mage/abilities/common/DiesAttachedTriggeredAbility.java b/Mage/src/mage/abilities/common/DiesAttachedTriggeredAbility.java index e22e9c5674..70113a4564 100644 --- a/Mage/src/mage/abilities/common/DiesAttachedTriggeredAbility.java +++ b/Mage/src/mage/abilities/common/DiesAttachedTriggeredAbility.java @@ -59,7 +59,8 @@ public class DiesAttachedTriggeredAbility extends TriggeredAbilityImpl { // If both (attachment and attached went to graveyard at the same time, the attachemnets can be already removed from the attached object.) // So check here with the LKI of the enchantment Permanent attachment = game.getPermanentOrLKIBattlefield(getSourceId()); - if (attachment != null && attachment.getAttachedTo().equals(zEvent.getTargetId()) + if (attachment != null + && zEvent.getTargetId().equals(attachment.getAttachedTo()) && attachment.getAttachedToZoneChangeCounter() == zEvent.getTarget().getZoneChangeCounter(game) - 1) { triggered = true; } From c8ba5fc50ac06d343374e2fdad0783b2c54bedd2 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 14 Oct 2015 00:13:57 +0200 Subject: [PATCH 24/46] * Blinding Powder - Fixed check for source object. --- .../betrayersofkamigawa/BlindingPowder.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/Mage.Sets/src/mage/sets/betrayersofkamigawa/BlindingPowder.java b/Mage.Sets/src/mage/sets/betrayersofkamigawa/BlindingPowder.java index d1030fbd9c..727a67b0c6 100644 --- a/Mage.Sets/src/mage/sets/betrayersofkamigawa/BlindingPowder.java +++ b/Mage.Sets/src/mage/sets/betrayersofkamigawa/BlindingPowder.java @@ -61,7 +61,7 @@ public class BlindingPowder extends CardImpl { // Equipped creature has "Unattach Blinding Powder: Prevent all combat damage that would be dealt to this creature this turn." Effect effect = new PreventCombatDamageToSourceEffect(Duration.EndOfTurn); effect.setText("Prevent all combat damage that would be dealt to this creature this turn"); - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new BlindingPowderUnattachCost()); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new BlindingPowderUnattachCost(getName(), getId())); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(ability, AttachmentType.EQUIPMENT, Duration.WhileOnBattlefield))); // Equip {2} this.addAbility(new EquipAbility(Outcome.PreventDamage, new GenericManaCost(2))); @@ -79,28 +79,32 @@ public class BlindingPowder extends CardImpl { class BlindingPowderUnattachCost extends CostImpl { - public BlindingPowderUnattachCost() { - this.text = "Unattach Blinding Powder"; + protected UUID sourceEquipmentId; + + public BlindingPowderUnattachCost(String name, UUID sourceId) { + this.text = "Unattach " + name; + this.sourceEquipmentId = sourceId; } public BlindingPowderUnattachCost(final BlindingPowderUnattachCost cost) { super(cost); + this.sourceEquipmentId = cost.sourceEquipmentId; } @Override public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { Permanent permanent = game.getPermanent(sourceId); if (permanent != null) { - for (UUID attachmentId :permanent.getAttachments()) { + for (UUID attachmentId : permanent.getAttachments()) { Permanent attachment = game.getPermanent(attachmentId); - if (attachment != null && attachment.getName().equals("Blinding Powder")) { + if (attachment != null && attachment.getId().equals(sourceEquipmentId)) { paid = permanent.removeAttachment(attachmentId, game); if (paid) { break; } } } - + } return paid; } @@ -109,9 +113,9 @@ class BlindingPowderUnattachCost extends CostImpl { public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { Permanent permanent = game.getPermanent(sourceId); if (permanent != null) { - for (UUID attachmentId :permanent.getAttachments()) { + for (UUID attachmentId : permanent.getAttachments()) { Permanent attachment = game.getPermanent(attachmentId); - if (attachment != null && attachment.getName().equals("Blinding Powder")) { + if (attachment != null && attachment.getId().equals(sourceEquipmentId)) { return true; } } From 2c01d86fc0f8baee6838039bfe390c3eda466401 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 14 Oct 2015 08:30:29 +0200 Subject: [PATCH 25/46] * Some fixed to card movement. --- ...LeaveReturnExiledToBattlefieldAbility.java | 19 ++++--------------- .../ReturnFromExileForSourceEffect.java | 12 +----------- Mage/src/mage/players/Player.java | 3 ++- Mage/src/mage/players/PlayerImpl.java | 8 +------- 4 files changed, 8 insertions(+), 34 deletions(-) diff --git a/Mage/src/mage/abilities/common/delayed/OnLeaveReturnExiledToBattlefieldAbility.java b/Mage/src/mage/abilities/common/delayed/OnLeaveReturnExiledToBattlefieldAbility.java index 62e9404457..e632bc96f7 100644 --- a/Mage/src/mage/abilities/common/delayed/OnLeaveReturnExiledToBattlefieldAbility.java +++ b/Mage/src/mage/abilities/common/delayed/OnLeaveReturnExiledToBattlefieldAbility.java @@ -27,13 +27,12 @@ */ package mage.abilities.common.delayed; -import java.util.LinkedList; +import java.util.LinkedHashSet; import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; import mage.abilities.effects.OneShotEffect; -import mage.cards.Card; import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.Zone; @@ -50,9 +49,9 @@ import mage.util.CardUtil; * Returns the exiled cards/permanents as source leaves battlefield * * Uses no stack + * * @author LevelX2 */ - public class OnLeaveReturnExiledToBattlefieldAbility extends DelayedTriggeredAbility { public OnLeaveReturnExiledToBattlefieldAbility() { @@ -108,22 +107,12 @@ 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; + int zoneChangeCounter = (sourceObject instanceof PermanentToken) ? source.getSourceObjectZoneChangeCounter() : source.getSourceObjectZoneChangeCounter() - 1; UUID exileZone = CardUtil.getExileZoneId(game, source.getSourceId(), zoneChangeCounter); if (exileZone != null) { ExileZone exile = game.getExile().getExileZone(exileZone); if (exile != null) { - LinkedList cards = new LinkedList<>(exile); - for (UUID cardId : cards) { - Card card = game.getCard(cardId); - if (card != null) { - Player owner = game.getPlayer(card.getOwnerId()); - if (owner != null && owner.isInGame()) { - owner.putOntoBattlefieldWithInfo(card, game, Zone.EXILED, source.getSourceId()); - } - } - } - exile.clear(); + controller.moveCards(new LinkedHashSet<>(exile.getCards(game)), Zone.EXILED, source, game, false, false, true, null); } return true; } diff --git a/Mage/src/mage/abilities/effects/common/ReturnFromExileForSourceEffect.java b/Mage/src/mage/abilities/effects/common/ReturnFromExileForSourceEffect.java index 181bb35f94..8d7b8a7c2b 100644 --- a/Mage/src/mage/abilities/effects/common/ReturnFromExileForSourceEffect.java +++ b/Mage/src/mage/abilities/effects/common/ReturnFromExileForSourceEffect.java @@ -30,7 +30,6 @@ package mage.abilities.effects.common; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; -import mage.cards.Card; import mage.constants.Outcome; import mage.constants.Zone; import static mage.constants.Zone.BATTLEFIELD; @@ -102,16 +101,7 @@ public class ReturnFromExileForSourceEffect extends OneShotEffect { } ExileZone exile = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source.getSourceId(), zoneChangeCounter)); if (exile != null) { // null is valid if source left battlefield before enters the battlefield effect resolved - if (returnToZone.equals(Zone.BATTLEFIELD)) { - for (Card card : exile.getCards(game)) { - Player owner = game.getPlayer(card.getOwnerId()); - if (owner != null) { - owner.putOntoBattlefieldWithInfo(card, game, Zone.EXILED, source.getSourceId()); - } - } - } else { - controller.moveCards(exile, Zone.EXILED, returnToZone, source, game); - } + controller.moveCards(exile, null, returnToZone, source, game); } return true; } diff --git a/Mage/src/mage/players/Player.java b/Mage/src/mage/players/Player.java index fe56815b05..d00471867c 100644 --- a/Mage/src/mage/players/Player.java +++ b/Mage/src/mage/players/Player.java @@ -644,7 +644,8 @@ public interface Player extends MageItem, Copyable { * @param tapped tha cards are tapped on the battlefield * @param faceDown the cards are face down in the to zone * @param byOwner the card is moved (or put onto battlefield) by the owner - * of the card (instead of the controller of the source) + * of the card and if target zone is battlefield controlls the permanent + * (instead of the controller of the source) * @return */ boolean moveCards(Set cards, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, ArrayList appliedEffects); diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index f1efe5d330..49e8ffb656 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -3015,13 +3015,7 @@ public abstract class PlayerImpl implements Player, Serializable { } break; case BATTLEFIELD: - for (Card card : cards) { - fromZone = game.getState().getZone(card.getId()); - if (putOntoBattlefieldWithInfo(card, game, fromZone, source == null ? null : source.getSourceId(), false, card.isFaceDown(game))) { - successfulMovedCards.add(card); - } - } - break; + return moveCards(cards, toZone, source, game, false, false, false, null); case LIBRARY: for (Card card : cards) { fromZone = game.getState().getZone(card.getId()); From 8d8607d14318100126a6b3f637c1146ab5ba6526 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 14 Oct 2015 14:23:13 +0200 Subject: [PATCH 26/46] Fixed wrong target zone. --- .../common/delayed/OnLeaveReturnExiledToBattlefieldAbility.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage/src/mage/abilities/common/delayed/OnLeaveReturnExiledToBattlefieldAbility.java b/Mage/src/mage/abilities/common/delayed/OnLeaveReturnExiledToBattlefieldAbility.java index e632bc96f7..3d61104c9a 100644 --- a/Mage/src/mage/abilities/common/delayed/OnLeaveReturnExiledToBattlefieldAbility.java +++ b/Mage/src/mage/abilities/common/delayed/OnLeaveReturnExiledToBattlefieldAbility.java @@ -112,7 +112,7 @@ class ReturnExiledPermanentsEffect extends OneShotEffect { if (exileZone != null) { ExileZone exile = game.getExile().getExileZone(exileZone); if (exile != null) { - controller.moveCards(new LinkedHashSet<>(exile.getCards(game)), Zone.EXILED, source, game, false, false, true, null); + controller.moveCards(new LinkedHashSet<>(exile.getCards(game)), Zone.BATTLEFIELD, source, game, false, false, true, null); } return true; } From e3b45629db030df3d19b1b3066288e204689e8a0 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 14 Oct 2015 17:54:55 +0200 Subject: [PATCH 27/46] Fixed some problems with UUID comparing and some problems with card moving. --- .gitignore | 7 +- Mage.Common/src/mage/view/GameView.java | 2 +- .../mage/sets/alarareborn/Thraximundar.java | 8 +- .../mage/sets/apocalypse/DesolationAngel.java | 14 +-- .../UlamogTheCeaselessHunger.java | 22 ++-- .../sets/bornofthegods/SpitefulReturned.java | 5 +- .../HallOfTheBanditLord.java | 31 ++--- .../championsofkamigawa/NightDealings.java | 27 ++--- .../championsofkamigawa/SiftThroughSands.java | 8 +- .../mage/sets/coldsnap/HibernationsEnd.java | 7 +- .../sets/commander/ChorusOfTheConclave.java | 2 +- .../sets/commander2013/RubiniaSoulsinger.java | 6 +- .../sets/commander2014/InfernalOffering.java | 21 ++-- .../src/mage/sets/darksteel/LichsTomb.java | 14 +-- .../src/mage/sets/eventide/DreamThief.java | 7 +- .../mage/sets/eventide/EndlessHorizons.java | 50 +++++---- .../mage/sets/eventide/HotheadedGiant.java | 7 +- .../src/mage/sets/eventide/SoulReap.java | 16 ++- .../mage/sets/eventide/TalarasBattalion.java | 3 +- .../mage/sets/exodus/SoltariVisionary.java | 2 +- .../sets/fatereforged/MarduWoeReaper.java | 10 +- .../sets/fatereforged/WardscaleDragon.java | 7 +- .../mage/sets/fifthedition/InstillEnergy.java | 3 +- .../src/mage/sets/limitedalpha/Fastbond.java | 14 +-- .../mage/sets/magic2015/GeneratorServant.java | 20 ++-- .../mage/sets/magicorigins/SigilOfValor.java | 4 +- .../sets/masterseditionii/ThoughtLash.java | 26 ++--- .../src/mage/sets/planeshift/OrimsChant.java | 60 +++++----- .../sets/returntoravnica/VraskaTheUnseen.java | 16 ++- .../sets/scarsofmirrodin/RevokeExistence.java | 14 +-- .../mage/sets/shadowmoor/MossbridgeTroll.java | 14 +-- .../sets/shadowmoor/ThoughtweftGambit.java | 3 +- .../sets/shardsofalara/GatherSpecimens.java | 6 +- .../mage/sets/tempest/HelmOfPossession.java | 10 +- .../mage/sets/worldwake/TuktukScrapper.java | 2 +- .../sets/worldwake/WrexialTheRisenDeep.java | 28 ++--- .../test/cards/triggers/OblivionRingTest.java | 4 + .../common/EntersBattlefieldAbility.java | 90 ++++++++------- .../costs/common/DiscardTargetCost.java | 2 +- .../abilities/effects/ContinuousEffects.java | 4 +- .../ReturnFromExileForSourceEffect.java | 6 +- .../abilities/keyword/ReboundAbility.java | 106 +++++++++--------- Mage/src/mage/cards/CardImpl.java | 9 +- Mage/src/mage/game/Exile.java | 5 +- Mage/src/mage/players/PlayerImpl.java | 2 +- 45 files changed, 364 insertions(+), 360 deletions(-) diff --git a/.gitignore b/.gitignore index b129f38e3c..ca85c84005 100644 --- a/.gitignore +++ b/.gitignore @@ -50,7 +50,7 @@ Mage.Updater/target mage.updater.client/target releases -Utils/author.txt +Utils/author.txt .DS_Store .metadata .project @@ -88,5 +88,6 @@ Mage.Server.Plugins/Mage.Draft.8PlayerBooster/target /Utils/*_unimplemented.txt *.netbeans_automatic_build *.txt -Mage.Client/serverlist.txt -/bin/ +Mage.Client/serverlist.txt +/bin/ +/target/ \ No newline at end of file diff --git a/Mage.Common/src/mage/view/GameView.java b/Mage.Common/src/mage/view/GameView.java index 80ce4867c5..15731967b2 100644 --- a/Mage.Common/src/mage/view/GameView.java +++ b/Mage.Common/src/mage/view/GameView.java @@ -184,7 +184,7 @@ public class GameView implements Serializable { } if (isPlayer) { // has only to be set for active palyer with priority (e.g. pay mana by delve or Quenchable Fire special action) - if (state.getPriorityPlayerId() == createdForPlayerId && createdForPlayer != null) { + if (createdForPlayer != null && createdForPlayerId.equals(state.getPriorityPlayerId())) { this.special = state.getSpecialActions().getControlledBy(state.getPriorityPlayerId(), createdForPlayer.isInPayManaMode()).size() > 0; } } else { diff --git a/Mage.Sets/src/mage/sets/alarareborn/Thraximundar.java b/Mage.Sets/src/mage/sets/alarareborn/Thraximundar.java index 9fe05560f0..08898a2dcc 100644 --- a/Mage.Sets/src/mage/sets/alarareborn/Thraximundar.java +++ b/Mage.Sets/src/mage/sets/alarareborn/Thraximundar.java @@ -60,9 +60,6 @@ public class Thraximundar extends CardImpl { this.subtype.add("Zombie"); this.subtype.add("Assassin"); - - - this.power = new MageInt(6); this.toughness = new MageInt(6); @@ -116,7 +113,8 @@ class ThraximundarTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (event.getSourceId() == this.getSourceId()) { + if (event.getSourceId() != null + && event.getSourceId().equals(this.getSourceId())) { UUID defender = game.getCombat().getDefendingPlayerId(this.getSourceId(), game); this.getEffects().get(0).setTargetPointer(new FixedTarget(defender)); return true; @@ -160,4 +158,4 @@ class PlayerSacrificesCreatureTriggeredAbility extends TriggeredAbilityImpl { public PlayerSacrificesCreatureTriggeredAbility copy() { return new PlayerSacrificesCreatureTriggeredAbility(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/apocalypse/DesolationAngel.java b/Mage.Sets/src/mage/sets/apocalypse/DesolationAngel.java index 4c32f5136e..dd1b5db3a3 100644 --- a/Mage.Sets/src/mage/sets/apocalypse/DesolationAngel.java +++ b/Mage.Sets/src/mage/sets/apocalypse/DesolationAngel.java @@ -25,13 +25,9 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.sets.apocalypse; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Rarity; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -41,6 +37,9 @@ import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.KickerAbility; import mage.cards.Card; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; import mage.filter.common.FilterLandPermanent; import mage.game.Game; import mage.game.permanent.Permanent; @@ -79,6 +78,7 @@ public class DesolationAngel extends CardImpl { } class DesolationAngelEntersBattlefieldEffect extends OneShotEffect { + DesolationAngelEntersBattlefieldEffect() { super(Outcome.DestroyPermanent); staticText = "destroy all lands you control. If it was kicked, destroy all lands instead"; @@ -93,8 +93,8 @@ class DesolationAngelEntersBattlefieldEffect extends OneShotEffect { Card p = game.getCard(source.getSourceId()); boolean kicked = KickedCondition.getInstance().apply(game, source); for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterLandPermanent(), source.getControllerId(), source.getSourceId(), game)) { - if ((!kicked && permanent.getControllerId() == source.getControllerId()) - || kicked) { + if ((!kicked && permanent.getControllerId().equals(source.getControllerId())) + || kicked) { permanent.destroy(source.getSourceId(), game, false); } } @@ -106,4 +106,4 @@ class DesolationAngelEntersBattlefieldEffect extends OneShotEffect { return new DesolationAngelEntersBattlefieldEffect(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/UlamogTheCeaselessHunger.java b/Mage.Sets/src/mage/sets/battleforzendikar/UlamogTheCeaselessHunger.java index 5b6d8c45eb..038df1a77e 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/UlamogTheCeaselessHunger.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/UlamogTheCeaselessHunger.java @@ -67,10 +67,10 @@ public class UlamogTheCeaselessHunger extends CardImpl { // When you cast Ulamog, the Ceaseless Hunger, exile two target permanents. this.addAbility(new UlamogExilePermanentsOnCastAbility()); - + // Indestructible this.addAbility(IndestructibleAbility.getInstance()); - + // Whenever Ulamog attacks, defending player exiles the top twenty cards of his or her library. Effect effect = new UlamogExileLibraryEffect(); effect.setText("defending player exiles the top twenty cards of his or her library"); @@ -139,18 +139,20 @@ class UlamogAttackTriggeredAbility extends TriggeredAbilityImpl { public boolean checkEventType(GameEvent event, Game game) { return event.getType() == EventType.ATTACKER_DECLARED; } - + @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent sourcePermanent = game.getPermanent(this.getSourceId()); - if (sourcePermanent != null && event.getSourceId() == this.getSourceId()) { + if (sourcePermanent != null + && event.getSourceId() != null + && event.getSourceId().equals(this.getSourceId())) { UUID defender = game.getCombat().getDefendingPlayerId(this.getSourceId(), game); this.getEffects().get(0).setTargetPointer(new FixedTarget(defender)); return true; - } - return false; } - + return false; + } + @Override public String getRule() { return new StringBuilder("Whenever {this} attacks, ").append(super.getRule()).toString(); @@ -184,8 +186,8 @@ class UlamogExileLibraryEffect extends OneShotEffect { card.moveToExile(null, null, source.getSourceId(), game); } } - return true; + return true; } - return false; + return false; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/bornofthegods/SpitefulReturned.java b/Mage.Sets/src/mage/sets/bornofthegods/SpitefulReturned.java index 3f132ca507..93a3d82a41 100644 --- a/Mage.Sets/src/mage/sets/bornofthegods/SpitefulReturned.java +++ b/Mage.Sets/src/mage/sets/bornofthegods/SpitefulReturned.java @@ -67,7 +67,7 @@ public class SpitefulReturned extends CardImpl { effect.setText("defending player loses 2 life"); this.addAbility(new SpitefulReturnedTriggeredAbility(effect)); // Enchanted creature gets +1/+1. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(1,1, Duration.WhileOnBattlefield))); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(1, 1, Duration.WhileOnBattlefield))); } public SpitefulReturned(final SpitefulReturned card) { @@ -105,7 +105,8 @@ class SpitefulReturnedTriggeredAbility extends TriggeredAbilityImpl { Permanent sourcePermanent = game.getPermanent(this.getSourceId()); if (sourcePermanent != null) { if (sourcePermanent.getCardType().contains(CardType.CREATURE)) { - if (event.getSourceId() == this.getSourceId()) { + if (event.getSourceId() != null + && event.getSourceId().equals(this.getSourceId())) { UUID defender = game.getCombat().getDefendingPlayerId(this.getSourceId(), game); this.getEffects().get(0).setTargetPointer(new FixedTarget(defender)); return true; diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/HallOfTheBanditLord.java b/Mage.Sets/src/mage/sets/championsofkamigawa/HallOfTheBanditLord.java index b07a580697..a23e783906 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/HallOfTheBanditLord.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/HallOfTheBanditLord.java @@ -69,7 +69,7 @@ public class HallOfTheBanditLord extends CardImpl { // Hall of the Bandit Lord enters the battlefield tapped. this.addAbility(new EntersBattlefieldTappedAbility()); - + // {T}, Pay 3 life: Add {1} to your mana pool. If that mana is spent on a creature spell, it gains haste. Mana mana = Mana.ColorlessMana; mana.setFlag(true); @@ -94,12 +94,12 @@ class HallOfTheBanditLordWatcher extends Watcher { private final Ability source; private final List creatures = new ArrayList<>(); - + HallOfTheBanditLordWatcher(Ability source) { super("HallOfTheBanditLordWatcher", WatcherScope.CARD); this.source = source; } - + HallOfTheBanditLordWatcher(final HallOfTheBanditLordWatcher watcher) { super(watcher); this.creatures.addAll(watcher.creatures); @@ -110,22 +110,25 @@ class HallOfTheBanditLordWatcher extends Watcher { public HallOfTheBanditLordWatcher copy() { return new HallOfTheBanditLordWatcher(this); } - + @Override public void watch(GameEvent event, Game game) { if (event.getType() == EventType.MANA_PAYED) { MageObject target = game.getObject(event.getTargetId()); - if (event.getSourceId() == this.getSourceId() && target != null && target.getCardType().contains(CardType.CREATURE) && event.getFlag()) { + if (event.getSourceId() != null + && event.getSourceId().equals(this.getSourceId()) + && target != null && target.getCardType().contains(CardType.CREATURE) + && event.getFlag()) { if (target instanceof Spell) { this.creatures.add(((Spell) target).getCard().getId()); } } } if (event.getType() == EventType.COUNTERED) { - if (creatures.contains(event.getTargetId())) { + if (creatures.contains(event.getTargetId())) { creatures.remove(event.getSourceId()); - } - } + } + } if (event.getType() == EventType.ZONE_CHANGE) { if (creatures.contains(event.getSourceId())) { ZoneChangeEvent zEvent = (ZoneChangeEvent) event; @@ -133,22 +136,22 @@ class HallOfTheBanditLordWatcher extends Watcher { if (zEvent.getToZone() == Zone.STACK) { creatures.remove(event.getSourceId()); } - } - } + } + } if (event.getType() == EventType.ENTERS_THE_BATTLEFIELD) { - if (creatures.contains(event.getSourceId())) { + if (creatures.contains(event.getSourceId())) { ContinuousEffect effect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.Custom); effect.setTargetPointer(new FixedTarget(event.getSourceId())); game.addEffect(effect, source); creatures.remove(event.getSourceId()); - } + } } } - + @Override public void reset() { super.reset(); creatures.clear(); } - + } diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/NightDealings.java b/Mage.Sets/src/mage/sets/championsofkamigawa/NightDealings.java index 2a9ee7434d..79ca6d3680 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/NightDealings.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/NightDealings.java @@ -25,14 +25,9 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.sets.championsofkamigawa; import java.util.UUID; - -import mage.constants.CardType; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.SimpleActivatedAbility; @@ -44,7 +39,10 @@ import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.Cards; import mage.cards.CardsImpl; +import mage.constants.CardType; import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.Filter; import mage.filter.common.FilterNonlandCard; @@ -61,7 +59,7 @@ import mage.target.common.TargetCardInLibrary; */ public class NightDealings extends CardImpl { - public NightDealings (UUID ownerId) { + public NightDealings(UUID ownerId) { super(ownerId, 132, "Night Dealings", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}{B}"); this.expansionSetCode = "CHK"; @@ -74,7 +72,7 @@ public class NightDealings extends CardImpl { this.addAbility(ability); } - public NightDealings (final NightDealings card) { + public NightDealings(final NightDealings card) { super(card); } @@ -83,7 +81,6 @@ public class NightDealings extends CardImpl { return new NightDealings(this); } - private class NightDealingsTriggeredAbility extends TriggeredAbilityImpl { public NightDealingsTriggeredAbility() { @@ -106,17 +103,17 @@ public class NightDealings extends CardImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - // to another player + // to another player if (this.getControllerId() != event.getTargetId()) { // a source you control UUID sourceControllerId = game.getControllerId(event.getSourceId()); - if (sourceControllerId != null && sourceControllerId == this.getControllerId()) { + if (sourceControllerId != null && sourceControllerId.equals(this.getControllerId())) { // save amount of damage to effect this.getEffects().get(0).setValue("damageAmount", event.getAmount()); return true; } } - return false; + return false; } @Override @@ -181,9 +178,9 @@ public class NightDealings extends CardImpl { int cmc = 0; for (Cost cost : source.getCosts()) { if (cost instanceof RemoveVariableCountersSourceCost) { - cmc = ((RemoveVariableCountersSourceCost)cost).getAmount(); + cmc = ((RemoveVariableCountersSourceCost) cost).getAmount(); } - } + } FilterNonlandCard filter = new FilterNonlandCard("nonland card with converted mana cost X = " + cmc); filter.add(new ConvertedManaCostPredicate(Filter.ComparisonType.Equal, cmc)); @@ -192,8 +189,8 @@ public class NightDealings extends CardImpl { if (player.searchLibrary(target, game)) { Card card = player.getLibrary().getCard(target.getFirstTarget(), game); if (card != null) { - card.moveToZone(Zone.HAND, source.getSourceId(), game, false); - + card.moveToZone(Zone.HAND, source.getSourceId(), game, false); + String name = "Reveal"; Cards cards = new CardsImpl(); cards.add(card); diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/SiftThroughSands.java b/Mage.Sets/src/mage/sets/championsofkamigawa/SiftThroughSands.java index 58e84d068a..2e2206feef 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/SiftThroughSands.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/SiftThroughSands.java @@ -32,8 +32,8 @@ import mage.abilities.Ability; import mage.abilities.condition.Condition; import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.Effect; -import mage.abilities.effects.common.discard.DiscardControllerEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.discard.DiscardControllerEffect; import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; import mage.cards.CardImpl; import mage.constants.CardType; @@ -56,6 +56,7 @@ public class SiftThroughSands extends CardImpl { private static final String rule = "If you've cast a spell named Peer Through Depths and a spell named Reach Through Mists this turn, you may search your library for a card named The Unspeakable, put it onto the battlefield, then shuffle your library"; private static final FilterCreatureCard filter = new FilterCreatureCard("a card named The Unspeakable"); + static { filter.add(new NamePredicate("The Unspeakable")); } @@ -65,13 +66,12 @@ public class SiftThroughSands extends CardImpl { this.expansionSetCode = "CHK"; this.subtype.add("Arcane"); - // Draw two cards, then discard a card. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(2)); Effect effect = new DiscardControllerEffect(1); effect.setText(", then discard a card"); this.getSpellAbility().addEffect(effect); - + // If you've cast a spell named Peer Through Depths and a spell named Reach Through Mists this turn, you may search your library for a card named The Unspeakable, put it onto the battlefield, then shuffle your library. this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter), false, true), new SiftThroughSandsCondition(), rule)); this.getSpellAbility().addWatcher(new SiftThroughSandsWatcher()); @@ -125,7 +125,7 @@ class SiftThroughSandsWatcher extends Watcher { return; } if (event.getType() == EventType.SPELL_CAST - && controllerId == event.getPlayerId()) { + && controllerId.equals(event.getPlayerId())) { Spell spell = game.getStack().getSpell(event.getTargetId()); if (spell.getCard().getName().equals("Peer Through Depths")) { castPeerThroughDepths = true; diff --git a/Mage.Sets/src/mage/sets/coldsnap/HibernationsEnd.java b/Mage.Sets/src/mage/sets/coldsnap/HibernationsEnd.java index e62a91d9b3..09d46b4974 100644 --- a/Mage.Sets/src/mage/sets/coldsnap/HibernationsEnd.java +++ b/Mage.Sets/src/mage/sets/coldsnap/HibernationsEnd.java @@ -44,8 +44,8 @@ import mage.filter.FilterCard; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; import mage.game.Game; -import mage.game.events.GameEvent.EventType; import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCardInLibrary; @@ -98,7 +98,7 @@ class HibernationsEndAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - return event.getSourceId() == this.getSourceId(); + return event.getSourceId() != null && event.getSourceId().equals(this.getSourceId()); } @Override @@ -127,7 +127,7 @@ class HibernationsEndEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); - if(sourcePermanent != null && player != null) { + if (sourcePermanent != null && player != null) { int newConvertedCost = sourcePermanent.getCounters().getCount("age"); FilterCard filter = new FilterCard("creature card with converted mana cost " + newConvertedCost); filter.add(new ConvertedManaCostPredicate(Filter.ComparisonType.Equal, newConvertedCost)); @@ -138,4 +138,3 @@ class HibernationsEndEffect extends OneShotEffect { return false; } } - diff --git a/Mage.Sets/src/mage/sets/commander/ChorusOfTheConclave.java b/Mage.Sets/src/mage/sets/commander/ChorusOfTheConclave.java index 8377498150..70fc31b695 100644 --- a/Mage.Sets/src/mage/sets/commander/ChorusOfTheConclave.java +++ b/Mage.Sets/src/mage/sets/commander/ChorusOfTheConclave.java @@ -135,7 +135,7 @@ class ChorusOfTheConclaveReplacementEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getPlayerId() == source.getControllerId()) { + if (event.getPlayerId().equals(source.getControllerId())) { MageObject spellObject = game.getObject(event.getSourceId()); if (spellObject != null) { return spellObject.getCardType().contains(CardType.CREATURE); diff --git a/Mage.Sets/src/mage/sets/commander2013/RubiniaSoulsinger.java b/Mage.Sets/src/mage/sets/commander2013/RubiniaSoulsinger.java index 0580c020d3..26b8c62ebf 100644 --- a/Mage.Sets/src/mage/sets/commander2013/RubiniaSoulsinger.java +++ b/Mage.Sets/src/mage/sets/commander2013/RubiniaSoulsinger.java @@ -92,9 +92,9 @@ class RubiniaSoulsingerCondition implements Condition { controllerId = source.getControllerId(); } Permanent permanent = game.getBattlefield().getPermanent(source.getSourceId()); - if (permanent != null){ - if (permanent.isTapped()){ - return controllerId == source.getControllerId(); + if (permanent != null) { + if (permanent.isTapped()) { + return controllerId.equals(source.getControllerId()); } } return false; diff --git a/Mage.Sets/src/mage/sets/commander2014/InfernalOffering.java b/Mage.Sets/src/mage/sets/commander2014/InfernalOffering.java index f0bb1741ad..18a0fef42c 100644 --- a/Mage.Sets/src/mage/sets/commander2014/InfernalOffering.java +++ b/Mage.Sets/src/mage/sets/commander2014/InfernalOffering.java @@ -61,10 +61,9 @@ public class InfernalOffering extends CardImpl { super(ownerId, 24, "Infernal Offering", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{4}{B}"); this.expansionSetCode = "C14"; - // Choose an opponent. You and that player each sacrifice a creature. Each player who sacrificed a creature this way draws two cards. this.getSpellAbility().addEffect(new InfernalOfferingSacrificeEffect()); - + // Choose an opponent. Return a creature card from your graveyard to the battlefield, then that player returns a creature card from his or her graveyard to the battlefield. this.getSpellAbility().addEffect(new InfernalOfferingReturnEffect()); } @@ -80,21 +79,21 @@ public class InfernalOffering extends CardImpl { } class InfernalOfferingSacrificeEffect extends OneShotEffect { - + InfernalOfferingSacrificeEffect() { super(Outcome.Sacrifice); this.staticText = "Choose an opponent. You and that player each sacrifice a creature. Each player who sacrificed a creature this way draws two cards"; } - + InfernalOfferingSacrificeEffect(final InfernalOfferingSacrificeEffect effect) { super(effect); } - + @Override public InfernalOfferingSacrificeEffect copy() { return new InfernalOfferingSacrificeEffect(this); } - + @Override public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); @@ -106,7 +105,7 @@ class InfernalOfferingSacrificeEffect extends OneShotEffect { //Choose creatures to sacrifice Map toSacrifice = new HashMap<>(2); for (UUID playerId : player.getInRange()) { - if (playerId == player.getId() || playerId == opponent.getId()) { + if (playerId.equals(player.getId()) || playerId.equals(opponent.getId())) { target = new TargetControlledCreaturePermanent(1, 1, new FilterControlledCreaturePermanent(), true); if (target.choose(Outcome.Sacrifice, playerId, source.getControllerId(), game)) { toSacrifice.put(playerId, target.getFirstTarget()); @@ -138,21 +137,21 @@ class InfernalOfferingSacrificeEffect extends OneShotEffect { } class InfernalOfferingReturnEffect extends OneShotEffect { - + InfernalOfferingReturnEffect() { super(Outcome.PutCreatureInPlay); this.staticText = "Choose an opponent. Return a creature card from your graveyard to the battlefield, then that player returns a creature card from his or her graveyard to the battlefield"; } - + InfernalOfferingReturnEffect(final InfernalOfferingReturnEffect effect) { super(effect); } - + @Override public InfernalOfferingReturnEffect copy() { return new InfernalOfferingReturnEffect(this); } - + @Override public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); diff --git a/Mage.Sets/src/mage/sets/darksteel/LichsTomb.java b/Mage.Sets/src/mage/sets/darksteel/LichsTomb.java index 3ec918d011..33a0f45d56 100644 --- a/Mage.Sets/src/mage/sets/darksteel/LichsTomb.java +++ b/Mage.Sets/src/mage/sets/darksteel/LichsTomb.java @@ -56,7 +56,7 @@ public class LichsTomb extends CardImpl { // You don't lose the game for having 0 or less life. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new DontLoseByZeroOrLessLifeEffect(Duration.WhileOnBattlefield))); - + // Whenever you lose life, sacrifice a permanent for each 1 life you lost. this.addAbility(new LichsTombTriggeredAbility()); } @@ -72,15 +72,15 @@ public class LichsTomb extends CardImpl { } class LichsTombTriggeredAbility extends TriggeredAbilityImpl { - + LichsTombTriggeredAbility() { super(Zone.BATTLEFIELD, new SacrificeControllerEffect(new FilterPermanent(), 0, ""), false); } - + LichsTombTriggeredAbility(final LichsTombTriggeredAbility ability) { super(ability); } - + @Override public LichsTombTriggeredAbility copy() { return new LichsTombTriggeredAbility(this); @@ -90,16 +90,16 @@ class LichsTombTriggeredAbility extends TriggeredAbilityImpl { public boolean checkEventType(GameEvent event, Game game) { return event.getType() == EventType.LOST_LIFE; } - + @Override public boolean checkTrigger(GameEvent event, Game game) { - if (event.getPlayerId() == this.getControllerId()) { + if (event.getPlayerId().equals(this.getControllerId())) { ((SacrificeEffect) this.getEffects().get(0)).setAmount(new StaticValue(event.getAmount())); return true; } return false; } - + @Override public String getRule() { return "Whenever you lose life, sacrifice a permanent for each 1 life you lost."; diff --git a/Mage.Sets/src/mage/sets/eventide/DreamThief.java b/Mage.Sets/src/mage/sets/eventide/DreamThief.java index f0373c53cc..a3dc86a47d 100644 --- a/Mage.Sets/src/mage/sets/eventide/DreamThief.java +++ b/Mage.Sets/src/mage/sets/eventide/DreamThief.java @@ -53,7 +53,7 @@ import mage.watchers.Watcher; * @author jeffwadsworth */ public class DreamThief extends CardImpl { - + private static final String rule = "draw a card if you've cast another blue spell this turn"; public DreamThief(UUID ownerId) { @@ -70,7 +70,7 @@ public class DreamThief extends CardImpl { // When Dream Thief enters the battlefield, draw a card if you've cast another blue spell this turn. this.addAbility(new EntersBattlefieldTriggeredAbility(new ConditionalOneShotEffect(new DrawCardSourceControllerEffect(1), new CastBlueSpellThisTurnCondition(), rule)), new DreamThiefWatcher(this.getId())); - + } public DreamThief(final DreamThief card) { @@ -98,6 +98,7 @@ class CastBlueSpellThisTurnCondition implements Condition { class DreamThiefWatcher extends Watcher { private static final FilterSpell filter = new FilterSpell(); + static { filter.add(new ColorPredicate(ObjectColor.BLUE)); } @@ -125,7 +126,7 @@ class DreamThiefWatcher extends Watcher { return; } if (event.getType() == EventType.SPELL_CAST - && controllerId == event.getPlayerId()) { + && controllerId.equals(event.getPlayerId())) { Spell spell = game.getStack().getSpell(event.getTargetId()); if (!spell.getSourceId().equals(cardId) && filter.match(spell, game)) { condition = true; diff --git a/Mage.Sets/src/mage/sets/eventide/EndlessHorizons.java b/Mage.Sets/src/mage/sets/eventide/EndlessHorizons.java index 240c94a021..17af8a3fdc 100644 --- a/Mage.Sets/src/mage/sets/eventide/EndlessHorizons.java +++ b/Mage.Sets/src/mage/sets/eventide/EndlessHorizons.java @@ -40,11 +40,13 @@ import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.TargetController; import mage.constants.Zone; +import mage.filter.FilterCard; import mage.filter.common.FilterLandCard; import mage.filter.predicate.mageobject.SubtypePredicate; import mage.game.ExileZone; import mage.game.Game; import mage.players.Player; +import mage.target.TargetCard; import mage.target.common.TargetCardInLibrary; import mage.util.CardUtil; @@ -58,7 +60,6 @@ public class EndlessHorizons extends CardImpl { super(ownerId, 4, "Endless Horizons", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}"); this.expansionSetCode = "EVE"; - // When Endless Horizons enters the battlefield, search your library for any number of Plains cards and exile them. Then shuffle your library. this.addAbility(new EntersBattlefieldTriggeredAbility(new EndlessHorizonsEffect(), false)); @@ -122,34 +123,41 @@ class EndlessHorizonsEffect extends SearchEffect { } } - class EndlessHorizonsEffect2 extends OneShotEffect { +class EndlessHorizonsEffect2 extends OneShotEffect { - public EndlessHorizonsEffect2() { - super(Outcome.ReturnToHand); - this.staticText = "you may put a card you own exiled with {this} into your hand"; - } + public EndlessHorizonsEffect2() { + super(Outcome.ReturnToHand); + this.staticText = "you may put a card you own exiled with {this} into your hand"; + } - public EndlessHorizonsEffect2(final EndlessHorizonsEffect2 effect) { - super(effect); - } + public EndlessHorizonsEffect2(final EndlessHorizonsEffect2 effect) { + super(effect); + } - @Override - public EndlessHorizonsEffect2 copy() { - return new EndlessHorizonsEffect2(this); - } + @Override + public EndlessHorizonsEffect2 copy() { + return new EndlessHorizonsEffect2(this); + } - @Override - public boolean apply(Game game, Ability source) { + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { ExileZone exZone = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source)); if (exZone != null) { - for (Card card : exZone.getCards(game)) { - if (card.getOwnerId() == source.getControllerId()) { - card.moveToZone(Zone.HAND, source.getSourceId(), game, false); - break; // only one - } + Card card = null; + if (exZone.size() > 1) { + TargetCard target = new TargetCard(Zone.EXILED, new FilterCard()); + controller.choose(outcome, exZone, target, game); + card = game.getCard(target.getFirstTarget()); + } else { + card = exZone.getRandom(game); } + controller.moveCards(card, null, Zone.HAND, source, game); } return true; } - + return false; + } + } diff --git a/Mage.Sets/src/mage/sets/eventide/HotheadedGiant.java b/Mage.Sets/src/mage/sets/eventide/HotheadedGiant.java index 41c797b735..1e099413f2 100644 --- a/Mage.Sets/src/mage/sets/eventide/HotheadedGiant.java +++ b/Mage.Sets/src/mage/sets/eventide/HotheadedGiant.java @@ -67,11 +67,11 @@ public class HotheadedGiant extends CardImpl { // Haste this.addAbility(HasteAbility.getInstance()); - + // Hotheaded Giant enters the battlefield with two -1/-1 counters on it unless you've cast another red spell this turn. Condition condition = new CastRedSpellThisTurnCondition(); this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.M1M1.createInstance(2)), new InvertCondition(condition), ""), "with two -1/-1 counters on it unless you've cast another red spell this turn"), new HotHeadedGiantWatcher(this.getId())); - + } public HotheadedGiant(final HotheadedGiant card) { @@ -99,6 +99,7 @@ class CastRedSpellThisTurnCondition implements Condition { class HotHeadedGiantWatcher extends Watcher { private static final FilterSpell filter = new FilterSpell(); + static { filter.add(new ColorPredicate(ObjectColor.RED)); } @@ -126,7 +127,7 @@ class HotHeadedGiantWatcher extends Watcher { return; } if (event.getType() == EventType.SPELL_CAST - && controllerId == event.getPlayerId()) { + && controllerId.equals(event.getPlayerId())) { Spell spell = game.getStack().getSpell(event.getTargetId()); if (!spell.getSourceId().equals(cardId) && filter.match(spell, game)) { condition = true; diff --git a/Mage.Sets/src/mage/sets/eventide/SoulReap.java b/Mage.Sets/src/mage/sets/eventide/SoulReap.java index 8c47750a96..3bb073a7db 100644 --- a/Mage.Sets/src/mage/sets/eventide/SoulReap.java +++ b/Mage.Sets/src/mage/sets/eventide/SoulReap.java @@ -32,7 +32,6 @@ import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.condition.Condition; import mage.abilities.decorator.ConditionalOneShotEffect; -import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; @@ -59,26 +58,25 @@ import mage.watchers.Watcher; * @author jeffwadsworth */ public class SoulReap extends CardImpl { - + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nongreen creature"); - + static { filter.add(Predicates.not(new ColorPredicate(ObjectColor.GREEN))); } - + private String rule = "Its controller loses 3 life if you've cast another black spell this turn"; public SoulReap(UUID ownerId) { super(ownerId, 44, "Soul Reap", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{1}{B}"); this.expansionSetCode = "EVE"; - // Destroy target nongreen creature. Its controller loses 3 life if you've cast another black spell this turn. this.getSpellAbility().addEffect(new DestroyTargetEffect()); this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new SoulReapEffect(), new CastBlackSpellThisTurnCondition(), rule)); this.getSpellAbility().addWatcher(new SoulReapWatcher(this.getId())); - + } public SoulReap(final SoulReap card) { @@ -106,7 +104,7 @@ class CastBlackSpellThisTurnCondition implements Condition { class SoulReapWatcher extends Watcher { private static final FilterSpell filter = new FilterSpell(); - + static { filter.add(new ColorPredicate(ObjectColor.BLACK)); } @@ -134,7 +132,7 @@ class SoulReapWatcher extends Watcher { return; } if (event.getType() == EventType.SPELL_CAST - && controllerId == event.getPlayerId()) { + && controllerId.equals(event.getPlayerId())) { Spell spell = game.getStack().getSpell(event.getTargetId()); if (!spell.getSourceId().equals(cardId) && filter.match(spell, game)) { condition = true; @@ -177,4 +175,4 @@ class SoulReapEffect extends OneShotEffect { } return false; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/eventide/TalarasBattalion.java b/Mage.Sets/src/mage/sets/eventide/TalarasBattalion.java index 3220bda751..190a6d3f5b 100644 --- a/Mage.Sets/src/mage/sets/eventide/TalarasBattalion.java +++ b/Mage.Sets/src/mage/sets/eventide/TalarasBattalion.java @@ -34,7 +34,6 @@ import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; -import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.constants.CardType; @@ -159,7 +158,7 @@ class TalarasBattalionWatcher extends Watcher { return; } if (event.getType() == EventType.SPELL_CAST - && controllerId == event.getPlayerId()) { + && controllerId.equals(event.getPlayerId())) { Spell spell = game.getStack().getSpell(event.getTargetId()); if (!spell.getSourceId().equals(cardId) && filter.match(spell, game)) { condition = true; diff --git a/Mage.Sets/src/mage/sets/exodus/SoltariVisionary.java b/Mage.Sets/src/mage/sets/exodus/SoltariVisionary.java index 4e07f51447..99d614dd6a 100644 --- a/Mage.Sets/src/mage/sets/exodus/SoltariVisionary.java +++ b/Mage.Sets/src/mage/sets/exodus/SoltariVisionary.java @@ -99,7 +99,7 @@ class SoltariVisionaryTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent soltari = game.getPermanent(event.getSourceId()); - if (soltari != null && soltari.getId() == this.getSourceId()) { + if (soltari != null && soltari.getId().equals(this.getSourceId())) { FilterEnchantmentPermanent filter = new FilterEnchantmentPermanent("enchantment that player controls."); filter.add(new ControllerIdPredicate(event.getPlayerId())); filter.setMessage("enchantment controlled by " + game.getPlayer(event.getTargetId()).getLogName()); diff --git a/Mage.Sets/src/mage/sets/fatereforged/MarduWoeReaper.java b/Mage.Sets/src/mage/sets/fatereforged/MarduWoeReaper.java index 15a433d0ea..4b594d31ca 100644 --- a/Mage.Sets/src/mage/sets/fatereforged/MarduWoeReaper.java +++ b/Mage.Sets/src/mage/sets/fatereforged/MarduWoeReaper.java @@ -99,7 +99,7 @@ class MarduWoeReaperTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { if (event.getPlayerId().equals(this.getControllerId())) { Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent != null && (permanent.getId() == this.getSourceId() || permanent.hasSubtype("Warrior"))) { + if (permanent != null && (permanent.getId().equals(this.getSourceId()) || permanent.hasSubtype("Warrior"))) { return true; } } @@ -113,21 +113,21 @@ class MarduWoeReaperTriggeredAbility extends TriggeredAbilityImpl { } class MarduWoeReaperEffect extends OneShotEffect { - + MarduWoeReaperEffect() { super(Outcome.GainLife); this.staticText = "you may exile target creature card from a graveyard. If you do, you gain 1 life"; } - + MarduWoeReaperEffect(final MarduWoeReaperEffect effect) { super(effect); } - + @Override public MarduWoeReaperEffect copy() { return new MarduWoeReaperEffect(this); } - + @Override public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); diff --git a/Mage.Sets/src/mage/sets/fatereforged/WardscaleDragon.java b/Mage.Sets/src/mage/sets/fatereforged/WardscaleDragon.java index fadb7c5a88..61869d4745 100644 --- a/Mage.Sets/src/mage/sets/fatereforged/WardscaleDragon.java +++ b/Mage.Sets/src/mage/sets/fatereforged/WardscaleDragon.java @@ -58,11 +58,10 @@ public class WardscaleDragon extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); - + // As long as Wardscale Dragon is attacking, defending player can't cast spells. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new WardscaleDragonRuleEffect())); - - + } public WardscaleDragon(final WardscaleDragon card) { @@ -105,7 +104,7 @@ class WardscaleDragonRuleEffect extends ContinuousRuleModifyingEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { Permanent sourcePermanent = game.getPermanent(source.getSourceId()); if (sourcePermanent != null && sourcePermanent.isAttacking()) { - return event.getPlayerId() == game.getCombat().getDefendingPlayerId(sourcePermanent.getId(), game); + return event.getPlayerId().equals(game.getCombat().getDefendingPlayerId(sourcePermanent.getId(), game)); } return false; } diff --git a/Mage.Sets/src/mage/sets/fifthedition/InstillEnergy.java b/Mage.Sets/src/mage/sets/fifthedition/InstillEnergy.java index 5c82efdeba..9c0b869103 100644 --- a/Mage.Sets/src/mage/sets/fifthedition/InstillEnergy.java +++ b/Mage.Sets/src/mage/sets/fifthedition/InstillEnergy.java @@ -92,6 +92,7 @@ public class InstillEnergy extends CardImpl { } class CanAttackAsThoughItHadHasteEnchantedEffect extends AsThoughEffectImpl { + public CanAttackAsThoughItHadHasteEnchantedEffect(Duration duration) { super(AsThoughEffectType.ATTACK, duration, Outcome.Benefit); staticText = "Enchanted creature can attack as though it had haste"; @@ -114,7 +115,7 @@ class CanAttackAsThoughItHadHasteEnchantedEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { Permanent enchantment = game.getPermanent(source.getSourceId()); - return enchantment != null && enchantment.getAttachedTo() != null && enchantment.getAttachedTo() == objectId; + return enchantment != null && enchantment.getAttachedTo() != null && enchantment.getAttachedTo().equals(objectId); } } diff --git a/Mage.Sets/src/mage/sets/limitedalpha/Fastbond.java b/Mage.Sets/src/mage/sets/limitedalpha/Fastbond.java index 3be02bbc3d..ddcdabe0e9 100644 --- a/Mage.Sets/src/mage/sets/limitedalpha/Fastbond.java +++ b/Mage.Sets/src/mage/sets/limitedalpha/Fastbond.java @@ -52,13 +52,11 @@ public class Fastbond extends CardImpl { super(ownerId, 101, "Fastbond", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{G}"); this.expansionSetCode = "LEA"; - // You may play any number of additional lands on each of your turns. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PlayAdditionalLandsControllerEffect(Integer.MAX_VALUE, Duration.WhileOnBattlefield))); // Whenever you play a land, if it wasn't the first land you played this turn, Fastbond deals 1 damage to you. this.addAbility(new PlayALandTriggeredAbility()); } - public Fastbond(final Fastbond card) { super(card); @@ -70,7 +68,6 @@ public class Fastbond extends CardImpl { } } - class PlayALandTriggeredAbility extends TriggeredAbilityImpl { public PlayALandTriggeredAbility() { @@ -88,14 +85,14 @@ class PlayALandTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - return event.getPlayerId() == this.getControllerId(); + return event.getPlayerId().equals(this.getControllerId()); } @Override public boolean checkInterveningIfClause(Game game) { Player player = game.getPlayer(this.getControllerId()); - if (player != null){ - if (player.getLandsPlayed() != 1){ + if (player != null) { + if (player.getLandsPlayed() != 1) { return true; } } @@ -111,8 +108,5 @@ class PlayALandTriggeredAbility extends TriggeredAbilityImpl { public String getRule() { return "Whenever you play a land, if it wasn't the first land you played this turn, {source} deals 1 damage to you"; } - - + } - - diff --git a/Mage.Sets/src/mage/sets/magic2015/GeneratorServant.java b/Mage.Sets/src/mage/sets/magic2015/GeneratorServant.java index 1bda0be009..898e79c694 100644 --- a/Mage.Sets/src/mage/sets/magic2015/GeneratorServant.java +++ b/Mage.Sets/src/mage/sets/magic2015/GeneratorServant.java @@ -77,7 +77,7 @@ public class GeneratorServant extends CardImpl { ability.addCost(new SacrificeSourceCost()); ability.getEffects().get(0).setText("Add {2} to your mana pool. If that mana is spent on a creature spell, it gains haste until end of turn."); this.addAbility(ability); - + this.addAbility(new SimpleStaticAbility(Zone.ALL, new GeneratorServantHasteEffect()), new GeneratorServantWatcher()); } @@ -94,11 +94,11 @@ public class GeneratorServant extends CardImpl { class GeneratorServantWatcher extends Watcher { public List creatures = new ArrayList<>(); - + public GeneratorServantWatcher() { super("GeneratorServantWatcher", WatcherScope.CARD); } - + public GeneratorServantWatcher(final GeneratorServantWatcher watcher) { super(watcher); this.creatures.addAll(watcher.creatures); @@ -108,13 +108,13 @@ class GeneratorServantWatcher extends Watcher { public GeneratorServantWatcher copy() { return new GeneratorServantWatcher(this); } - + @Override public void watch(GameEvent event, Game game) { if (event.getType() == GameEvent.EventType.MANA_PAYED) { MageObject target = game.getObject(event.getTargetId()); - MageObject source = game.getObject(this.getSourceId()); - if (event.getSourceId() == this.getSourceId() && target != null && target.getCardType().contains(CardType.CREATURE) && event.getFlag()) { + if (event.getSourceId() != null + && event.getSourceId().equals(this.getSourceId()) && target != null && target.getCardType().contains(CardType.CREATURE) && event.getFlag()) { if (target instanceof Spell) { this.creatures.add(((Spell) target).getCard().getId()); } @@ -127,7 +127,7 @@ class GeneratorServantWatcher extends Watcher { super.reset(); creatures.clear(); } - + } class GeneratorServantHasteEffect extends ContinuousEffectImpl { @@ -135,7 +135,7 @@ class GeneratorServantHasteEffect extends ContinuousEffectImpl { public GeneratorServantHasteEffect() { super(Duration.EndOfGame, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); } - + public GeneratorServantHasteEffect(final GeneratorServantHasteEffect effect) { super(effect); } @@ -144,7 +144,7 @@ class GeneratorServantHasteEffect extends ContinuousEffectImpl { public ContinuousEffect copy() { return new GeneratorServantHasteEffect(this); } - + @Override public boolean apply(Game game, Ability source) { GeneratorServantWatcher watcher = (GeneratorServantWatcher) game.getState().getWatchers().get("GeneratorServantWatcher", source.getSourceId()); @@ -158,5 +158,5 @@ class GeneratorServantHasteEffect extends ContinuousEffectImpl { } return false; } - + } diff --git a/Mage.Sets/src/mage/sets/magicorigins/SigilOfValor.java b/Mage.Sets/src/mage/sets/magicorigins/SigilOfValor.java index bc849bbcf5..be8c354a8e 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/SigilOfValor.java +++ b/Mage.Sets/src/mage/sets/magicorigins/SigilOfValor.java @@ -105,7 +105,9 @@ class SigilOfValorTriggeredAbility extends TriggeredAbilityImpl { if (game.getCombat().attacksAlone()) { Permanent equipment = game.getPermanent(getSourceId()); UUID attackerId = game.getCombat().getAttackers().get(0); - if (equipment != null && equipment.getAttachedTo() == attackerId) { + if (equipment != null + && equipment.getAttachedTo() != null + && equipment.getAttachedTo().equals(attackerId)) { this.getEffects().get(0).setTargetPointer(new FixedTarget(attackerId)); return true; } diff --git a/Mage.Sets/src/mage/sets/masterseditionii/ThoughtLash.java b/Mage.Sets/src/mage/sets/masterseditionii/ThoughtLash.java index e8a28e8196..65a48ed577 100644 --- a/Mage.Sets/src/mage/sets/masterseditionii/ThoughtLash.java +++ b/Mage.Sets/src/mage/sets/masterseditionii/ThoughtLash.java @@ -60,10 +60,10 @@ public class ThoughtLash extends CardImpl { // Cumulative upkeep - Exile the top card of your library. this.addAbility(new CumulativeUpkeepAbility(new ExileFromTopOfLibraryCost(1))); - + // When a player doesn't pay Thought Lash's cumulative upkeep, that player exiles all cards from his or her library. this.addAbility(new ThoughtLashTriggeredAbility()); - + // Exile the top card of your library: Prevent the next 1 damage that would be dealt to you this turn. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new ThoughtLashPreventionEffect(), new ExileFromTopOfLibraryCost(1))); } @@ -79,30 +79,30 @@ public class ThoughtLash extends CardImpl { } class ThoughtLashTriggeredAbility extends TriggeredAbilityImpl { - + ThoughtLashTriggeredAbility() { super(Zone.BATTLEFIELD, new ThoughtLashExileLibraryEffect(), false); } - + ThoughtLashTriggeredAbility(final ThoughtLashTriggeredAbility ability) { super(ability); } - + @Override public ThoughtLashTriggeredAbility copy() { return new ThoughtLashTriggeredAbility(this); } - + @Override public boolean checkEventType(GameEvent event, Game game) { return event.getType() == EventType.DIDNT_PAY_CUMULATIVE_UPKEEP; } - + @Override public boolean checkTrigger(GameEvent event, Game game) { - return event.getSourceId() == this.getSourceId(); + return event.getSourceId() != null && event.getSourceId().equals(this.getSourceId()); } - + @Override public String getRule() { return "When a player doesn't pay {this}'s cumulative upkeep, that player exiles all cards from his or her library."; @@ -110,21 +110,21 @@ class ThoughtLashTriggeredAbility extends TriggeredAbilityImpl { } class ThoughtLashExileLibraryEffect extends OneShotEffect { - + ThoughtLashExileLibraryEffect() { super(Outcome.Detriment); this.staticText = "that player exiles all cards from his or her library"; } - + ThoughtLashExileLibraryEffect(final ThoughtLashExileLibraryEffect effect) { super(effect); } - + @Override public ThoughtLashExileLibraryEffect copy() { return new ThoughtLashExileLibraryEffect(this); } - + @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); diff --git a/Mage.Sets/src/mage/sets/planeshift/OrimsChant.java b/Mage.Sets/src/mage/sets/planeshift/OrimsChant.java index 6c87841a9e..5a35bbde4f 100644 --- a/Mage.Sets/src/mage/sets/planeshift/OrimsChant.java +++ b/Mage.Sets/src/mage/sets/planeshift/OrimsChant.java @@ -1,31 +1,30 @@ /* -* 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. -*/ - + * 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.planeshift; import java.util.UUID; @@ -56,7 +55,6 @@ public class OrimsChant extends CardImpl { super(ownerId, 11, "Orim's Chant", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{W}"); this.expansionSetCode = "PLS"; - // Kicker {W} (You may pay an additional {W} as you cast this spell.) this.addAbility(new KickerAbility("{W}")); @@ -81,7 +79,7 @@ public class OrimsChant extends CardImpl { class OrimsChantCantCastEffect extends ContinuousRuleModifyingEffectImpl { - public OrimsChantCantCastEffect() { + public OrimsChantCantCastEffect() { super(Duration.EndOfTurn, Outcome.Benefit); staticText = "Target player can't cast spells this turn"; } @@ -97,12 +95,12 @@ class OrimsChantCantCastEffect extends ContinuousRuleModifyingEffectImpl { @Override public boolean checksEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.CAST_SPELL; + return GameEvent.EventType.CAST_SPELL.equals(event.getType()); } @Override public boolean applies(GameEvent event, Ability source, Game game) { - return event.getPlayerId() == getTargetPointer().getFirst(game, source); + return event.getPlayerId().equals(getTargetPointer().getFirst(game, source)); } } diff --git a/Mage.Sets/src/mage/sets/returntoravnica/VraskaTheUnseen.java b/Mage.Sets/src/mage/sets/returntoravnica/VraskaTheUnseen.java index e04c58658c..3c890808dd 100644 --- a/Mage.Sets/src/mage/sets/returntoravnica/VraskaTheUnseen.java +++ b/Mage.Sets/src/mage/sets/returntoravnica/VraskaTheUnseen.java @@ -66,7 +66,7 @@ import mage.target.targetpointer.FixedTarget; * Each Assassin token's triggered ability will trigger whenever it deals combat * damage to any player, including you. * - * + * * @author LevelX2 */ public class VraskaTheUnseen extends CardImpl { @@ -76,11 +76,10 @@ public class VraskaTheUnseen extends CardImpl { this.expansionSetCode = "RTR"; this.subtype.add("Vraska"); - this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.LOYALTY.createInstance(5)), false)); // +1: Until your next turn, whenever a creature deals combat damage to Vraska the Unseen, destroy that creature. - this.addAbility(new LoyaltyAbility(new VraskaTheUnseenGainAbilityEffect(new VraskaTheUnseenTriggeredAbility()),1)); + this.addAbility(new LoyaltyAbility(new VraskaTheUnseenGainAbilityEffect(new VraskaTheUnseenTriggeredAbility()), 1)); // -3: Destroy target nonland permanent. LoyaltyAbility ability = new LoyaltyAbility(new DestroyTargetEffect(), -3); @@ -101,7 +100,6 @@ public class VraskaTheUnseen extends CardImpl { } } - class VraskaTheUnseenGainAbilityEffect extends ContinuousEffectImpl { protected Ability ability; @@ -142,8 +140,7 @@ class VraskaTheUnseenGainAbilityEffect extends ContinuousEffectImpl { @Override public boolean isInactive(Ability source, Game game) { - if (startingTurn != 0 && game.getTurnNum() != startingTurn) - { + if (startingTurn != 0 && game.getTurnNum() != startingTurn) { if (game.getActivePlayerId().equals(source.getControllerId())) { return true; } @@ -153,6 +150,7 @@ class VraskaTheUnseenGainAbilityEffect extends ContinuousEffectImpl { } class AssassinToken extends Token { + AssassinToken() { super("Assassin", "1/1 black Assassin creature tokens with \"Whenever this creature deals combat damage to a player, that player loses the game.\""); cardType.add(CardType.CREATURE); @@ -160,7 +158,7 @@ class AssassinToken extends Token { subtype.add("Assassin"); power = new MageInt(1); toughness = new MageInt(1); - addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new LoseGameTargetPlayerEffect(),false, true)); + addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new LoseGameTargetPlayerEffect(), false, true)); } } @@ -186,7 +184,7 @@ class VraskaTheUnseenTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (((DamagedPlaneswalkerEvent) event).isCombatDamage() && event.getTargetId() == sourceId) { + if (((DamagedPlaneswalkerEvent) event).isCombatDamage() && getSourceId().equals(event.getTargetId())) { Permanent sourceOfDamage = game.getPermanent(event.getSourceId()); if (sourceOfDamage != null && sourceOfDamage.getCardType().contains(CardType.CREATURE)) { Effect effect = this.getEffects().get(0); @@ -202,4 +200,4 @@ class VraskaTheUnseenTriggeredAbility extends TriggeredAbilityImpl { return "Until your next turn, whenever a creature deals combat damage to {this}, destroy that creature"; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/RevokeExistence.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/RevokeExistence.java index 554cefc08b..1186f719ae 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/RevokeExistence.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/RevokeExistence.java @@ -25,25 +25,24 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.sets.scarsofmirrodin; -import mage.constants.CardType; -import mage.constants.Rarity; +import java.util.UUID; import mage.abilities.effects.common.ExileTargetEffect; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; import mage.filter.FilterPermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.target.TargetPermanent; -import java.util.UUID; - /** * * @author Loki */ public class RevokeExistence extends CardImpl { + private static final FilterPermanent filter = new FilterPermanent("artifact or enchantment"); static { @@ -52,15 +51,16 @@ public class RevokeExistence extends CardImpl { new CardTypePredicate(CardType.ENCHANTMENT))); } - public RevokeExistence (UUID ownerId) { + public RevokeExistence(UUID ownerId) { super(ownerId, 18, "Revoke Existence", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{1}{W}"); this.expansionSetCode = "SOM"; + // Exile target artifact or enchantment. this.getSpellAbility().addEffect(new ExileTargetEffect()); this.getSpellAbility().addTarget(new TargetPermanent(filter)); } - public RevokeExistence (final RevokeExistence card) { + public RevokeExistence(final RevokeExistence card) { super(card); } diff --git a/Mage.Sets/src/mage/sets/shadowmoor/MossbridgeTroll.java b/Mage.Sets/src/mage/sets/shadowmoor/MossbridgeTroll.java index 539b8f9d3d..bc44a0a95d 100644 --- a/Mage.Sets/src/mage/sets/shadowmoor/MossbridgeTroll.java +++ b/Mage.Sets/src/mage/sets/shadowmoor/MossbridgeTroll.java @@ -56,7 +56,7 @@ import mage.target.common.TargetControlledCreaturePermanent; * @author jeffwadsworth */ public class MossbridgeTroll extends CardImpl { - + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creatures you control"); static { @@ -78,7 +78,7 @@ public class MossbridgeTroll extends CardImpl { Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(20, 20, Duration.EndOfTurn), new MossbridgeTrollCost()); ability.setAdditionalCostsRuleVisible(false); this.addAbility(ability); - + } public MossbridgeTroll(final MossbridgeTroll card) { @@ -115,10 +115,11 @@ class MossbridgeTrollReplacementEffect extends ReplacementEffectImpl { public boolean checksEventType(GameEvent event, Game game) { return event.getType() == GameEvent.EventType.DESTROY_PERMANENT; } - + @Override public boolean applies(GameEvent event, Ability source, Game game) { - return event.getTargetId() == source.getSourceId(); + return event.getTargetId() != null + && event.getTargetId().equals(source.getSourceId()); } @Override @@ -150,7 +151,7 @@ class MossbridgeTrollCost extends CostImpl { public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { int sumPower = 0; if (targets.choose(Outcome.Tap, controllerId, sourceId, game)) { - for (UUID targetId: targets.get(0).getTargets()) { + for (UUID targetId : targets.get(0).getTargets()) { Permanent permanent = game.getPermanent(targetId); if (permanent != null && permanent.tap(game)) { sumPower += permanent.getPower().getValue(); @@ -165,7 +166,7 @@ class MossbridgeTrollCost extends CostImpl { @Override public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { int sumPower = 0; - for (Permanent permanent :game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), controllerId, game)) { + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), controllerId, game)) { if (!permanent.getId().equals(sourceId)) { sumPower += permanent.getPower().getValue(); } @@ -178,4 +179,3 @@ class MossbridgeTrollCost extends CostImpl { return new MossbridgeTrollCost(this); } } - diff --git a/Mage.Sets/src/mage/sets/shadowmoor/ThoughtweftGambit.java b/Mage.Sets/src/mage/sets/shadowmoor/ThoughtweftGambit.java index f6c0b113a1..5246fd4459 100644 --- a/Mage.Sets/src/mage/sets/shadowmoor/ThoughtweftGambit.java +++ b/Mage.Sets/src/mage/sets/shadowmoor/ThoughtweftGambit.java @@ -50,7 +50,6 @@ public class ThoughtweftGambit extends CardImpl { super(ownerId, 154, "Thoughtweft Gambit", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{4}{W/U}{W/U}"); this.expansionSetCode = "SHM"; - // Tap all creatures your opponents control and untap all creatures you control. this.getSpellAbility().addEffect(new ThoughtweftGambitEffect()); @@ -94,7 +93,7 @@ class ThoughtweftGambitEffect extends OneShotEffect { } if (controller != null) { for (Permanent creature : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)) { - if (controller.getId() == creature.getControllerId()) { + if (controller.getId().equals(creature.getControllerId())) { creature.untap(game); } } diff --git a/Mage.Sets/src/mage/sets/shardsofalara/GatherSpecimens.java b/Mage.Sets/src/mage/sets/shardsofalara/GatherSpecimens.java index 1287b0fc32..f33ff12365 100644 --- a/Mage.Sets/src/mage/sets/shardsofalara/GatherSpecimens.java +++ b/Mage.Sets/src/mage/sets/shardsofalara/GatherSpecimens.java @@ -52,10 +52,8 @@ public class GatherSpecimens extends CardImpl { super(ownerId, 45, "Gather Specimens", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{3}{U}{U}{U}"); this.expansionSetCode = "ALA"; - // If a creature would enter the battlefield under an opponent's control this turn, it enters the battlefield under your control instead. this.getSpellAbility().addEffect(new GatherSpecimensReplacementEffect()); - } public GatherSpecimens(final GatherSpecimens card) { @@ -114,7 +112,7 @@ class GatherSpecimensReplacementEffect extends ReplacementEffectImpl { } return false; } - + @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { Player controller = game.getPlayer(source.getControllerId()); @@ -122,5 +120,5 @@ class GatherSpecimensReplacementEffect extends ReplacementEffectImpl { event.setPlayerId(controller.getId()); } return false; - } + } } diff --git a/Mage.Sets/src/mage/sets/tempest/HelmOfPossession.java b/Mage.Sets/src/mage/sets/tempest/HelmOfPossession.java index f80c784301..b20810eabf 100644 --- a/Mage.Sets/src/mage/sets/tempest/HelmOfPossession.java +++ b/Mage.Sets/src/mage/sets/tempest/HelmOfPossession.java @@ -59,7 +59,7 @@ public class HelmOfPossession extends CardImpl { // You may choose not to untap Helm of Possession during your untap step. this.addAbility(new SkipUntapOptionalAbility()); - + // {2}, {tap}, Sacrifice a creature: Gain control of target creature for as long as you control Helm of Possession and Helm of Possession remains tapped. ConditionalContinuousEffect effect = new ConditionalContinuousEffect( new GainControlTargetEffect(Duration.Custom), @@ -92,11 +92,11 @@ class HelmOfPossessionCondition implements Condition { controllerId = source.getControllerId(); } Permanent permanent = game.getBattlefield().getPermanent(source.getSourceId()); - if (permanent != null){ - if (permanent.isTapped()){ - return controllerId == source.getControllerId(); + if (permanent != null) { + if (permanent.isTapped()) { + return controllerId.equals(source.getControllerId()); } } return false; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/worldwake/TuktukScrapper.java b/Mage.Sets/src/mage/sets/worldwake/TuktukScrapper.java index f1476ca3ae..2a22757c2e 100644 --- a/Mage.Sets/src/mage/sets/worldwake/TuktukScrapper.java +++ b/Mage.Sets/src/mage/sets/worldwake/TuktukScrapper.java @@ -100,7 +100,7 @@ class TuktukScrapperTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null) { - if (permanent.getId() == this.getSourceId()) { + if (permanent.getId().equals(this.getSourceId())) { return true; } if (permanent.hasSubtype("Ally") diff --git a/Mage.Sets/src/mage/sets/worldwake/WrexialTheRisenDeep.java b/Mage.Sets/src/mage/sets/worldwake/WrexialTheRisenDeep.java index c0c7699178..678fbf386b 100644 --- a/Mage.Sets/src/mage/sets/worldwake/WrexialTheRisenDeep.java +++ b/Mage.Sets/src/mage/sets/worldwake/WrexialTheRisenDeep.java @@ -28,11 +28,6 @@ package mage.sets.worldwake; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; @@ -42,6 +37,11 @@ import mage.abilities.keyword.IslandwalkAbility; import mage.abilities.keyword.SwampwalkAbility; import mage.cards.Card; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardTypePredicate; @@ -50,7 +50,6 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; import mage.game.events.ZoneChangeEvent; -import mage.game.stack.Spell; import mage.game.stack.StackObject; import mage.players.Player; import mage.target.Target; @@ -156,29 +155,22 @@ class WrexialReplacementEffect extends ReplacementEffectImpl { public boolean checksEventType(GameEvent event, Game game) { return event.getType() == EventType.ZONE_CHANGE; } - + @Override public boolean applies(GameEvent event, Ability source, Game game) { ZoneChangeEvent zEvent = (ZoneChangeEvent) event; - if (zEvent.getToZone() == Zone.GRAVEYARD - && ((ZoneChangeEvent) event).getTargetId() == cardid) { - return true; - } - return false; + return zEvent.getToZone() == Zone.GRAVEYARD + && ((ZoneChangeEvent) event).getTargetId().equals(cardid); } - + @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { UUID eventObject = ((ZoneChangeEvent) event).getTargetId(); StackObject card = game.getStack().getStackObject(eventObject); Player controller = game.getPlayer(source.getControllerId()); if (card != null && controller != null) { - if (card instanceof Spell) { - game.rememberLKI(card.getId(), Zone.STACK, (Spell) card); - } if (card instanceof Card) { - controller.moveCardToExileWithInfo((Card)card, null, "", source.getSourceId(), game, game.getState().getZone(event.getTargetId()), true); - return true; + return controller.moveCards((Card) card, null, Zone.EXILED, source, game); } } return false; diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/OblivionRingTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/OblivionRingTest.java index ef5dc6ae62..d09251969f 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/OblivionRingTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/OblivionRingTest.java @@ -90,6 +90,7 @@ public class OblivionRingTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerA, "Plains", 5); addCard(Zone.HAND, playerA, "Oblivion Ring"); addCard(Zone.BATTLEFIELD, playerA, "Jace Beleren"); + // Exile target artifact or enchantment. addCard(Zone.HAND, playerA, "Revoke Existence"); activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "-1: Target player draws a card", playerA); @@ -100,7 +101,10 @@ public class OblivionRingTest extends CardTestPlayerBase { setStopAt(1, PhaseStep.END_TURN); execute(); + assertExileCount("Oblivion Ring", 1); + assertGraveyardCount(playerA, "Revoke Existence", 1); assertPermanentCount(playerA, "Oblivion Ring", 0); + assertGraveyardCount(playerA, "Jace Beleren", 0); assertPermanentCount(playerA, "Jace Beleren", 1); // returns back assertHandCount(playerA, 2); // can use ability twice } diff --git a/Mage/src/mage/abilities/common/EntersBattlefieldAbility.java b/Mage/src/mage/abilities/common/EntersBattlefieldAbility.java index fa51f39054..64bd2c40fe 100644 --- a/Mage/src/mage/abilities/common/EntersBattlefieldAbility.java +++ b/Mage/src/mage/abilities/common/EntersBattlefieldAbility.java @@ -1,31 +1,30 @@ /* -* 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. -*/ - + * 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.common; import mage.abilities.StaticAbility; @@ -41,15 +40,17 @@ import mage.constants.Zone; public class EntersBattlefieldAbility extends StaticAbility { protected String abilityRule; - + public EntersBattlefieldAbility(Effect effect) { this(effect, true); } -/** - * - * @param effect effect that happens when the permanent enters the battlefield - * @param showRule show the rule for this ability - */ + + /** + * + * @param effect effect that happens when the permanent enters the + * battlefield + * @param showRule show the rule for this ability + */ public EntersBattlefieldAbility(Effect effect, Boolean showRule) { this(effect, null, showRule, null, null); } @@ -57,16 +58,19 @@ public class EntersBattlefieldAbility extends StaticAbility { public EntersBattlefieldAbility(Effect effect, String effectText) { this(effect, null, true, null, effectText); } -/** - * - * @param effect effect that happens when the permanent enters the battlefield - * @param condition only if this condition is true, the effect will happen - * @param ruleVisible show the rule for this ability - * @param abilityRule rule for this ability (no text from effects will be added) - * @param effectText this text will be used for the EnterBattlefieldEffect - */ + + /** + * + * @param effect effect that happens when the permanent enters the + * battlefield + * @param condition only if this condition is true, the effect will happen + * @param ruleVisible show the rule for this ability + * @param abilityRule rule for this ability (no text from effects will be + * added) + * @param effectText this text will be used for the EnterBattlefieldEffect + */ public EntersBattlefieldAbility(Effect effect, Condition condition, Boolean ruleVisible, String abilityRule, String effectText) { - super(Zone.BATTLEFIELD, new EntersBattlefieldEffect(effect, condition, effectText)); + super(Zone.ALL, new EntersBattlefieldEffect(effect, condition, effectText)); this.setRuleVisible(ruleVisible); this.abilityRule = abilityRule; } @@ -96,7 +100,7 @@ public class EntersBattlefieldAbility extends StaticAbility { @Override public String getRule() { if (!ruleVisible) { - return ""; + return ""; } if (abilityRule != null && !abilityRule.isEmpty()) { return abilityRule; diff --git a/Mage/src/mage/abilities/costs/common/DiscardTargetCost.java b/Mage/src/mage/abilities/costs/common/DiscardTargetCost.java index 5ba87b8191..c62ecfc395 100644 --- a/Mage/src/mage/abilities/costs/common/DiscardTargetCost.java +++ b/Mage/src/mage/abilities/costs/common/DiscardTargetCost.java @@ -68,7 +68,7 @@ public class DiscardTargetCost extends CostImpl { @Override public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { this.cards.clear(); - this.targets.clear(); + this.targets.clearChosen();; Player player = game.getPlayer(controllerId); if (player == null) { return false; diff --git a/Mage/src/mage/abilities/effects/ContinuousEffects.java b/Mage/src/mage/abilities/effects/ContinuousEffects.java index 241c3de528..de323f1202 100644 --- a/Mage/src/mage/abilities/effects/ContinuousEffects.java +++ b/Mage/src/mage/abilities/effects/ContinuousEffects.java @@ -1246,7 +1246,7 @@ public class ContinuousEffects implements Serializable { HashSet abilities = preventionEffects.getAbility(effect.getId()); for (Ability ability : abilities) { if (ability.getSourceId().equals(sourceId)) { - if (controllerFound == null || controllerFound == ability.getControllerId()) { + if (controllerFound == null || controllerFound.equals(ability.getControllerId())) { controllerFound = ability.getControllerId(); } else { // not unique controller - No solution yet @@ -1260,7 +1260,7 @@ public class ContinuousEffects implements Serializable { for (Ability ability : abilities) { if (ability.getSourceId() != null) { if (ability.getSourceId().equals(sourceId)) { - if (controllerFound == null || controllerFound == ability.getControllerId()) { + if (controllerFound == null || controllerFound.equals(ability.getControllerId())) { controllerFound = ability.getControllerId(); } else { // not unique controller - No solution yet diff --git a/Mage/src/mage/abilities/effects/common/ReturnFromExileForSourceEffect.java b/Mage/src/mage/abilities/effects/common/ReturnFromExileForSourceEffect.java index 8d7b8a7c2b..1276b0acdf 100644 --- a/Mage/src/mage/abilities/effects/common/ReturnFromExileForSourceEffect.java +++ b/Mage/src/mage/abilities/effects/common/ReturnFromExileForSourceEffect.java @@ -101,7 +101,11 @@ public class ReturnFromExileForSourceEffect extends OneShotEffect { } ExileZone exile = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source.getSourceId(), zoneChangeCounter)); if (exile != null) { // null is valid if source left battlefield before enters the battlefield effect resolved - controller.moveCards(exile, null, returnToZone, source, game); + if (returnToZone.equals(Zone.BATTLEFIELD)) { + controller.moveCards(exile.getCards(game), returnToZone, source, game, false, false, true, null); + } else { + controller.moveCards(exile, null, returnToZone, source, game); + } } return true; } diff --git a/Mage/src/mage/abilities/keyword/ReboundAbility.java b/Mage/src/mage/abilities/keyword/ReboundAbility.java index 6bd8c0d652..7ab46d546e 100644 --- a/Mage/src/mage/abilities/keyword/ReboundAbility.java +++ b/Mage/src/mage/abilities/keyword/ReboundAbility.java @@ -1,31 +1,30 @@ /* -* 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. -*/ - + * 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.keyword; import java.util.UUID; @@ -48,28 +47,29 @@ import mage.game.stack.Spell; import mage.players.Player; /** - * This ability has no effect by default and will always return false on the call - * to apply. This is because of how the {@link ReboundEffect} works. It will - * install the effect if and only if the spell was cast from the {@link Zone#HAND Hand}. + * This ability has no effect by default and will always return false on the + * call to apply. This is because of how the {@link ReboundEffect} works. It + * will install the effect if and only if the spell was cast from the + * {@link Zone#HAND Hand}. *

* 702.85. Rebound *

- * 702.85a Rebound appears on some instants and sorceries. It represents a static - * ability that functions while the spell is on the stack and may create a delayed - * triggered ability. "Rebound" means "If this spell was cast from your hand, - * instead of putting it into your graveyard as it resolves, exile it and, at - * the beginning of your next upkeep, you may cast this card from exile without - * paying its mana cost." + * 702.85a Rebound appears on some instants and sorceries. It represents a + * static ability that functions while the spell is on the stack and may create + * a delayed triggered ability. "Rebound" means "If this spell was cast from + * your hand, instead of putting it into your graveyard as it resolves, exile it + * and, at the beginning of your next upkeep, you may cast this card from exile + * without paying its mana cost." *

- * 702.85b Casting a card without paying its mana cost as the result of a rebound - * ability follows the rules for paying alternative costs in rules 601.2b and 601.2e-g. + * 702.85b Casting a card without paying its mana cost as the result of a + * rebound ability follows the rules for paying alternative costs in rules + * 601.2b and 601.2e-g. *

* 702.85c Multiple instances of rebound on the same spell are redundant. * * @author maurer.it_at_gmail.com, noxx */ - -public class ReboundAbility extends SimpleStaticAbility { +public class ReboundAbility extends SimpleStaticAbility { public ReboundAbility() { super(Zone.STACK, new ReboundCastFromHandReplacementEffect()); @@ -81,8 +81,8 @@ public class ReboundAbility extends SimpleStaticAbility { @Override public ReboundAbility copy() { - return new ReboundAbility(this); - } + return new ReboundAbility(this); + } } class ReboundCastFromHandReplacementEffect extends ReplacementEffectImpl { @@ -95,7 +95,7 @@ class ReboundCastFromHandReplacementEffect extends ReplacementEffectImpl { ReboundCastFromHandReplacementEffect(ReboundCastFromHandReplacementEffect effect) { super(effect); } - + @Override public boolean checksEventType(GameEvent event, Game game) { return event.getType() == GameEvent.EventType.ZONE_CHANGE; @@ -103,16 +103,18 @@ class ReboundCastFromHandReplacementEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (((ZoneChangeEvent) event).getFromZone() == Zone.STACK && - ((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD && - event.getSourceId() == source.getSourceId()) { // if countered the source.sourceId is different or null if it fizzles + if (((ZoneChangeEvent) event).getFromZone() == Zone.STACK + && ((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD + && event.getSourceId() != null + && event.getSourceId().equals(source.getSourceId())) { // if countered the source.sourceId is different or null if it fizzles Spell spell = game.getStack().getSpell(event.getTargetId()); if (spell != null && spell.getFromZone().equals(Zone.HAND)) { return true; - } + } } return false; } + @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { Spell sourceSpell = game.getStack().getSpell(source.getSourceId()); @@ -126,9 +128,9 @@ class ReboundCastFromHandReplacementEffect extends ReplacementEffectImpl { // Add the delayed triggered effect ReboundEffectCastFromExileDelayedTrigger trigger = new ReboundEffectCastFromExileDelayedTrigger(source.getSourceId(), source.getSourceId()); trigger.setControllerId(source.getControllerId()); - trigger.setSourceObject(source.getSourceObject(game), game); + trigger.setSourceObject(source.getSourceObject(game), game); game.addDelayedTriggeredAbility(trigger); - + player.moveCardToExileWithInfo(sourceCard, sourceCard.getId(), player.getName() + " Rebound", source.getSourceId(), game, Zone.STACK, true); return true; } @@ -144,7 +146,6 @@ class ReboundCastFromHandReplacementEffect extends ReplacementEffectImpl { } - class ReboundEffectCastFromExileDelayedTrigger extends DelayedTriggeredAbility { ReboundEffectCastFromExileDelayedTrigger(UUID cardId, UUID sourceId) { @@ -171,6 +172,7 @@ class ReboundEffectCastFromExileDelayedTrigger extends DelayedTriggeredAbility { public boolean checkTrigger(GameEvent event, Game game) { return MyTurnCondition.getInstance().apply(game, this); } + @Override public String getRule() { return "Rebound - You may cast {this} from exile without paying its mana cost."; @@ -178,8 +180,8 @@ class ReboundEffectCastFromExileDelayedTrigger extends DelayedTriggeredAbility { } /** - * Will be triggered by {@link ReboundEffectCastFromExileDelayedTrigger} and will - * simply cast the spell then remove it from its former home in exile. + * Will be triggered by {@link ReboundEffectCastFromExileDelayedTrigger} and + * will simply cast the spell then remove it from its former home in exile. * * @author maurer.it_at_gmail.com */ diff --git a/Mage/src/mage/cards/CardImpl.java b/Mage/src/mage/cards/CardImpl.java index d6dc1f58c7..2d3fa165cf 100644 --- a/Mage/src/mage/cards/CardImpl.java +++ b/Mage/src/mage/cards/CardImpl.java @@ -507,8 +507,8 @@ public abstract class CardImpl extends MageObjectImpl implements Card { break; case EXILED: if (game.getExile().getCard(getId(), game) != null) { - game.getExile().removeCard(this, game); - removed = true; + removed = game.getExile().removeCard(this, game); + } break; case STACK: @@ -552,8 +552,9 @@ public abstract class CardImpl extends MageObjectImpl implements Card { + "] source [" + (sourceObject != null ? sourceObject.getName() : "null") + "]"); break; } - game.rememberLKI(objectId, fromZone, lkiObject != null ? lkiObject : this); - if (!removed) { + if (removed) { + game.rememberLKI(objectId, fromZone, lkiObject != null ? lkiObject : this); + } else { logger.warn("Couldn't find card in fromZone, card=" + getIdName() + ", fromZone=" + fromZone); } return removed; diff --git a/Mage/src/mage/game/Exile.java b/Mage/src/mage/game/Exile.java index 42b513092f..8abb6d4cb5 100644 --- a/Mage/src/mage/game/Exile.java +++ b/Mage/src/mage/game/Exile.java @@ -107,12 +107,13 @@ public class Exile implements Serializable, Copyable { return cards; } - public void removeCard(Card card, Game game) { + public boolean removeCard(Card card, Game game) { for (ExileZone exile : exileZones.values()) { if (exile.contains(card.getId())) { - exile.remove(card); + return exile.remove(card.getId()); } } + return false; } @Override diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index 49e8ffb656..bb1250e1b5 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -3052,7 +3052,7 @@ public abstract class PlayerImpl implements Player, Serializable { ZoneChangeEvent event = new ZoneChangeEvent(card.getId(), source.getSourceId(), controllingPlayerId, fromZone, Zone.BATTLEFIELD, appliedEffects, tapped); if (!game.replaceEvent(event)) { // get permanent - Permanent permanent = new PermanentCard(card, controllingPlayerId, game); + Permanent permanent = new PermanentCard(card, event.getPlayerId(), game);// controlling player can be replaced so use event player now permanents.add(permanent); card.checkForCountersToAdd(permanent, game); permanent.setTapped(tapped); From 7924d301bade5b9c06d82b12ca564f4cc95c7988 Mon Sep 17 00:00:00 2001 From: LoneFox Date: Wed, 14 Oct 2015 21:00:55 +0300 Subject: [PATCH 28/46] Implement cards: Alexi's Cloak; Barbed Field; Chilling Apparition; and Latulla, Keldon Overseer --- .../src/mage/sets/prophecy/AlexisCloak.java | 78 +++++++++++++++++ .../src/mage/sets/prophecy/BarbedField.java | 84 +++++++++++++++++++ .../sets/prophecy/ChillingApparition.java | 69 +++++++++++++++ .../sets/prophecy/LatullaKeldonOverseer.java | 78 +++++++++++++++++ 4 files changed, 309 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/prophecy/AlexisCloak.java create mode 100644 Mage.Sets/src/mage/sets/prophecy/BarbedField.java create mode 100644 Mage.Sets/src/mage/sets/prophecy/ChillingApparition.java create mode 100644 Mage.Sets/src/mage/sets/prophecy/LatullaKeldonOverseer.java diff --git a/Mage.Sets/src/mage/sets/prophecy/AlexisCloak.java b/Mage.Sets/src/mage/sets/prophecy/AlexisCloak.java new file mode 100644 index 0000000000..f2616d74fd --- /dev/null +++ b/Mage.Sets/src/mage/sets/prophecy/AlexisCloak.java @@ -0,0 +1,78 @@ +/* + * 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.prophecy; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.FlashAbility; +import mage.abilities.keyword.ShroudAbility; +import mage.cards.CardImpl; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LoneFox + */ +public class AlexisCloak extends CardImpl { + + public AlexisCloak(UUID ownerId) { + super(ownerId, 29, "Alexi's Cloak", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}"); + this.expansionSetCode = "PCY"; + this.subtype.add("Aura"); + + // Flash + this.addAbility(FlashAbility.getInstance()); + // 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); + // Enchanted creature has shroud. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(ShroudAbility.getInstance(), AttachmentType.AURA))); + } + + public AlexisCloak(final AlexisCloak card) { + super(card); + } + + @Override + public AlexisCloak copy() { + return new AlexisCloak(this); + } +} diff --git a/Mage.Sets/src/mage/sets/prophecy/BarbedField.java b/Mage.Sets/src/mage/sets/prophecy/BarbedField.java new file mode 100644 index 0000000000..794f5688e2 --- /dev/null +++ b/Mage.Sets/src/mage/sets/prophecy/BarbedField.java @@ -0,0 +1,84 @@ +/* + * 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.prophecy; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreatureOrPlayer; +import mage.target.common.TargetLandPermanent; + +/** + * + * @author LoneFox + */ +public class BarbedField extends CardImpl { + + public BarbedField(UUID ownerId) { + super(ownerId, 83, "Barbed Field", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}{R}"); + this.expansionSetCode = "PCY"; + this.subtype.add("Aura"); + + // Enchant land + TargetPermanent auraTarget = new TargetLandPermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + // Enchanted land has "{tap}: This land deals 1 damage to target creature or player." + ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new TapSourceCost()); + ability.addTarget(new TargetCreatureOrPlayer()); + Effect effect = new GainAbilityAttachedEffect(ability, AttachmentType.AURA); + effect.setText("Enchanted land has \"{T}: This land deals 1 damage to target creature or player.\""); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); + } + + public BarbedField(final BarbedField card) { + super(card); + } + + @Override + public BarbedField copy() { + return new BarbedField(this); + } +} diff --git a/Mage.Sets/src/mage/sets/prophecy/ChillingApparition.java b/Mage.Sets/src/mage/sets/prophecy/ChillingApparition.java new file mode 100644 index 0000000000..e47fc63331 --- /dev/null +++ b/Mage.Sets/src/mage/sets/prophecy/ChillingApparition.java @@ -0,0 +1,69 @@ +/* + * 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.prophecy; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.DealsDamageToOpponentTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.RegenerateSourceEffect; +import mage.abilities.effects.common.discard.DiscardTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author LoneFox + */ +public class ChillingApparition extends CardImpl { + + public ChillingApparition(UUID ownerId) { + super(ownerId, 59, "Chilling Apparition", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{2}{B}"); + this.expansionSetCode = "PCY"; + this.subtype.add("Spirit"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // {B}: Regenerate Chilling Apparition. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateSourceEffect(), new ManaCostsImpl("{B}"))); + // Whenever Chilling Apparition deals combat damage to a player, that player discards a card. + this.addAbility(new DealsDamageToOpponentTriggeredAbility(new DiscardTargetEffect(1), false, true, true)); + } + + public ChillingApparition(final ChillingApparition card) { + super(card); + } + + @Override + public ChillingApparition copy() { + return new ChillingApparition(this); + } +} diff --git a/Mage.Sets/src/mage/sets/prophecy/LatullaKeldonOverseer.java b/Mage.Sets/src/mage/sets/prophecy/LatullaKeldonOverseer.java new file mode 100644 index 0000000000..5d7ca6f1de --- /dev/null +++ b/Mage.Sets/src/mage/sets/prophecy/LatullaKeldonOverseer.java @@ -0,0 +1,78 @@ +/* + * 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.prophecy; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.DiscardTargetCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.common.ManacostVariableValue; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.target.common.TargetCardInHand; +import mage.target.common.TargetCreatureOrPlayer; + +/** + * + * @author LoneFox + */ +public class LatullaKeldonOverseer extends CardImpl { + + public LatullaKeldonOverseer(UUID ownerId) { + super(ownerId, 95, "Latulla, Keldon Overseer", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{R}{R}"); + this.expansionSetCode = "PCY"; + this.supertype.add("Legendary"); + this.subtype.add("Human"); + this.subtype.add("Spellshaper"); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // {X}{R}, {tap}, Discard two cards: Latulla, Keldon Overseer deals X damage to target creature or player. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new ManacostVariableValue()), new ManaCostsImpl("{X}{R}")); + ability.addCost(new TapSourceCost()); + ability.addCost(new DiscardTargetCost(new TargetCardInHand(2, 2, new FilterCard("two cards")))); + ability.addTarget(new TargetCreatureOrPlayer()); + this.addAbility(ability); + } + + public LatullaKeldonOverseer(final LatullaKeldonOverseer card) { + super(card); + } + + @Override + public LatullaKeldonOverseer copy() { + return new LatullaKeldonOverseer(this); + } +} From 806a52c1c05c2ed241d4d20c85ff0ae56968b38d Mon Sep 17 00:00:00 2001 From: LoneFox Date: Wed, 14 Oct 2015 21:17:54 +0300 Subject: [PATCH 29/46] Fix Chilling Apparition to affect any player it damages --- Mage.Sets/src/mage/sets/prophecy/ChillingApparition.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/prophecy/ChillingApparition.java b/Mage.Sets/src/mage/sets/prophecy/ChillingApparition.java index e47fc63331..816f89bac4 100644 --- a/Mage.Sets/src/mage/sets/prophecy/ChillingApparition.java +++ b/Mage.Sets/src/mage/sets/prophecy/ChillingApparition.java @@ -29,7 +29,7 @@ package mage.sets.prophecy; import java.util.UUID; import mage.MageInt; -import mage.abilities.common.DealsDamageToOpponentTriggeredAbility; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.RegenerateSourceEffect; @@ -55,7 +55,7 @@ public class ChillingApparition extends CardImpl { // {B}: Regenerate Chilling Apparition. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateSourceEffect(), new ManaCostsImpl("{B}"))); // Whenever Chilling Apparition deals combat damage to a player, that player discards a card. - this.addAbility(new DealsDamageToOpponentTriggeredAbility(new DiscardTargetEffect(1), false, true, true)); + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new DiscardTargetEffect(1), false, true)); } public ChillingApparition(final ChillingApparition card) { From c6ff078c09b38d4cc98592a35c0211cdeefcb0b9 Mon Sep 17 00:00:00 2001 From: Anton Date: Wed, 14 Oct 2015 20:34:10 +0200 Subject: [PATCH 30/46] Added Forgotten Ancient --- .../mage/sets/archenemy/ForgottenAncient.java | 52 ++++++ .../sets/planechase/ForgottenAncient.java | 52 ++++++ .../mage/sets/scourge/ForgottenAncient.java | 158 ++++++++++++++++++ 3 files changed, 262 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/archenemy/ForgottenAncient.java create mode 100644 Mage.Sets/src/mage/sets/planechase/ForgottenAncient.java create mode 100644 Mage.Sets/src/mage/sets/scourge/ForgottenAncient.java diff --git a/Mage.Sets/src/mage/sets/archenemy/ForgottenAncient.java b/Mage.Sets/src/mage/sets/archenemy/ForgottenAncient.java new file mode 100644 index 0000000000..0ac189d66b --- /dev/null +++ b/Mage.Sets/src/mage/sets/archenemy/ForgottenAncient.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.archenemy; + +import java.util.UUID; + +/** + * + * @author Blinke + */ +public class ForgottenAncient extends mage.sets.scourge.ForgottenAncient { + + public ForgottenAncient(UUID ownerId) { + super(ownerId); + this.cardNumber = 57; + this.expansionSetCode = "ARC"; + } + + public ForgottenAncient(final ForgottenAncient card) { + super(card); + } + + @Override + public ForgottenAncient copy() { + return new ForgottenAncient(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planechase/ForgottenAncient.java b/Mage.Sets/src/mage/sets/planechase/ForgottenAncient.java new file mode 100644 index 0000000000..e8b9b7dfc5 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planechase/ForgottenAncient.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.planechase; + +import java.util.UUID; + +/** + * + * @author Blinke + */ +public class ForgottenAncient extends mage.sets.scourge.ForgottenAncient { + + public ForgottenAncient(UUID ownerId) { + super(ownerId); + this.cardNumber = 73; + this.expansionSetCode = "HOP"; + } + + public ForgottenAncient(final ForgottenAncient card) { + super(card); + } + + @Override + public ForgottenAncient copy() { + return new ForgottenAncient(this); + } +} diff --git a/Mage.Sets/src/mage/sets/scourge/ForgottenAncient.java b/Mage.Sets/src/mage/sets/scourge/ForgottenAncient.java new file mode 100644 index 0000000000..8107c48a39 --- /dev/null +++ b/Mage.Sets/src/mage/sets/scourge/ForgottenAncient.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 mage.sets.scourge; + +import java.util.ArrayList; +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SpellCastAllTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.AnotherPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.Target; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author Blinke + */ +public class ForgottenAncient extends CardImpl { + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); + static { + filter.add(new AnotherPredicate()); + } + + public ForgottenAncient(UUID ownerId) { + super(ownerId, 120, "Forgotten Ancient", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{G}"); + this.expansionSetCode = "SCG"; + this.subtype.add("Elemental"); + this.power = new MageInt(0); + this.toughness = new MageInt(3); + + // Whenever a player casts a spell, you may put a +1/+1 counter on Forgotten Ancient. + Effect effect = new AddCountersSourceEffect(CounterType.P1P1.createInstance()); + Ability ability = new SpellCastAllTriggeredAbility(effect, true); + this.addAbility(ability); + + // At the beginning of your upkeep, you may move any number of +1/+1 counters from Forgotten Ancient onto other creatures. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new ForgottenAncientEffect(), TargetController.YOU, true)); + } + + public ForgottenAncient(final ForgottenAncient card) { + super(card); + } + + @Override + public ForgottenAncient copy() { + return new ForgottenAncient(this); + } + + class CounterMovement { + public UUID target; + public int counters; + } + + class ForgottenAncientEffect extends OneShotEffect { + + public ForgottenAncientEffect() { + super(Outcome.Benefit); + this.staticText = "you may move any number of +1/+1 counters from Forgotten Ancient onto other creatures."; + } + + public ForgottenAncientEffect(final ForgottenAncientEffect effect) { + super(effect); + } + + @Override + public ForgottenAncientEffect copy() { + return new ForgottenAncientEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); + + if(controller == null || sourcePermanent == null) { + return false; + } + + int numCounters = sourcePermanent.getCounters().getCount(CounterType.P1P1); + ArrayList counterMovements = new ArrayList<>(); + + do { + Target target = new TargetCreaturePermanent(1, 1, filter, true); + if(numCounters == 0 || !target.choose(Outcome.Benefit, source.getControllerId(), source.getSourceId(), game)) { + continue; + } + + int amountToMove = controller.getAmount(0, numCounters, "How many counters do you want to move? " + "(" + numCounters + ")" + " counters remaining.", game); + if(amountToMove > 0) + { + boolean previouslyChosen = false; + for (CounterMovement cm : counterMovements) { + if(cm.target.equals(target.getFirstTarget())) + { + cm.counters += amountToMove; + previouslyChosen = true; + } + } + if(!previouslyChosen) { + CounterMovement cm = new CounterMovement(); + cm.target = target.getFirstTarget(); + cm.counters = amountToMove; + counterMovements.add(cm); + } + + numCounters -= amountToMove; + } + } while(numCounters > 0 && controller.chooseUse(Outcome.Benefit, "Move additonal counters?", source, game)); + + //Move all the counters for each chosen creature + for(CounterMovement cm: counterMovements) { + sourcePermanent.removeCounters(CounterType.P1P1.createInstance(cm.counters), game); + game.getPermanent(cm.target).addCounters(CounterType.P1P1.createInstance(cm.counters), game); + } + return true; + } + } +} From 058650d7315feeaf74a5d86c349805e1d58dfded Mon Sep 17 00:00:00 2001 From: Plopman Date: Wed, 14 Oct 2015 21:19:44 +0200 Subject: [PATCH 31/46] Small changes to sylvan Library and Chrome Mox.It's now possible to select cards directly in the hand instead of in an other window --- .../mage/sets/fifthedition/SylvanLibrary.java | 35 +- .../src/mage/sets/mirrodin/ChromeMox.java | 408 +++++++++--------- 2 files changed, 237 insertions(+), 206 deletions(-) diff --git a/Mage.Sets/src/mage/sets/fifthedition/SylvanLibrary.java b/Mage.Sets/src/mage/sets/fifthedition/SylvanLibrary.java index e6d7c57a60..afa1cd2890 100644 --- a/Mage.Sets/src/mage/sets/fifthedition/SylvanLibrary.java +++ b/Mage.Sets/src/mage/sets/fifthedition/SylvanLibrary.java @@ -30,6 +30,7 @@ package mage.sets.fifthedition; import java.util.HashSet; import java.util.Set; import java.util.UUID; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.BeginningOfDrawTriggeredAbility; import mage.abilities.effects.OneShotEffect; @@ -44,6 +45,7 @@ import mage.constants.TargetController; import mage.constants.WatcherScope; import mage.constants.Zone; import mage.filter.FilterCard; +import mage.filter.predicate.Predicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.players.Player; @@ -110,8 +112,10 @@ class SylvanLibraryEffect extends OneShotEffect { } int numberOfTargets = Math.min(2, cards.size()); if (numberOfTargets > 0) { - TargetCardInHand target = new TargetCardInHand(numberOfTargets, new FilterCard(numberOfTargets + " cards of cards drawn this turn")); - controller.chooseTarget(outcome, cards, target, source, game); + FilterCard filter = new FilterCard(numberOfTargets + " cards of cards drawn this turn"); + filter.add(new CardIdPredicate(cards)); + TargetCardInHand target = new TargetCardInHand(numberOfTargets, filter); + controller.choose(outcome, target, source.getSourceId(), game); Cards cardsPutBack = new CardsImpl(); for (UUID cardId : target.getTargets()) { @@ -190,3 +194,30 @@ class CardsDrawnThisTurnWatcher extends Watcher { return new CardsDrawnThisTurnWatcher(this); } } + + +class CardIdPredicate implements Predicate { + + private final Cards cardsId; + + public CardIdPredicate(Cards cardsId) { + this.cardsId = cardsId; + } + + @Override + public boolean apply(MageObject input, Game game) { + for(UUID uuid : cardsId) + { + if(uuid.equals(input.getId())) + { + return true; + } + } + return false; + } + + @Override + public String toString() { + return "CardsId"; + } +} diff --git a/Mage.Sets/src/mage/sets/mirrodin/ChromeMox.java b/Mage.Sets/src/mage/sets/mirrodin/ChromeMox.java index af94a37a99..73fff870bc 100644 --- a/Mage.Sets/src/mage/sets/mirrodin/ChromeMox.java +++ b/Mage.Sets/src/mage/sets/mirrodin/ChromeMox.java @@ -1,205 +1,205 @@ -/* - * 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.mirrodin; - -import java.util.List; -import java.util.UUID; -import mage.Mana; -import mage.ObjectColor; -import mage.abilities.Ability; -import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.ManaEffect; -import mage.abilities.mana.SimpleManaAbility; -import mage.cards.Card; -import mage.cards.CardImpl; -import mage.choices.Choice; -import mage.choices.ChoiceImpl; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.constants.Zone; -import mage.filter.FilterCard; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.mageobject.CardTypePredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; -import mage.target.TargetCard; - -/** - * - * @author Plopman - */ -public class ChromeMox extends CardImpl { - - public ChromeMox(UUID ownerId) { - super(ownerId, 152, "Chrome Mox", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{0}"); - this.expansionSetCode = "MRD"; - - // Imprint - When Chrome Mox enters the battlefield, you may exile a nonartifact, nonland card from your hand. - this.addAbility(new EntersBattlefieldTriggeredAbility(new ChromeMoxEffect(), true)); - // {tap}: Add one mana of any of the exiled card's colors to your mana pool. - this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, new ChromeMoxManaEffect(), new TapSourceCost())); - } - - public ChromeMox(final ChromeMox card) { - super(card); - } - - @java.lang.Override - public ChromeMox copy() { - return new ChromeMox(this); - } -} - -class ChromeMoxEffect extends OneShotEffect { - - private static final FilterCard filter = new FilterCard("nonartifact, nonland card"); - static { - filter.add(Predicates.not(Predicates.or(new CardTypePredicate(CardType.LAND), new CardTypePredicate(CardType.ARTIFACT)))); - } - public ChromeMoxEffect() { - super(Outcome.Benefit); - staticText = "exile a nonartifact, nonland card from your hand"; - } - - public ChromeMoxEffect(ChromeMoxEffect effect) { - super(effect); - } - - @java.lang.Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player.getHand().size() > 0) { - TargetCard target = new TargetCard(Zone.HAND, filter); - player.choose(Outcome.Benefit, player.getHand(), target, game); - Card card = player.getHand().get(target.getFirstTarget(), game); - if (card != null) { - card.moveToExile(getId(), "Chrome Mox (Imprint)", source.getSourceId(), game); - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - permanent.imprint(card.getId(), game); - } - return true; - } - } - return true; - } - - @java.lang.Override - public ChromeMoxEffect copy() { - return new ChromeMoxEffect(this); - } - - -} - -class ChromeMoxManaEffect extends ManaEffect { - - - ChromeMoxManaEffect() { - super(); - staticText = "Add one mana of any of the exiled card's colors to your mana pool"; - } - - ChromeMoxManaEffect(ChromeMoxManaEffect effect) { - super(effect); - } - - - - @java.lang.Override - public ChromeMoxManaEffect copy() { - return new ChromeMoxManaEffect(this); - } - - @java.lang.Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); - Player player = game.getPlayer(source.getControllerId()); - if (permanent != null && player != null) { - List imprinted = permanent.getImprinted(); - if (imprinted.size() > 0) { - Card imprintedCard = game.getCard(imprinted.get(0)); - if (imprintedCard != null) { - Choice choice = new ChoiceImpl(true); - choice.setMessage("Pick a mana color"); - ObjectColor color = imprintedCard.getColor(game); - if (color.isBlack()) { - choice.getChoices().add("Black"); - } - if (color.isRed()) { - choice.getChoices().add("Red"); - } - if (color.isBlue()) { - choice.getChoices().add("Blue"); - } - if (color.isGreen()) { - choice.getChoices().add("Green"); - } - if (color.isWhite()) { - choice.getChoices().add("White"); - } - - if (choice.getChoices().size() > 0) { - Mana mana = new Mana(); - if (choice.getChoices().size() == 1) { - choice.setChoice(choice.getChoices().iterator().next()); - } else { - player.choose(outcome, choice, game); - } - if (choice.getChoice().equals("Black")) { - player.getManaPool().addMana(Mana.BlackMana, game, source); - } else if (choice.getChoice().equals("Blue")) { - player.getManaPool().addMana(Mana.BlueMana, game, source); - } else if (choice.getChoice().equals("Red")) { - player.getManaPool().addMana(Mana.RedMana, game, source); - } else if (choice.getChoice().equals("Green")) { - player.getManaPool().addMana(Mana.GreenMana, game, source); - } else if (choice.getChoice().equals("White")) { - player.getManaPool().addMana(Mana.WhiteMana, game, source); - } else if (choice.getChoice().equals("Colorless")) { - player.getManaPool().addMana(Mana.ColorlessMana, game, source); - } - checkToFirePossibleEvents(mana, game, source); - player.getManaPool().addMana(mana, game, source); - } - } - } - } - return true; - } - - @java.lang.Override - public Mana getMana(Game game, Ability source) { - return null; - } - +/* + * 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.mirrodin; + +import java.util.List; +import java.util.UUID; +import mage.Mana; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ManaEffect; +import mage.abilities.mana.SimpleManaAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.choices.Choice; +import mage.choices.ChoiceImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetCard; + +/** + * + * @author Plopman + */ +public class ChromeMox extends CardImpl { + + public ChromeMox(UUID ownerId) { + super(ownerId, 152, "Chrome Mox", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{0}"); + this.expansionSetCode = "MRD"; + + // Imprint - When Chrome Mox enters the battlefield, you may exile a nonartifact, nonland card from your hand. + this.addAbility(new EntersBattlefieldTriggeredAbility(new ChromeMoxEffect(), true)); + // {tap}: Add one mana of any of the exiled card's colors to your mana pool. + this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, new ChromeMoxManaEffect(), new TapSourceCost())); + } + + public ChromeMox(final ChromeMox card) { + super(card); + } + + @java.lang.Override + public ChromeMox copy() { + return new ChromeMox(this); + } +} + +class ChromeMoxEffect extends OneShotEffect { + + private static final FilterCard filter = new FilterCard("nonartifact, nonland card"); + static { + filter.add(Predicates.not(Predicates.or(new CardTypePredicate(CardType.LAND), new CardTypePredicate(CardType.ARTIFACT)))); + } + public ChromeMoxEffect() { + super(Outcome.Benefit); + staticText = "exile a nonartifact, nonland card from your hand"; + } + + public ChromeMoxEffect(ChromeMoxEffect effect) { + super(effect); + } + + @java.lang.Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player.getHand().size() > 0) { + TargetCard target = new TargetCard(Zone.HAND, filter); + player.choose(Outcome.Benefit, target, source.getSourceId(), game); + Card card = player.getHand().get(target.getFirstTarget(), game); + if (card != null) { + card.moveToExile(getId(), "Chrome Mox (Imprint)", source.getSourceId(), game); + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + permanent.imprint(card.getId(), game); + } + return true; + } + } + return true; + } + + @java.lang.Override + public ChromeMoxEffect copy() { + return new ChromeMoxEffect(this); + } + + +} + +class ChromeMoxManaEffect extends ManaEffect { + + + ChromeMoxManaEffect() { + super(); + staticText = "Add one mana of any of the exiled card's colors to your mana pool"; + } + + ChromeMoxManaEffect(ChromeMoxManaEffect effect) { + super(effect); + } + + + + @java.lang.Override + public ChromeMoxManaEffect copy() { + return new ChromeMoxManaEffect(this); + } + + @java.lang.Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getSourceId()); + Player player = game.getPlayer(source.getControllerId()); + if (permanent != null && player != null) { + List imprinted = permanent.getImprinted(); + if (imprinted.size() > 0) { + Card imprintedCard = game.getCard(imprinted.get(0)); + if (imprintedCard != null) { + Choice choice = new ChoiceImpl(true); + choice.setMessage("Pick a mana color"); + ObjectColor color = imprintedCard.getColor(game); + if (color.isBlack()) { + choice.getChoices().add("Black"); + } + if (color.isRed()) { + choice.getChoices().add("Red"); + } + if (color.isBlue()) { + choice.getChoices().add("Blue"); + } + if (color.isGreen()) { + choice.getChoices().add("Green"); + } + if (color.isWhite()) { + choice.getChoices().add("White"); + } + + if (choice.getChoices().size() > 0) { + Mana mana = new Mana(); + if (choice.getChoices().size() == 1) { + choice.setChoice(choice.getChoices().iterator().next()); + } else { + player.choose(outcome, choice, game); + } + if (choice.getChoice().equals("Black")) { + player.getManaPool().addMana(Mana.BlackMana, game, source); + } else if (choice.getChoice().equals("Blue")) { + player.getManaPool().addMana(Mana.BlueMana, game, source); + } else if (choice.getChoice().equals("Red")) { + player.getManaPool().addMana(Mana.RedMana, game, source); + } else if (choice.getChoice().equals("Green")) { + player.getManaPool().addMana(Mana.GreenMana, game, source); + } else if (choice.getChoice().equals("White")) { + player.getManaPool().addMana(Mana.WhiteMana, game, source); + } else if (choice.getChoice().equals("Colorless")) { + player.getManaPool().addMana(Mana.ColorlessMana, game, source); + } + checkToFirePossibleEvents(mana, game, source); + player.getManaPool().addMana(mana, game, source); + } + } + } + } + return true; + } + + @java.lang.Override + public Mana getMana(Game game, Ability source) { + return null; + } + } \ No newline at end of file From 11efdcad789545fa0ecb3e46bc48c4e8a13d2b7f Mon Sep 17 00:00:00 2001 From: LoneFox Date: Wed, 14 Oct 2015 22:32:38 +0300 Subject: [PATCH 32/46] Add TargetsPermanentPredicate and use it for existing cards. Implement card: Hydromorph Gull --- .../sets/riseoftheeldrazi/NotOfThisWorld.java | 110 ++------------ .../mage/sets/scarsofmirrodin/TurnAside.java | 134 ++---------------- .../mage/sets/torment/HydromorphGuardian.java | 40 +----- .../src/mage/sets/torment/HydromorphGull.java | 85 +++++++++++ .../src/mage/sets/urzaslegacy/Intervene.java | 116 ++------------- .../other/TargetsPermanentPredicate.java | 76 ++++++++++ 6 files changed, 200 insertions(+), 361 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/torment/HydromorphGull.java create mode 100644 Mage/src/mage/filter/predicate/other/TargetsPermanentPredicate.java diff --git a/Mage.Sets/src/mage/sets/riseoftheeldrazi/NotOfThisWorld.java b/Mage.Sets/src/mage/sets/riseoftheeldrazi/NotOfThisWorld.java index 558d240f73..1ee4a1ce98 100644 --- a/Mage.Sets/src/mage/sets/riseoftheeldrazi/NotOfThisWorld.java +++ b/Mage.Sets/src/mage/sets/riseoftheeldrazi/NotOfThisWorld.java @@ -27,8 +27,6 @@ */ package mage.sets.riseoftheeldrazi; -import java.util.HashSet; -import java.util.Set; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; @@ -40,18 +38,17 @@ import mage.constants.CardType; import mage.constants.Rarity; import mage.constants.TargetController; import mage.constants.Zone; -import mage.filter.Filter; +import mage.filter.FilterSpell; +import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.filter.predicate.other.TargetsPermanentPredicate; import mage.filter.predicate.permanent.ControllerPredicate; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.game.stack.Spell; -import mage.game.stack.StackAbility; import mage.game.stack.StackObject; import mage.target.Target; -import mage.target.TargetObject; -import mage.target.Targets; +import mage.target.TargetSpell; /** * @@ -59,15 +56,19 @@ import mage.target.Targets; */ public class NotOfThisWorld extends CardImpl { + private final static FilterSpell filter = new FilterSpell("spell that targets a permanent you control"); + + static { + filter.add(new TargetsPermanentPredicate(new FilterControlledPermanent())); + } + public NotOfThisWorld(UUID ownerId) { - super(ownerId, 8, "Not of This World", Rarity.UNCOMMON, - new CardType[]{CardType.TRIBAL, CardType.INSTANT}, "{7}"); + super(ownerId, 8, "Not of This World", Rarity.UNCOMMON, new CardType[]{CardType.TRIBAL, CardType.INSTANT}, "{7}"); this.expansionSetCode = "ROE"; this.subtype.add("Eldrazi"); // Counter target spell or ability that targets a permanent you control. - this.getSpellAbility().addTarget( - new TargetStackObjectTargetingControlledPermanent()); + this.getSpellAbility().addTarget(new TargetSpell(filter)); this.getSpellAbility().addEffect(new CounterTargetEffect()); // Not of This World costs {7} less to cast if it targets a spell or ability that targets a creature you control with power 7 or greater. this.addAbility(new SimpleStaticAbility(Zone.STACK, new SpellCostReductionSourceEffect(7, NotOfThisWorldCondition.getInstance()))); @@ -83,93 +84,6 @@ public class NotOfThisWorld extends CardImpl { } } -class TargetStackObjectTargetingControlledPermanent extends TargetObject { - - - public TargetStackObjectTargetingControlledPermanent() { - this.minNumberOfTargets = 1; - this.maxNumberOfTargets = 1; - this.zone = Zone.STACK; - this.targetName = "spell or ability that targets a permanent you control"; - } - - public TargetStackObjectTargetingControlledPermanent(final TargetStackObjectTargetingControlledPermanent target) { - super(target); - } - - @Override - public Filter getFilter() { - throw new UnsupportedOperationException("Not supported."); //To change body of generated methods, choose Tools | Templates. - } - - @Override - public boolean canTarget(UUID id, Ability source, Game game) { - StackObject stackObject = game.getStack().getStackObject(id); - if ((stackObject instanceof Spell) || (stackObject instanceof StackAbility)) { - return true; - } - return false; - } - - @Override - public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { - return canChoose(sourceControllerId, game); - } - - @Override - public boolean canChoose(UUID sourceControllerId, Game game) { - for (StackObject stackObject : game.getStack()) { - if ((stackObject instanceof Spell) || (stackObject instanceof StackAbility)) { - Targets objectTargets = stackObject.getStackAbility().getTargets(); - if(!objectTargets.isEmpty()) { - for (Target target : objectTargets) { - for (UUID targetId : target.getTargets()) { - Permanent targetedPermanent = game.getPermanentOrLKIBattlefield(targetId); - if (targetedPermanent != null && targetedPermanent.getControllerId().equals(sourceControllerId)) { - return true; - } - } - } - } - } - } - return false; - } - - @Override - public Set possibleTargets(UUID sourceId, UUID sourceControllerId, - Game game) { - return possibleTargets(sourceControllerId, game); - } - - @Override - public Set possibleTargets(UUID sourceControllerId, Game game) { - Set possibleTargets = new HashSet<>(); - for (StackObject stackObject : game.getStack()) { - if ((stackObject instanceof Spell) || (stackObject instanceof StackAbility)) { - Targets objectTargets = stackObject.getStackAbility().getTargets(); - if(!objectTargets.isEmpty()) { - for (Target target : objectTargets) { - for (UUID targetId : target.getTargets()) { - Permanent targetedPermanent = game.getPermanentOrLKIBattlefield(targetId); - if (targetedPermanent != null && targetedPermanent.getControllerId().equals(sourceControllerId)) { - possibleTargets.add(stackObject.getId()); - } - } - } - } - } - } - return possibleTargets; - } - - @Override - public TargetStackObjectTargetingControlledPermanent copy() { - return new TargetStackObjectTargetingControlledPermanent(this); - } - -} - class NotOfThisWorldCondition implements Condition { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature you control with power 7 or greater"); diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/TurnAside.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/TurnAside.java index f6f9cb5c4c..a878638f92 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/TurnAside.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/TurnAside.java @@ -28,40 +28,35 @@ package mage.sets.scarsofmirrodin; -import mage.constants.CardType; -import mage.constants.Rarity; -import mage.abilities.Ability; +import java.util.UUID; import mage.abilities.effects.common.CounterTargetEffect; import mage.cards.CardImpl; -import mage.constants.Zone; -import mage.filter.Filter; +import mage.constants.CardType; +import mage.constants.Rarity; import mage.filter.FilterSpell; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.game.stack.Spell; -import mage.game.stack.StackObject; -import mage.target.TargetObject; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.other.TargetsPermanentPredicate; +import mage.target.TargetSpell; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; -import mage.target.Target; /** * @author ayratn */ public class TurnAside extends CardImpl { - private static FilterSpell filter = new FilterSpell("spell that targets a permanent you control"); + private final static FilterSpell filter = new FilterSpell("spell that targets a permanent you control"); + + static { + filter.add(new TargetsPermanentPredicate(new FilterControlledPermanent())); + } public TurnAside(UUID ownerId) { super(ownerId, 49, "Turn Aside", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{U}"); this.expansionSetCode = "SOM"; - // Counter target spell that targets a permanent you control. this.getSpellAbility().addEffect(new CounterTargetEffect()); - this.getSpellAbility().addTarget(new CustomTargetSpell(filter)); + this.getSpellAbility().addTarget(new TargetSpell(filter)); } public TurnAside(final TurnAside card) { @@ -72,109 +67,4 @@ public class TurnAside extends CardImpl { public TurnAside copy() { return new TurnAside(this); } - - private class CustomTargetSpell extends TargetObject { - - protected FilterSpell filter; - - public CustomTargetSpell() { - this(1, 1, new FilterSpell()); - } - - public CustomTargetSpell(FilterSpell filter) { - this(1, 1, filter); - } - - public CustomTargetSpell(int numTargets, FilterSpell filter) { - this(numTargets, numTargets, filter); - } - - public CustomTargetSpell(int minNumTargets, int maxNumTargets, FilterSpell filter) { - this.minNumberOfTargets = minNumTargets; - this.maxNumberOfTargets = maxNumTargets; - this.zone = Zone.STACK; - this.filter = filter; - this.targetName = filter.getMessage(); - } - - public CustomTargetSpell(final CustomTargetSpell target) { - super(target); - this.filter = target.filter.copy(); - } - - @Override - public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { - return canChoose(sourceControllerId, game); - } - - @Override - public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { - return possibleTargets(sourceControllerId, game); - } - - @Override - public boolean canTarget(UUID id, Ability source, Game game) { - if (super.canTarget(id, source, game)) { - if (targetsMyPermanent(id, source.getControllerId(), game)) { - return true; - } - } - return false; - } - - @Override - public boolean canChoose(UUID sourceControllerId, Game game) { - int count = 0; - for (StackObject stackObject : game.getStack()) { - if (stackObject instanceof Spell && game.getPlayer(sourceControllerId).getInRange().contains(stackObject.getControllerId()) && filter.match((Spell) stackObject, game)) { - if (targetsMyPermanent(stackObject.getId(), sourceControllerId, game)) { - count++; - if (count >= this.minNumberOfTargets) - return true; - } - } - } - return false; - } - - @Override - public Set possibleTargets(UUID sourceControllerId, Game game) { - Set possibleTargets = new HashSet(); - for (StackObject stackObject : game.getStack()) { - if (stackObject instanceof Spell && game.getPlayer(sourceControllerId).getInRange().contains(stackObject.getControllerId()) && filter.match((Spell) stackObject, game)) { - if (targetsMyPermanent(stackObject.getId(), sourceControllerId, game)) { - - possibleTargets.add(stackObject.getId()); - } - } - } - return possibleTargets; - } - - @Override - public Filter getFilter() { - return filter; - } - - private boolean targetsMyPermanent(UUID id, UUID controllerId, Game game) { - StackObject spell = game.getStack().getStackObject(id); - if (spell != null) { - Ability ability = spell.getStackAbility(); - for (Target target : ability.getTargets()) { - for (UUID permanentId : target.getTargets()) { - Permanent permanent = game.getPermanent(permanentId); - if (permanent != null && permanent.getControllerId().equals(controllerId)) { - return true; - } - } - } - } - return false; - } - - @Override - public CustomTargetSpell copy() { - return new CustomTargetSpell(this); - } - } } diff --git a/Mage.Sets/src/mage/sets/torment/HydromorphGuardian.java b/Mage.Sets/src/mage/sets/torment/HydromorphGuardian.java index 261fc1c2e3..0eaaf30cd1 100644 --- a/Mage.Sets/src/mage/sets/torment/HydromorphGuardian.java +++ b/Mage.Sets/src/mage/sets/torment/HydromorphGuardian.java @@ -29,9 +29,7 @@ package mage.sets.torment; import java.util.UUID; import mage.MageInt; -import mage.MageObject; import mage.abilities.Ability; -import mage.abilities.Mode; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.mana.ColoredManaCost; @@ -42,12 +40,8 @@ import mage.constants.ColoredManaSymbol; import mage.constants.Rarity; import mage.constants.Zone; import mage.filter.FilterSpell; -import mage.filter.predicate.ObjectSourcePlayer; -import mage.filter.predicate.ObjectSourcePlayerPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.game.stack.Spell; -import mage.target.Target; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.other.TargetsPermanentPredicate; import mage.target.TargetSpell; /** @@ -59,7 +53,7 @@ public class HydromorphGuardian extends CardImpl { private final static FilterSpell filter = new FilterSpell("spell that targets one or more creatures you control"); static { - filter.add(new HydromorphGuardianPredicate()); + filter.add(new TargetsPermanentPredicate(new FilterControlledCreaturePermanent())); } public HydromorphGuardian(UUID ownerId) { @@ -85,31 +79,3 @@ public class HydromorphGuardian extends CardImpl { return new HydromorphGuardian(this); } } - -class HydromorphGuardianPredicate implements ObjectSourcePlayerPredicate> { - - @Override - public boolean apply(ObjectSourcePlayer input, Game game) { - Spell spell = game.getStack().getSpell(input.getObject().getId()); - if (spell != null) { - for (UUID modeId : spell.getSpellAbility().getModes().getSelectedModes()) { - Mode mode = spell.getSpellAbility().getModes().get(modeId); - for (Target target : mode.getTargets()) { - for (UUID targetId : target.getTargets()) { - Permanent permanent = game.getPermanent(targetId); - if (permanent.getCardType().contains(CardType.CREATURE) - && permanent.getControllerId().equals(input.getPlayerId())) { - return true; - } - } - } - } - } - return false; - } - - @Override - public String toString() { - return "that targets one or more creatures you control"; - } -} diff --git a/Mage.Sets/src/mage/sets/torment/HydromorphGull.java b/Mage.Sets/src/mage/sets/torment/HydromorphGull.java new file mode 100644 index 0000000000..c427837724 --- /dev/null +++ b/Mage.Sets/src/mage/sets/torment/HydromorphGull.java @@ -0,0 +1,85 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.torment; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.mana.ColoredManaCost; +import mage.abilities.effects.common.CounterTargetEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.ColoredManaSymbol; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterSpell; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.other.TargetsPermanentPredicate; +import mage.target.TargetSpell; + +/** + * + * @author LoneFox + */ +public class HydromorphGull extends CardImpl { + + private final static FilterSpell filter = new FilterSpell("spell that targets one or more creatures you control"); + + static { + filter.add(new TargetsPermanentPredicate(new FilterControlledCreaturePermanent())); + } + + public HydromorphGull(UUID ownerId) { + super(ownerId, 40, "Hydromorph Gull", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{3}{U}{U}"); + this.expansionSetCode = "TOR"; + this.subtype.add("Elemental"); + this.subtype.add("Bird"); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + // {U}, Sacrifice Hydromorph Gull: Counter target spell that targets one or more creatures you control. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CounterTargetEffect(), new ColoredManaCost(ColoredManaSymbol.U)); + ability.addCost(new SacrificeSourceCost()); + ability.addTarget(new TargetSpell(filter)); + this.addAbility(ability); + } + + public HydromorphGull(final HydromorphGull card) { + super(card); + } + + @Override + public HydromorphGull copy() { + return new HydromorphGull(this); + } +} diff --git a/Mage.Sets/src/mage/sets/urzaslegacy/Intervene.java b/Mage.Sets/src/mage/sets/urzaslegacy/Intervene.java index 2713856744..aa35fd116b 100644 --- a/Mage.Sets/src/mage/sets/urzaslegacy/Intervene.java +++ b/Mage.Sets/src/mage/sets/urzaslegacy/Intervene.java @@ -27,24 +27,15 @@ */ package mage.sets.urzaslegacy; -import java.util.HashSet; -import java.util.Set; import java.util.UUID; - -import mage.constants.CardType; -import mage.constants.Rarity; -import mage.abilities.Ability; import mage.abilities.effects.common.CounterTargetEffect; import mage.cards.CardImpl; -import mage.constants.Zone; -import mage.filter.Filter; +import mage.constants.CardType; +import mage.constants.Rarity; import mage.filter.FilterSpell; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.game.stack.Spell; -import mage.game.stack.StackObject; -import mage.target.Target; -import mage.target.TargetObject; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.other.TargetsPermanentPredicate; +import mage.target.TargetSpell; /** * @@ -52,13 +43,19 @@ import mage.target.TargetObject; */ public class Intervene extends CardImpl { + private final static FilterSpell filter = new FilterSpell("spell that targets a creature"); + + static { + filter.add(new TargetsPermanentPredicate(new FilterCreaturePermanent())); + } + public Intervene(UUID ownerId) { super(ownerId, 33, "Intervene", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{U}"); this.expansionSetCode = "ULG"; // Counter target spell that targets a creature. - this.getSpellAbility().addTarget(new InterveneTargetSpell()); + this.getSpellAbility().addTarget(new TargetSpell(filter)); this.getSpellAbility().addEffect(new CounterTargetEffect()); } @@ -70,93 +67,4 @@ public class Intervene extends CardImpl { public Intervene copy() { return new Intervene(this); } - - private class InterveneTargetSpell extends TargetObject { - - - public InterveneTargetSpell() { - super(1, Zone.STACK); - this.targetName = "spell that targets a creature"; - } - - public InterveneTargetSpell(final InterveneTargetSpell target) { - super(target); - } - - @Override - public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { - return canChoose(sourceControllerId, game); - } - - @Override - public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { - return possibleTargets(sourceControllerId, game); - } - - @Override - public boolean canTarget(UUID id, Ability source, Game game) { - if (super.canTarget(id, source, game)) { - if (targetsCreature(id, game)) { - return true; - } - } - return false; - } - - @Override - public boolean canChoose(UUID sourceControllerId, Game game) { - for (StackObject stackObject : game.getStack()) { - if (stackObject instanceof Spell) { - if (targetsCreature(stackObject.getId(), game)) { - return true; - } - } - } - return false; - } - - @Override - public Set possibleTargets(UUID sourceControllerId, Game game) { - Set possibleTargets = new HashSet(); - for (StackObject stackObject : game.getStack()) { - if (stackObject instanceof Spell) { - if (targetsCreature(stackObject.getId(), game)) { - possibleTargets.add(stackObject.getId()); - } - } - } - return possibleTargets; - } - - - private boolean targetsCreature(UUID id, Game game) { - StackObject spell = game.getStack().getStackObject(id); - if (spell != null) { - Ability ability = spell.getStackAbility(); - if (ability != null && !ability.getTargets().isEmpty()) { - for (Target target : ability.getTargets()) { - for (UUID targetId : target.getTargets()) { - Permanent permanent = game.getPermanent(targetId); - if (permanent != null && permanent.getCardType().contains(CardType.CREATURE)) { - return true; - } - } - } - } - } - return false; - } - - @Override - public InterveneTargetSpell copy() { - return new InterveneTargetSpell(this); - } - - @Override - public Filter getFilter() { - return new FilterSpell(); - } - } } - - diff --git a/Mage/src/mage/filter/predicate/other/TargetsPermanentPredicate.java b/Mage/src/mage/filter/predicate/other/TargetsPermanentPredicate.java new file mode 100644 index 0000000000..0cf864bbc4 --- /dev/null +++ b/Mage/src/mage/filter/predicate/other/TargetsPermanentPredicate.java @@ -0,0 +1,76 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.filter.predicate.other; + +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Mode; +import mage.filter.FilterPermanent; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.stack.StackObject; +import mage.target.Target; + +/** + * + * @author LoneFox + */ +public class TargetsPermanentPredicate implements ObjectSourcePlayerPredicate> { + + private final FilterPermanent targetFilter; + + public TargetsPermanentPredicate(FilterPermanent targetFilter) { + this.targetFilter = targetFilter; + } + + @Override + public boolean apply(ObjectSourcePlayer input, Game game) { + StackObject object = game.getStack().getStackObject(input.getObject().getId()); + if(object != null) { + for(UUID modeId : object.getStackAbility().getModes().getSelectedModes()) { + Mode mode = object.getStackAbility().getModes().get(modeId); + for(Target target : mode.getTargets()) { + for(UUID targetId : target.getTargets()) { + Permanent permanent = game.getPermanentOrLKIBattlefield(targetId); + if(permanent != null) { + return targetFilter.match(permanent, input.getSourceId(), input.getPlayerId(), game); + } + } + } + } + } + return false; + } + + @Override + public String toString() { + return "that targets " + targetFilter.getMessage(); + } +} From f801477ab5ab8fec98e64d5f144db4ae88b991af Mon Sep 17 00:00:00 2001 From: LoneFox Date: Wed, 14 Oct 2015 22:58:43 +0300 Subject: [PATCH 33/46] Fix TargetStackObject not handling some predicate types correctly. Implement card to test it: Diplomatic Escort --- .../mercadianmasques/DiplomaticEscort.java | 83 +++++++++++++++++++ Mage/src/mage/target/TargetStackObject.java | 32 +++---- 2 files changed, 99 insertions(+), 16 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/mercadianmasques/DiplomaticEscort.java diff --git a/Mage.Sets/src/mage/sets/mercadianmasques/DiplomaticEscort.java b/Mage.Sets/src/mage/sets/mercadianmasques/DiplomaticEscort.java new file mode 100644 index 0000000000..0abf5537b9 --- /dev/null +++ b/Mage.Sets/src/mage/sets/mercadianmasques/DiplomaticEscort.java @@ -0,0 +1,83 @@ +/* + * 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.mercadianmasques; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.DiscardCardCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.CounterTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.FilterStackObject; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.other.TargetsPermanentPredicate; +import mage.target.TargetStackObject; + +/** + * + * @author LoneFox + */ +public class DiplomaticEscort extends CardImpl { + + private final static FilterStackObject filter = new FilterStackObject("spell or ability that targets a creature"); + + static { + filter.add(new TargetsPermanentPredicate(new FilterCreaturePermanent())); + } + + public DiplomaticEscort(UUID ownerId) { + super(ownerId, 74, "Diplomatic Escort", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{U}"); + this.expansionSetCode = "MMQ"; + this.subtype.add("Human"); + this.subtype.add("Spellshaper"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // {U}, {tap}, Discard a card: Counter target spell or ability that targets a creature. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CounterTargetEffect(), new ManaCostsImpl("{U}")); + ability.addCost(new TapSourceCost()); + ability.addCost(new DiscardCardCost()); + ability.addTarget(new TargetStackObject(filter)); + this.addAbility(ability); + } + + public DiplomaticEscort(final DiplomaticEscort card) { + super(card); + } + + @Override + public DiplomaticEscort copy() { + return new DiplomaticEscort(this); + } +} diff --git a/Mage/src/mage/target/TargetStackObject.java b/Mage/src/mage/target/TargetStackObject.java index 0a8e91a4e9..467565ee72 100644 --- a/Mage/src/mage/target/TargetStackObject.java +++ b/Mage/src/mage/target/TargetStackObject.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,7 +20,7 @@ * 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. @@ -80,21 +80,16 @@ public class TargetStackObject extends TargetObject { public boolean canTarget(UUID id, Ability source, Game game) { StackObject stackObject = game.getStack().getStackObject(id); if (stackObject != null) { - return filter.match(stackObject, game); + return filter.match(stackObject, source.getSourceId(), source.getControllerId(), game); } return false; } @Override public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { - return canChoose(sourceControllerId, game); - } - - @Override - public boolean canChoose(UUID sourceControllerId, Game game) { int count = 0; for (StackObject stackObject: game.getStack()) { - if (game.getPlayer(sourceControllerId).getInRange().contains(stackObject.getControllerId()) && filter.match(stackObject, game)) { + if (game.getPlayer(sourceControllerId).getInRange().contains(stackObject.getControllerId()) && filter.match(stackObject, sourceId, sourceControllerId, game)) { count++; if (count >= this.minNumberOfTargets) { return true; @@ -105,21 +100,26 @@ public class TargetStackObject extends TargetObject { } @Override - public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { - return possibleTargets(sourceControllerId, game); + public boolean canChoose(UUID sourceControllerId, Game game) { + return canChoose(null, sourceControllerId, game); } @Override - public Set possibleTargets(UUID sourceControllerId, Game game) { + public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { Set possibleTargets = new HashSet<>(); for (StackObject stackObject: game.getStack()) { - if (game.getPlayer(sourceControllerId).getInRange().contains(stackObject.getControllerId()) && filter.match(stackObject, game)) { + if (game.getPlayer(sourceControllerId).getInRange().contains(stackObject.getControllerId()) && filter.match(stackObject, sourceId, sourceControllerId, game)) { possibleTargets.add(stackObject.getId()); } } return possibleTargets; } + @Override + public Set possibleTargets(UUID sourceControllerId, Game game) { + return this.possibleTargets(null, sourceControllerId, game); + } + @Override public TargetStackObject copy() { return new TargetStackObject(this); From 7cee34be546ab123d73f12b9585b1bfce76211d7 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 15 Oct 2015 08:32:58 +0200 Subject: [PATCH 34/46] * Some changed to card moving (not finished) --- .../avacynrestored/InfiniteReflection.java | 5 +- .../sets/timespiral/ScionOfTheUrDragon.java | 12 +-- .../cards/copy/InfiniteReflectionTest.java | 69 ++++++++++++++ .../org/mage/test/cards/copy/VesuvaTest.java | 22 ++--- .../java/org/mage/test/player/TestPlayer.java | 5 + .../common/AsEntersBattlefieldAbility.java | 7 +- .../abilities/effects/ContinuousEffects.java | 4 +- .../effects/EntersBattlefieldEffect.java | 6 +- .../effects/common/ChooseColorEffect.java | 9 +- .../abilities/effects/common/CopyEffect.java | 91 ++++++++++--------- ...romGraveyardToBattlefieldTargetEffect.java | 2 +- .../counter/AddCountersSourceEffect.java | 27 +++--- Mage/src/mage/game/stack/Spell.java | 5 + Mage/src/mage/players/Player.java | 3 + Mage/src/mage/players/PlayerImpl.java | 39 ++++---- 15 files changed, 202 insertions(+), 104 deletions(-) create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/copy/InfiniteReflectionTest.java diff --git a/Mage.Sets/src/mage/sets/avacynrestored/InfiniteReflection.java b/Mage.Sets/src/mage/sets/avacynrestored/InfiniteReflection.java index 1744100e91..e2b81f4ec5 100644 --- a/Mage.Sets/src/mage/sets/avacynrestored/InfiniteReflection.java +++ b/Mage.Sets/src/mage/sets/avacynrestored/InfiniteReflection.java @@ -46,6 +46,7 @@ import mage.constants.Zone; import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; import mage.game.Game; +import mage.game.events.EntersTheBattlefieldEvent; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.game.permanent.PermanentToken; @@ -141,7 +142,7 @@ class InfiniteReflectionEntersBattlefieldEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - Permanent permanent = game.getPermanent(event.getTargetId()); + Permanent permanent = ((EntersTheBattlefieldEvent) event).getTarget(); return permanent != null && permanent.getControllerId().equals(source.getControllerId()) && permanent.getCardType().contains(CardType.CREATURE) && !(permanent instanceof PermanentToken); @@ -149,7 +150,7 @@ class InfiniteReflectionEntersBattlefieldEffect extends ReplacementEffectImpl { @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { - MageObject toCopyToObject = game.getObject(event.getTargetId()); + MageObject toCopyToObject = ((EntersTheBattlefieldEvent) event).getTarget(); Permanent sourcePermanent = game.getPermanent(source.getSourceId()); if (sourcePermanent != null && toCopyToObject != null && sourcePermanent.getAttachedTo() != null) { Permanent toCopyFromPermanent = game.getPermanent(sourcePermanent.getAttachedTo()); diff --git a/Mage.Sets/src/mage/sets/timespiral/ScionOfTheUrDragon.java b/Mage.Sets/src/mage/sets/timespiral/ScionOfTheUrDragon.java index 3112e6b86b..1a3700f00b 100644 --- a/Mage.Sets/src/mage/sets/timespiral/ScionOfTheUrDragon.java +++ b/Mage.Sets/src/mage/sets/timespiral/ScionOfTheUrDragon.java @@ -53,7 +53,6 @@ import mage.target.common.TargetCardInLibrary; /** * @author duncant */ - public class ScionOfTheUrDragon extends CardImpl { public ScionOfTheUrDragon(UUID ownerId) { @@ -69,8 +68,8 @@ public class ScionOfTheUrDragon extends CardImpl { // {2}: Search your library for a Dragon permanent card and put it into your graveyard. If you do, Scion of the Ur-Dragon becomes a copy of that card until end of turn. Then shuffle your library. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, - new ScionOfTheUrDragonEffect(), - new ManaCostsImpl("{2}"))); + new ScionOfTheUrDragonEffect(), + new ManaCostsImpl("{2}"))); } public ScionOfTheUrDragon(final ScionOfTheUrDragon card) { @@ -84,15 +83,16 @@ public class ScionOfTheUrDragon extends CardImpl { } class ScionOfTheUrDragonEffect extends SearchEffect { + private static final FilterCard filter = new FilterPermanentCard("Dragon permanent card"); - + static { filter.add(new SubtypePredicate("Dragon")); } - + public ScionOfTheUrDragonEffect() { super(new TargetCardInLibrary(filter), Outcome.Copy); - staticText = "Search your library for a Dragon permanent card and put it into your graveyard. If you do, Scion of the Ur-Dragon becomes a copy of that card until end of turn. Then shuffle your library."; + staticText = "Search your library for a Dragon permanent card and put it into your graveyard. If you do, {this} becomes a copy of that card until end of turn. Then shuffle your library."; } ScionOfTheUrDragonEffect(final ScionOfTheUrDragonEffect effect) { diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/InfiniteReflectionTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/InfiniteReflectionTest.java new file mode 100644 index 0000000000..c60f7e912b --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/InfiniteReflectionTest.java @@ -0,0 +1,69 @@ +/* + * 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.copy; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class InfiniteReflectionTest extends CardTestPlayerBase { + + /** + * + */ + @Test + public void testCopyAsEnters() { + addCard(Zone.BATTLEFIELD, playerA, "Island", 1); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 9); + addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 1); +// addCard(Zone.BATTLEFIELD, playerA, "Birds of Paradise", 1); +// addCard(Zone.HAND, playerA, "Nantuko Husk", 1);// {2}{B} + addCard(Zone.GRAVEYARD, playerA, "Pillarfield Ox", 1); + // 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); // {B} + + // Enchant creature + // When Infinite Reflection enters the battlefield attached to a creature, each other nontoken creature you control becomes a copy of that creature. + // Nontoken creatures you control enter the battlefield as a copy of enchanted creature. + addCard(Zone.HAND, playerA, "Infinite Reflection", 1); // {5}{U} + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Infinite Reflection", "Silvercoat Lion"); +// castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Nantuko Husk"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reanimate", "Pillarfield Ox"); + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "Silvercoat Lion", 2); + } + +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/VesuvaTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/VesuvaTest.java index 601be2d21f..48fc3962b1 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/VesuvaTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/VesuvaTest.java @@ -60,12 +60,11 @@ public class VesuvaTest extends CardTestPlayerBase { addCard(Zone.HAND, playerB, "Glimmerpost", 1); - playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Glimmerpost"); playLand(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Glimmerpost"); playLand(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Vesuva"); setChoice(playerA, "Glimmerpost"); - + setStopAt(3, PhaseStep.BEGIN_COMBAT); execute(); @@ -75,31 +74,32 @@ public class VesuvaTest extends CardTestPlayerBase { assertLife(playerA, 24); // 20 + 1 + 3 assertLife(playerB, 22); // 20 + 2 } - + @Test public void testDarkDepth() { // Dark Depths enters the battlefield with ten ice counters on it. // {3}: Remove an ice counter from Dark Depths. // When Dark Depths has no ice counters on it, sacrifice it. If you do, put a legendary 20/20 black Avatar creature token with flying and "This creature is indestructible" named Marit Lage onto the battlefield. addCard(Zone.BATTLEFIELD, playerB, "Dark Depths", 1); - + // You may have Vesuva enter the battlefield tapped as a copy of any land on the battlefield. - addCard(Zone.HAND, playerA, "Vesuva", 1); - + addCard(Zone.HAND, playerA, "Vesuva", 1); + playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Vesuva"); setChoice(playerA, "Dark Depths"); - + setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); - assertPermanentCount(playerA, "Dark Depths", 1); assertPermanentCount(playerB, "Dark Depths", 1); - + assertPermanentCount(playerA, "Vesuva", 0); + assertPermanentCount(playerA, "Dark Depths", 1); + Permanent darkDepth = getPermanent("Dark Depths", playerA); if (darkDepth != null) { - Assert.assertEquals(darkDepth.getCounters().getCount("ice"), 10); + Assert.assertEquals(10, darkDepth.getCounters().getCount("ice")); } - + assertTappedCount("Dark Depths", true, 1); } } diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java index 55ebad8d17..5d0df67f11 100644 --- a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java +++ b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java @@ -1970,6 +1970,11 @@ public class TestPlayer implements Player { return computerPlayer.scry(value, source, game); } + @Override + public boolean moveCards(Card card, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, ArrayList appliedEffects) { + return computerPlayer.moveCards(card, toZone, source, game, tapped, faceDown, byOwner, appliedEffects); + } + @Override public boolean moveCards(Set cards, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, ArrayList appliedEffects) { return computerPlayer.moveCards(cards, toZone, source, game, tapped, faceDown, byOwner, appliedEffects); diff --git a/Mage/src/mage/abilities/common/AsEntersBattlefieldAbility.java b/Mage/src/mage/abilities/common/AsEntersBattlefieldAbility.java index e41774bf77..d6f0e0fea6 100644 --- a/Mage/src/mage/abilities/common/AsEntersBattlefieldAbility.java +++ b/Mage/src/mage/abilities/common/AsEntersBattlefieldAbility.java @@ -39,11 +39,11 @@ import mage.constants.Zone; public class AsEntersBattlefieldAbility extends StaticAbility { public AsEntersBattlefieldAbility(Effect effect) { - super(Zone.BATTLEFIELD, new EntersBattlefieldEffect(effect)); + super(Zone.ALL, new EntersBattlefieldEffect(effect)); } public AsEntersBattlefieldAbility(Effect effect, String text) { - super(Zone.BATTLEFIELD, new EntersBattlefieldEffect(effect, text)); + super(Zone.ALL, new EntersBattlefieldEffect(effect, text)); } public AsEntersBattlefieldAbility(AsEntersBattlefieldAbility ability) { @@ -59,10 +59,9 @@ public class AsEntersBattlefieldAbility extends StaticAbility { return; } } - super.addEffect(effect); + super.addEffect(effect); } - @Override public AsEntersBattlefieldAbility copy() { return new AsEntersBattlefieldAbility(this); diff --git a/Mage/src/mage/abilities/effects/ContinuousEffects.java b/Mage/src/mage/abilities/effects/ContinuousEffects.java index de323f1202..c5b4661816 100644 --- a/Mage/src/mage/abilities/effects/ContinuousEffects.java +++ b/Mage/src/mage/abilities/effects/ContinuousEffects.java @@ -876,7 +876,9 @@ public class ContinuousEffects implements Serializable { } } // Must be called here for some effects to be able to work correctly - // TODO: add info which effects need that call + // For example: Vesuva copying a Dark Depth (VesuvaTest:testDarkDepth) + // This call should be removed if possible as replacement effects of EntersTheBattlefield events + // do no longer work correctly because the entering permanents are not yet on the battlefield (before they were). game.applyEffects(); } while (true); return caught; diff --git a/Mage/src/mage/abilities/effects/EntersBattlefieldEffect.java b/Mage/src/mage/abilities/effects/EntersBattlefieldEffect.java index 5a03cbcf33..ef6bb795d1 100644 --- a/Mage/src/mage/abilities/effects/EntersBattlefieldEffect.java +++ b/Mage/src/mage/abilities/effects/EntersBattlefieldEffect.java @@ -34,6 +34,7 @@ import mage.abilities.condition.Condition; import mage.constants.Duration; import mage.constants.Zone; import mage.game.Game; +import mage.game.events.EntersTheBattlefieldEvent; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; import mage.game.stack.Spell; @@ -51,6 +52,7 @@ public class EntersBattlefieldEffect extends ReplacementEffectImpl { protected Condition condition; protected boolean optional; + public static final String ENTERING_PERMANENT = "enteringPermanent"; public static final String SOURCE_CAST_SPELL_ABILITY = "sourceCastSpellAbility"; public EntersBattlefieldEffect(Effect baseEffect) { @@ -112,7 +114,7 @@ public class EntersBattlefieldEffect extends ReplacementEffectImpl { if (controller == null || object == null) { return false; } - if (!controller.chooseUse(outcome, new StringBuilder("Use effect of ").append(object.getLogName()).append("?").toString(), source, game)) { + if (!controller.chooseUse(outcome, "Use effect of " + object.getLogName() + "?", source, game)) { return false; } } @@ -131,6 +133,8 @@ public class EntersBattlefieldEffect extends ReplacementEffectImpl { if (spell != null) { effect.setValue(SOURCE_CAST_SPELL_ABILITY, spell.getSpellAbility()); } + // Because the permanent is not on the battlefield yet, it has to be taken from the event + effect.setValue(ENTERING_PERMANENT, ((EntersTheBattlefieldEvent) event).getTarget()); effect.apply(game, source); } } diff --git a/Mage/src/mage/abilities/effects/common/ChooseColorEffect.java b/Mage/src/mage/abilities/effects/common/ChooseColorEffect.java index 8f22a961ad..43836dd2f7 100644 --- a/Mage/src/mage/abilities/effects/common/ChooseColorEffect.java +++ b/Mage/src/mage/abilities/effects/common/ChooseColorEffect.java @@ -25,10 +25,10 @@ * 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.abilities.Ability; +import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.OneShotEffect; import mage.choices.ChoiceColor; import mage.constants.Outcome; @@ -56,6 +56,9 @@ public class ChooseColorEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent == null) { + permanent = (Permanent) getValue(EntersBattlefieldEffect.ENTERING_PERMANENT); + } if (controller != null && permanent != null) { ChoiceColor choice = new ChoiceColor(); while (!choice.isChosen()) { @@ -65,7 +68,7 @@ public class ChooseColorEffect extends OneShotEffect { } } if (!game.isSimulation()) { - game.informPlayers(permanent.getLogName()+": "+controller.getLogName()+" has chosen "+choice.getChoice()); + game.informPlayers(permanent.getLogName() + ": " + controller.getLogName() + " has chosen " + choice.getChoice()); } game.getState().setValue(source.getSourceId() + "_color", choice.getColor()); permanent.addInfo("chosen color", CardUtil.addToolTipMarkTags("Chosen color: " + choice.getChoice()), game); @@ -79,4 +82,4 @@ public class ChooseColorEffect extends OneShotEffect { return new ChooseColorEffect(this); } -} \ No newline at end of file +} diff --git a/Mage/src/mage/abilities/effects/common/CopyEffect.java b/Mage/src/mage/abilities/effects/common/CopyEffect.java index 9d1194fda2..86bc3f060f 100644 --- a/Mage/src/mage/abilities/effects/common/CopyEffect.java +++ b/Mage/src/mage/abilities/effects/common/CopyEffect.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,15 +20,13 @@ * 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 java.util.UUID; import mage.MageObject; import mage.MageObjectReference; @@ -56,39 +54,42 @@ public class CopyEffect extends ContinuousEffectImpl { /** * Object we copy from */ - private MageObject target; - - private UUID sourceId; + private MageObject copyFromObject; + + private UUID copyToObjectId; private ApplyToPermanent applier; - - public CopyEffect(MageObject target, UUID sourceId) { - this(Duration.Custom, target, sourceId); + + public CopyEffect(MageObject copyFromObject, UUID copyToObjectId) { + this(Duration.Custom, copyFromObject, copyToObjectId); } - - public CopyEffect(Duration duration, MageObject target, UUID sourceId) { + + public CopyEffect(Duration duration, MageObject copyFromObject, UUID copyToObjectId) { super(duration, Layer.CopyEffects_1, SubLayer.NA, Outcome.BecomeCreature); - this.target = target; - this.sourceId = sourceId; + this.copyFromObject = copyFromObject; + this.copyToObjectId = copyToObjectId; } public CopyEffect(final CopyEffect effect) { super(effect); - this.target = effect.target.copy(); - this.sourceId = effect.sourceId; + this.copyFromObject = effect.copyFromObject.copy(); + this.copyToObjectId = effect.copyToObjectId; this.applier = effect.applier; } @Override public void init(Ability source, Game game) { super.init(source, game); - if (!(target instanceof Permanent) && (target instanceof Card)) { - this.target = new PermanentCard((Card)target, source.getControllerId(), game); + if (!(copyFromObject instanceof Permanent) && (copyFromObject instanceof Card)) { + this.copyFromObject = new PermanentCard((Card) copyFromObject, source.getControllerId(), game); } - affectedObjectList.add(new MageObjectReference(getSourceId(), game)); + } @Override public boolean apply(Game game, Ability source) { + if (affectedObjectList.isEmpty()) { + affectedObjectList.add(new MageObjectReference(getSourceId(), game)); + } Permanent permanent = affectedObjectList.get(0).getPermanent(game); if (permanent == null) { permanent = (Permanent) game.getLastKnownInformation(getSourceId(), Zone.BATTLEFIELD, source.getSourceObjectZoneChangeCounter()); @@ -99,31 +100,31 @@ public class CopyEffect extends ContinuousEffectImpl { } } permanent.setCopy(true); - permanent.setName(target.getName()); - permanent.getColor(game).setColor(target.getColor(game)); + permanent.setName(copyFromObject.getName()); + permanent.getColor(game).setColor(copyFromObject.getColor(game)); permanent.getManaCost().clear(); - permanent.getManaCost().add(target.getManaCost()); + permanent.getManaCost().add(copyFromObject.getManaCost()); permanent.getCardType().clear(); - for (CardType type: target.getCardType()) { + for (CardType type : copyFromObject.getCardType()) { permanent.getCardType().add(type); } permanent.getSubtype().clear(); - for (String type: target.getSubtype()) { + for (String type : copyFromObject.getSubtype()) { permanent.getSubtype().add(type); } permanent.getSupertype().clear(); - for (String type: target.getSupertype()) { + for (String type : copyFromObject.getSupertype()) { permanent.getSupertype().add(type); } permanent.removeAllAbilities(source.getSourceId(), game); - for (Ability ability: target.getAbilities()) { - permanent.addAbility(ability, getSourceId(), game, false); // no new Id so consumed replacement effects are known while new continuousEffects.apply happen. + for (Ability ability : copyFromObject.getAbilities()) { + permanent.addAbility(ability, getSourceId(), game, false); // no new Id so consumed replacement effects are known while new continuousEffects.apply happen. } - permanent.getPower().setValue(target.getPower().getValue()); - permanent.getToughness().setValue(target.getToughness().getValue()); - if (target instanceof Permanent) { - Permanent targetPermanent = (Permanent) target; + permanent.getPower().setValue(copyFromObject.getPower().getValue()); + permanent.getToughness().setValue(copyFromObject.getToughness().getValue()); + if (copyFromObject instanceof Permanent) { + Permanent targetPermanent = (Permanent) copyFromObject; permanent.setTransformed(targetPermanent.isTransformed()); permanent.setSecondCardFace(targetPermanent.getSecondCardFace()); permanent.setFlipCard(targetPermanent.isFlipCard()); @@ -131,13 +132,13 @@ public class CopyEffect extends ContinuousEffectImpl { } // to get the image of the copied permanent copy number und expansionCode - if (target instanceof PermanentCard) { - permanent.setCardNumber(((PermanentCard) target).getCard().getCardNumber()); - permanent.setExpansionSetCode(((PermanentCard) target).getCard().getExpansionSetCode()); - } else if (target instanceof PermanentToken || target instanceof Card) { - permanent.setCardNumber(((Card) target).getCardNumber()); - permanent.setExpansionSetCode(((Card) target).getExpansionSetCode()); - } + if (copyFromObject instanceof PermanentCard) { + permanent.setCardNumber(((PermanentCard) copyFromObject).getCard().getCardNumber()); + permanent.setExpansionSetCode(((PermanentCard) copyFromObject).getCard().getExpansionSetCode()); + } else if (copyFromObject instanceof PermanentToken || copyFromObject instanceof Card) { + permanent.setCardNumber(((Card) copyFromObject).getCardNumber()); + permanent.setExpansionSetCode(((Card) copyFromObject).getExpansionSetCode()); + } return true; } @@ -147,15 +148,15 @@ public class CopyEffect extends ContinuousEffectImpl { } public MageObject getTarget() { - return target; + return copyFromObject; } public void setTarget(MageObject target) { - this.target = target; + this.copyFromObject = target; } public UUID getSourceId() { - return sourceId; + return copyToObjectId; } public ApplyToPermanent getApplier() { @@ -165,5 +166,5 @@ public class CopyEffect extends ContinuousEffectImpl { public void setApplier(ApplyToPermanent applier) { this.applier = applier; } - + } diff --git a/Mage/src/mage/abilities/effects/common/ReturnFromGraveyardToBattlefieldTargetEffect.java b/Mage/src/mage/abilities/effects/common/ReturnFromGraveyardToBattlefieldTargetEffect.java index da7960e743..dd2e279704 100644 --- a/Mage/src/mage/abilities/effects/common/ReturnFromGraveyardToBattlefieldTargetEffect.java +++ b/Mage/src/mage/abilities/effects/common/ReturnFromGraveyardToBattlefieldTargetEffect.java @@ -73,7 +73,7 @@ public class ReturnFromGraveyardToBattlefieldTargetEffect extends OneShotEffect for (UUID targetId : getTargetPointer().getTargets(game, source)) { Card card = game.getCard(targetId); if (card != null) { - controller.putOntoBattlefieldWithInfo(card, game, Zone.GRAVEYARD, source.getSourceId(), tapped); + controller.moveCards(card, Zone.BATTLEFIELD, source, game, tapped, false, false, null); } } return true; diff --git a/Mage/src/mage/abilities/effects/common/counter/AddCountersSourceEffect.java b/Mage/src/mage/abilities/effects/common/counter/AddCountersSourceEffect.java index 82c14c0cdb..0633ff60c6 100644 --- a/Mage/src/mage/abilities/effects/common/counter/AddCountersSourceEffect.java +++ b/Mage/src/mage/abilities/effects/common/counter/AddCountersSourceEffect.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,20 +20,20 @@ * 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.counter; -import mage.constants.Outcome; import mage.abilities.Ability; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.OneShotEffect; import mage.cards.Card; +import mage.constants.Outcome; import mage.counters.Counter; import mage.game.Game; import mage.game.permanent.Permanent; @@ -63,11 +63,12 @@ public class AddCountersSourceEffect extends OneShotEffect { } /** - * + * * @param counter * @param amount this amount will be added to the counter instances * @param informPlayers - * @param putOnCard - counters have to be put on a card instead of a permanent + * @param putOnCard - counters have to be put on a card instead of a + * permanent */ public AddCountersSourceEffect(Counter counter, DynamicValue amount, boolean informPlayers, boolean putOnCard) { super(Outcome.Benefit); @@ -106,7 +107,7 @@ public class AddCountersSourceEffect extends OneShotEffect { if (informPlayers && !game.isSimulation()) { Player player = game.getPlayer(source.getControllerId()); if (player != null) { - game.informPlayers(new StringBuilder(player.getLogName()).append(" puts ").append(newCounter.getCount()).append(" ").append(newCounter.getName().toLowerCase()).append(" counter on ").append(card.getLogName()).toString()); + game.informPlayers(player.getLogName() + " puts " + newCounter.getCount() + " " + newCounter.getName().toLowerCase() + " counter on " + card.getLogName()); } } } @@ -114,6 +115,9 @@ public class AddCountersSourceEffect extends OneShotEffect { } } else { Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent == null) { + permanent = (Permanent) getValue(EntersBattlefieldEffect.ENTERING_PERMANENT); + } if (permanent != null) { if (counter != null) { Counter newCounter = counter.copy(); @@ -129,7 +133,7 @@ public class AddCountersSourceEffect extends OneShotEffect { int amountAdded = permanent.getCounters().getCount(newCounter.getName()) - before; Player player = game.getPlayer(source.getControllerId()); if (player != null) { - game.informPlayers(player.getLogName()+" puts "+amountAdded+" "+newCounter.getName().toLowerCase()+" counter on "+permanent.getLogName()); + game.informPlayers(player.getLogName() + " puts " + amountAdded + " " + newCounter.getName().toLowerCase() + " counter on " + permanent.getLogName()); } } } @@ -165,5 +169,4 @@ public class AddCountersSourceEffect extends OneShotEffect { return new AddCountersSourceEffect(this); } - } diff --git a/Mage/src/mage/game/stack/Spell.java b/Mage/src/mage/game/stack/Spell.java index 2972b65d2d..482bfb8451 100644 --- a/Mage/src/mage/game/stack/Spell.java +++ b/Mage/src/mage/game/stack/Spell.java @@ -167,6 +167,10 @@ public class Spell extends StackObjImpl implements Card { @Override public boolean resolve(Game game) { boolean result; + Player controller = game.getPlayer(getControllerId()); + if (controller == null) { + return false; + } if (this.getCardType().contains(CardType.INSTANT) || this.getCardType().contains(CardType.SORCERY)) { int index = 0; result = false; @@ -261,6 +265,7 @@ public class Spell extends StackObjImpl implements Card { } } else { updateOptionalCosts(0); +// return controller.moveCards(card, Zone.BATTLEFIELD, ability, game, false, faceDown, false, null); result = card.putOntoBattlefield(game, Zone.STACK, ability.getSourceId(), controllerId, false, faceDown); return result; } diff --git a/Mage/src/mage/players/Player.java b/Mage/src/mage/players/Player.java index d00471867c..b484fb8ccf 100644 --- a/Mage/src/mage/players/Player.java +++ b/Mage/src/mage/players/Player.java @@ -635,6 +635,8 @@ public interface Player extends MageItem, Copyable { boolean moveCards(Set cards, Zone fromZone, Zone toZone, Ability source, Game game); + boolean moveCards(Card card, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, ArrayList appliedEffects); + /** * * @param cards @@ -646,6 +648,7 @@ public interface Player extends MageItem, Copyable { * @param byOwner the card is moved (or put onto battlefield) by the owner * of the card and if target zone is battlefield controlls the permanent * (instead of the controller of the source) + * @param appliedEffects * @return */ boolean moveCards(Set cards, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, ArrayList appliedEffects); diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index bb1250e1b5..011d716acd 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -1022,7 +1022,7 @@ public abstract class PlayerImpl implements Player, Serializable { game.fireEvent(GameEvent.getEvent(GameEvent.EventType.LAND_PLAYED, card.getId(), card.getId(), playerId)); game.fireInformEvent(getLogName() + " plays " + card.getLogName()); // game.removeBookmark(bookmark); - resetStoredBookmark(game); + resetStoredBookmark(game); // prevent undo after playing a land return true; } // putOntoBattlefield retured false if putOntoBattlefield was replaced by replacement effect (e.g. Kjeldorian Outpost). @@ -2998,22 +2998,6 @@ public abstract class PlayerImpl implements Player, Serializable { successfulMovedCards = moveCardsToGraveyardWithInfo(cards, source, game, fromZone); break; case HAND: - for (Card card : cards) { - fromZone = game.getState().getZone(card.getId()); -// if (fromZone == Zone.STACK) { -// // If a spell is returned to its owner's hand, it's removed from the stack and thus will not resolve -// Spell spell = game.getStack().getSpell(card.getId()); -// if (spell != null) { -// game.getStack().remove(spell); -// } -// } - boolean hideCard = fromZone.equals(Zone.LIBRARY) - || (card.isFaceDown(game) && !fromZone.equals(Zone.STACK) && !fromZone.equals(Zone.BATTLEFIELD)); - if (moveCardToHandWithInfo(card, source == null ? null : source.getSourceId(), game, !hideCard)) { - successfulMovedCards.add(card); - } - } - break; case BATTLEFIELD: return moveCards(cards, toZone, source, game, false, false, false, null); case LIBRARY: @@ -3032,6 +3016,15 @@ public abstract class PlayerImpl implements Player, Serializable { return successfulMovedCards.size() > 0; } + @Override + public boolean moveCards(Card card, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, ArrayList appliedEffects) { + Set cardList = new HashSet<>(); + if (card != null) { + cardList.add(card); + } + return moveCards(cardList, toZone, source, game, tapped, faceDown, byOwner, appliedEffects); + } + @Override public boolean moveCards(Set cards, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, ArrayList appliedEffects) { if (cards.isEmpty()) { @@ -3070,7 +3063,6 @@ public abstract class PlayerImpl implements Player, Serializable { } } game.setScopeRelevant(false); - game.applyEffects(); for (Permanent permanent : permanentsEntered) { fromZone = game.getState().getZone(permanent.getId()); if (((Card) permanent).removeFromZone(game, fromZone, source.getSourceId())) { @@ -3086,6 +3078,17 @@ public abstract class PlayerImpl implements Player, Serializable { game.addSimultaneousEvent(new ZoneChangeEvent(permanent, permanent.getControllerId(), fromZone, Zone.BATTLEFIELD)); } } + game.applyEffects(); + break; + case HAND: + for (Card card : cards) { + fromZone = game.getState().getZone(card.getId()); + boolean hideCard = fromZone.equals(Zone.LIBRARY) + || (card.isFaceDown(game) && !fromZone.equals(Zone.STACK) && !fromZone.equals(Zone.BATTLEFIELD)); + if (moveCardToHandWithInfo(card, source == null ? null : source.getSourceId(), game, !hideCard)) { + successfulMovedCards.add(card); + } + } break; default: throw new UnsupportedOperationException("to Zone not supported yet"); From b88884b4ab3682fe8486d636f66f1be60ff5e628 Mon Sep 17 00:00:00 2001 From: LoneFox Date: Thu, 15 Oct 2015 09:51:59 +0300 Subject: [PATCH 35/46] Fix compilation (But why did it work before? I tested it...) --- Mage.Sets/src/mage/sets/riseoftheeldrazi/NotOfThisWorld.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage.Sets/src/mage/sets/riseoftheeldrazi/NotOfThisWorld.java b/Mage.Sets/src/mage/sets/riseoftheeldrazi/NotOfThisWorld.java index 1ee4a1ce98..97363cb0aa 100644 --- a/Mage.Sets/src/mage/sets/riseoftheeldrazi/NotOfThisWorld.java +++ b/Mage.Sets/src/mage/sets/riseoftheeldrazi/NotOfThisWorld.java @@ -38,6 +38,7 @@ import mage.constants.CardType; import mage.constants.Rarity; import mage.constants.TargetController; import mage.constants.Zone; +import mage.filter.Filter; import mage.filter.FilterSpell; import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterCreaturePermanent; From 4ec6164c86f04121057985389f3a80253c0cf59f Mon Sep 17 00:00:00 2001 From: LoneFox Date: Thu, 15 Oct 2015 09:53:24 +0300 Subject: [PATCH 36/46] Check all targets if necessary and not just the first one --- .../filter/predicate/other/TargetsPermanentPredicate.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mage/src/mage/filter/predicate/other/TargetsPermanentPredicate.java b/Mage/src/mage/filter/predicate/other/TargetsPermanentPredicate.java index 0cf864bbc4..5471eae280 100644 --- a/Mage/src/mage/filter/predicate/other/TargetsPermanentPredicate.java +++ b/Mage/src/mage/filter/predicate/other/TargetsPermanentPredicate.java @@ -59,8 +59,8 @@ public class TargetsPermanentPredicate implements ObjectSourcePlayerPredicate Date: Thu, 15 Oct 2015 09:28:02 +0200 Subject: [PATCH 37/46] Added Spoils of Evil --- .../src/mage/sets/iceage/SpoilsOfEvil.java | 105 ++++++++++++++++++ .../mage/sets/scourge/ForgottenAncient.java | 2 +- 2 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 Mage.Sets/src/mage/sets/iceage/SpoilsOfEvil.java diff --git a/Mage.Sets/src/mage/sets/iceage/SpoilsOfEvil.java b/Mage.Sets/src/mage/sets/iceage/SpoilsOfEvil.java new file mode 100644 index 0000000000..731676b24a --- /dev/null +++ b/Mage.Sets/src/mage/sets/iceage/SpoilsOfEvil.java @@ -0,0 +1,105 @@ +/* + * 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.iceage; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.filter.FilterCard; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetOpponent; + +/** + * + * @author Blinke + */ +public class SpoilsOfEvil extends CardImpl { + private static final FilterCard filter = new FilterCard("artifact or creature card in target opponents graveyard"); + static { + filter.add(Predicates.or( + new CardTypePredicate(CardType.ARTIFACT), + new CardTypePredicate(CardType.CREATURE))); + } + + public SpoilsOfEvil(UUID ownerId) { + super(ownerId, 51, "Spoils of Evil", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{2}{B}"); + this.expansionSetCode = "ICE"; + + // For each artifact or creature card in target opponent's graveyard, add {1} to your mana pool and you gain 1 life. + this.getSpellAbility().addEffect(new SpoilsOfEvilEffect()); + this.getSpellAbility().addTarget(new TargetOpponent()); + } + + public SpoilsOfEvil(final SpoilsOfEvil card) { + super(card); + } + + @Override + public SpoilsOfEvil copy() { + return new SpoilsOfEvil(this); + } + + class SpoilsOfEvilEffect extends OneShotEffect { + + public SpoilsOfEvilEffect() { + super(Outcome.GainLife); + this.staticText = "For each artifact or creature card in target opponent's graveyard, add {1} to your mana pool and you gain 1 life."; + } + + public SpoilsOfEvilEffect(final SpoilsOfEvilEffect effect) { + super(effect); + } + + @Override + public SpoilsOfEvilEffect copy() { + return new SpoilsOfEvilEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player targetOpponent = game.getPlayer(targetPointer.getFirst(game, source)); + Player controller = game.getPlayer(source.getControllerId()); + + if(targetOpponent != null && controller != null) { + int cardCount = targetOpponent.getGraveyard().count(filter, game); + controller.gainLife(cardCount, game); + controller.getManaPool().addMana(Mana.ColorlessMana(cardCount), game, source); + return true; + } + return false; + } + } +} diff --git a/Mage.Sets/src/mage/sets/scourge/ForgottenAncient.java b/Mage.Sets/src/mage/sets/scourge/ForgottenAncient.java index 8107c48a39..b6ad87f8e2 100644 --- a/Mage.Sets/src/mage/sets/scourge/ForgottenAncient.java +++ b/Mage.Sets/src/mage/sets/scourge/ForgottenAncient.java @@ -95,7 +95,7 @@ public class ForgottenAncient extends CardImpl { public ForgottenAncientEffect() { super(Outcome.Benefit); - this.staticText = "you may move any number of +1/+1 counters from Forgotten Ancient onto other creatures."; + this.staticText = "you may move any number of +1/+1 counters from {this} onto other creatures."; } public ForgottenAncientEffect(final ForgottenAncientEffect effect) { From a0e824134751b6c665dcd3e33339c9158438eb75 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 15 Oct 2015 17:19:34 +0200 Subject: [PATCH 38/46] Minor change. --- Mage/src/mage/abilities/common/DiesAttachedTriggeredAbility.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage/src/mage/abilities/common/DiesAttachedTriggeredAbility.java b/Mage/src/mage/abilities/common/DiesAttachedTriggeredAbility.java index 70113a4564..963df6092b 100644 --- a/Mage/src/mage/abilities/common/DiesAttachedTriggeredAbility.java +++ b/Mage/src/mage/abilities/common/DiesAttachedTriggeredAbility.java @@ -60,6 +60,7 @@ public class DiesAttachedTriggeredAbility extends TriggeredAbilityImpl { // So check here with the LKI of the enchantment Permanent attachment = game.getPermanentOrLKIBattlefield(getSourceId()); if (attachment != null + && zEvent.getTargetId() != null && attachment.getAttachedTo() != null && zEvent.getTargetId().equals(attachment.getAttachedTo()) && attachment.getAttachedToZoneChangeCounter() == zEvent.getTarget().getZoneChangeCounter(game) - 1) { triggered = true; From 7274f9a8ac1782fb60825fb610c097a18bc27dee Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 15 Oct 2015 21:56:03 +0200 Subject: [PATCH 39/46] Replaced some custom classes by ChooseCreatureTypeEffect. --- .../sets/avacynrestored/CavernOfSouls.java | 70 ++++--------------- .../sets/avacynrestored/RidersOfGavony.java | 63 ++++------------- .../mage/sets/magic2014/DoorOfDestinies.java | 47 +------------ .../src/mage/sets/magic2015/ObeliskOfUrd.java | 52 ++------------ .../src/mage/sets/newphyrexia/Xenograft.java | 58 +++------------ .../tempestremastered/VolrathsLaboratory.java | 15 ++-- 6 files changed, 50 insertions(+), 255 deletions(-) diff --git a/Mage.Sets/src/mage/sets/avacynrestored/CavernOfSouls.java b/Mage.Sets/src/mage/sets/avacynrestored/CavernOfSouls.java index 00e88453cb..5ff7b12ef6 100644 --- a/Mage.Sets/src/mage/sets/avacynrestored/CavernOfSouls.java +++ b/Mage.Sets/src/mage/sets/avacynrestored/CavernOfSouls.java @@ -38,15 +38,12 @@ import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ChooseCreatureTypeEffect; import mage.abilities.mana.ColorlessManaAbility; import mage.abilities.mana.ConditionalAnyColorManaAbility; import mage.abilities.mana.builder.ConditionalManaBuilder; import mage.abilities.mana.conditional.CreatureCastManaCondition; import mage.cards.CardImpl; -import mage.cards.repository.CardRepository; -import mage.choices.Choice; -import mage.choices.ChoiceImpl; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; @@ -55,10 +52,8 @@ import mage.constants.WatcherScope; import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; import mage.game.stack.Spell; import mage.players.Player; -import mage.util.CardUtil; import mage.watchers.Watcher; /** @@ -67,14 +62,12 @@ import mage.watchers.Watcher; */ public class CavernOfSouls extends CardImpl { - private static final String ruleText = "choose a creature type"; - public CavernOfSouls(UUID ownerId) { super(ownerId, 226, "Cavern of Souls", Rarity.RARE, new CardType[]{CardType.LAND}, ""); this.expansionSetCode = "AVR"; // As Cavern of Souls enters the battlefield, choose a creature type. - this.addAbility(new AsEntersBattlefieldAbility(new CavernOfSoulsEffect(), ruleText)); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseCreatureTypeEffect(Outcome.BoostCreature))); // {T}: Add {1} to your mana pool. this.addAbility(new ColorlessManaAbility()); @@ -82,7 +75,7 @@ public class CavernOfSouls extends CardImpl { // {T}: Add one mana of any color to your mana pool. Spend this mana only to cast a creature spell of the chosen type, and that spell can't be countered. Ability ability = new ConditionalAnyColorManaAbility(new TapSourceCost(), 1, new CavernOfSoulsManaBuilder(), true); this.addAbility(ability, new CavernOfSoulsWatcher(ability.getOriginalId())); - this.addAbility(new SimpleStaticAbility(Zone.ALL, new CavernOfSoulsCantCounterEffect())); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new CavernOfSoulsCantCounterEffect())); } public CavernOfSouls(final CavernOfSouls card) { @@ -95,60 +88,23 @@ public class CavernOfSouls extends CardImpl { } } -class CavernOfSoulsEffect extends OneShotEffect { - - public CavernOfSoulsEffect() { - super(Outcome.Benefit); - staticText = "As {this} enters the battlefield, choose a creature type"; - } - - public CavernOfSoulsEffect(final CavernOfSoulsEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - Permanent permanent = game.getPermanent(source.getSourceId()); - if (player != null && permanent != null) { - Choice typeChoice = new ChoiceImpl(true); - typeChoice.setMessage("Choose creature type"); - typeChoice.setChoices(CardRepository.instance.getCreatureTypes()); - while (!player.choose(Outcome.Benefit, typeChoice, game)) { - if (!player.canRespond()) { - return false; - } - } - game.informPlayers(permanent.getName() + ": " + player.getLogName() + " has chosen " + typeChoice.getChoice()); - game.getState().setValue(permanent.getId() + "_type", typeChoice.getChoice()); - permanent.addInfo("chosen type", CardUtil.addToolTipMarkTags("Chosen type: " + typeChoice.getChoice()), game); - } - return false; - } - - @Override - public CavernOfSoulsEffect copy() { - return new CavernOfSoulsEffect(this); - } -} - class CavernOfSoulsManaBuilder extends ConditionalManaBuilder { String creatureType; - + @Override public ConditionalManaBuilder setMana(Mana mana, Ability source, Game game) { Object value = game.getState().getValue(source.getSourceId() + "_type"); if (value != null && value instanceof String) { creatureType = (String) value; - } + } Player controller = game.getPlayer(source.getControllerId()); MageObject sourceObject = game.getObject(source.getSourceId()); if (controller != null && sourceObject != null) { - game.informPlayers(controller.getLogName() + " produces " + mana.toString() + " with " + sourceObject.getLogName() + - " (can only be spend to cast for creatures of type " + creatureType + " and that spell can't be countered)"); - } - return super.setMana(mana, source, game); + game.informPlayers(controller.getLogName() + " produces " + mana.toString() + " with " + sourceObject.getLogName() + + " (can only be spend to cast for creatures of type " + creatureType + " and that spell can't be countered)"); + } + return super.setMana(mana, source, game); } @Override @@ -174,11 +130,11 @@ class CavernOfSoulsConditionalMana extends ConditionalMana { class CavernOfSoulsManaCondition extends CreatureCastManaCondition { String creatureType; - + CavernOfSoulsManaCondition(String creatureType) { this.creatureType = creatureType; } - + @Override public boolean apply(Game game, Ability source, UUID manaProducer) { // check: ... to cast a creature spell @@ -197,7 +153,7 @@ class CavernOfSoulsWatcher extends Watcher { private List spells = new ArrayList<>(); private final String originalId; - + public CavernOfSoulsWatcher(UUID originalId) { super("ManaPaidFromCavernOfSoulsWatcher", WatcherScope.CARD); this.originalId = originalId.toString(); @@ -222,7 +178,7 @@ class CavernOfSoulsWatcher extends Watcher { } } } - + public boolean spellCantBeCountered(UUID spellId) { return spells.contains(spellId); } diff --git a/Mage.Sets/src/mage/sets/avacynrestored/RidersOfGavony.java b/Mage.Sets/src/mage/sets/avacynrestored/RidersOfGavony.java index 8a0ead3bfc..2f687150aa 100644 --- a/Mage.Sets/src/mage/sets/avacynrestored/RidersOfGavony.java +++ b/Mage.Sets/src/mage/sets/avacynrestored/RidersOfGavony.java @@ -27,27 +27,28 @@ */ package mage.sets.avacynrestored; -import mage.constants.*; +import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ChooseCreatureTypeEffect; import mage.abilities.keyword.ProtectionAbility; import mage.abilities.keyword.VigilanceAbility; import mage.cards.CardImpl; -import mage.cards.repository.CardRepository; -import mage.choices.Choice; -import mage.choices.ChoiceImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Layer; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.SubLayer; +import mage.constants.Zone; import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.SubtypePredicate; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.players.Player; - -import java.util.UUID; /** * @author noxx @@ -66,7 +67,7 @@ public class RidersOfGavony extends CardImpl { this.addAbility(VigilanceAbility.getInstance()); // As Riders of Gavony enters the battlefield, choose a creature type. - this.addAbility(new AsEntersBattlefieldAbility(new RidersOfGavonyEffect())); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseCreatureTypeEffect(Outcome.Protect))); // Human creatures you control have protection from creatures of the chosen type. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new RidersOfGavonyGainAbilityControlledEffect())); @@ -82,46 +83,6 @@ public class RidersOfGavony extends CardImpl { } } -class RidersOfGavonyEffect extends OneShotEffect { - - public RidersOfGavonyEffect() { - super(Outcome.BoostCreature); - staticText = "choose a creature type"; - } - - public RidersOfGavonyEffect(final RidersOfGavonyEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - Permanent permanent = game.getPermanent(source.getSourceId()); - if (player != null && permanent != null) { - Choice typeChoice = new ChoiceImpl(true); - typeChoice.setMessage("Choose creature type"); - typeChoice.setChoices(CardRepository.instance.getCreatureTypes()); - while (!player.choose(Outcome.BoostCreature, typeChoice, game)) { - if (!player.canRespond()) { - return false; - } - } - if (typeChoice.getChoice() != null) { - game.informPlayers(permanent.getName() + ": " + player.getLogName() + " has chosen " + typeChoice.getChoice()); - game.getState().setValue(permanent.getId() + "_type", typeChoice.getChoice()); - permanent.addInfo("chosen type", "Chosen type: " + typeChoice.getChoice() + "", game); - } - } - return false; - } - - @Override - public RidersOfGavonyEffect copy() { - return new RidersOfGavonyEffect(this); - } - -} - class RidersOfGavonyGainAbilityControlledEffect extends ContinuousEffectImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("Human creatures you control"); @@ -154,13 +115,13 @@ class RidersOfGavonyGainAbilityControlledEffect extends ContinuousEffectImpl { if (permanent != null) { String subtype = (String) game.getState().getValue(permanent.getId() + "_type"); if (subtype != null) { - protectionFilter = new FilterPermanent(subtype+"s"); + protectionFilter = new FilterPermanent(subtype + "s"); protectionFilter.add(new SubtypePredicate(subtype)); } } } if (protectionFilter != null) { - for (Permanent perm: game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) { + for (Permanent perm : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) { perm.addAbility(new ProtectionAbility(protectionFilter), source.getSourceId(), game); } return true; diff --git a/Mage.Sets/src/mage/sets/magic2014/DoorOfDestinies.java b/Mage.Sets/src/mage/sets/magic2014/DoorOfDestinies.java index 95ef1ee610..d1aab90188 100644 --- a/Mage.Sets/src/mage/sets/magic2014/DoorOfDestinies.java +++ b/Mage.Sets/src/mage/sets/magic2014/DoorOfDestinies.java @@ -33,12 +33,9 @@ import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ChooseCreatureTypeEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; -import mage.cards.repository.CardRepository; -import mage.choices.Choice; -import mage.choices.ChoiceImpl; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Layer; @@ -57,7 +54,6 @@ import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; import mage.game.stack.Spell; -import mage.players.Player; /** * @@ -70,7 +66,8 @@ public class DoorOfDestinies extends CardImpl { this.expansionSetCode = "M14"; // As Door of Destinies enters the battlefield, choose a creature type. - this.addAbility(new AsEntersBattlefieldAbility(new ChooseCreatureTypeEffect())); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseCreatureTypeEffect(Outcome.BoostCreature))); + // Whenever you cast a spell of the chosen type, put a charge counter on Door of Destinies. this.addAbility(new AddCounterAbility()); // Creatures you control of the chosen type get +1/+1 for each charge counter on Door of Destinies. @@ -87,44 +84,6 @@ public class DoorOfDestinies extends CardImpl { } } -class ChooseCreatureTypeEffect extends OneShotEffect { - - public ChooseCreatureTypeEffect() { - super(Outcome.BoostCreature); - staticText = "choose a creature type"; - } - - public ChooseCreatureTypeEffect(final ChooseCreatureTypeEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - Permanent permanent = game.getPermanent(source.getSourceId()); - if (player != null && permanent != null) { - Choice typeChoice = new ChoiceImpl(true); - typeChoice.setMessage("Choose creature type"); - typeChoice.setChoices(CardRepository.instance.getCreatureTypes()); - while (!player.choose(Outcome.BoostCreature, typeChoice, game)) { - if (!player.canRespond()) { - return false; - } - } - game.informPlayers(permanent.getName() + ": " + player.getLogName() + " has chosen " + typeChoice.getChoice()); - game.getState().setValue(permanent.getId() + "_type", typeChoice.getChoice()); - permanent.addInfo("chosen type", "Chosen type: " + typeChoice.getChoice().toString() + "", game); - } - return false; - } - - @Override - public ChooseCreatureTypeEffect copy() { - return new ChooseCreatureTypeEffect(this); - } - -} - class AddCounterAbility extends TriggeredAbilityImpl { public AddCounterAbility() { diff --git a/Mage.Sets/src/mage/sets/magic2015/ObeliskOfUrd.java b/Mage.Sets/src/mage/sets/magic2015/ObeliskOfUrd.java index d4a6c4f3a1..7a20f8d586 100644 --- a/Mage.Sets/src/mage/sets/magic2015/ObeliskOfUrd.java +++ b/Mage.Sets/src/mage/sets/magic2015/ObeliskOfUrd.java @@ -32,12 +32,9 @@ import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ChooseCreatureTypeEffect; import mage.abilities.keyword.ConvokeAbility; import mage.cards.CardImpl; -import mage.cards.repository.CardRepository; -import mage.choices.Choice; -import mage.choices.ChoiceImpl; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Layer; @@ -48,8 +45,6 @@ import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.players.Player; -import mage.util.CardUtil; /** * @@ -63,10 +58,10 @@ public class ObeliskOfUrd extends CardImpl { // Convoke this.addAbility(new ConvokeAbility()); - + // As Obelisk of Urd enters the battlefield, choose a creature type. - this.addAbility(new AsEntersBattlefieldAbility(new ObeliskOfUrdEnterBattlefieldEffect())); - + this.addAbility(new AsEntersBattlefieldAbility(new ChooseCreatureTypeEffect(Outcome.BoostCreature))); + // Creatures you control of the chosen type get +2/+2. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ObeliskOfUrdBoostEffect())); } @@ -81,43 +76,6 @@ public class ObeliskOfUrd extends CardImpl { } } -class ObeliskOfUrdEnterBattlefieldEffect extends OneShotEffect { - - ObeliskOfUrdEnterBattlefieldEffect() { - super(Outcome.BoostCreature); - staticText = "choose a creature type"; - } - - ObeliskOfUrdEnterBattlefieldEffect(final ObeliskOfUrdEnterBattlefieldEffect effect) { - super(effect); - } - - @Override - public ObeliskOfUrdEnterBattlefieldEffect copy() { - return new ObeliskOfUrdEnterBattlefieldEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - Permanent permanent = game.getPermanent(source.getSourceId()); - if (player != null && permanent != null) { - Choice typeChoice = new ChoiceImpl(true); - typeChoice.setMessage("Choose a creature type:"); - typeChoice.setChoices(CardRepository.instance.getCreatureTypes()); - while (!player.choose(Outcome.BoostCreature, typeChoice, game)) { - if (!player.canRespond()) { - return false; - } - } - game.informPlayers(permanent.getName() + ": " + player.getLogName() + " has chosen " + typeChoice.getChoice()); - game.getState().setValue(permanent.getId() + "_type", typeChoice.getChoice()); - permanent.addInfo("chosen type", CardUtil.addToolTipMarkTags("Chosen type: " + typeChoice.getChoice()), game); - } - return false; - } -} - class ObeliskOfUrdBoostEffect extends ContinuousEffectImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); @@ -142,7 +100,7 @@ class ObeliskOfUrdBoostEffect extends ContinuousEffectImpl { if (permanent != null) { String subtype = (String) game.getState().getValue(permanent.getId() + "_type"); if (subtype != null) { - for (Permanent perm: game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) { + for (Permanent perm : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) { if (perm.hasSubtype(subtype)) { perm.addPower(2); perm.addToughness(2); diff --git a/Mage.Sets/src/mage/sets/newphyrexia/Xenograft.java b/Mage.Sets/src/mage/sets/newphyrexia/Xenograft.java index df7da67622..0bcb89be3a 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/Xenograft.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/Xenograft.java @@ -29,6 +29,12 @@ package mage.sets.newphyrexia; import java.util.List; import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.AsEntersBattlefieldAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.common.ChooseCreatureTypeEffect; +import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Layer; @@ -36,19 +42,9 @@ import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.SubLayer; import mage.constants.Zone; -import mage.abilities.Ability; -import mage.abilities.common.AsEntersBattlefieldAbility; -import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ContinuousEffectImpl; -import mage.abilities.effects.OneShotEffect; -import mage.cards.CardImpl; -import mage.cards.repository.CardRepository; -import mage.choices.Choice; -import mage.choices.ChoiceImpl; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.players.Player; /** * @@ -60,9 +56,8 @@ public class Xenograft extends CardImpl { super(ownerId, 51, "Xenograft", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{4}{U}"); this.expansionSetCode = "NPH"; - // As Xenograft enters the battlefield, choose a creature type. - this.addAbility(new AsEntersBattlefieldAbility(new XenograftEffect())); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseCreatureTypeEffect(Outcome.Detriment))); // Each creature you control is the chosen type in addition to its other types. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new XenograftAddSubtypeEffect())); } @@ -77,43 +72,6 @@ public class Xenograft extends CardImpl { } } -class XenograftEffect extends OneShotEffect { - - public XenograftEffect() { - super(Outcome.DrawCard); - staticText = "choose a creature type"; - } - - public XenograftEffect(final XenograftEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - Permanent permanent = game.getPermanent(source.getSourceId()); - if (player != null && permanent != null) { - Choice typeChoice = new ChoiceImpl(true); - typeChoice.setMessage("Choose creature type"); - typeChoice.setChoices(CardRepository.instance.getCreatureTypes()); - while (!player.choose(Outcome.BoostCreature, typeChoice, game)) { - if (!player.canRespond()) { - return false; - } - } - game.informPlayers(permanent.getName() + ": " + player.getLogName() + " has chosen " + typeChoice.getChoice()); - game.getState().setValue(source.getSourceId() + "_XenograftType", typeChoice.getChoice()); - permanent.addInfo("chosen type", "Chosen type: " + typeChoice.getChoice().toString() + "", game); - } - return false; - } - - @Override - public XenograftEffect copy() { - return new XenograftEffect(this); - } -} - class XenograftAddSubtypeEffect extends ContinuousEffectImpl { public XenograftAddSubtypeEffect() { @@ -127,7 +85,7 @@ class XenograftAddSubtypeEffect extends ContinuousEffectImpl { @Override public boolean apply(Game game, Ability source) { - String subtype = (String) game.getState().getValue(source.getSourceId() + "_XenograftType"); + String subtype = (String) game.getState().getValue(source.getSourceId() + "_type"); if (subtype != null) { List permanents = game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), game); for (Permanent permanent : permanents) { diff --git a/Mage.Sets/src/mage/sets/tempestremastered/VolrathsLaboratory.java b/Mage.Sets/src/mage/sets/tempestremastered/VolrathsLaboratory.java index 10b1208bbe..70f4a27f8c 100644 --- a/Mage.Sets/src/mage/sets/tempestremastered/VolrathsLaboratory.java +++ b/Mage.Sets/src/mage/sets/tempestremastered/VolrathsLaboratory.java @@ -35,6 +35,7 @@ import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ChooseColorEffect; import mage.abilities.effects.common.ChooseCreatureTypeEffect; @@ -57,10 +58,12 @@ public class VolrathsLaboratory extends CardImpl { this.expansionSetCode = "TPR"; // As Volrath's Laboratory enters the battlefield, choose a color and a creature type. - Ability ability = new EntersBattlefieldAbility(new ChooseColorEffect(Outcome.Neutral), null, true, "As Volrath's Laboratory enters the battlefield, choose a color and a creature type.", ""); + Ability ability = new EntersBattlefieldAbility(new ChooseColorEffect(Outcome.Neutral)); + Effect effect = new ChooseColorEffect(Outcome.Neutral); + effect.setText("and a creature type"); ability.addEffect(new ChooseCreatureTypeEffect(Outcome.Neutral)); this.addAbility(ability); - + // {5}, {T}: Put a 2/2 creature token of the chosen color and type onto the battlefield. ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new VolrathsLaboratoryEffect(), new GenericManaCost(5)); ability.addCost(new TapSourceCost()); @@ -78,21 +81,21 @@ public class VolrathsLaboratory extends CardImpl { } class VolrathsLaboratoryEffect extends OneShotEffect { - + VolrathsLaboratoryEffect() { super(Outcome.PutCreatureInPlay); this.staticText = "Put a 2/2 creature token of the chosen color and type onto the battlefield"; } - + VolrathsLaboratoryEffect(final VolrathsLaboratoryEffect effect) { super(effect); } - + @Override public VolrathsLaboratoryEffect copy() { return new VolrathsLaboratoryEffect(this); } - + @Override public boolean apply(Game game, Ability source) { ObjectColor color = (ObjectColor) game.getState().getValue(source.getSourceId() + "_color"); From 328f7dd7a356b28e20710f4f3f20c350fbc31bf5 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 15 Oct 2015 22:02:04 +0200 Subject: [PATCH 40/46] * Phylactery Lich - Fixed that the replacement effect to select an artifact was handled targeted. --- .../mage/sets/magic2011/PhylacteryLich.java | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/Mage.Sets/src/mage/sets/magic2011/PhylacteryLich.java b/Mage.Sets/src/mage/sets/magic2011/PhylacteryLich.java index a42e28768d..6cf3a7c724 100644 --- a/Mage.Sets/src/mage/sets/magic2011/PhylacteryLich.java +++ b/Mage.Sets/src/mage/sets/magic2011/PhylacteryLich.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,19 +20,14 @@ * 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.magic2011; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.StateTriggeredAbility; @@ -41,6 +36,10 @@ import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.abilities.keyword.IndestructibleAbility; 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.filter.common.FilterControlledPermanent; import mage.filter.predicate.mageobject.CardTypePredicate; @@ -64,8 +63,13 @@ public class PhylacteryLich extends CardImpl { this.power = new MageInt(5); this.toughness = new MageInt(5); - this.addAbility(new AsEntersBattlefieldAbility(new PhylacteryLichEffect(), "put a phylactery counter on an artifact you control")); + // Indestructible this.addAbility(IndestructibleAbility.getInstance()); + + // As Phylactery Lich enters the battlefield, put a phylactery counter on an artifact you control. + this.addAbility(new AsEntersBattlefieldAbility(new PhylacteryLichEffect(), "put a phylactery counter on an artifact you control")); + + // When you control no permanents with phylactery counters on them, sacrifice Phylactery Lich. this.addAbility(new PhylacteryLichAbility()); } @@ -95,7 +99,7 @@ public class PhylacteryLich extends CardImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - for (Permanent perm: game.getBattlefield().getAllActivePermanents(controllerId)) { + for (Permanent perm : game.getBattlefield().getAllActivePermanents(controllerId)) { if (perm.getCounters().getCount("phylactery") > 0) { return false; } @@ -133,7 +137,7 @@ class PhylacteryLichEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); if (player != null) { - TargetControlledPermanent target = new TargetControlledPermanent(filter); + TargetControlledPermanent target = new TargetControlledPermanent(1, 1, filter, true); if (target.canChoose(source.getControllerId(), game)) { if (player.choose(Outcome.Neutral, target, source.getSourceId(), game)) { Permanent permanent = game.getPermanent(target.getFirstTarget()); @@ -151,4 +155,4 @@ class PhylacteryLichEffect extends OneShotEffect { return new PhylacteryLichEffect(this); } -} \ No newline at end of file +} From 3c8a9a75fb7a028b415b39f6283655f834d2b9c9 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 15 Oct 2015 22:15:23 +0200 Subject: [PATCH 41/46] * Replaced some custom choose player effects. --- .../src/mage/sets/commander/SewerNemesis.java | 42 +------------ .../sets/commander2013/TrueNameNemesis.java | 62 ++++--------------- .../src/mage/sets/timespiral/StuffyDoll.java | 42 +------------ .../effects/common/ChoosePlayerEffect.java | 55 ++++++++++++++++ 4 files changed, 73 insertions(+), 128 deletions(-) create mode 100644 Mage/src/mage/abilities/effects/common/ChoosePlayerEffect.java diff --git a/Mage.Sets/src/mage/sets/commander/SewerNemesis.java b/Mage.Sets/src/mage/sets/commander/SewerNemesis.java index fa7df34d3f..e8955959ee 100644 --- a/Mage.Sets/src/mage/sets/commander/SewerNemesis.java +++ b/Mage.Sets/src/mage/sets/commander/SewerNemesis.java @@ -35,7 +35,7 @@ import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ChoosePlayerEffect; import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveTargetEffect; import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect; import mage.cards.CardImpl; @@ -47,9 +47,7 @@ import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; -import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.TargetPlayer; import mage.target.targetpointer.FixedTarget; /** @@ -67,7 +65,7 @@ public class SewerNemesis extends CardImpl { this.toughness = new MageInt(0); // As Sewer Nemesis enters the battlefield, choose a player. - this.addAbility(new AsEntersBattlefieldAbility(new SewerNemesisChoosePlayerEffect())); + this.addAbility(new AsEntersBattlefieldAbility(new ChoosePlayerEffect(Outcome.Detriment))); // Sewer Nemesis's power and toughness are each equal to the number of cards in the chosen player's graveyard. this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(new CardsInTargetOpponentsGraveyardCount(), Duration.WhileOnBattlefield))); // Whenever the chosen player casts a spell, that player puts the top card of his or her library into his or her graveyard. @@ -85,42 +83,8 @@ public class SewerNemesis extends CardImpl { } } -class SewerNemesisChoosePlayerEffect extends OneShotEffect { - - public SewerNemesisChoosePlayerEffect() { - super(Outcome.Detriment); - this.staticText = "choose a player"; - } - - public SewerNemesisChoosePlayerEffect(final SewerNemesisChoosePlayerEffect effect) { - super(effect); - } - - @Override - public SewerNemesisChoosePlayerEffect copy() { - return new SewerNemesisChoosePlayerEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - Permanent permanent = game.getPermanent(source.getSourceId()); - if (player != null && permanent != null) { - TargetPlayer target = new TargetPlayer(1,1,true); - if (player.choose(this.outcome, target, source.getSourceId(), game)) { - Player chosenPlayer = game.getPlayer(target.getFirstTarget()); - if (chosenPlayer != null) { - game.informPlayers(permanent.getLogName() + ": " + player.getLogName() + " has chosen " + chosenPlayer.getLogName()); - game.getState().setValue(permanent.getId() + "_player", target.getFirstTarget()); - return true; - } - } - } - return false; - } -} - class CardsInTargetOpponentsGraveyardCount implements DynamicValue { + @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { if (sourceAbility != null) { diff --git a/Mage.Sets/src/mage/sets/commander2013/TrueNameNemesis.java b/Mage.Sets/src/mage/sets/commander2013/TrueNameNemesis.java index 18c7db6b70..6c3967a3e6 100644 --- a/Mage.Sets/src/mage/sets/commander2013/TrueNameNemesis.java +++ b/Mage.Sets/src/mage/sets/commander2013/TrueNameNemesis.java @@ -30,9 +30,8 @@ package mage.sets.commander2013; import java.util.UUID; import mage.MageInt; import mage.MageObject; -import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ChoosePlayerEffect; import mage.abilities.keyword.ProtectionAbility; import mage.cards.Card; import mage.cards.CardImpl; @@ -44,18 +43,19 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.stack.Spell; import mage.game.stack.StackObject; -import mage.players.Player; -import mage.target.TargetPlayer; /** - * Protection from a player is a new variant of the protection ability. It means the following: - * -- True-Name Nemesis can’t be the target of spells or abilities controlled by the chosen player. - * -- True-Name Nemesis can’t be enchanted by Auras or equipped by Equipment controlled - * by the chosen player. (The same is true for Fortifications controlled by the chosen player, - * if True-Name Nemesis becomes a land.) - * -- True-Name Nemesis can’t be blocked by creatures controlled by the chosen player. - * -- All damage that would be dealt to True-Name Nemesis by sources controlled by the chosen player - * is prevented. (The same is true for sources owned by the chosen player that don’t have controllers.) + * Protection from a player is a new variant of the protection ability. It means + * the following: -- True-Name Nemesis can’t be the target of spells or + * abilities controlled by the chosen player. -- True-Name Nemesis can’t be + * enchanted by Auras or equipped by Equipment controlled by the chosen player. + * (The same is true for Fortifications controlled by the chosen player, if + * True-Name Nemesis becomes a land.) -- True-Name Nemesis can’t be blocked by + * creatures controlled by the chosen player. -- All damage that would be dealt + * to True-Name Nemesis by sources controlled by the chosen player is prevented. + * (The same is true for sources owned by the chosen player that don’t have + * controllers.) + * * @author LevelX2 */ public class TrueNameNemesis extends CardImpl { @@ -70,7 +70,7 @@ public class TrueNameNemesis extends CardImpl { this.toughness = new MageInt(1); // As True-Name Nemesis enters the battlefield, choose a player. - this.addAbility(new AsEntersBattlefieldAbility(new TrueNameNemesisChoosePlayerEffect())); + this.addAbility(new AsEntersBattlefieldAbility(new ChoosePlayerEffect(Outcome.Protect))); // True-Name Nemesis has protection from the chosen player. this.addAbility(new ProtectionFromPlayerAbility()); } @@ -85,42 +85,6 @@ public class TrueNameNemesis extends CardImpl { } } -class TrueNameNemesisChoosePlayerEffect extends OneShotEffect { - - public TrueNameNemesisChoosePlayerEffect() { - super(Outcome.Detriment); - this.staticText = "choose a player"; - } - - public TrueNameNemesisChoosePlayerEffect(final TrueNameNemesisChoosePlayerEffect effect) { - super(effect); - } - - @Override - public TrueNameNemesisChoosePlayerEffect copy() { - return new TrueNameNemesisChoosePlayerEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - Permanent permanent = game.getPermanent(source.getSourceId()); - if (player != null && permanent != null) { - TargetPlayer target = new TargetPlayer(1,1,true); - if (player.choose(this.outcome, target, source.getSourceId(), game)) { - Player chosenPlayer = game.getPlayer(target.getFirstTarget()); - if (chosenPlayer != null) { - game.informPlayers(permanent.getName() + ": " + player.getLogName() + " has chosen " + chosenPlayer.getLogName()); - game.getState().setValue(permanent.getId() + "_player", target.getFirstTarget()); - permanent.addInfo("chosen player", "Chosen player: " + chosenPlayer.getLogName() + "", game); - return true; - } - } - } - return false; - } -} - class ProtectionFromPlayerAbility extends ProtectionAbility { public ProtectionFromPlayerAbility() { diff --git a/Mage.Sets/src/mage/sets/timespiral/StuffyDoll.java b/Mage.Sets/src/mage/sets/timespiral/StuffyDoll.java index 7927019a7b..2a30d32798 100644 --- a/Mage.Sets/src/mage/sets/timespiral/StuffyDoll.java +++ b/Mage.Sets/src/mage/sets/timespiral/StuffyDoll.java @@ -35,6 +35,7 @@ import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ChoosePlayerEffect; import mage.abilities.effects.common.DamageSelfEffect; import mage.abilities.keyword.IndestructibleAbility; import mage.cards.CardImpl; @@ -45,10 +46,7 @@ import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; -import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.TargetPlayer; - /** * @@ -64,7 +62,7 @@ public class StuffyDoll extends CardImpl { this.toughness = new MageInt(1); // As Stuffy Doll enters the battlefield, choose a player. - this.addAbility(new AsEntersBattlefieldAbility(new StuffyDollChoosePlayerEffect())); + this.addAbility(new AsEntersBattlefieldAbility(new ChoosePlayerEffect(Outcome.Damage))); // Stuffy Doll is indestructible. this.addAbility(IndestructibleAbility.getInstance()); // Whenever Stuffy Doll is dealt damage, it deals that much damage to the chosen player. @@ -83,41 +81,6 @@ public class StuffyDoll extends CardImpl { } } -class StuffyDollChoosePlayerEffect extends OneShotEffect { - - public StuffyDollChoosePlayerEffect() { - super(Outcome.Detriment); - this.staticText = "choose a player"; - } - - public StuffyDollChoosePlayerEffect(final StuffyDollChoosePlayerEffect effect) { - super(effect); - } - - @Override - public StuffyDollChoosePlayerEffect copy() { - return new StuffyDollChoosePlayerEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - Permanent permanent = game.getPermanent(source.getSourceId()); - if (player != null && permanent != null) { - TargetPlayer target = new TargetPlayer(); - if (player.choose(this.outcome, target, source.getSourceId(), game)) { - Player chosenPlayer = game.getPlayer(target.getFirstTarget()); - if (chosenPlayer != null) { - game.informPlayers(permanent.getName() + ": " + player.getLogName() + " has chosen " + chosenPlayer.getLogName()); - game.getState().setValue(permanent.getId() + "_player", target.getFirstTarget()); - return true; - } - } - } - return false; - } -} - class StuffyDollTriggeredAbility extends TriggeredAbilityImpl { public StuffyDollTriggeredAbility() { @@ -179,4 +142,3 @@ class StuffyDollGainLifeEffect extends OneShotEffect { return true; } } - diff --git a/Mage/src/mage/abilities/effects/common/ChoosePlayerEffect.java b/Mage/src/mage/abilities/effects/common/ChoosePlayerEffect.java new file mode 100644 index 0000000000..9f4481515c --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/ChoosePlayerEffect.java @@ -0,0 +1,55 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package mage.abilities.effects.common; + +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPlayer; +import mage.util.CardUtil; + +/** + * + * @author LevelX2 + */ +public class ChoosePlayerEffect extends OneShotEffect { + + public ChoosePlayerEffect(Outcome outcome) { + super(outcome); + this.staticText = "choose a player"; + } + + public ChoosePlayerEffect(final ChoosePlayerEffect effect) { + super(effect); + } + + @Override + public ChoosePlayerEffect copy() { + return new ChoosePlayerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(source.getSourceId()); + if (player != null && permanent != null) { + TargetPlayer target = new TargetPlayer(1, 1, true); + if (player.choose(this.outcome, target, source.getSourceId(), game)) { + Player chosenPlayer = game.getPlayer(target.getFirstTarget()); + if (chosenPlayer != null) { + game.informPlayers(permanent.getName() + ": " + player.getLogName() + " has chosen " + chosenPlayer.getLogName()); + game.getState().setValue(permanent.getId() + "_player", target.getFirstTarget()); + permanent.addInfo("chosen player", CardUtil.addToolTipMarkTags("Chosen player: " + chosenPlayer.getLogName()), game); + return true; + } + } + } + return false; + } +} From ff0aace404d30a4f89daabdc7ab2bd7e65918e56 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 15 Oct 2015 22:25:52 +0200 Subject: [PATCH 42/46] * Replaced some custom name a card effects. --- .../src/mage/sets/innistrad/Nevermore.java | 67 +++---------------- .../mirrodinbesieged/PhyrexianRevoker.java | 65 +++--------------- .../sets/planarchaos/VoidstoneGargoyle.java | 11 +-- .../effects/common/NameACardEffect.java | 6 +- 4 files changed, 31 insertions(+), 118 deletions(-) diff --git a/Mage.Sets/src/mage/sets/innistrad/Nevermore.java b/Mage.Sets/src/mage/sets/innistrad/Nevermore.java index dee67c6f07..dee1d81fe7 100644 --- a/Mage.Sets/src/mage/sets/innistrad/Nevermore.java +++ b/Mage.Sets/src/mage/sets/innistrad/Nevermore.java @@ -1,16 +1,16 @@ /* * Copyright 2011 BetaSteward_at_googlemail.com. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR @@ -20,7 +20,7 @@ * 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. @@ -33,11 +33,8 @@ import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.NameACardEffect; import mage.cards.CardImpl; -import mage.cards.repository.CardRepository; -import mage.choices.Choice; -import mage.choices.ChoiceImpl; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; @@ -46,9 +43,6 @@ import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; -import mage.game.permanent.Permanent; -import mage.players.Player; -import mage.util.CardUtil; /** * @@ -60,11 +54,10 @@ public class Nevermore extends CardImpl { super(ownerId, 25, "Nevermore", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}{W}"); this.expansionSetCode = "ISD"; + // As Nevermore enters the battlefield, name a nonland card. + this.addAbility(new AsEntersBattlefieldAbility(new NameACardEffect(NameACardEffect.TypeOfName.NON_LAND_NAME))); - //As Nevermore enters the battlefield, name a nonland card. - this.addAbility(new AsEntersBattlefieldAbility(new NevermoreEffect1())); - - //The named card can't be cast. + // The named card can't be cast. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new NevermoreEffect2())); } @@ -80,46 +73,6 @@ public class Nevermore extends CardImpl { } -class NevermoreEffect1 extends OneShotEffect { - - public NevermoreEffect1() { - super(Outcome.Detriment); - staticText = "name a nonland card"; - } - - public NevermoreEffect1(final NevermoreEffect1 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) { - Choice cardChoice = new ChoiceImpl(); - cardChoice.setChoices(CardRepository.instance.getNonLandNames()); - cardChoice.clearChoice(); - while (!controller.choose(Outcome.Detriment, cardChoice, game)) { - if (!controller.canRespond()) { - return false; - } - } - String cardName = cardChoice.getChoice(); - game.informPlayers(permanent.getLogName() + ", named card: [" + cardName + "]"); - game.getState().setValue(source.getSourceId().toString(), cardName); - permanent.addInfo("named card", CardUtil.addToolTipMarkTags("Named card: [" + cardName +"]"), game); - return true; - } - return false; - } - - @Override - public NevermoreEffect1 copy() { - return new NevermoreEffect1(this); - } - -} - class NevermoreEffect2 extends ContinuousRuleModifyingEffectImpl { public NevermoreEffect2() { @@ -145,7 +98,7 @@ class NevermoreEffect2 extends ContinuousRuleModifyingEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { if (event.getType() == EventType.CAST_SPELL) { MageObject object = game.getObject(event.getSourceId()); - if (object != null && object.getName().equals(game.getState().getValue(source.getSourceId().toString()))) { + if (object != null && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY))) { return true; } } diff --git a/Mage.Sets/src/mage/sets/mirrodinbesieged/PhyrexianRevoker.java b/Mage.Sets/src/mage/sets/mirrodinbesieged/PhyrexianRevoker.java index 279bd69352..6a51fef04b 100644 --- a/Mage.Sets/src/mage/sets/mirrodinbesieged/PhyrexianRevoker.java +++ b/Mage.Sets/src/mage/sets/mirrodinbesieged/PhyrexianRevoker.java @@ -25,32 +25,25 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.sets.mirrodinbesieged; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.NameACardEffect; import mage.cards.CardImpl; -import mage.cards.repository.CardRepository; -import mage.choices.Choice; -import mage.choices.ChoiceImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; -import mage.game.permanent.Permanent; -import mage.players.Player; -import mage.util.CardUtil; /** * @@ -66,7 +59,7 @@ public class PhyrexianRevoker extends CardImpl { this.toughness = new MageInt(1); // As Phyrexian Revoker enters the battlefield, name a nonland card. - this.addAbility(new AsEntersBattlefieldAbility(new PhyrexianRevokerEffect1())); + this.addAbility(new AsEntersBattlefieldAbility(new NameACardEffect(NameACardEffect.TypeOfName.NON_LAND_NAME))); // Activated abilities of sources with the chosen name can't be activated. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PhyrexianRevokerEffect2())); @@ -83,46 +76,6 @@ public class PhyrexianRevoker extends CardImpl { } -class PhyrexianRevokerEffect1 extends OneShotEffect { - - public PhyrexianRevokerEffect1() { - super(Outcome.Detriment); - staticText = "name a nonland card"; - } - - public PhyrexianRevokerEffect1(final PhyrexianRevokerEffect1 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) { - Choice cardChoice = new ChoiceImpl(); - cardChoice.setChoices(CardRepository.instance.getNonLandNames()); - cardChoice.clearChoice(); - while (!controller.choose(Outcome.Detriment, cardChoice, game)) { - if (!controller.canRespond()) { - return false; - } - } - String cardName = cardChoice.getChoice(); - game.informPlayers(permanent.getLogName() + ", named card: [" + cardName + "]"); - game.getState().setValue(source.getSourceId().toString(), cardName); - permanent.addInfo("named card", CardUtil.addToolTipMarkTags("Named card: [" + cardName +"]"), game); - return true; - } - return false; - } - - @Override - public PhyrexianRevokerEffect1 copy() { - return new PhyrexianRevokerEffect1(this); - } - -} - class PhyrexianRevokerEffect2 extends ContinuousRuleModifyingEffectImpl { public PhyrexianRevokerEffect2() { @@ -143,7 +96,7 @@ class PhyrexianRevokerEffect2 extends ContinuousRuleModifyingEffectImpl { public PhyrexianRevokerEffect2 copy() { return new PhyrexianRevokerEffect2(this); } - + @Override public String getInfoMessage(Ability source, GameEvent event, Game game) { MageObject mageObject = game.getObject(source.getSourceId()); @@ -157,7 +110,7 @@ class PhyrexianRevokerEffect2 extends ContinuousRuleModifyingEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { if (event.getType() == EventType.ACTIVATE_ABILITY) { MageObject object = game.getObject(event.getSourceId()); - if (object != null && object.getName().equals(game.getState().getValue(source.getSourceId().toString()))) { + if (object != null && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY))) { return true; } } diff --git a/Mage.Sets/src/mage/sets/planarchaos/VoidstoneGargoyle.java b/Mage.Sets/src/mage/sets/planarchaos/VoidstoneGargoyle.java index 9292efe16a..4505e34677 100644 --- a/Mage.Sets/src/mage/sets/planarchaos/VoidstoneGargoyle.java +++ b/Mage.Sets/src/mage/sets/planarchaos/VoidstoneGargoyle.java @@ -34,7 +34,9 @@ import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; +import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.NameACardEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.repository.CardRepository; @@ -69,7 +71,7 @@ public class VoidstoneGargoyle extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); // As Voidstone Gargoyle enters the battlefield, name a nonland card. - this.addAbility(new AsEntersBattlefieldAbility(new VoidstoneGargoyleChooseCardEffect())); + this.addAbility(new AsEntersBattlefieldAbility(new NameACardEffect(NameACardEffect.TypeOfName.NON_LAND_NAME))); // The named card can't be cast. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new VoidstoneGargoyleReplacementEffect1())); // Activated abilities of sources with the chosen name can't be activated. @@ -100,7 +102,7 @@ class VoidstoneGargoyleChooseCardEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - Permanent permanent = game.getPermanent(source.getSourceId()); + Permanent permanent = (Permanent) getValue(EntersBattlefieldEffect.ENTERING_PERMANENT); if (controller != null && permanent != null) { Choice cardChoice = new ChoiceImpl(); cardChoice.setChoices(CardRepository.instance.getNonLandNames()); @@ -160,7 +162,8 @@ class VoidstoneGargoyleReplacementEffect1 extends ContinuousRuleModifyingEffectI public boolean applies(GameEvent event, Ability source, Game game) { if (event.getType() == GameEvent.EventType.CAST_SPELL) { MageObject object = game.getObject(event.getSourceId()); - if (object != null && object.getName().equals(game.getState().getValue(source.getSourceId().toString()))) { + if (object != null + && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY))) { return true; } } @@ -203,7 +206,7 @@ class VoidstoneGargoyleRuleModifyingEffect2 extends ContinuousRuleModifyingEffec public boolean applies(GameEvent event, Ability source, Game game) { if (event.getType() == EventType.ACTIVATE_ABILITY) { MageObject object = game.getObject(event.getSourceId()); - if (object != null && object.getName().equals(game.getState().getValue(source.getSourceId().toString()))) { + if (object != null && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + NameACardEffect.INFO_KEY))) { return true; } } diff --git a/Mage/src/mage/abilities/effects/common/NameACardEffect.java b/Mage/src/mage/abilities/effects/common/NameACardEffect.java index 0123f9fd6f..b75279a993 100644 --- a/Mage/src/mage/abilities/effects/common/NameACardEffect.java +++ b/Mage/src/mage/abilities/effects/common/NameACardEffect.java @@ -29,6 +29,7 @@ package mage.abilities.effects.common; import mage.MageObject; import mage.abilities.Ability; +import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.OneShotEffect; import mage.cards.repository.CardRepository; import mage.choices.Choice; @@ -71,7 +72,10 @@ public class NameACardEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - MageObject sourceObject = game.getObject(source.getSourceId()); + MageObject sourceObject = (Permanent) getValue(EntersBattlefieldEffect.ENTERING_PERMANENT); + if (sourceObject == null) { + game.getObject(source.getSourceId()); + } if (controller != null && sourceObject != null) { Choice cardChoice = new ChoiceImpl(); switch (typeOfName) { From 9ab99883079c6af0dc84f433b0b91637e1907dda Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Thu, 15 Oct 2015 23:47:06 +0200 Subject: [PATCH 43/46] * Replaced some custom card effects. Updated enters battlefield replacement effects for new handling. --- .../sets/alarareborn/ArsenalThresher.java | 25 +++---- .../mage/sets/commander/TheMimeoplasm.java | 15 ++-- .../mage/sets/commander2014/BitterFeud.java | 3 +- Mage.Sets/src/mage/sets/conflux/Nyxathid.java | 53 +++----------- .../mage/sets/eventide/CankerAbomination.java | 28 ++++---- .../src/mage/sets/exodus/EntropicSpecter.java | 60 ++++------------ .../src/mage/sets/fourthedition/TheRack.java | 44 +----------- .../src/mage/sets/futuresight/CloudKey.java | 17 +++-- .../src/mage/sets/gatecrash/Realmwright.java | 63 ++++------------ .../mage/sets/guildpact/StompingGround.java | 13 ++-- .../sets/journeyintonyx/HallOfTriumph.java | 48 +------------ .../src/mage/sets/limitedalpha/BlackVise.java | 47 ++---------- .../sets/limitedalpha/PhantasmalTerrain.java | 58 +++------------ .../mage/sets/magic2010/ConvincingMirage.java | 72 +++++-------------- .../src/mage/sets/magic2012/SuturedGhoul.java | 46 ++++++------ .../returntoravnica/TabletOfTheGuilds.java | 16 ++--- .../riseoftheeldrazi/CurseOfWizardry.java | 40 +---------- .../sets/shadowmoor/LureboundScarecrow.java | 4 +- .../mage/sets/shadowmoor/PaintersServant.java | 43 ++--------- .../cards/single/avr/CavernOfSoulsTest.java | 55 +++++++------- .../common/ChooseBasicLandTypeEffect.java | 68 ++++++++++++++++++ .../effects/common/ChooseColorEffect.java | 17 +++-- .../common/ChooseCreatureTypeEffect.java | 18 +++-- .../effects/common/ChooseLandTypeEffect.java | 17 +++-- .../common/ChooseNewTargetsTargetEffect.java | 63 ++++++++-------- .../effects/common/ChooseOpponentEffect.java | 64 +++++++++++++++++ .../effects/common/ChoosePlayerEffect.java | 21 ++++-- .../common/TapSourceUnlessPaysEffect.java | 18 ++--- .../abilities/keyword/ModularAbility.java | 33 +++++---- 29 files changed, 437 insertions(+), 632 deletions(-) create mode 100644 Mage/src/mage/abilities/effects/common/ChooseBasicLandTypeEffect.java create mode 100644 Mage/src/mage/abilities/effects/common/ChooseOpponentEffect.java diff --git a/Mage.Sets/src/mage/sets/alarareborn/ArsenalThresher.java b/Mage.Sets/src/mage/sets/alarareborn/ArsenalThresher.java index 16bc181405..f4203cb0d5 100644 --- a/Mage.Sets/src/mage/sets/alarareborn/ArsenalThresher.java +++ b/Mage.Sets/src/mage/sets/alarareborn/ArsenalThresher.java @@ -31,6 +31,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; +import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.Cards; @@ -41,7 +42,6 @@ import mage.constants.Rarity; import mage.counters.CounterType; import mage.filter.common.FilterArtifactCard; import mage.filter.predicate.mageobject.AnotherCardPredicate; -import mage.filter.predicate.permanent.AnotherPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -62,7 +62,8 @@ public class ArsenalThresher extends CardImpl { this.toughness = new MageInt(2); // As Arsenal Thresher enters the battlefield, you may reveal any number of other artifact cards from your hand. Arsenal Thresher enters the battlefield with a +1/+1 counter on it for each card revealed this way. - this.addAbility(new AsEntersBattlefieldAbility(new ArsenalThresherEffect(), "you may reveal any number of other artifact cards from your hand. {this} enters the battlefield with a +1/+1 counter on it for each card revealed this way")); + this.addAbility(new AsEntersBattlefieldAbility(new ArsenalThresherEffect(), + "you may reveal any number of other artifact cards from your hand. {this} enters the battlefield with a +1/+1 counter on it for each card revealed this way")); } public ArsenalThresher(final ArsenalThresher card) { @@ -92,29 +93,29 @@ class ArsenalThresherEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player you = game.getPlayer(source.getControllerId()); - if (you == null) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { return false; } - Permanent arsenalThresher = game.getPermanent(source.getSourceId()); + Permanent arsenalThresher = (Permanent) getValue(EntersBattlefieldEffect.ENTERING_PERMANENT); FilterArtifactCard filter = new FilterArtifactCard(); filter.add(new AnotherCardPredicate()); - if (you.chooseUse(Outcome.Benefit, "Do you want to reveal other artifacts in your hand?", source, game)) { + if (controller.chooseUse(Outcome.Benefit, "Do you want to reveal other artifacts in your hand?", source, game)) { Cards cards = new CardsImpl(); - if (you.getHand().count(filter, source.getSourceId(), source.getControllerId(), game) > 0) { + if (controller.getHand().count(filter, source.getSourceId(), source.getControllerId(), game) > 0) { TargetCardInHand target = new TargetCardInHand(0, Integer.MAX_VALUE, filter); - if (you.choose(Outcome.Benefit, target, source.getSourceId(), game)) { + if (controller.choose(Outcome.Benefit, target, source.getSourceId(), game)) { for (UUID uuid : target.getTargets()) { - cards.add(you.getHand().get(uuid, game)); + cards.add(controller.getHand().get(uuid, game)); } - you.revealCards("Revealed cards", cards, game); if (arsenalThresher != null) { + controller.revealCards(arsenalThresher.getIdName(), cards, game); arsenalThresher.addCounters(CounterType.P1P1.createInstance(cards.size()), game); - return true; } } } + return true; } return false; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/commander/TheMimeoplasm.java b/Mage.Sets/src/mage/sets/commander/TheMimeoplasm.java index 5be1bed0a2..238bb1bc6c 100644 --- a/Mage.Sets/src/mage/sets/commander/TheMimeoplasm.java +++ b/Mage.Sets/src/mage/sets/commander/TheMimeoplasm.java @@ -32,6 +32,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.dynamicvalue.common.CardsInAllGraveyardsCount; +import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CopyEffect; import mage.cards.Card; @@ -80,27 +81,27 @@ public class TheMimeoplasm extends CardImpl { } class TheMimeoplasmEffect extends OneShotEffect { - + TheMimeoplasmEffect() { super(Outcome.Copy); } - + TheMimeoplasmEffect(final TheMimeoplasmEffect effect) { super(effect); } - + @Override public TheMimeoplasmEffect copy() { return new TheMimeoplasmEffect(this); } - + @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - Permanent permanent = game.getPermanent(source.getSourceId()); + Permanent permanent = (Permanent) getValue(EntersBattlefieldEffect.ENTERING_PERMANENT); if (controller != null && permanent != null) { if (new CardsInAllGraveyardsCount(new FilterCreatureCard()).calculate(game, source, this) >= 2) { - if (controller.chooseUse(Outcome.Benefit, "Do you want to exile two creature cards from graveyards?", source, game)) { + if (controller.chooseUse(Outcome.Benefit, "Do you want to exile two creature cards from graveyards?", source, game)) { TargetCardInGraveyard targetCopy = new TargetCardInGraveyard(new FilterCreatureCard("creature card to become a copy of")); TargetCardInGraveyard targetCounters = new TargetCardInGraveyard(new FilterCreatureCard("creature card to determine amount of additional +1/+1 counters")); if (controller.choose(Outcome.Copy, targetCopy, source.getSourceId(), game)) { @@ -122,7 +123,7 @@ class TheMimeoplasmEffect extends OneShotEffect { } } } - return true; + return true; } return false; } diff --git a/Mage.Sets/src/mage/sets/commander2014/BitterFeud.java b/Mage.Sets/src/mage/sets/commander2014/BitterFeud.java index 7ba41f2371..22d87b793e 100644 --- a/Mage.Sets/src/mage/sets/commander2014/BitterFeud.java +++ b/Mage.Sets/src/mage/sets/commander2014/BitterFeud.java @@ -32,6 +32,7 @@ import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.ReplacementEffectImpl; import mage.cards.Card; @@ -91,7 +92,7 @@ class BitterFeudEntersBattlefieldEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - Permanent permanent = game.getPermanent(source.getSourceId()); + Permanent permanent = (Permanent) getValue(EntersBattlefieldEffect.ENTERING_PERMANENT); if (controller != null && permanent != null) { TargetPlayer target = new TargetPlayer(2, 2, true); controller.chooseTarget(outcome, target, source, game); diff --git a/Mage.Sets/src/mage/sets/conflux/Nyxathid.java b/Mage.Sets/src/mage/sets/conflux/Nyxathid.java index 22fb19bced..0a7e5fee51 100644 --- a/Mage.Sets/src/mage/sets/conflux/Nyxathid.java +++ b/Mage.Sets/src/mage/sets/conflux/Nyxathid.java @@ -27,6 +27,7 @@ */ package mage.sets.conflux; +import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; @@ -34,16 +35,16 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.SignInversionDynamicValue; import mage.abilities.effects.Effect; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ChooseOpponentEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.cards.CardImpl; -import mage.constants.*; +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.players.Player; -import mage.target.common.TargetOpponent; - -import java.util.UUID; /** * @@ -60,7 +61,7 @@ public class Nyxathid extends CardImpl { this.toughness = new MageInt(7); // As Nyxathid enters the battlefield, choose an opponent. - this.addAbility(new AsEntersBattlefieldAbility(new ChooseOpponent())); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseOpponentEffect(Outcome.Detriment))); // Nyxathid gets -1/-1 for each card in the chosen player's hand. DynamicValue chosenPlayerHand = new SignInversionDynamicValue(new CardsInChosenPlayerHandCount()); @@ -78,48 +79,12 @@ public class Nyxathid extends CardImpl { } } -class ChooseOpponent extends OneShotEffect { - - public ChooseOpponent() { - super(Outcome.Neutral); - this.staticText = "choose an opponent"; - } - - public ChooseOpponent(final ChooseOpponent effect) { - super(effect); - } - - @Override - public ChooseOpponent copy() { - return new ChooseOpponent(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - Permanent permanent = game.getPermanent(source.getSourceId()); - if (player != null && permanent != null) { - TargetOpponent target = new TargetOpponent(); - target.setNotTarget(true); - if (player.choose(this.outcome, target, source.getSourceId(), game)) { - Player chosenPlayer = game.getPlayer(target.getFirstTarget()); - if (chosenPlayer != null) { - game.informPlayers(permanent.getName() + ": " + player.getLogName() + " has chosen " + chosenPlayer.getLogName()); - game.getState().setValue(permanent.getId() + "_player", target.getFirstTarget()); - return true; - } - } - } - return false; - } -} - class CardsInChosenPlayerHandCount implements DynamicValue { @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { if (sourceAbility != null) { - UUID playerId = (UUID) game.getState().getValue(sourceAbility.getSourceId() + "_player"); + UUID playerId = (UUID) game.getState().getValue(sourceAbility.getSourceId() + ChooseOpponentEffect.VALUE_KEY); Player chosenPlayer = game.getPlayer(playerId); if (chosenPlayer != null) { return chosenPlayer.getHand().size(); diff --git a/Mage.Sets/src/mage/sets/eventide/CankerAbomination.java b/Mage.Sets/src/mage/sets/eventide/CankerAbomination.java index 5b8107dd5f..812f571064 100644 --- a/Mage.Sets/src/mage/sets/eventide/CankerAbomination.java +++ b/Mage.Sets/src/mage/sets/eventide/CankerAbomination.java @@ -31,6 +31,7 @@ import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; +import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.constants.CardType; @@ -61,11 +62,7 @@ public class CankerAbomination extends CardImpl { this.toughness = new MageInt(6); // As Canker Abomination enters the battlefield, choose an opponent. Canker Abomination enters the battlefield with a -1/-1 counter on it for each creature that player controls. - Ability ability = new AsEntersBattlefieldAbility(new CankerAbominationEffect()); - Target target = new TargetOpponent(); - target.setNotTarget(true); - ability.addTarget(target); - this.addAbility(ability); + this.addAbility(new AsEntersBattlefieldAbility(new CankerAbominationEffect())); } @@ -97,14 +94,19 @@ class CankerAbominationEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - Permanent CankerAbomination = game.getPermanent(source.getSourceId()); - if (player != null && CankerAbomination != null) { - Player chosenPlayer = game.getPlayer(source.getFirstTarget()); - if (chosenPlayer != null) { - game.informPlayers(CankerAbomination.getName() + ": " + player.getLogName() + " has chosen " + chosenPlayer.getLogName()); - int amount = game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), chosenPlayer.getId(), game).size(); - CankerAbomination.addCounters(CounterType.M1M1.createInstance(amount), game); + Player controller = game.getPlayer(source.getControllerId()); + Permanent cankerAbomination = (Permanent) getValue(EntersBattlefieldEffect.ENTERING_PERMANENT); + if (controller != null && cankerAbomination != null) { + Target target = new TargetOpponent(); + target.setNotTarget(true); + controller.choose(outcome, target, source.getSourceId(), game); + Player opponent = game.getPlayer(target.getFirstTarget()); + if (opponent != null) { + game.informPlayers(cankerAbomination.getName() + ": " + controller.getLogName() + " has chosen " + opponent.getLogName()); + int amount = game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), opponent.getId(), game).size(); + if (amount > 0) { + cankerAbomination.addCounters(CounterType.M1M1.createInstance(amount), game); + } return true; } } diff --git a/Mage.Sets/src/mage/sets/exodus/EntropicSpecter.java b/Mage.Sets/src/mage/sets/exodus/EntropicSpecter.java index 1e5348392f..b2e6ebf7cc 100644 --- a/Mage.Sets/src/mage/sets/exodus/EntropicSpecter.java +++ b/Mage.Sets/src/mage/sets/exodus/EntropicSpecter.java @@ -27,6 +27,7 @@ */ package mage.sets.exodus; +import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; @@ -34,18 +35,18 @@ import mage.abilities.common.DealsDamageToAPlayerTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ChooseOpponentEffect; import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; -import mage.constants.*; +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.players.Player; -import mage.target.common.TargetOpponent; - -import java.util.UUID; /** * @@ -64,13 +65,13 @@ public class EntropicSpecter extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); - + // As Entropic Specter enters the battlefield, choose an opponent. - this.addAbility(new AsEntersBattlefieldAbility(new ChooseOpponent())); - + this.addAbility(new AsEntersBattlefieldAbility(new ChooseOpponentEffect(Outcome.Detriment))); + // Entropic Specter's power and toughness are each equal to the number of cards in the chosen player's hand. this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerToughnessSourceEffect(new CardsInTargetPlayerHandCount(), Duration.WhileOnBattlefield))); - + // Whenever Entropic Specter deals damage to a player, that player discards a card. this.addAbility(new DealsDamageToAPlayerTriggeredAbility(new DiscardTargetEffect(1, false), false, true)); } @@ -85,47 +86,12 @@ public class EntropicSpecter extends CardImpl { } } -class ChooseOpponent extends OneShotEffect { - - public ChooseOpponent() { - super(Outcome.Neutral); - this.staticText = "choose an opponent"; - } - - public ChooseOpponent(final ChooseOpponent effect) { - super(effect); - } - - @Override - public ChooseOpponent copy() { - return new ChooseOpponent(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - Permanent permanent = game.getPermanent(source.getSourceId()); - if (player != null && permanent != null) { - TargetOpponent target = new TargetOpponent(); - target.setNotTarget(true); - if (player.choose(this.outcome, target, source.getSourceId(), game)) { - Player chosenPlayer = game.getPlayer(target.getFirstTarget()); - if (chosenPlayer != null) { - game.informPlayers(permanent.getName() + ": " + player.getLogName() + " has chosen " + chosenPlayer.getLogName()); - game.getState().setValue(permanent.getId() + "_player", target.getFirstTarget()); - return true; - } - } - } - return false; - } -} - class CardsInTargetPlayerHandCount implements DynamicValue { + @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { if (sourceAbility != null) { - UUID playerId = (UUID) game.getState().getValue(sourceAbility.getSourceId() + "_player"); + UUID playerId = (UUID) game.getState().getValue(sourceAbility.getSourceId() + ChooseOpponentEffect.VALUE_KEY); Player chosenPlayer = game.getPlayer(playerId); if (chosenPlayer != null) { return chosenPlayer.getHand().size(); diff --git a/Mage.Sets/src/mage/sets/fourthedition/TheRack.java b/Mage.Sets/src/mage/sets/fourthedition/TheRack.java index 98b564a6bb..a99f13634f 100644 --- a/Mage.Sets/src/mage/sets/fourthedition/TheRack.java +++ b/Mage.Sets/src/mage/sets/fourthedition/TheRack.java @@ -32,6 +32,7 @@ import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ChooseOpponentEffect; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Outcome; @@ -40,9 +41,7 @@ import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; -import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.common.TargetOpponent; /** * @@ -55,7 +54,7 @@ public class TheRack extends CardImpl { this.expansionSetCode = "4ED"; // As The Rack enters the battlefield, choose an opponent. - this.addAbility(new AsEntersBattlefieldAbility(new ChooseOpponent())); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseOpponentEffect(Outcome.Detriment))); // At the beginning of the chosen player's upkeep, The Rack deals X damage to that player, where X is 3 minus the number of cards in his or her hand. this.addAbility(new TheRackTriggeredAbility()); } @@ -72,7 +71,6 @@ public class TheRack extends CardImpl { class TheRackTriggeredAbility extends TriggeredAbilityImpl { - public TheRackTriggeredAbility() { super(Zone.BATTLEFIELD, new TheRackEffect(), false); } @@ -93,7 +91,7 @@ class TheRackTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - return event.getPlayerId().equals((UUID) game.getState().getValue(new StringBuilder(this.getSourceId().toString()).append("_player").toString())); + return event.getPlayerId().equals((UUID) game.getState().getValue(this.getSourceId().toString() + ChooseOpponentEffect.VALUE_KEY)); } @Override @@ -103,42 +101,6 @@ class TheRackTriggeredAbility extends TriggeredAbilityImpl { } -class ChooseOpponent extends OneShotEffect { - - public ChooseOpponent() { - super(Outcome.Neutral); - this.staticText = "choose an opponent"; - } - - public ChooseOpponent(final ChooseOpponent effect) { - super(effect); - } - - @Override - public ChooseOpponent copy() { - return new ChooseOpponent(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - Permanent permanent = game.getPermanent(source.getSourceId()); - if (player != null && permanent != null) { - TargetOpponent target = new TargetOpponent(); - target.setNotTarget(true); - if (player.choose(this.outcome, target, source.getSourceId(), game)) { - Player chosenPlayer = game.getPlayer(target.getFirstTarget()); - if (chosenPlayer != null) { - game.informPlayers(permanent.getName() + ": " + player.getLogName() + " has chosen " + chosenPlayer.getLogName()); - game.getState().setValue(permanent.getId() + "_player", target.getFirstTarget()); - return true; - } - } - } - return false; - } -} - class TheRackEffect extends OneShotEffect { public TheRackEffect() { diff --git a/Mage.Sets/src/mage/sets/futuresight/CloudKey.java b/Mage.Sets/src/mage/sets/futuresight/CloudKey.java index 7fc55b9445..33e946d939 100644 --- a/Mage.Sets/src/mage/sets/futuresight/CloudKey.java +++ b/Mage.Sets/src/mage/sets/futuresight/CloudKey.java @@ -11,6 +11,7 @@ import mage.abilities.Ability; import mage.abilities.SpellAbility; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.cost.CostModificationEffectImpl; import mage.cards.Card; @@ -23,6 +24,7 @@ import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; import mage.game.Game; +import mage.game.permanent.Permanent; import mage.players.Player; import mage.util.CardUtil; @@ -73,8 +75,11 @@ class CloudKeyChooseTypeEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - MageObject sourceObject = source.getSourceObject(game); - if (sourceObject != null && controller != null) { + MageObject mageObject = (Permanent) getValue(EntersBattlefieldEffect.ENTERING_PERMANENT); + if (mageObject == null) { + mageObject = game.getObject(source.getSourceId()); + } + if (mageObject != null && controller != null) { ChoiceImpl choices = new ChoiceImpl(true); choices.setMessage("Choose a spell type"); choices.getChoices().add(CardType.ARTIFACT.toString()); @@ -82,9 +87,12 @@ class CloudKeyChooseTypeEffect extends OneShotEffect { choices.getChoices().add(CardType.ENCHANTMENT.toString()); choices.getChoices().add(CardType.INSTANT.toString()); choices.getChoices().add(CardType.SORCERY.toString()); - if(controller.choose(Outcome.Neutral, choices, game)) { - game.informPlayers(sourceObject.getLogName() + ": chosen spell type is " + choices.getChoice()); + if (controller.choose(Outcome.Neutral, choices, game)) { + game.informPlayers(mageObject.getLogName() + ": chosen spell type is " + choices.getChoice()); game.getState().setValue(source.getSourceId().toString() + "_CloudKey", choices.getChoice()); + if (mageObject instanceof Permanent) { + ((Permanent) mageObject).addInfo("chosenCardType", CardUtil.addToolTipMarkTags("Chosen card type: " + choices.getChoice()), game); + } return true; } } @@ -129,4 +137,3 @@ class CloudKeyCostModificationEffect extends CostModificationEffectImpl { return false; } } - diff --git a/Mage.Sets/src/mage/sets/gatecrash/Realmwright.java b/Mage.Sets/src/mage/sets/gatecrash/Realmwright.java index dfb670e3dd..f0707af005 100644 --- a/Mage.Sets/src/mage/sets/gatecrash/Realmwright.java +++ b/Mage.Sets/src/mage/sets/gatecrash/Realmwright.java @@ -29,6 +29,18 @@ package mage.sets.gatecrash; import java.util.List; import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AsEntersBattlefieldAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.common.ChooseBasicLandTypeEffect; +import mage.abilities.mana.BlackManaAbility; +import mage.abilities.mana.BlueManaAbility; +import mage.abilities.mana.GreenManaAbility; +import mage.abilities.mana.RedManaAbility; +import mage.abilities.mana.WhiteManaAbility; +import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Layer; @@ -36,15 +48,6 @@ import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.SubLayer; import mage.constants.Zone; -import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.common.AsEntersBattlefieldAbility; -import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ContinuousEffectImpl; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.mana.*; -import mage.cards.CardImpl; -import mage.choices.ChoiceImpl; import mage.filter.common.FilterControlledLandPermanent; import mage.game.Game; import mage.game.permanent.Permanent; @@ -66,7 +69,7 @@ public class Realmwright extends CardImpl { this.toughness = new MageInt(1); // As Realmwright enters the battlefield, choose a basic land type. - this.addAbility(new AsEntersBattlefieldAbility(new RealmwrightEffect())); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseBasicLandTypeEffect(Outcome.Neutral))); // Lands you control are the chosen type in addition to their other types. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new RealmwrightEffect2())); @@ -82,44 +85,6 @@ public class Realmwright extends CardImpl { } } -class RealmwrightEffect extends OneShotEffect { - - public RealmwrightEffect() { - super(Outcome.Neutral); - this.staticText = "Choose a basic land type"; - } - - public RealmwrightEffect(final RealmwrightEffect effect) { - super(effect); - } - - @Override - public RealmwrightEffect copy() { - return new RealmwrightEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player you = game.getPlayer(source.getControllerId()); - if (you != null) { - ChoiceImpl choices = new ChoiceImpl(true); - choices.setMessage("Choose basic land type"); - choices.isRequired(); - choices.getChoices().add("Forest"); - choices.getChoices().add("Plains"); - choices.getChoices().add("Mountain"); - choices.getChoices().add("Island"); - choices.getChoices().add("Swamp"); - if (you.choose(Outcome.Neutral, choices, game)) { - game.informPlayers(new StringBuilder("Realmwright: ").append(" Chosen basic land type is ").append(choices.getChoice()).toString()); - game.getState().setValue(source.getSourceId().toString() + "_Realmwright", choices.getChoice()); - return true; - } - } - return false; - } -} - class RealmwrightEffect2 extends ContinuousEffectImpl { public RealmwrightEffect2() { @@ -140,7 +105,7 @@ class RealmwrightEffect2 extends ContinuousEffectImpl { public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { Player you = game.getPlayer(source.getControllerId()); List lands = game.getBattlefield().getAllActivePermanents(new FilterControlledLandPermanent(), source.getControllerId(), game); - String choice = (String) game.getState().getValue(source.getSourceId().toString() + "_Realmwright"); + String choice = (String) game.getState().getValue(source.getSourceId().toString() + ChooseBasicLandTypeEffect.VALUE_KEY); if (you != null && choice != null) { for (Permanent land : lands) { if (land != null) { diff --git a/Mage.Sets/src/mage/sets/guildpact/StompingGround.java b/Mage.Sets/src/mage/sets/guildpact/StompingGround.java index 0bce046017..85c8b2ce2d 100644 --- a/Mage.Sets/src/mage/sets/guildpact/StompingGround.java +++ b/Mage.Sets/src/mage/sets/guildpact/StompingGround.java @@ -25,18 +25,17 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.sets.guildpact; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Rarity; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.costs.common.PayLifeCost; import mage.abilities.effects.common.TapSourceUnlessPaysEffect; import mage.abilities.mana.GreenManaAbility; import mage.abilities.mana.RedManaAbility; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; /** * @@ -44,17 +43,19 @@ import mage.cards.CardImpl; */ public class StompingGround extends CardImpl { - public StompingGround (UUID ownerId) { + public StompingGround(UUID ownerId) { super(ownerId, 165, "Stomping Ground", Rarity.RARE, new CardType[]{CardType.LAND}, null); this.expansionSetCode = "GPT"; this.subtype.add("Mountain"); this.subtype.add("Forest"); + this.addAbility(new RedManaAbility()); this.addAbility(new GreenManaAbility()); - this.addAbility(new AsEntersBattlefieldAbility(new TapSourceUnlessPaysEffect(new PayLifeCost(2)), "you may pay 2 life. If you don't, Stomping Ground enters the battlefield tapped")); + this.addAbility(new AsEntersBattlefieldAbility(new TapSourceUnlessPaysEffect(new PayLifeCost(2)), + "you may pay 2 life. If you don't, {this} enters the battlefield tapped")); } - public StompingGround (final StompingGround card) { + public StompingGround(final StompingGround card) { super(card); } diff --git a/Mage.Sets/src/mage/sets/journeyintonyx/HallOfTriumph.java b/Mage.Sets/src/mage/sets/journeyintonyx/HallOfTriumph.java index 6fb34b789b..6423e7622b 100644 --- a/Mage.Sets/src/mage/sets/journeyintonyx/HallOfTriumph.java +++ b/Mage.Sets/src/mage/sets/journeyintonyx/HallOfTriumph.java @@ -33,9 +33,8 @@ import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ChooseColorEffect; import mage.cards.CardImpl; -import mage.choices.ChoiceColor; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Layer; @@ -46,8 +45,6 @@ import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.players.Player; - /** * @@ -61,7 +58,7 @@ public class HallOfTriumph extends CardImpl { this.supertype.add("Legendary"); // As Hall of Triumph enters the battlefield choose a color. - this.addAbility(new AsEntersBattlefieldAbility(new HallOfTriumphEffect())); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseColorEffect(Outcome.Neutral))); // Creatures you control of the chosen color get +1/+1. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new HallOfTriumphBoostControlledEffect())); } @@ -76,45 +73,6 @@ public class HallOfTriumph extends CardImpl { } } -class HallOfTriumphEffect extends OneShotEffect { - - public HallOfTriumphEffect() { - super(Outcome.BoostCreature); - staticText = "choose a color"; - } - - public HallOfTriumphEffect(final HallOfTriumphEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - Permanent permanent = game.getPermanent(source.getSourceId()); - if (player != null && permanent != null) { - ChoiceColor colorChoice = new ChoiceColor(); - colorChoice.setMessage("Choose color"); - while (!player.choose(Outcome.BoostCreature, colorChoice, game)) { - if (!player.canRespond()) { - return false; - } - } - if (colorChoice.getChoice() != null) { - game.informPlayers(permanent.getName() + ": " + player.getLogName() + " has chosen " + colorChoice.getChoice()); - game.getState().setValue(permanent.getId() + "_color", colorChoice.getColor()); - permanent.addInfo("chosen color", "Chosen color: " + colorChoice.getColor().getDescription() + "", game); - } - } - return false; - } - - @Override - public HallOfTriumphEffect copy() { - return new HallOfTriumphEffect(this); - } - -} - class HallOfTriumphBoostControlledEffect extends ContinuousEffectImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); @@ -137,7 +95,7 @@ class HallOfTriumphBoostControlledEffect extends ContinuousEffectImpl { public boolean apply(Game game, Ability source) { ObjectColor color = (ObjectColor) game.getState().getValue(source.getSourceId() + "_color"); if (color != null) { - for (Permanent perm: game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) { + for (Permanent perm : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) { if (perm.getColor(game).shares(color)) { perm.addPower(1); perm.addToughness(1); diff --git a/Mage.Sets/src/mage/sets/limitedalpha/BlackVise.java b/Mage.Sets/src/mage/sets/limitedalpha/BlackVise.java index 057ebaa541..57732f4911 100644 --- a/Mage.Sets/src/mage/sets/limitedalpha/BlackVise.java +++ b/Mage.Sets/src/mage/sets/limitedalpha/BlackVise.java @@ -32,6 +32,7 @@ import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ChooseOpponentEffect; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Outcome; @@ -40,9 +41,7 @@ import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; -import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.common.TargetOpponent; /** * @@ -55,7 +54,7 @@ public class BlackVise extends CardImpl { this.expansionSetCode = "LEA"; // As Black Vise enters the battlefield, choose an opponent. - this.addAbility(new AsEntersBattlefieldAbility(new BlackViseChooseOpponent())); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseOpponentEffect(Outcome.Detriment))); // At the beginning of the chosen player's upkeep, Black Vise deals X damage to that player, where X is the number of cards in his or her hand minus 4. this.addAbility(new BlackViseTriggeredAbility()); } @@ -70,42 +69,6 @@ public class BlackVise extends CardImpl { } } -class BlackViseChooseOpponent extends OneShotEffect { - - public BlackViseChooseOpponent() { - super(Outcome.Neutral); - this.staticText = "choose an opponent"; - } - - public BlackViseChooseOpponent(final BlackViseChooseOpponent effect) { - super(effect); - } - - @Override - public BlackViseChooseOpponent copy() { - return new BlackViseChooseOpponent(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - Permanent permanent = game.getPermanent(source.getSourceId()); - if (player != null && permanent != null) { - TargetOpponent target = new TargetOpponent(); - target.setNotTarget(true); - if (player.choose(this.outcome, target, source.getSourceId(), game)) { - Player chosenPlayer = game.getPlayer(target.getFirstTarget()); - if (chosenPlayer != null) { - game.informPlayers(permanent.getName() + ": " + player.getLogName() + " has chosen " + chosenPlayer.getLogName()); - game.getState().setValue(permanent.getId() + "_player", target.getFirstTarget()); - return true; - } - } - } - return false; - } -} - class BlackViseTriggeredAbility extends TriggeredAbilityImpl { public BlackViseTriggeredAbility() { @@ -128,12 +91,12 @@ class BlackViseTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - return event.getPlayerId().equals(game.getState().getValue(getSourceId().toString() + "_player")); + return event.getPlayerId().equals(game.getState().getValue(getSourceId().toString() + ChooseOpponentEffect.VALUE_KEY)); } @Override public String getRule() { - return new StringBuilder("At the beginning of the chosen player's upkeep, ").append(super.getRule()).toString(); + return "At the beginning of the chosen player's upkeep, " + super.getRule(); } } @@ -155,7 +118,7 @@ class BlackViseEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - UUID playerId = (UUID) game.getState().getValue(source.getSourceId().toString() + "_player"); + UUID playerId = (UUID) game.getState().getValue(source.getSourceId().toString() + ChooseOpponentEffect.VALUE_KEY); Player chosenPlayer = game.getPlayer(playerId); if (chosenPlayer != null) { int damage = chosenPlayer.getHand().size() - 4; diff --git a/Mage.Sets/src/mage/sets/limitedalpha/PhantasmalTerrain.java b/Mage.Sets/src/mage/sets/limitedalpha/PhantasmalTerrain.java index f38d3ea0f7..d7de486907 100644 --- a/Mage.Sets/src/mage/sets/limitedalpha/PhantasmalTerrain.java +++ b/Mage.Sets/src/mage/sets/limitedalpha/PhantasmalTerrain.java @@ -28,13 +28,12 @@ package mage.sets.limitedalpha; import java.util.UUID; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.ChooseBasicLandTypeEffect; import mage.abilities.keyword.EnchantAbility; import mage.abilities.mana.BlackManaAbility; import mage.abilities.mana.BlueManaAbility; @@ -42,7 +41,6 @@ import mage.abilities.mana.GreenManaAbility; import mage.abilities.mana.RedManaAbility; import mage.abilities.mana.WhiteManaAbility; import mage.cards.CardImpl; -import mage.choices.ChoiceImpl; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Layer; @@ -52,7 +50,6 @@ import mage.constants.SubLayer; import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.TargetPermanent; import mage.target.common.TargetLandPermanent; @@ -72,10 +69,10 @@ public class PhantasmalTerrain extends CardImpl { this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment)); this.addAbility(new EnchantAbility(auraTarget.getTargetName())); - + // As Phantasmal Terrain enters the battlefield, choose a basic land type. - this.addAbility(new AsEntersBattlefieldAbility(new PhantasmalTerrainChooseEffect())); - + this.addAbility(new AsEntersBattlefieldAbility(new ChooseBasicLandTypeEffect(Outcome.Neutral))); + // Enchanted land is the chosen type. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PhantasmalTerrainContinuousEffect())); } @@ -90,52 +87,13 @@ public class PhantasmalTerrain extends CardImpl { } } -class PhantasmalTerrainChooseEffect extends OneShotEffect { - - public PhantasmalTerrainChooseEffect() { - super(Outcome.Neutral); - this.staticText = "choose a basic land type"; - } - - public PhantasmalTerrainChooseEffect(final PhantasmalTerrainChooseEffect effect) { - super(effect); - } - - @Override - public PhantasmalTerrainChooseEffect copy() { - return new PhantasmalTerrainChooseEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - MageObject sourceObject = source.getSourceObject(game); - if (sourceObject != null && controller != null) { - ChoiceImpl choices = new ChoiceImpl(true); - choices.setMessage("Choose basic land type"); - choices.getChoices().add("Forest"); - choices.getChoices().add("Plains"); - choices.getChoices().add("Mountain"); - choices.getChoices().add("Island"); - choices.getChoices().add("Swamp"); - if (controller.choose(Outcome.Neutral, choices, game)) { - game.informPlayers(sourceObject.getLogName() + ": chosen basic land type is " + choices.getChoice()); - game.getState().setValue(source.getSourceId().toString() + "_PhantasmalTerrain", choices.getChoice()); - return true; - } - } - return false; - } - -} - class PhantasmalTerrainContinuousEffect extends ContinuousEffectImpl { - public PhantasmalTerrainContinuousEffect(){ + public PhantasmalTerrainContinuousEffect() { super(Duration.WhileOnBattlefield, Outcome.Neutral); this.staticText = "enchanted land is the chosen type"; } - + public PhantasmalTerrainContinuousEffect(final PhantasmalTerrainContinuousEffect effect) { super(effect); } @@ -148,7 +106,7 @@ class PhantasmalTerrainContinuousEffect extends ContinuousEffectImpl { @Override public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { Permanent enchantment = game.getPermanent(source.getSourceId()); - String choice = (String) game.getState().getValue(source.getSourceId().toString() + "_PhantasmalTerrain"); + String choice = (String) game.getState().getValue(source.getSourceId().toString() + ChooseBasicLandTypeEffect.VALUE_KEY); if (enchantment != null && enchantment.getAttachedTo() != null && choice != null) { Permanent land = game.getPermanent(enchantment.getAttachedTo()); if (land != null) { @@ -195,5 +153,5 @@ class PhantasmalTerrainContinuousEffect extends ContinuousEffectImpl { public boolean hasLayer(Layer layer) { return layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.TypeChangingEffects_4; } - + } diff --git a/Mage.Sets/src/mage/sets/magic2010/ConvincingMirage.java b/Mage.Sets/src/mage/sets/magic2010/ConvincingMirage.java index 5ee4db516f..9049656edd 100644 --- a/Mage.Sets/src/mage/sets/magic2010/ConvincingMirage.java +++ b/Mage.Sets/src/mage/sets/magic2010/ConvincingMirage.java @@ -27,21 +27,13 @@ */ package mage.sets.magic2010; -import java.util.Set; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.constants.SubLayer; -import mage.constants.Zone; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.ChooseBasicLandTypeEffect; import mage.abilities.keyword.EnchantAbility; import mage.abilities.mana.BlackManaAbility; import mage.abilities.mana.BlueManaAbility; @@ -49,10 +41,15 @@ import mage.abilities.mana.GreenManaAbility; import mage.abilities.mana.RedManaAbility; import mage.abilities.mana.WhiteManaAbility; import mage.cards.CardImpl; -import mage.choices.ChoiceImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Layer; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.SubLayer; +import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.TargetPermanent; import mage.target.common.TargetLandPermanent; @@ -67,13 +64,12 @@ public class ConvincingMirage extends CardImpl { this.expansionSetCode = "M10"; this.subtype.add("Aura"); - // Enchant land TargetPermanent auraTarget = new TargetLandPermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment)); // As Convincing Mirage enters the battlefield, choose a basic land type. - this.addAbility(new AsEntersBattlefieldAbility(new ConvincingMirageEffect())); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseBasicLandTypeEffect(Outcome.Neutral))); // Enchanted land is the chosen type. Ability ability = new EnchantAbility(auraTarget.getTargetName()); this.addAbility(ability); @@ -90,42 +86,6 @@ public class ConvincingMirage extends CardImpl { } } -class ConvincingMirageEffect extends OneShotEffect { - - public ConvincingMirageEffect() { - super(Outcome.Neutral); - this.staticText = "choose a basic land type"; - } - - public ConvincingMirageEffect(final ConvincingMirageEffect effect) { - super(effect); - } - - @Override - public ConvincingMirageEffect copy() { - return new ConvincingMirageEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player != null) { - ChoiceImpl choices = new ChoiceImpl(true); - Set choicesSet = choices.getChoices(); - choicesSet.add("Forest"); - choicesSet.add("Plains"); - choicesSet.add("Mountain"); - choicesSet.add("Island"); - choicesSet.add("Swamp"); - if (player.choose(Outcome.Neutral, choices, game)) { - game.getState().setValue(source.getSourceId().toString() + "_ConvincingMirage", choices.getChoice()); - return true; - } - } - return false; - } -} - class ConvincingMirageContinousEffect extends ContinuousEffectImpl { public ConvincingMirageContinousEffect() { @@ -145,7 +105,7 @@ class ConvincingMirageContinousEffect extends ContinuousEffectImpl { @Override public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { Permanent enchantment = game.getPermanent(source.getSourceId()); - String choice = (String) game.getState().getValue(source.getSourceId().toString() + "_ConvincingMirage"); + String choice = (String) game.getState().getValue(source.getSourceId().toString() + ChooseBasicLandTypeEffect.VALUE_KEY); if (enchantment != null && enchantment.getAttachedTo() != null && choice != null) { Permanent land = game.getPermanent(enchantment.getAttachedTo()); if (land != null) { @@ -160,19 +120,19 @@ class ConvincingMirageContinousEffect extends ContinuousEffectImpl { if (sublayer == SubLayer.NA) { land.getAbilities().clear(); if (choice.equals("Forest")) { - land.addAbility(new GreenManaAbility(), game); + land.addAbility(new GreenManaAbility(), source.getSourceId(), game); } if (choice.equals("Plains")) { - land.addAbility(new WhiteManaAbility(), game); + land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); } if (choice.equals("Mountain")) { - land.addAbility(new RedManaAbility(), game); + land.addAbility(new RedManaAbility(), source.getSourceId(), game); } if (choice.equals("Island")) { - land.addAbility(new BlueManaAbility(), game); + land.addAbility(new BlueManaAbility(), source.getSourceId(), game); } if (choice.equals("Swamp")) { - land.addAbility(new BlackManaAbility(), game); + land.addAbility(new BlackManaAbility(), source.getSourceId(), game); } } break; @@ -192,4 +152,4 @@ class ConvincingMirageContinousEffect extends ContinuousEffectImpl { public boolean hasLayer(Layer layer) { return layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.TypeChangingEffects_4; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/magic2012/SuturedGhoul.java b/Mage.Sets/src/mage/sets/magic2012/SuturedGhoul.java index 42a2b16593..44cc9264d2 100644 --- a/Mage.Sets/src/mage/sets/magic2012/SuturedGhoul.java +++ b/Mage.Sets/src/mage/sets/magic2012/SuturedGhoul.java @@ -27,26 +27,32 @@ */ package mage.sets.magic2012; +import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; +import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.keyword.TrampleAbility; import mage.cards.Card; import mage.cards.CardImpl; -import mage.constants.*; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.filter.common.FilterCreatureCard; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCardInYourGraveyard; -import java.util.UUID; - /** * @author nantuko */ @@ -97,30 +103,32 @@ class SuturedGhoulEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - Permanent permanent = game.getPermanent(source.getSourceId()); - if (player.getGraveyard().size() > 0) { - + Player controller = game.getPlayer(source.getControllerId()); + Permanent permanent = (Permanent) getValue(EntersBattlefieldEffect.ENTERING_PERMANENT); + if (permanent == null) { + return false; + } + if (controller.getGraveyard().size() > 0) { TargetCardInYourGraveyard target = new TargetCardInYourGraveyard(0, Integer.MAX_VALUE, new FilterCreatureCard("creature cards from your graveyard")); - if (player.chooseTarget(Outcome.Benefit, target, source, game)) { + if (controller.chooseTarget(Outcome.Benefit, target, source, game)) { int count = 0; for (UUID uuid : target.getTargets()) { - Card card = player.getGraveyard().get(uuid, game); + Card card = controller.getGraveyard().get(uuid, game); if (card != null) { - card.moveToExile(getId(), "Sutured Ghoul", source.getSourceId(), game); - if (permanent != null) { - permanent.imprint(card.getId(), game); - count++; - } + card.moveToExile(getId(), permanent.getIdName(), source.getSourceId(), game); + permanent.imprint(card.getId(), game); + count++; } } + Cards cardsToExile = new CardsImpl(target.getTargets()); + controller.moveCards(cardsToExile, null, Zone.EXILED, source, game); String msg = count == 1 ? "1 card" : count + "cards"; - game.informPlayers("Sutured Ghoul: " + player.getLogName() + " exiled " + msg); + game.informPlayers(permanent.getLogName() + ": " + controller.getLogName() + " exiled " + msg); } } else { - game.informPlayers("Sutured Ghoul: No cards in graveyard."); + game.informPlayers(permanent.getLogName() + ": No cards in graveyard."); } return true; } @@ -147,7 +155,7 @@ class SuturedGhoulPowerCount implements DynamicValue { int amount = 0; Permanent permanent = game.getPermanent(sourceAbility.getSourceId()); if (permanent != null) { - for (UUID uuid: permanent.getImprinted()) { + for (UUID uuid : permanent.getImprinted()) { Card card = game.getCard(uuid); if (card != null) { amount += card.getPower().getValue(); @@ -189,7 +197,7 @@ class SuturedGhoulToughnessCount implements DynamicValue { int amount = 0; Permanent permanent = game.getPermanent(sourceAbility.getSourceId()); if (permanent != null) { - for (UUID uuid: permanent.getImprinted()) { + for (UUID uuid : permanent.getImprinted()) { Card card = game.getCard(uuid); if (card != null) { amount += card.getToughness().getValue(); @@ -214,5 +222,3 @@ class SuturedGhoulToughnessCount implements DynamicValue { return "the total toughness of the exiled cards"; } } - - diff --git a/Mage.Sets/src/mage/sets/returntoravnica/TabletOfTheGuilds.java b/Mage.Sets/src/mage/sets/returntoravnica/TabletOfTheGuilds.java index ffe0df331b..c13d4cf613 100644 --- a/Mage.Sets/src/mage/sets/returntoravnica/TabletOfTheGuilds.java +++ b/Mage.Sets/src/mage/sets/returntoravnica/TabletOfTheGuilds.java @@ -28,17 +28,17 @@ package mage.sets.returntoravnica; import java.util.UUID; - -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Rarity; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.choices.ChoiceColor; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; import mage.filter.FilterSpell; import mage.game.Game; import mage.game.permanent.Permanent; @@ -59,7 +59,7 @@ public class TabletOfTheGuilds extends CardImpl { this.addAbility(new AsEntersBattlefieldAbility(new TabletOfTheGuildsEntersBattlefieldEffect())); // Whenever you cast a spell, if it's at least one of the chosen colors, you gain 1 life for each of the chosen colors it is. - this.addAbility(new SpellCastControllerTriggeredAbility(new TabletOfTheGuildsGainLifeEffect(), new FilterSpell("a spell"), false, true )); + this.addAbility(new SpellCastControllerTriggeredAbility(new TabletOfTheGuildsGainLifeEffect(), new FilterSpell("a spell"), false, true)); } public TabletOfTheGuilds(final TabletOfTheGuilds card) { @@ -86,7 +86,7 @@ class TabletOfTheGuildsEntersBattlefieldEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); - Permanent permanent = game.getPermanent(source.getSourceId()); + Permanent permanent = (Permanent) getValue(EntersBattlefieldEffect.ENTERING_PERMANENT); if (player != null && permanent != null) { String colors; ChoiceColor colorChoice = new ChoiceColor(); @@ -101,7 +101,7 @@ class TabletOfTheGuildsEntersBattlefieldEffect extends OneShotEffect { colorChoice.getChoices().remove(colorChoice.getChoice()); colorChoice.setMessage("Choose the second color"); - while (!player.choose(Outcome.GainLife, colorChoice, game) && player.canRespond()) { + while (!player.choose(Outcome.GainLife, colorChoice, game) && player.canRespond()) { game.debugMessage("player canceled choosing type. retrying."); } game.getState().setValue(permanent.getId() + "_color2", colorChoice.getColor().toString()); @@ -157,4 +157,4 @@ class TabletOfTheGuildsGainLifeEffect extends OneShotEffect { public TabletOfTheGuildsGainLifeEffect copy() { return new TabletOfTheGuildsGainLifeEffect(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/riseoftheeldrazi/CurseOfWizardry.java b/Mage.Sets/src/mage/sets/riseoftheeldrazi/CurseOfWizardry.java index bd4d6e4b53..db2d0e3902 100644 --- a/Mage.Sets/src/mage/sets/riseoftheeldrazi/CurseOfWizardry.java +++ b/Mage.Sets/src/mage/sets/riseoftheeldrazi/CurseOfWizardry.java @@ -29,13 +29,11 @@ package mage.sets.riseoftheeldrazi; import java.util.UUID; import mage.ObjectColor; -import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.AsEntersBattlefieldAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ChooseColorEffect; import mage.abilities.effects.common.LoseLifeTargetEffect; import mage.cards.CardImpl; -import mage.choices.ChoiceColor; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Rarity; @@ -45,7 +43,6 @@ import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; import mage.game.stack.Spell; -import mage.players.Player; import mage.target.targetpointer.FixedTarget; /** @@ -57,9 +54,8 @@ public class CurseOfWizardry extends CardImpl { super(ownerId, 104, "Curse of Wizardry", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}{B}"); this.expansionSetCode = "ROE"; - // As Curse of Wizardry enters the battlefield, choose a color. - this.addAbility(new AsEntersBattlefieldAbility(new CurseOfWizardryChooseColorEffect())); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseColorEffect(Outcome.Neutral))); // Whenever a player casts a spell of the chosen color, that player loses 1 life. this.addAbility(new CurseOfWizardryPlayerCastsSpellChosenColorTriggeredAbility()); @@ -76,38 +72,6 @@ public class CurseOfWizardry extends CardImpl { } } -class CurseOfWizardryChooseColorEffect extends OneShotEffect { - - public CurseOfWizardryChooseColorEffect() { - super(Outcome.Detriment); - staticText = "choose a color"; - } - - public CurseOfWizardryChooseColorEffect(final CurseOfWizardryChooseColorEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - Permanent curseOfWizardry = game.getPermanent(source.getSourceId()); - if (player != null && curseOfWizardry != null) { - ChoiceColor colorChoice = new ChoiceColor(); - if (player.choose(Outcome.Detriment, colorChoice, game)) { - game.informPlayers(curseOfWizardry.getName() + ": " + player.getLogName() + " has chosen " + colorChoice.getChoice()); - game.getState().setValue(curseOfWizardry.getId() + "_color", colorChoice.getColor()); - curseOfWizardry.addInfo("chosen color", "Chosen color: " + colorChoice.getColor().getDescription() + "", game); - } - } - return false; - } - - @Override - public CurseOfWizardryChooseColorEffect copy() { - return new CurseOfWizardryChooseColorEffect(this); - } -} - class CurseOfWizardryPlayerCastsSpellChosenColorTriggeredAbility extends TriggeredAbilityImpl { public CurseOfWizardryPlayerCastsSpellChosenColorTriggeredAbility() { diff --git a/Mage.Sets/src/mage/sets/shadowmoor/LureboundScarecrow.java b/Mage.Sets/src/mage/sets/shadowmoor/LureboundScarecrow.java index 1964cd1cc4..ba232975d0 100644 --- a/Mage.Sets/src/mage/sets/shadowmoor/LureboundScarecrow.java +++ b/Mage.Sets/src/mage/sets/shadowmoor/LureboundScarecrow.java @@ -32,9 +32,11 @@ import mage.MageInt; import mage.ObjectColor; import mage.abilities.StateTriggeredAbility; import mage.abilities.common.AsEntersBattlefieldAbility; +import mage.abilities.effects.common.ChooseColorEffect; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.cards.CardImpl; import mage.constants.CardType; +import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; import mage.game.Game; @@ -56,7 +58,7 @@ public class LureboundScarecrow extends CardImpl { this.toughness = new MageInt(4); // As Lurebound Scarecrow enters the battlefield, choose a color. - this.addAbility(new AsEntersBattlefieldAbility(new ChooseColorEffect())); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseColorEffect(Outcome.Detriment))); // When you control no permanents of the chosen color, sacrifice Lurebound Scarecrow. this.addAbility(new LureboundScarecrowTriggeredAbility()); diff --git a/Mage.Sets/src/mage/sets/shadowmoor/PaintersServant.java b/Mage.Sets/src/mage/sets/shadowmoor/PaintersServant.java index 10364727e8..8ec07fbc98 100644 --- a/Mage.Sets/src/mage/sets/shadowmoor/PaintersServant.java +++ b/Mage.Sets/src/mage/sets/shadowmoor/PaintersServant.java @@ -35,10 +35,9 @@ import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousEffectImpl; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ChooseColorEffect; import mage.cards.Card; import mage.cards.CardImpl; -import mage.choices.ChoiceColor; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Layer; @@ -68,7 +67,7 @@ public class PaintersServant extends CardImpl { this.toughness = new MageInt(3); // As Painter's Servant enters the battlefield, choose a color. - this.addAbility(new AsEntersBattlefieldAbility(new ChooseColorEffect())); + this.addAbility(new AsEntersBattlefieldAbility(new ChooseColorEffect(Outcome.Detriment))); // All cards that aren't on the battlefield, spells, and permanents are the chosen color in addition to their other colors. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PaintersServantEffect())); @@ -84,40 +83,6 @@ public class PaintersServant extends CardImpl { } } -class ChooseColorEffect extends OneShotEffect { - - public ChooseColorEffect() { - super(Outcome.Detriment); - staticText = "choose a color"; - } - - public ChooseColorEffect(final ChooseColorEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - Permanent permanent = game.getPermanent(source.getSourceId()); - if (player != null && permanent != null) { - ChoiceColor colorChoice = new ChoiceColor(); - if (player.choose(Outcome.Neutral, colorChoice, game)) { - game.informPlayers(new StringBuilder(permanent.getName()).append(": ").append(player.getLogName()).append(" has chosen ").append(colorChoice.getChoice()).toString()); - game.getState().setValue(source.getSourceId() + "_color", colorChoice.getColor()); - permanent.addInfo("chosen color", "Chosen color: " + colorChoice.getColor().getDescription() + "", game); - } - return true; - } - return false; - } - - @Override - public ChooseColorEffect copy() { - return new ChooseColorEffect(this); - } - -} - class PaintersServantEffect extends ContinuousEffectImpl { public PaintersServantEffect() { @@ -175,10 +140,10 @@ class PaintersServantEffect extends ContinuousEffectImpl { } return false; } - + protected static void setCardColor(Card card, String colorString, Game game) { ObjectColor color = game.getState().getCreateCardAttribute(card).getColor(); - switch (colorString) { + switch (colorString) { case "W": color.setWhite(true); break; diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/avr/CavernOfSoulsTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/avr/CavernOfSoulsTest.java index eb69c8b1c4..5062c9244a 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/avr/CavernOfSoulsTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/avr/CavernOfSoulsTest.java @@ -33,8 +33,9 @@ public class CavernOfSoulsTest extends CardTestPlayerBase { } /** - * Tests "Cavern of Souls" with "Human" creature type chosen. - * Then tests casting Azure Drake (should fail) and Elite Vanguard (should be ok as it has "Human" subtype) + * Tests "Cavern of Souls" with "Human" creature type chosen. Then tests + * casting Azure Drake (should fail) and Elite Vanguard (should be ok as it + * has "Human" subtype) */ @Test public void testNoCastBecauseOfCreatureType() { @@ -87,6 +88,9 @@ public class CavernOfSoulsTest extends CardTestPlayerBase { @Test public void testDrakeCantBeCountered() { addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3); + // As Cavern of Souls enters the battlefield, choose a creature type. + // {T}: Add {1} to your mana pool. + // {T}: Add one mana of any color to your mana pool. Spend this mana only to cast a creature spell of the chosen type, and that spell can't be countered. addCard(Zone.HAND, playerA, "Cavern of Souls"); addCard(Zone.HAND, playerA, "Azure Drake"); @@ -108,6 +112,7 @@ public class CavernOfSoulsTest extends CardTestPlayerBase { assertGraveyardCount(playerA, "Azure Drake", 0); assertPermanentCount(playerA, "Azure Drake", 1); } + /** * Tests spell can be countered if cast with colorless mana from Cavern */ @@ -136,59 +141,59 @@ public class CavernOfSoulsTest extends CardTestPlayerBase { assertGraveyardCount(playerA, "Azure Drake", 1); assertPermanentCount(playerA, "Azure Drake", 0); } - + /** - * Tests conditional mana from Cavern in pool will still work if Cavern got back to hand and is played again with other creature type + * Tests conditional mana from Cavern in pool will still work if Cavern got + * back to hand and is played again with other creature type */ @Test public void testConditionlManaWorksIfCavernIsReplayed() { addCard(Zone.HAND, playerA, "Cavern of Souls"); addCard(Zone.HAND, playerA, "Gladecover Scout"); // Elf costing {G} // addCard(Zone.HAND, playerA, "Fume Spitter"); // Horror costing {B} - + // Instant - {U}{U} - Return target permanent to its owner's hand. addCard(Zone.HAND, playerB, "Boomerang"); addCard(Zone.BATTLEFIELD, playerB, "Island", 2); playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cavern of Souls"); setChoice(playerA, "Elf"); - + // getting green mana for Elf into pool activateManaAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add 1 mana of any one color to your mana pool. Spend this mana only to cast a creature spell of the chosen type, and that spell can't be countered."); - setChoice(playerA, "Green"); - + setChoice(playerA, "Green"); + // return cavern to hand castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerB, "Boomerang", "Cavern of Souls"); - + // playing the cavern again choose different creature type playLand(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Cavern of Souls"); setChoice(playerA, "Horror"); - // the green mana usable for Elf should be in the mana pool + // the green mana usable for Elf should be in the mana pool castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Gladecover Scout"); activateManaAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add 1 mana of any one color to your mana pool. Spend this mana only to cast a creature spell of the chosen type, and that spell can't be countered."); - setChoice(playerA, "Black"); + setChoice(playerA, "Black"); - // the black mana usable for Horror should be in the mana pool + // the black mana usable for Horror should be in the mana pool // castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Fume Spitter"); - setStopAt(3, PhaseStep.BEGIN_COMBAT); execute(); - assertGraveyardCount(playerB, "Boomerang", 1); assertPermanentCount(playerA, "Cavern of Souls", 1); - + // Check the elf was cast assertPermanentCount(playerA, "Gladecover Scout", 1); // Check Horror on the Battlefield // assertPermanentCount(playerA, "Fume Spitter", 1); - } + } /** - * Return to the Ranks cannot be countered if mana produced by Cavern of Souls - * was used to pay X. Can be bug also for all other spells with X in their cost, not sure. + * Return to the Ranks cannot be countered if mana produced by Cavern of + * Souls was used to pay X. Can be bug also for all other spells with X in + * their cost, not sure. * */ @Test @@ -205,12 +210,11 @@ public class CavernOfSoulsTest extends CardTestPlayerBase { addCard(Zone.HAND, playerB, "Counterspell"); addCard(Zone.BATTLEFIELD, playerB, "Island", 2); - playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cavern of Souls"); setChoice(playerA, "Drake"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Return to the Ranks", "Silvercoat Lion"); setChoice(playerA, "X=1"); - + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Counterspell", "Return to the Ranks"); setStopAt(1, PhaseStep.BEGIN_COMBAT); @@ -223,11 +227,12 @@ public class CavernOfSoulsTest extends CardTestPlayerBase { assertPermanentCount(playerA, "Silvercoat Lion", 0); } - + /** - * Cavern of Souls can produce any colour of mana with its second ability when Contamination is in play. + * Cavern of Souls can produce any colour of mana with its second ability + * when Contamination is in play. */ - @Test + @Test public void testUseWithConversionInPlay() { addCard(Zone.BATTLEFIELD, playerA, "Plains", 3); addCard(Zone.HAND, playerA, "Cavern of Souls"); @@ -235,8 +240,6 @@ public class CavernOfSoulsTest extends CardTestPlayerBase { addCard(Zone.HAND, playerA, "Desert Drake"); addCard(Zone.BATTLEFIELD, playerB, "Contamination", 1); - - playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cavern of Souls"); setChoice(playerA, "Drake"); @@ -249,5 +252,5 @@ public class CavernOfSoulsTest extends CardTestPlayerBase { assertPermanentCount(playerA, "Desert Drake", 0); } - + } diff --git a/Mage/src/mage/abilities/effects/common/ChooseBasicLandTypeEffect.java b/Mage/src/mage/abilities/effects/common/ChooseBasicLandTypeEffect.java new file mode 100644 index 0000000000..07c1e706e9 --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/ChooseBasicLandTypeEffect.java @@ -0,0 +1,68 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package mage.abilities.effects.common; + +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.effects.EntersBattlefieldEffect; +import mage.abilities.effects.OneShotEffect; +import mage.choices.ChoiceImpl; +import mage.constants.Outcome; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.util.CardUtil; + +/** + * + * @author LevelX2 + */ +public class ChooseBasicLandTypeEffect extends OneShotEffect { + + public static String VALUE_KEY = "BasicLandType"; + + public ChooseBasicLandTypeEffect(Outcome outcome) { + super(outcome); + this.staticText = "Choose a basic land type"; + } + + public ChooseBasicLandTypeEffect(final ChooseBasicLandTypeEffect effect) { + super(effect); + } + + @Override + public ChooseBasicLandTypeEffect copy() { + return new ChooseBasicLandTypeEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject mageObject = (Permanent) getValue(EntersBattlefieldEffect.ENTERING_PERMANENT); + if (mageObject == null) { + mageObject = game.getObject(source.getSourceId()); + } + if (controller != null && mageObject != null) { + ChoiceImpl choices = new ChoiceImpl(true); + choices.setMessage("Choose basic land type"); + choices.isRequired(); + choices.getChoices().add("Forest"); + choices.getChoices().add("Plains"); + choices.getChoices().add("Mountain"); + choices.getChoices().add("Island"); + choices.getChoices().add("Swamp"); + if (controller.choose(Outcome.Neutral, choices, game)) { + game.informPlayers(mageObject.getName() + ": Chosen basic land type is " + choices.getChoice()); + game.getState().setValue(mageObject.getId().toString() + VALUE_KEY, choices.getChoice()); + if (mageObject instanceof Permanent) { + ((Permanent) mageObject).addInfo("chosen color", CardUtil.addToolTipMarkTags("Chosen basic land type: " + choices.getChoice()), game); + } + return true; + } + } + return false; + } +} diff --git a/Mage/src/mage/abilities/effects/common/ChooseColorEffect.java b/Mage/src/mage/abilities/effects/common/ChooseColorEffect.java index 43836dd2f7..2fe0111675 100644 --- a/Mage/src/mage/abilities/effects/common/ChooseColorEffect.java +++ b/Mage/src/mage/abilities/effects/common/ChooseColorEffect.java @@ -27,6 +27,7 @@ */ package mage.abilities.effects.common; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.OneShotEffect; @@ -55,11 +56,11 @@ public class ChooseColorEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent == null) { - permanent = (Permanent) getValue(EntersBattlefieldEffect.ENTERING_PERMANENT); + MageObject mageObject = (Permanent) getValue(EntersBattlefieldEffect.ENTERING_PERMANENT); + if (mageObject == null) { + mageObject = game.getObject(source.getSourceId()); } - if (controller != null && permanent != null) { + if (controller != null && mageObject != null) { ChoiceColor choice = new ChoiceColor(); while (!choice.isChosen()) { controller.choose(outcome, choice, game); @@ -68,10 +69,12 @@ public class ChooseColorEffect extends OneShotEffect { } } if (!game.isSimulation()) { - game.informPlayers(permanent.getLogName() + ": " + controller.getLogName() + " has chosen " + choice.getChoice()); + game.informPlayers(mageObject.getLogName() + ": " + controller.getLogName() + " has chosen " + choice.getChoice()); + } + game.getState().setValue(mageObject.getId() + "_color", choice.getColor()); + if (mageObject instanceof Permanent) { + ((Permanent) mageObject).addInfo("chosen color", CardUtil.addToolTipMarkTags("Chosen color: " + choice.getChoice()), game); } - game.getState().setValue(source.getSourceId() + "_color", choice.getColor()); - permanent.addInfo("chosen color", CardUtil.addToolTipMarkTags("Chosen color: " + choice.getChoice()), game); return true; } return false; diff --git a/Mage/src/mage/abilities/effects/common/ChooseCreatureTypeEffect.java b/Mage/src/mage/abilities/effects/common/ChooseCreatureTypeEffect.java index 2ebd99cc9d..06178b0284 100644 --- a/Mage/src/mage/abilities/effects/common/ChooseCreatureTypeEffect.java +++ b/Mage/src/mage/abilities/effects/common/ChooseCreatureTypeEffect.java @@ -27,7 +27,9 @@ */ package mage.abilities.effects.common; +import mage.MageObject; import mage.abilities.Ability; +import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.OneShotEffect; import mage.cards.repository.CardRepository; import mage.choices.Choice; @@ -42,7 +44,6 @@ import mage.util.CardUtil; * * @author LevelX2 */ - public class ChooseCreatureTypeEffect extends OneShotEffect { public ChooseCreatureTypeEffect(Outcome outcome) { @@ -57,8 +58,11 @@ public class ChooseCreatureTypeEffect extends OneShotEffect { @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) { + MageObject mageObject = (Permanent) getValue(EntersBattlefieldEffect.ENTERING_PERMANENT); + if (mageObject == null) { + mageObject = game.getObject(source.getSourceId()); + } + if (controller != null && mageObject != null) { Choice typeChoice = new ChoiceImpl(true); typeChoice.setMessage("Choose creature type"); typeChoice.setChoices(CardRepository.instance.getCreatureTypes()); @@ -68,10 +72,12 @@ public class ChooseCreatureTypeEffect extends OneShotEffect { } } if (!game.isSimulation()) { - game.informPlayers(permanent.getName() + ": " + controller.getLogName() + " has chosen " + typeChoice.getChoice()); + game.informPlayers(mageObject.getName() + ": " + controller.getLogName() + " has chosen " + typeChoice.getChoice()); + } + game.getState().setValue(mageObject.getId() + "_type", typeChoice.getChoice()); + if (mageObject instanceof Permanent) { + ((Permanent) mageObject).addInfo("chosen type", CardUtil.addToolTipMarkTags("Chosen type: " + typeChoice.getChoice()), game); } - game.getState().setValue(permanent.getId() + "_type", typeChoice.getChoice()); - permanent.addInfo("chosen type", CardUtil.addToolTipMarkTags("Chosen type: " + typeChoice.getChoice()), game); } return false; } diff --git a/Mage/src/mage/abilities/effects/common/ChooseLandTypeEffect.java b/Mage/src/mage/abilities/effects/common/ChooseLandTypeEffect.java index 0480effa49..52259dbac5 100644 --- a/Mage/src/mage/abilities/effects/common/ChooseLandTypeEffect.java +++ b/Mage/src/mage/abilities/effects/common/ChooseLandTypeEffect.java @@ -5,7 +5,9 @@ */ package mage.abilities.effects.common; +import mage.MageObject; import mage.abilities.Ability; +import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.OneShotEffect; import mage.cards.repository.CardRepository; import mage.choices.Choice; @@ -34,8 +36,11 @@ public class ChooseLandTypeEffect extends OneShotEffect { @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) { + MageObject mageObject = (Permanent) getValue(EntersBattlefieldEffect.ENTERING_PERMANENT); + if (mageObject == null) { + mageObject = game.getObject(source.getSourceId()); + } + if (controller != null && mageObject != null) { Choice typeChoice = new ChoiceImpl(true); typeChoice.setMessage("Choose land type"); typeChoice.setChoices(CardRepository.instance.getLandTypes()); @@ -45,10 +50,12 @@ public class ChooseLandTypeEffect extends OneShotEffect { } } if (!game.isSimulation()) { - game.informPlayers(permanent.getName() + ": " + controller.getLogName() + " has chosen " + typeChoice.getChoice()); + game.informPlayers(mageObject.getName() + ": " + controller.getLogName() + " has chosen " + typeChoice.getChoice()); + } + game.getState().setValue(mageObject.getId() + "_type", typeChoice.getChoice()); + if (mageObject instanceof Permanent) { + ((Permanent) mageObject).addInfo("chosen type", CardUtil.addToolTipMarkTags("Chosen type: " + typeChoice.getChoice()), game); } - game.getState().setValue(permanent.getId() + "_type", typeChoice.getChoice()); - permanent.addInfo("chosen type", CardUtil.addToolTipMarkTags("Chosen type: " + typeChoice.getChoice()), game); } return false; } diff --git a/Mage/src/mage/abilities/effects/common/ChooseNewTargetsTargetEffect.java b/Mage/src/mage/abilities/effects/common/ChooseNewTargetsTargetEffect.java index 265b66e9cd..35ac9818cd 100644 --- a/Mage/src/mage/abilities/effects/common/ChooseNewTargetsTargetEffect.java +++ b/Mage/src/mage/abilities/effects/common/ChooseNewTargetsTargetEffect.java @@ -1,38 +1,36 @@ /* -* 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. -*/ - + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ package mage.abilities.effects.common; -import mage.constants.Outcome; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.effects.OneShotEffect; -import mage.filter.Filter; +import mage.constants.Outcome; import mage.filter.FilterPermanent; import mage.game.Game; import mage.game.stack.StackObject; @@ -46,21 +44,22 @@ public class ChooseNewTargetsTargetEffect extends OneShotEffect { private boolean forceChange; private boolean onlyOneTarget; private FilterPermanent filterNewTarget; - + public ChooseNewTargetsTargetEffect() { this(false, false); } + public ChooseNewTargetsTargetEffect(boolean forceChange, boolean onlyOneTarget) { this(forceChange, onlyOneTarget, null); } /** * - * @param forceChange forces the user to choose another target (only targets with maxtargets = 1 supported) + * @param forceChange forces the user to choose another target (only targets + * with maxtargets = 1 supported) * @param onlyOneTarget only one target can be selected for the change * @param filterNewTarget restriction to the new target */ - public ChooseNewTargetsTargetEffect(boolean forceChange, boolean onlyOneTarget, FilterPermanent filterNewTarget) { super(Outcome.Benefit); this.forceChange = forceChange; diff --git a/Mage/src/mage/abilities/effects/common/ChooseOpponentEffect.java b/Mage/src/mage/abilities/effects/common/ChooseOpponentEffect.java new file mode 100644 index 0000000000..9ac1910128 --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/ChooseOpponentEffect.java @@ -0,0 +1,64 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package mage.abilities.effects.common; + +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.effects.EntersBattlefieldEffect; +import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetOpponent; +import mage.util.CardUtil; + +/** + * + * @author LevelX2 + */ +public class ChooseOpponentEffect extends OneShotEffect { + + public static String VALUE_KEY = "_opponent"; + + public ChooseOpponentEffect(Outcome outcome) { + super(outcome); + this.staticText = "choose an opponent"; + } + + public ChooseOpponentEffect(final ChooseOpponentEffect effect) { + super(effect); + } + + @Override + public ChooseOpponentEffect copy() { + return new ChooseOpponentEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject mageObject = (Permanent) getValue(EntersBattlefieldEffect.ENTERING_PERMANENT); + if (mageObject == null) { + mageObject = game.getObject(source.getSourceId()); + } + if (controller != null && mageObject != null) { + TargetOpponent target = new TargetOpponent(true); + if (controller.choose(this.outcome, target, source.getSourceId(), game)) { + Player chosenPlayer = game.getPlayer(target.getFirstTarget()); + if (chosenPlayer != null) { + game.informPlayers(mageObject.getName() + ": " + controller.getLogName() + " has chosen " + chosenPlayer.getLogName()); + game.getState().setValue(mageObject.getId() + VALUE_KEY, target.getFirstTarget()); + if (mageObject instanceof Permanent) { + ((Permanent) mageObject).addInfo("chosen opponent", CardUtil.addToolTipMarkTags("Chosen player: " + chosenPlayer.getLogName()), game); + } + return true; + } + } + } + return false; + } +} diff --git a/Mage/src/mage/abilities/effects/common/ChoosePlayerEffect.java b/Mage/src/mage/abilities/effects/common/ChoosePlayerEffect.java index 9f4481515c..7e5c6402c1 100644 --- a/Mage/src/mage/abilities/effects/common/ChoosePlayerEffect.java +++ b/Mage/src/mage/abilities/effects/common/ChoosePlayerEffect.java @@ -5,7 +5,9 @@ */ package mage.abilities.effects.common; +import mage.MageObject; import mage.abilities.Ability; +import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.OneShotEffect; import mage.constants.Outcome; import mage.game.Game; @@ -36,16 +38,21 @@ public class ChoosePlayerEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - Permanent permanent = game.getPermanent(source.getSourceId()); - if (player != null && permanent != null) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject mageObject = (Permanent) getValue(EntersBattlefieldEffect.ENTERING_PERMANENT); + if (mageObject == null) { + mageObject = game.getObject(source.getSourceId()); + } + if (controller != null && mageObject != null) { TargetPlayer target = new TargetPlayer(1, 1, true); - if (player.choose(this.outcome, target, source.getSourceId(), game)) { + if (controller.choose(this.outcome, target, source.getSourceId(), game)) { Player chosenPlayer = game.getPlayer(target.getFirstTarget()); if (chosenPlayer != null) { - game.informPlayers(permanent.getName() + ": " + player.getLogName() + " has chosen " + chosenPlayer.getLogName()); - game.getState().setValue(permanent.getId() + "_player", target.getFirstTarget()); - permanent.addInfo("chosen player", CardUtil.addToolTipMarkTags("Chosen player: " + chosenPlayer.getLogName()), game); + game.informPlayers(mageObject.getName() + ": " + controller.getLogName() + " has chosen " + chosenPlayer.getLogName()); + game.getState().setValue(mageObject.getId() + "_player", target.getFirstTarget()); + if (mageObject instanceof Permanent) { + ((Permanent) mageObject).addInfo("chosen player", CardUtil.addToolTipMarkTags("Chosen player: " + chosenPlayer.getLogName()), game); + } return true; } } diff --git a/Mage/src/mage/abilities/effects/common/TapSourceUnlessPaysEffect.java b/Mage/src/mage/abilities/effects/common/TapSourceUnlessPaysEffect.java index 55bc3ad99e..0d2e474b15 100644 --- a/Mage/src/mage/abilities/effects/common/TapSourceUnlessPaysEffect.java +++ b/Mage/src/mage/abilities/effects/common/TapSourceUnlessPaysEffect.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,16 +20,16 @@ * 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.abilities.Ability; import mage.abilities.costs.Cost; +import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.OneShotEffect; import mage.constants.Outcome; import mage.game.Game; @@ -59,7 +59,10 @@ public class TapSourceUnlessPaysEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanent(source.getSourceId()); - if (player != null && permanent != null) { + if (permanent == null) { + permanent = (Permanent) getValue(EntersBattlefieldEffect.ENTERING_PERMANENT); + } + if (player != null && permanent != null) { if (cost.canPay(source, source.getSourceId(), source.getControllerId(), game) && player.chooseUse(Outcome.Benefit, cost.getText() + "? (otherwise " + permanent.getName() + " becomes tapped)", source, game)) { cost.clearPaid(); @@ -78,5 +81,4 @@ public class TapSourceUnlessPaysEffect extends OneShotEffect { return new TapSourceUnlessPaysEffect(this); } - } diff --git a/Mage/src/mage/abilities/keyword/ModularAbility.java b/Mage/src/mage/abilities/keyword/ModularAbility.java index 19219e21b2..3d9133f57e 100644 --- a/Mage/src/mage/abilities/keyword/ModularAbility.java +++ b/Mage/src/mage/abilities/keyword/ModularAbility.java @@ -22,24 +22,24 @@ import mage.target.Target; import mage.target.common.TargetArtifactPermanent; import mage.util.CardUtil; - /** * * 702.41. Modular * - * 702.41a Modular represents both a static ability and a triggered ability. - * "Modular N" means "This permanent enters the battlefield with N +1/+1 - * counters on it" and "When this permanent is put into a graveyard - * from the battlefield, you may put a +1/+1 counter on target artifact - * creature for each +1/+1 counter on this permanent." - * 702.41b If a creature has multiple instances of modular, each one works separately. + * 702.41a Modular represents both a static ability and a triggered ability. + * "Modular N" means "This permanent enters the battlefield with N +1/+1 + * counters on it" and "When this permanent is put into a graveyard from the + * battlefield, you may put a +1/+1 counter on target artifact creature for each + * +1/+1 counter on this permanent." 702.41b If a creature has multiple + * instances of modular, each one works separately. + * * - * * @author Loki, LevelX2 */ - public class ModularAbility extends DiesTriggeredAbility { + private static final FilterArtifactPermanent filter = new FilterArtifactPermanent("artifact creature"); + static { filter.add(new CardTypePredicate(CardType.CREATURE)); } @@ -74,7 +74,7 @@ public class ModularAbility extends DiesTriggeredAbility { @Override public boolean checkTrigger(GameEvent event, Game game) { if (super.checkTrigger(event, game)) { - ZoneChangeEvent zEvent = (ZoneChangeEvent)event; + ZoneChangeEvent zEvent = (ZoneChangeEvent) event; if (zEvent.getTarget().getCounters().getCount(CounterType.P1P1) > 0) { return true; } @@ -94,9 +94,9 @@ public class ModularAbility extends DiesTriggeredAbility { sb.append("-Sunburst (This enters the battlefield with a +1/+1 counter on it for each color of mana spent to cast it. When it dies, you may put its +1/+1 counters on target artifact creature.)"); } else { sb.append(" ").append(amount).append(" (This enters the battlefield with ") - .append(CardUtil.numberToText(amount, "a")) - .append(" +1/+1 counter").append(amount != 1 ? "s":"") - .append(" on it. When it dies, you may put its +1/+1 counters on target artifact creature.)"); + .append(CardUtil.numberToText(amount, "a")) + .append(" +1/+1 counter").append(amount != 1 ? "s" : "") + .append(" on it. When it dies, you may put its +1/+1 counters on target artifact creature.)"); } return sb.toString(); } @@ -109,9 +109,7 @@ class ModularStaticAbility extends StaticAbility { public ModularStaticAbility(int amount) { super(Zone.BATTLEFIELD, new EntersBattlefieldEffect(new AddCountersSourceEffect(CounterType.P1P1.createInstance(amount)))); - ruleText = new StringBuilder("This enters the battlefield with ").append(CardUtil.numberToText(amount, "a")) - .append(" +1/+1 counter").append(amount != 1 ? "s":"") - .append(" on it.").toString(); + ruleText = "This enters the battlefield with " + CardUtil.numberToText(amount, "a") + " +1/+1 counter" + (amount != 1 ? "s" : "") + " on it."; this.setRuleVisible(false); } @@ -131,9 +129,10 @@ class ModularStaticAbility extends StaticAbility { } } - class ModularDistributeCounterEffect extends OneShotEffect { + private static final FilterArtifactPermanent filter = new FilterArtifactPermanent("artifact creature"); + static { filter.add(new CardTypePredicate(CardType.CREATURE)); } From 9b7f56ca2ceaab5e93c79c4854e8c12ee4e76b4e Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 16 Oct 2015 00:32:55 +0200 Subject: [PATCH 44/46] * Updated enters battlefield replacement effects for new handling. --- .../sets/riseoftheeldrazi/NotOfThisWorld.java | 105 ++++++++++++++++-- .../EntersBattlefieldTappedAbility.java | 17 ++- .../EntersBattlefieldWithXCountersEffect.java | 3 + .../effects/common/TapSourceEffect.java | 60 +++++----- .../continuous/GainAbilitySourceEffect.java | 20 ++-- .../abilities/keyword/BloodthirstAbility.java | 14 ++- .../mage/abilities/keyword/FadingAbility.java | 36 +++--- .../abilities/keyword/SunburstAbility.java | 40 +++---- .../abilities/keyword/TributeAbility.java | 25 ++--- 9 files changed, 201 insertions(+), 119 deletions(-) diff --git a/Mage.Sets/src/mage/sets/riseoftheeldrazi/NotOfThisWorld.java b/Mage.Sets/src/mage/sets/riseoftheeldrazi/NotOfThisWorld.java index 97363cb0aa..42b6e9c8f4 100644 --- a/Mage.Sets/src/mage/sets/riseoftheeldrazi/NotOfThisWorld.java +++ b/Mage.Sets/src/mage/sets/riseoftheeldrazi/NotOfThisWorld.java @@ -27,6 +27,8 @@ */ package mage.sets.riseoftheeldrazi; +import java.util.HashSet; +import java.util.Set; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; @@ -39,17 +41,17 @@ import mage.constants.Rarity; import mage.constants.TargetController; import mage.constants.Zone; import mage.filter.Filter; -import mage.filter.FilterSpell; -import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; -import mage.filter.predicate.other.TargetsPermanentPredicate; import mage.filter.predicate.permanent.ControllerPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.game.stack.Spell; +import mage.game.stack.StackAbility; import mage.game.stack.StackObject; import mage.target.Target; -import mage.target.TargetSpell; +import mage.target.TargetObject; +import mage.target.Targets; /** * @@ -57,19 +59,14 @@ import mage.target.TargetSpell; */ public class NotOfThisWorld extends CardImpl { - private final static FilterSpell filter = new FilterSpell("spell that targets a permanent you control"); - - static { - filter.add(new TargetsPermanentPredicate(new FilterControlledPermanent())); - } - public NotOfThisWorld(UUID ownerId) { super(ownerId, 8, "Not of This World", Rarity.UNCOMMON, new CardType[]{CardType.TRIBAL, CardType.INSTANT}, "{7}"); this.expansionSetCode = "ROE"; this.subtype.add("Eldrazi"); // Counter target spell or ability that targets a permanent you control. - this.getSpellAbility().addTarget(new TargetSpell(filter)); + this.getSpellAbility().addTarget( + new TargetStackObjectTargetingControlledPermanent()); this.getSpellAbility().addEffect(new CounterTargetEffect()); // Not of This World costs {7} less to cast if it targets a spell or ability that targets a creature you control with power 7 or greater. this.addAbility(new SimpleStaticAbility(Zone.STACK, new SpellCostReductionSourceEffect(7, NotOfThisWorldCondition.getInstance()))); @@ -85,6 +82,92 @@ public class NotOfThisWorld extends CardImpl { } } +class TargetStackObjectTargetingControlledPermanent extends TargetObject { + + public TargetStackObjectTargetingControlledPermanent() { + this.minNumberOfTargets = 1; + this.maxNumberOfTargets = 1; + this.zone = Zone.STACK; + this.targetName = "spell or ability that targets a permanent you control"; + } + + public TargetStackObjectTargetingControlledPermanent(final TargetStackObjectTargetingControlledPermanent target) { + super(target); + } + + @Override + public Filter getFilter() { + throw new UnsupportedOperationException("Not supported."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + public boolean canTarget(UUID id, Ability source, Game game) { + StackObject stackObject = game.getStack().getStackObject(id); + if ((stackObject instanceof Spell) || (stackObject instanceof StackAbility)) { + return true; + } + return false; + } + + @Override + public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { + return canChoose(sourceControllerId, game); + } + + @Override + public boolean canChoose(UUID sourceControllerId, Game game) { + for (StackObject stackObject : game.getStack()) { + if ((stackObject instanceof Spell) || (stackObject instanceof StackAbility)) { + Targets objectTargets = stackObject.getStackAbility().getTargets(); + if (!objectTargets.isEmpty()) { + for (Target target : objectTargets) { + for (UUID targetId : target.getTargets()) { + Permanent targetedPermanent = game.getPermanentOrLKIBattlefield(targetId); + if (targetedPermanent != null && targetedPermanent.getControllerId().equals(sourceControllerId)) { + return true; + } + } + } + } + } + } + return false; + } + + @Override + public Set possibleTargets(UUID sourceId, UUID sourceControllerId, + Game game) { + return possibleTargets(sourceControllerId, game); + } + + @Override + public Set possibleTargets(UUID sourceControllerId, Game game) { + Set possibleTargets = new HashSet<>(); + for (StackObject stackObject : game.getStack()) { + if ((stackObject instanceof Spell) || (stackObject instanceof StackAbility)) { + Targets objectTargets = stackObject.getStackAbility().getTargets(); + if (!objectTargets.isEmpty()) { + for (Target target : objectTargets) { + for (UUID targetId : target.getTargets()) { + Permanent targetedPermanent = game.getPermanentOrLKIBattlefield(targetId); + if (targetedPermanent != null && targetedPermanent.getControllerId().equals(sourceControllerId)) { + possibleTargets.add(stackObject.getId()); + } + } + } + } + } + } + return possibleTargets; + } + + @Override + public TargetStackObjectTargetingControlledPermanent copy() { + return new TargetStackObjectTargetingControlledPermanent(this); + } + +} + class NotOfThisWorldCondition implements Condition { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature you control with power 7 or greater"); diff --git a/Mage/src/mage/abilities/common/EntersBattlefieldTappedAbility.java b/Mage/src/mage/abilities/common/EntersBattlefieldTappedAbility.java index 1d8d119f17..f62f02ab29 100644 --- a/Mage/src/mage/abilities/common/EntersBattlefieldTappedAbility.java +++ b/Mage/src/mage/abilities/common/EntersBattlefieldTappedAbility.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,18 +20,17 @@ * 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.common; -import mage.constants.Zone; import mage.abilities.StaticAbility; import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.common.TapSourceEffect; +import mage.constants.Zone; /** * @@ -40,9 +39,9 @@ import mage.abilities.effects.common.TapSourceEffect; public class EntersBattlefieldTappedAbility extends StaticAbility { private String ruleText; - + public EntersBattlefieldTappedAbility() { - super(Zone.BATTLEFIELD, new EntersBattlefieldEffect(new TapSourceEffect(true))); + super(Zone.ALL, new EntersBattlefieldEffect(new TapSourceEffect(true))); } public EntersBattlefieldTappedAbility(String ruleText) { diff --git a/Mage/src/mage/abilities/effects/common/EntersBattlefieldWithXCountersEffect.java b/Mage/src/mage/abilities/effects/common/EntersBattlefieldWithXCountersEffect.java index 999e70423d..7451cd90db 100644 --- a/Mage/src/mage/abilities/effects/common/EntersBattlefieldWithXCountersEffect.java +++ b/Mage/src/mage/abilities/effects/common/EntersBattlefieldWithXCountersEffect.java @@ -59,6 +59,9 @@ public class EntersBattlefieldWithXCountersEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent == null) { + permanent = (Permanent) getValue(EntersBattlefieldEffect.ENTERING_PERMANENT); + } if (permanent != null) { SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); if (spellAbility != null diff --git a/Mage/src/mage/abilities/effects/common/TapSourceEffect.java b/Mage/src/mage/abilities/effects/common/TapSourceEffect.java index fcbc92c1e4..aa655d15bf 100644 --- a/Mage/src/mage/abilities/effects/common/TapSourceEffect.java +++ b/Mage/src/mage/abilities/effects/common/TapSourceEffect.java @@ -1,36 +1,36 @@ /* -* 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. -*/ - + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ package mage.abilities.effects.common; -import mage.constants.Outcome; import mage.abilities.Ability; +import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; import mage.game.Game; import mage.game.permanent.Permanent; @@ -39,6 +39,7 @@ import mage.game.permanent.Permanent; * @author BetaSteward_at_googlemail.com */ public class TapSourceEffect extends OneShotEffect { + private boolean withoutTrigger; public TapSourceEffect() { @@ -64,6 +65,9 @@ public class TapSourceEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent == null) { + permanent = (Permanent) getValue(EntersBattlefieldEffect.ENTERING_PERMANENT); + } if (permanent != null) { if (withoutTrigger) { permanent.setTapped(true); diff --git a/Mage/src/mage/abilities/effects/common/continuous/GainAbilitySourceEffect.java b/Mage/src/mage/abilities/effects/common/continuous/GainAbilitySourceEffect.java index 81fc17c970..6d37cfc4ba 100644 --- a/Mage/src/mage/abilities/effects/common/continuous/GainAbilitySourceEffect.java +++ b/Mage/src/mage/abilities/effects/common/continuous/GainAbilitySourceEffect.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,7 +20,7 @@ * 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. @@ -30,6 +30,7 @@ package mage.abilities.effects.common.continuous; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.EntersBattlefieldEffect; import mage.cards.Card; import mage.constants.Duration; import mage.constants.Layer; @@ -88,12 +89,17 @@ public class GainAbilitySourceEffect extends ContinuousEffectImpl implements Sou public GainAbilitySourceEffect copy() { return new GainAbilitySourceEffect(this); } - + @Override public void init(Ability source, Game game) { super.init(source, game); if (affectedObjectsSet) { - affectedObjectList.add(new MageObjectReference(source.getSourceId(), game)); + Permanent permanent = (Permanent) getValue(EntersBattlefieldEffect.ENTERING_PERMANENT); + if (permanent != null) { + affectedObjectList.add(new MageObjectReference(source.getSourceId(), game.getState().getZoneChangeCounter(source.getSourceId()) + 1, game)); + } else { + affectedObjectList.add(new MageObjectReference(source.getSourceId(), game)); + } } } diff --git a/Mage/src/mage/abilities/keyword/BloodthirstAbility.java b/Mage/src/mage/abilities/keyword/BloodthirstAbility.java index f93ca9824d..a7ae3282a1 100644 --- a/Mage/src/mage/abilities/keyword/BloodthirstAbility.java +++ b/Mage/src/mage/abilities/keyword/BloodthirstAbility.java @@ -2,6 +2,7 @@ package mage.abilities.keyword; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.OneShotEffect; import mage.constants.Outcome; import mage.counters.CounterType; @@ -12,10 +13,11 @@ import mage.util.CardUtil; import mage.watchers.common.BloodthirstWatcher; /** - * + * * @author Loki */ public class BloodthirstAbility extends EntersBattlefieldAbility { + private int amount; public BloodthirstAbility(int amount) { @@ -48,12 +50,13 @@ public class BloodthirstAbility extends EntersBattlefieldAbility { } class BloodthirstEffect extends OneShotEffect { + private final int amount; BloodthirstEffect(int amount) { super(Outcome.BoostCreature); this.amount = amount; - staticText = new StringBuilder("this permanent comes into play with ").append(this.amount).append(" +1/+1 counters on it").toString(); + staticText = new StringBuilder("this permanent comes into play with ").append(this.amount).append(" +1/+1 counters on it").toString(); } BloodthirstEffect(final BloodthirstEffect effect) { @@ -67,9 +70,9 @@ class BloodthirstEffect extends OneShotEffect { if (player != null) { BloodthirstWatcher watcher = (BloodthirstWatcher) game.getState().getWatchers().get("DamagedOpponents", source.getControllerId()); if (watcher != null && watcher.conditionMet()) { - Permanent p = game.getPermanent(source.getSourceId()); - if (p != null) { - p.addCounters(CounterType.P1P1.createInstance(amount), game); + Permanent permanent = (Permanent) getValue(EntersBattlefieldEffect.ENTERING_PERMANENT); + if (permanent != null) { + permanent.addCounters(CounterType.P1P1.createInstance(amount), game); } } @@ -83,4 +86,3 @@ class BloodthirstEffect extends OneShotEffect { return new BloodthirstEffect(this); } } - diff --git a/Mage/src/mage/abilities/keyword/FadingAbility.java b/Mage/src/mage/abilities/keyword/FadingAbility.java index 4a66d7dcda..a433ac3cd5 100644 --- a/Mage/src/mage/abilities/keyword/FadingAbility.java +++ b/Mage/src/mage/abilities/keyword/FadingAbility.java @@ -3,6 +3,7 @@ package mage.abilities.keyword; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.Card; @@ -18,25 +19,17 @@ import mage.game.permanent.Permanent; * 702.31a Fading is a keyword that represents two abilities. “Fading N” means “This permanent enters the battlefield with N fade counters on it” and “At the beginning of your upkeep, remove a fade counter from this permanent. If you can’t, sacrifice the permanent.” * */ - public class FadingAbility extends EntersBattlefieldAbility { - - + private String ruleText; - + public FadingAbility(int fadeCounter, Card card) { super(new AddCountersSourceEffect(CounterType.FADE.createInstance(fadeCounter)), "with"); Ability ability = new BeginningOfUpkeepTriggeredAbility(new FadingEffect(), TargetController.YOU, false); ability.setRuleVisible(false); addSubAbility(ability); - StringBuilder sb = new StringBuilder("Fading "); - sb.append(fadeCounter); - sb.append(" (This permanent enters the battlefield with ") - .append(fadeCounter) - .append(" fade counters on it. ") - .append(" At the beginning of your upkeep, remove a fade counter from this permanent. If you can’t, sacrifice the permanent.") - .append(")"); - ruleText = sb.toString(); + ruleText = "Fading " + fadeCounter + " (This permanent enters the battlefield with " + fadeCounter + " fade counters on it." + + " At the beginning of your upkeep, remove a fade counter from this permanent. If you can’t, sacrifice the permanent."; } public FadingAbility(final FadingAbility ability) { @@ -54,7 +47,9 @@ public class FadingAbility extends EntersBattlefieldAbility { return ruleText; } } + class FadingEffect extends OneShotEffect { + FadingEffect() { super(Outcome.Sacrifice); staticText = "remove a fade counter from this permanent. If you can’t, sacrifice the permanent"; @@ -64,18 +59,15 @@ class FadingEffect extends OneShotEffect { super(effect); } - @Override public boolean apply(Game game, Ability source) { - Permanent p = game.getPermanent(source.getSourceId()); - if (p != null) { - int amount = p.getCounters().getCount(CounterType.FADE); + Permanent permanent = (Permanent) getValue(EntersBattlefieldEffect.ENTERING_PERMANENT); + if (permanent != null) { + int amount = permanent.getCounters().getCount(CounterType.FADE); if (amount > 0) { - p.removeCounters(CounterType.FADE.createInstance(), game); - } - else - { - p.sacrifice(source.getSourceId(), game); + permanent.removeCounters(CounterType.FADE.createInstance(), game); + } else { + permanent.sacrifice(source.getSourceId(), game); } return true; } @@ -86,4 +78,4 @@ class FadingEffect extends OneShotEffect { public FadingEffect copy() { return new FadingEffect(this); } -} \ No newline at end of file +} diff --git a/Mage/src/mage/abilities/keyword/SunburstAbility.java b/Mage/src/mage/abilities/keyword/SunburstAbility.java index 12b9d7834a..bc4a931904 100644 --- a/Mage/src/mage/abilities/keyword/SunburstAbility.java +++ b/Mage/src/mage/abilities/keyword/SunburstAbility.java @@ -25,13 +25,13 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.abilities.keyword; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.SunburstCount; +import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.OneShotEffect; import mage.cards.Card; import mage.constants.CardType; @@ -46,25 +46,22 @@ import mage.players.Player; * * @author Plopman */ +public class SunburstAbility extends EntersBattlefieldAbility { - -public class SunburstAbility extends EntersBattlefieldAbility{ - - private final static String ruleCreature ="Sunburst (This enters the battlefield with a +1/+1 counter on it for each color of mana spent to cast it.)"; - private final static String ruleNonCreature ="Sunburst (This enters the battlefield with a charge counter on it for each color of mana spent to cast it.)"; + private final static String ruleCreature = "Sunburst (This enters the battlefield with a +1/+1 counter on it for each color of mana spent to cast it.)"; + private final static String ruleNonCreature = "Sunburst (This enters the battlefield with a charge counter on it for each color of mana spent to cast it.)"; private boolean isCreature; - public SunburstAbility(Card card){ - super(new SunburstEffect(),""); + public SunburstAbility(Card card) { + super(new SunburstEffect(), ""); isCreature = card.getCardType().contains(CardType.CREATURE); } - - public SunburstAbility(final SunburstAbility ability){ + + public SunburstAbility(final SunburstAbility ability) { super(ability); this.isCreature = ability.isCreature; } - - + @Override public EntersBattlefieldAbility copy() { return new SunburstAbility(this); @@ -74,15 +71,13 @@ public class SunburstAbility extends EntersBattlefieldAbility{ public String getRule() { return isCreature ? ruleCreature : ruleNonCreature; } - - + } class SunburstEffect extends OneShotEffect { private static final DynamicValue amount = new SunburstCount(); - public SunburstEffect() { super(Outcome.Benefit); staticText = "Sunburst"; @@ -94,22 +89,21 @@ class SunburstEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); + Permanent permanent = (Permanent) getValue(EntersBattlefieldEffect.ENTERING_PERMANENT); if (permanent != null) { Counter counter; - if(permanent.getCardType().contains(CardType.CREATURE)){ - counter = CounterType.P1P1.createInstance(amount.calculate(game, source, this)); - } - else{ - counter = CounterType.CHARGE.createInstance(amount.calculate(game, source, this)); + if (permanent.getCardType().contains(CardType.CREATURE)) { + counter = CounterType.P1P1.createInstance(amount.calculate(game, source, this)); + } else { + counter = CounterType.CHARGE.createInstance(amount.calculate(game, source, this)); } if (counter != null) { - + permanent.addCounters(counter, game); if (!game.isSimulation()) { Player player = game.getPlayer(source.getControllerId()); if (player != null) { - game.informPlayers(player.getLogName()+ " puts " + counter.getCount() + " " + counter.getName() + " counter on " + permanent.getName()); + game.informPlayers(player.getLogName() + " puts " + counter.getCount() + " " + counter.getName() + " counter on " + permanent.getName()); } } } diff --git a/Mage/src/mage/abilities/keyword/TributeAbility.java b/Mage/src/mage/abilities/keyword/TributeAbility.java index ad5ad5b6b7..f752865498 100644 --- a/Mage/src/mage/abilities/keyword/TributeAbility.java +++ b/Mage/src/mage/abilities/keyword/TributeAbility.java @@ -25,12 +25,12 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.abilities.keyword; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.constants.Outcome; @@ -46,23 +46,20 @@ import mage.util.CardUtil; * * @author LevelX2 */ - - -public class TributeAbility extends EntersBattlefieldAbility{ +public class TributeAbility extends EntersBattlefieldAbility { private int tributeValue; - public TributeAbility(int tributeValue){ + public TributeAbility(int tributeValue) { super(new TributeEffect(tributeValue), false); this.tributeValue = tributeValue; } - public TributeAbility(final TributeAbility ability){ + public TributeAbility(final TributeAbility ability) { super(ability); this.tributeValue = ability.tributeValue; } - @Override public EntersBattlefieldAbility copy() { return new TributeAbility(this); @@ -81,7 +78,7 @@ public class TributeAbility extends EntersBattlefieldAbility{ class TributeEffect extends OneShotEffect { - private int tributeValue; + private final int tributeValue; public TributeEffect(int tributeValue) { super(Outcome.Detriment); @@ -101,7 +98,7 @@ class TributeEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - Permanent sourcePermanent = game.getPermanent(source.getSourceId()); + Permanent sourcePermanent = (Permanent) getValue(EntersBattlefieldEffect.ENTERING_PERMANENT); if (controller != null && sourcePermanent != null) { UUID opponentId; if (game.getOpponents(controller.getId()).size() == 1) { @@ -117,16 +114,18 @@ class TributeEffect extends OneShotEffect { StringBuilder sb = new StringBuilder("Pay tribute to "); sb.append(sourcePermanent.getName()); sb.append(" (add ").append(CardUtil.numberToText(tributeValue)).append(" +1/+1 counter"); - sb.append(tributeValue > 1 ? "s":"").append(" to it)?"); + sb.append(tributeValue > 1 ? "s" : "").append(" to it)?"); if (opponent.chooseUse(outcome, sb.toString(), source, game)) { - if (!game.isSimulation()) + if (!game.isSimulation()) { game.informPlayers(opponent.getLogName() + " pays tribute to " + sourcePermanent.getLogName()); + } game.getState().setValue("tributeValue" + source.getSourceId(), "yes"); return new AddCountersSourceEffect(CounterType.P1P1.createInstance(tributeValue), true).apply(game, source); } else { - if (!game.isSimulation()) + if (!game.isSimulation()) { game.informPlayers(opponent.getLogName() + " does not pay tribute to " + sourcePermanent.getLogName()); - game.getState().setValue("tributeValue"+ source.getSourceId(), "no"); + } + game.getState().setValue("tributeValue" + source.getSourceId(), "no"); } return true; } From c94be5f4d31e101696bd1f83533fdcb8edd344f0 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 16 Oct 2015 00:39:16 +0200 Subject: [PATCH 45/46] * Updated enters battlefield replacement effects for new handling. --- Mage/src/mage/abilities/keyword/FadingAbility.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Mage/src/mage/abilities/keyword/FadingAbility.java b/Mage/src/mage/abilities/keyword/FadingAbility.java index a433ac3cd5..e8e4529581 100644 --- a/Mage/src/mage/abilities/keyword/FadingAbility.java +++ b/Mage/src/mage/abilities/keyword/FadingAbility.java @@ -3,7 +3,6 @@ package mage.abilities.keyword; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldAbility; -import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.Card; @@ -61,7 +60,7 @@ class FadingEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent permanent = (Permanent) getValue(EntersBattlefieldEffect.ENTERING_PERMANENT); + Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { int amount = permanent.getCounters().getCount(CounterType.FADE); if (amount > 0) { From 57dfa70837bd0a697263a913422491910adc8ff0 Mon Sep 17 00:00:00 2001 From: AlumiuN Date: Thu, 15 Oct 2015 18:19:23 +1300 Subject: [PATCH 46/46] Updated Teferi's Response to use FilterControlledLandPermanent. --- .../sets/darksteel/SurestrikeTrident.java | 30 +++-- .../mage/sets/invasion/TeferisResponse.java | 107 ++---------------- 2 files changed, 29 insertions(+), 108 deletions(-) diff --git a/Mage.Sets/src/mage/sets/darksteel/SurestrikeTrident.java b/Mage.Sets/src/mage/sets/darksteel/SurestrikeTrident.java index 761ed72d84..4640efecad 100644 --- a/Mage.Sets/src/mage/sets/darksteel/SurestrikeTrident.java +++ b/Mage.Sets/src/mage/sets/darksteel/SurestrikeTrident.java @@ -64,15 +64,17 @@ public class SurestrikeTrident extends CardImpl { this.subtype.add("Equipment"); // Equipped creature has first strike and "{tap}, Unattach Surestrike Trident: This creature deals damage equal to its power to target player." - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(FirstStrikeAbility.getInstance(), AttachmentType.EQUIPMENT))); - + Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(FirstStrikeAbility.getInstance(), AttachmentType.EQUIPMENT)); DynamicValue xValue = new SourcePermanentPowerCount(); Effect effect = new DamageTargetEffect(xValue); effect.setText("This creature deals damage equal to its power to target player"); - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new TapSourceCost()); - ability.addTarget(new TargetPlayer()); - ability.addCost(new SurestrikeTridentUnattachCost()); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(ability, AttachmentType.EQUIPMENT, Duration.WhileOnBattlefield))); + Ability gainedAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new TapSourceCost()); + gainedAbility.addTarget(new TargetPlayer()); + gainedAbility.addCost(new SurestrikeTridentUnattachCost(getName(), getId())); + effect = new GainAbilityAttachedEffect(gainedAbility, AttachmentType.EQUIPMENT); + effect.setText("and \"{T}, Unattach {this}: This creature deals damage equal to its power to target player.\""); + ability.addEffect(effect); + this.addAbility(ability); // Equip {4} this.addAbility(new EquipAbility(Outcome.Benefit, new GenericManaCost(4))); @@ -90,21 +92,25 @@ public class SurestrikeTrident extends CardImpl { class SurestrikeTridentUnattachCost extends CostImpl { - public SurestrikeTridentUnattachCost() { - this.text = "Unattach Surestrike Trident"; + protected UUID sourceEquipmentId; + + public SurestrikeTridentUnattachCost(String name, UUID sourceId) { + this.text = "Unattach " + name; + this.sourceEquipmentId = sourceId; } public SurestrikeTridentUnattachCost(final SurestrikeTridentUnattachCost cost) { super(cost); + this.sourceEquipmentId = cost.sourceEquipmentId; } @Override public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { Permanent permanent = game.getPermanent(sourceId); if (permanent != null) { - for (UUID attachmentId :permanent.getAttachments()) { + for (UUID attachmentId : permanent.getAttachments()) { Permanent attachment = game.getPermanent(attachmentId); - if (attachment != null && attachment.getName().equals("Surestrike Trident")) { + if (attachment != null && attachment.getId().equals(sourceEquipmentId)) { paid = permanent.removeAttachment(attachmentId, game); if (paid) { break; @@ -120,9 +126,9 @@ class SurestrikeTridentUnattachCost extends CostImpl { public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { Permanent permanent = game.getPermanent(sourceId); if (permanent != null) { - for (UUID attachmentId :permanent.getAttachments()) { + for (UUID attachmentId : permanent.getAttachments()) { Permanent attachment = game.getPermanent(attachmentId); - if (attachment != null && attachment.getName().equals("Surestrike Trident") ) { + if (attachment != null && attachment.getId().equals(sourceEquipmentId)) { return true; } } diff --git a/Mage.Sets/src/mage/sets/invasion/TeferisResponse.java b/Mage.Sets/src/mage/sets/invasion/TeferisResponse.java index f61b1d22bd..57e5f15db4 100644 --- a/Mage.Sets/src/mage/sets/invasion/TeferisResponse.java +++ b/Mage.Sets/src/mage/sets/invasion/TeferisResponse.java @@ -27,8 +27,6 @@ */ package mage.sets.invasion; -import java.util.HashSet; -import java.util.Set; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; @@ -37,16 +35,13 @@ import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Rarity; -import mage.constants.Zone; -import mage.filter.Filter; +import mage.filter.FilterStackObject; +import mage.filter.common.FilterControlledLandPermanent; +import mage.filter.predicate.other.TargetsPermanentPredicate; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.game.stack.Spell; -import mage.game.stack.StackAbility; import mage.game.stack.StackObject; -import mage.target.Target; -import mage.target.TargetObject; -import mage.target.Targets; +import mage.target.TargetStackObject; /** * @@ -54,13 +49,19 @@ import mage.target.Targets; */ public class TeferisResponse extends CardImpl { + private final static FilterStackObject filter = new FilterStackObject("spell or ability an opponent controls that targets a land you control"); + + static { + filter.add(new TargetsPermanentPredicate(new FilterControlledLandPermanent())); + } + public TeferisResponse(UUID ownerId) { super(ownerId, 78, "Teferi's Response", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{1}{U}"); this.expansionSetCode = "INV"; // Counter target spell or ability an opponent controls that targets a land you control. If a permanent's ability is countered this way, destroy that permanent. this.getSpellAbility().addEffect(new TeferisResponseEffect()); - this.getSpellAbility().addTarget(new TargetStackObjectTargetingControlledLand()); + this.getSpellAbility().addTarget(new TargetStackObject(filter)); // Draw two cards. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(2)); @@ -76,92 +77,6 @@ public class TeferisResponse extends CardImpl { } } -class TargetStackObjectTargetingControlledLand extends TargetObject { - - public TargetStackObjectTargetingControlledLand() { - this.minNumberOfTargets = 1; - this.maxNumberOfTargets = 1; - this.zone = Zone.STACK; - this.targetName = "spell or ability an opponent controls that targets a land you control"; - } - - public TargetStackObjectTargetingControlledLand(final TargetStackObjectTargetingControlledLand target) { - super(target); - } - - @Override - public Filter getFilter() { - throw new UnsupportedOperationException("Not supported."); //To change body of generated methods, choose Tools | Templates. - } - - @Override - public boolean canTarget(UUID id, Ability source, Game game) { - StackObject stackObject = game.getStack().getStackObject(id); - if ((stackObject instanceof Spell) || (stackObject instanceof StackAbility)) { - return true; - } - return false; - } - - @Override - public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { - return canChoose(sourceControllerId, game); - } - - @Override - public boolean canChoose(UUID sourceControllerId, Game game) { - for (StackObject stackObject : game.getStack()) { - if (((stackObject instanceof Spell) || (stackObject instanceof StackAbility)) && stackObject.getControllerId() != sourceControllerId) { - Targets objectTargets = stackObject.getStackAbility().getTargets(); - if(!objectTargets.isEmpty()) { - for (Target target : objectTargets) { - for (UUID targetId : target.getTargets()) { - Permanent targetedPermanent = game.getPermanentOrLKIBattlefield(targetId); - if (targetedPermanent != null && targetedPermanent.getCardType().contains(CardType.LAND) && targetedPermanent.getControllerId().equals(sourceControllerId)) { - return true; - } - } - } - } - } - } - return false; - } - - @Override - public Set possibleTargets(UUID sourceId, UUID sourceControllerId, - Game game) { - return possibleTargets(sourceControllerId, game); - } - - @Override - public Set possibleTargets(UUID sourceControllerId, Game game) { - Set possibleTargets = new HashSet<>(); - for (StackObject stackObject : game.getStack()) { - if (((stackObject instanceof Spell) || (stackObject instanceof StackAbility)) && stackObject.getControllerId() != sourceControllerId) { - Targets objectTargets = stackObject.getStackAbility().getTargets(); - if(!objectTargets.isEmpty()) { - for (Target target : objectTargets) { - for (UUID targetId : target.getTargets()) { - Permanent targetedPermanent = game.getPermanentOrLKIBattlefield(targetId); - if (targetedPermanent != null && targetedPermanent.getCardType().contains(CardType.LAND) && targetedPermanent.getControllerId().equals(sourceControllerId)) { - possibleTargets.add(stackObject.getId()); - } - } - } - } - } - } - return possibleTargets; - } - - @Override - public TargetStackObjectTargetingControlledLand copy() { - return new TargetStackObjectTargetingControlledLand(this); - } - -} - class TeferisResponseEffect extends OneShotEffect { public TeferisResponseEffect() {