diff --git a/Mage.Sets/src/mage/cards/c/ConquerorsFlail.java b/Mage.Sets/src/mage/cards/c/ConquerorsFlail.java new file mode 100644 index 00000000000..349ff190712 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/ConquerorsFlail.java @@ -0,0 +1,183 @@ +/* + * 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.cards.c; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.BoostEquippedEffect; +import mage.abilities.keyword.EquipAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author spjspj + */ +public class ConquerorsFlail extends CardImpl { + + public ConquerorsFlail(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); + + this.subtype.add("Equipment"); + + // Equipped creature gets +1/+1 for each color among permanents you control. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(new ConquerorsFlailColorCount(), new ConquerorsFlailColorCount(), Duration.WhileOnBattlefield))); + + // As long as Conqueror's Flail is attached to a creature, your opponents can't cast spells during your turn. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConquerorsFlailEffect())); + + // Equip {2} + this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(2))); + } + + public ConquerorsFlail(final ConquerorsFlail card) { + super(card); + } + + @Override + public ConquerorsFlail copy() { + return new ConquerorsFlail(this); + } +} + +class ConquerorsFlailColorCount implements DynamicValue { + + public ConquerorsFlailColorCount() { + } + + public ConquerorsFlailColorCount(final ConquerorsFlailColorCount dynamicValue) { + } + + @Override + public int calculate(Game game, Ability source, Effect effect) { + Player controller = game.getPlayer(source.getControllerId()); + int count = 0; + if (controller != null) { + Mana mana = new Mana(); + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(controller.getId())) { + if (mana.getBlack() == 0 && permanent.getColor(game).isBlack()) { + mana.increaseBlack(); + count++; + } + if (mana.getBlue() == 0 && permanent.getColor(game).isBlue()) { + mana.increaseBlue(); + count++; + } + if (mana.getRed() == 0 && permanent.getColor(game).isRed()) { + mana.increaseRed(); + count++; + } + if (mana.getGreen() == 0 && permanent.getColor(game).isGreen()) { + mana.increaseGreen(); + count++; + } + if (mana.getWhite() == 0 && permanent.getColor(game).isWhite()) { + mana.increaseWhite(); + count++; + } + } + return count; + } + return 0; + } + + @Override + public String toString() { + return "1"; + } + + @Override + public String getMessage() { + return "for each color among permanents you control"; + } + + @Override + public DynamicValue copy() { + return new ConquerorsFlailColorCount(); + } +} + +class ConquerorsFlailEffect extends ContinuousRuleModifyingEffectImpl { + + public ConquerorsFlailEffect() { + super(Duration.WhileOnBattlefield, Outcome.Benefit); + staticText = "As long as {this} is attached to a creature, your opponents can't cast spells during your turn"; + } + + public ConquerorsFlailEffect(final ConquerorsFlailEffect effect) { + super(effect); + } + + @Override + public ConquerorsFlailEffect copy() { + return new ConquerorsFlailEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.CAST_SPELL; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + Permanent permanent = game.getPermanent(source.getSourceId()); + boolean isAttached = false; + if (permanent != null) { + UUID attachedTo = permanent.getAttachedTo(); + Permanent attachment = game.getPermanent(attachedTo); + if (attachment != null) { + isAttached = true; + } + } + + if (isAttached && game.getActivePlayerId().equals(source.getControllerId()) + && game.getPlayer(source.getControllerId()).hasOpponent(event.getPlayerId(), game)) { + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/c/CurseOfVengeance.java b/Mage.Sets/src/mage/cards/c/CurseOfVengeance.java new file mode 100644 index 00000000000..308b78659b4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CurseOfVengeance.java @@ -0,0 +1,194 @@ +/* + * 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.cards.c; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.game.Game; +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.TargetPlayer; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author spjspj + */ +public class CurseOfVengeance extends CardImpl { + + public CurseOfVengeance(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{B}"); + + this.subtype.add("Aura"); + this.subtype.add("Curse"); + + // Enchant player + TargetPlayer auraTarget = new TargetPlayer(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment)); + this.addAbility(new EnchantAbility(auraTarget.getTargetName())); + + // Whenever enchanted player casts a spell, put a spite counter on Curse of Vengeance. + this.addAbility(new CurseOfVengeanceTriggeredAbility()); + + // When enchanted player loses the game, you gain X life and draw X cards, where X is the number of spite counters on Curse of Vengeance. + this.addAbility(new CurseOfVengeancePlayerLosesTriggeredAbility()); + } + + public CurseOfVengeance(final CurseOfVengeance card) { + super(card); + } + + @Override + public CurseOfVengeance copy() { + return new CurseOfVengeance(this); + } +} + +class CurseOfVengeanceTriggeredAbility extends TriggeredAbilityImpl { + + public CurseOfVengeanceTriggeredAbility() { + super(Zone.BATTLEFIELD, new AddCountersTargetEffect(CounterType.SPITE.createInstance(), Outcome.Detriment), false); + } + + public CurseOfVengeanceTriggeredAbility(Effect effect, boolean optional, String text) { + super(Zone.BATTLEFIELD, effect, optional); + } + + public CurseOfVengeanceTriggeredAbility(final CurseOfVengeanceTriggeredAbility ability) { + super(ability); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == EventType.SPELL_CAST; + + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Permanent enchantment = game.getPermanent(getSourceId()); + Spell spell = game.getStack().getSpell(event.getSourceId()); + + if (enchantment != null && spell != null + && enchantment.getAttachedTo() != null + && enchantment.getAttachedTo().equals(spell.getControllerId())) { + this.getEffects().get(0).setTargetPointer(new FixedTarget(getSourceId())); + return true; + } + return false; + } + + @Override + public String getRule() { + return "Whenever enchanted player casts a spell, put a spite counter on {this}"; + } + + @Override + public CurseOfVengeanceTriggeredAbility copy() { + return new CurseOfVengeanceTriggeredAbility(this); + } +} + +class CurseOfVengeancePlayerLosesTriggeredAbility extends TriggeredAbilityImpl { + + public CurseOfVengeancePlayerLosesTriggeredAbility() { + super(Zone.BATTLEFIELD, new CurseOfVengeanceDrawLifeEffect(), false); + } + + public CurseOfVengeancePlayerLosesTriggeredAbility(final CurseOfVengeancePlayerLosesTriggeredAbility ability) { + super(ability); + } + + @Override + public CurseOfVengeancePlayerLosesTriggeredAbility copy() { + return new CurseOfVengeancePlayerLosesTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + System.out.println("Saw event of type: " + event.getType()); + return event.getType() == EventType.LOST; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return true; + } + + @Override + public String getRule() { + return "When enchanted player loses the game, you gain X life and draw X cards, where X is the number of spite counters on Curse of Vengeance"; + } +} + +class CurseOfVengeanceDrawLifeEffect extends OneShotEffect { + + public CurseOfVengeanceDrawLifeEffect() { + super(Outcome.Benefit); + staticText = "you gain X life and draw X cards, where X is the number of spite counters on {this}"; + } + + public CurseOfVengeanceDrawLifeEffect(final CurseOfVengeanceDrawLifeEffect effect) { + super(effect); + } + + @Override + public CurseOfVengeanceDrawLifeEffect copy() { + return new CurseOfVengeanceDrawLifeEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent sourceObject = (Permanent) source.getSourceObjectIfItStillExists(game); + + if (sourceObject != null) { + if (sourceObject.getCounters(game).containsKey(CounterType.SPITE)) { + controller.drawCards(sourceObject.getCounters(game).getCount(CounterType.SPITE), game); + controller.gainLife(sourceObject.getCounters(game).getCount(CounterType.SPITE), game); + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/Commander2016.java b/Mage.Sets/src/mage/sets/Commander2016.java index 046f92ccbde..a41c555cc7c 100644 --- a/Mage.Sets/src/mage/sets/Commander2016.java +++ b/Mage.Sets/src/mage/sets/Commander2016.java @@ -48,7 +48,6 @@ public class Commander2016 extends ExpansionSet { private Commander2016() { super("Commander 2016 Edition", "C16", ExpansionSet.buildDate(2016, 11, 11), SetType.SUPPLEMENTAL); this.blockName = "Command Zone"; - cards.add(new SetCardInfo("AStral Cornucopia", 243, Rarity.RARE, mage.cards.a.AstralCornucopia.class)); cards.add(new SetCardInfo("Abzan Charm", 177, Rarity.UNCOMMON, mage.cards.a.AbzanCharm.class)); cards.add(new SetCardInfo("Abzan Falconer", 57, Rarity.UNCOMMON, mage.cards.a.AbzanFalconer.class)); cards.add(new SetCardInfo("Academy Elite", 81, Rarity.RARE, mage.cards.a.AcademyElite.class)); @@ -63,6 +62,7 @@ public class Commander2016 extends ExpansionSet { cards.add(new SetCardInfo("Artifact Mutation", 179, Rarity.RARE, mage.cards.a.ArtifactMutation.class)); cards.add(new SetCardInfo("Ash Barrens", 56, Rarity.COMMON, mage.cards.a.AshBarrens.class)); cards.add(new SetCardInfo("Assault Suit", 242, Rarity.UNCOMMON, mage.cards.a.AssaultSuit.class)); + cards.add(new SetCardInfo("Astral Cornucopia", 243, Rarity.RARE, mage.cards.a.AstralCornucopia.class)); cards.add(new SetCardInfo("Atraxa, Praetors' Voice", 28, Rarity.MYTHIC, mage.cards.a.AtraxaPraetorsVoice.class)); cards.add(new SetCardInfo("Aura Mutation", 180, Rarity.RARE, mage.cards.a.AuraMutation.class)); cards.add(new SetCardInfo("Azorius Chancery", 282, Rarity.UNCOMMON, mage.cards.a.AzoriusChancery.class)); @@ -105,6 +105,7 @@ public class Commander2016 extends ExpansionSet { cards.add(new SetCardInfo("Collective Voyage", 145, Rarity.RARE, mage.cards.c.CollectiveVoyage.class)); cards.add(new SetCardInfo("Command Tower", 286, Rarity.COMMON, mage.cards.c.CommandTower.class)); cards.add(new SetCardInfo("Commander's Sphere", 248, Rarity.COMMON, mage.cards.c.CommandersSphere.class)); + cards.add(new SetCardInfo("Conqueror's Flail", 53, Rarity.RARE, mage.cards.c.ConquerorsFlail.class)); cards.add(new SetCardInfo("Consuming Aberration", 189, Rarity.RARE, mage.cards.c.ConsumingAberration.class)); cards.add(new SetCardInfo("Corpsejack Menace", 190, Rarity.RARE, mage.cards.c.CorpsejackMenace.class)); cards.add(new SetCardInfo("Crackling Doom", 191, Rarity.RARE, mage.cards.c.CracklingDoom.class)); @@ -113,6 +114,7 @@ public class Commander2016 extends ExpansionSet { cards.add(new SetCardInfo("Crystalline Crawler", 54, Rarity.RARE, mage.cards.c.CrystallineCrawler.class)); cards.add(new SetCardInfo("Cultivate", 146, Rarity.COMMON, mage.cards.c.Cultivate.class)); cards.add(new SetCardInfo("Curtains' Call", 13, Rarity.RARE, mage.cards.c.CurtainsCall.class)); + cards.add(new SetCardInfo("Curse of Vengeance", 12, Rarity.RARE, mage.cards.c.CurseOfVengeance.class)); cards.add(new SetCardInfo("Custodi Soulbinders", 63, Rarity.RARE, mage.cards.c.CustodiSoulbinders.class)); cards.add(new SetCardInfo("Daretti, Scrap Savant", 123, Rarity.MYTHIC, mage.cards.d.DarettiScrapSavant.class)); cards.add(new SetCardInfo("Darksteel Citadel", 288, Rarity.UNCOMMON, mage.cards.d.DarksteelCitadel.class)); @@ -236,7 +238,9 @@ public class Commander2016 extends ExpansionSet { cards.add(new SetCardInfo("Oath of Druids", 159, Rarity.RARE, mage.cards.o.OathOfDruids.class)); cards.add(new SetCardInfo("Oblation", 71, Rarity.RARE, mage.cards.o.Oblation.class)); cards.add(new SetCardInfo("Opal Palace", 312, Rarity.COMMON, mage.cards.o.OpalPalace.class)); + cards.add(new SetCardInfo("Open the Vaults", 72, Rarity.RARE, mage.cards.o.OpenTheVaults.class)); cards.add(new SetCardInfo("Opulent Palace", 313, Rarity.UNCOMMON, mage.cards.o.OpulentPalace.class)); + cards.add(new SetCardInfo("Order // Chaos", 240, Rarity.UNCOMMON, mage.cards.o.OrderChaos.class)); cards.add(new SetCardInfo("Orzhov Basilica", 314, Rarity.UNCOMMON, mage.cards.o.OrzhovBasilica.class)); cards.add(new SetCardInfo("Orzhov Signet", 266, Rarity.COMMON, mage.cards.o.OrzhovSignet.class)); cards.add(new SetCardInfo("Past in Flames", 131, Rarity.MYTHIC, mage.cards.p.PastInFlames.class)); @@ -326,6 +330,7 @@ public class Commander2016 extends ExpansionSet { cards.add(new SetCardInfo("Trading Post", 278, Rarity.RARE, mage.cards.t.TradingPost.class)); cards.add(new SetCardInfo("Trash for Treasure", 136, Rarity.RARE, mage.cards.t.TrashForTreasure.class)); cards.add(new SetCardInfo("Treasure Cruise", 101, Rarity.COMMON, mage.cards.t.TreasureCruise.class)); + cards.add(new SetCardInfo("Trial // Error", 239, Rarity.UNCOMMON, mage.cards.t.TrialError.class)); cards.add(new SetCardInfo("Trinket Mage", 102, Rarity.COMMON, mage.cards.t.TrinketMage.class)); cards.add(new SetCardInfo("Tuskguard Captain", 173, Rarity.UNCOMMON, mage.cards.t.TuskguardCaptain.class)); cards.add(new SetCardInfo("Underground River", 335, Rarity.RARE, mage.cards.u.UndergroundRiver.class)); diff --git a/Mage/src/main/java/mage/counters/CounterType.java b/Mage/src/main/java/mage/counters/CounterType.java index 876a5200db3..55584f295f2 100644 --- a/Mage/src/main/java/mage/counters/CounterType.java +++ b/Mage/src/main/java/mage/counters/CounterType.java @@ -101,6 +101,7 @@ public enum CounterType { SHIELD("shield"), SHRED("shred"), SLIME("slime"), + SPITE("spite"), SPORE("spore"), STORAGE("storage"), STRIFE("strife"), diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 40656ee1c96..2c89b60cd27 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -30039,7 +30039,7 @@ Hushwing Gryff|Commander 2016|68|R|{2}{W}|Creature - Hippogriff|2|1|Flash$Flying Mentor of the Meek|Commander 2016|69|R|{2}{W}|Creature - Human Soldier|2|2|Whenever another creature with power 2 or less enters the battlefield under your control, you may pay {1}. If you do, draw a card.| Mirror Entity|Commander 2016|70|R|{2}{W}|Creature - Shapeshifter|1|1|Changeing (This card is every creature type.)${X}: Until end of turn, creatures you control have base power and toughness X/X and gain all creatures types.| Oblation|Commander 2016|71|R|{2}{W}|Instant|||The owner of target nonland permanent shuffles it into his or her library, the draws two cards.| -Open the Vault|Commander 2016|72|R|{4}{W}{W}|Sorcery|||Return all artifact and enchantment cards from all graveyard to the battlefield under their owners' control. (Auras with to enchant remain in graveyard.)| +Open the Vaults|Commander 2016|72|R|{4}{W}{W}|Sorcery|||Return all artifact and enchantment cards from all graveyard to the battlefield under their owners' control. (Auras with to enchant remain in graveyard.)| Phyrexian Rebirth|Commander 2016|73|R|{4}{W}{W}|Sorcery|||Destroy all creatures, then create an X/X colorless Horror artifact creature token, where X is the number of creatures destroyed this way.| Reveillark|Commander 2016|74|R|{4}{W}|Creature - Elemental|4|3|Flying$When Reveillark leaves the battlefield, return up to two target creature cards with power 2 or less from your graveyard to the battlefield.$Evoke {5}{W} (You may cast this spell for its evoke cost. If you do, it's sacrificed when it enters the battlefield.)| Reverse the Sands|Commander 2016|75|R|{6}{W}{W}|Sorcery|||Redistribute any number of players' life totals. (Each of those players gets one life total back.)|