From 12f8dc31b85a05112c43f2335a1a8717a29f5ee9 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 6 Jul 2015 00:36:10 +0200 Subject: [PATCH] [ORI] Added last 4 white cards. --- .../sets/commander2014/ContainmentPriest.java | 76 +--------- .../sets/magicorigins/ArchangelOfTithes.java | 131 +++++++++++++++++ .../sets/magicorigins/ConsulsLieutenant.java | 78 ++++++++++ .../sets/magicorigins/HallowedMoonlight.java | 136 ++++++++++++++++++ .../sets/magicorigins/KytheonsTactics.java | 67 +++++++++ .../CantAttackYouUnlessPayManaAllEffect.java | 28 +++- .../CantBlockUnlessPayManaAllEffect.java | 88 ++++++++++++ .../common/CreatureWasCastWatcher.java | 93 ++++++++++++ 8 files changed, 625 insertions(+), 72 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/magicorigins/ArchangelOfTithes.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/ConsulsLieutenant.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/HallowedMoonlight.java create mode 100644 Mage.Sets/src/mage/sets/magicorigins/KytheonsTactics.java create mode 100644 Mage/src/mage/abilities/effects/common/combat/CantBlockUnlessPayManaAllEffect.java create mode 100644 Mage/src/mage/watchers/common/CreatureWasCastWatcher.java diff --git a/Mage.Sets/src/mage/sets/commander2014/ContainmentPriest.java b/Mage.Sets/src/mage/sets/commander2014/ContainmentPriest.java index caff08b740..12728e17d9 100644 --- a/Mage.Sets/src/mage/sets/commander2014/ContainmentPriest.java +++ b/Mage.Sets/src/mage/sets/commander2014/ContainmentPriest.java @@ -27,8 +27,6 @@ */ package mage.sets.commander2014; -import java.util.HashSet; -import java.util.Set; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; @@ -41,17 +39,12 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.Rarity; -import mage.constants.WatcherScope; import mage.constants.Zone; -import mage.filter.common.FilterCreatureCard; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.permanent.TokenPredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; -import mage.game.stack.Spell; import mage.players.Player; -import mage.watchers.Watcher; +import mage.watchers.common.CreatureWasCastWatcher; /** * @@ -71,7 +64,7 @@ public class ContainmentPriest extends CardImpl { // Flash this.addAbility(FlashAbility.getInstance()); // If a nontoken creature would enter the battlefield and it wasn't cast, exile it instead. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ContainmentPriestReplacementEffect()), new CreatureCastWatcher()); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ContainmentPriestReplacementEffect()), new CreatureWasCastWatcher()); } public ContainmentPriest(final ContainmentPriest card) { @@ -86,14 +79,8 @@ public class ContainmentPriest extends CardImpl { class ContainmentPriestReplacementEffect extends ReplacementEffectImpl { - private static final FilterCreatureCard filter = new FilterCreatureCard(); - - static { - filter.add(Predicates.not(new TokenPredicate())); - } - public ContainmentPriestReplacementEffect() { - super(Duration.WhileOnBattlefield, Outcome.GainControl); + super(Duration.WhileOnBattlefield, Outcome.Exile); staticText = "If a nontoken creature would enter the battlefield and it wasn't cast, exile it instead"; } @@ -125,19 +112,18 @@ class ContainmentPriestReplacementEffect extends ReplacementEffectImpl { } return false; } - - @Override + + @Override public boolean checksEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.ZONE_CHANGE; + return event.getType() == GameEvent.EventType.ZONE_CHANGE; // Token create the create Token event } - @Override public boolean applies(GameEvent event, Ability source, Game game) { if (((ZoneChangeEvent) event).getToZone() == Zone.BATTLEFIELD) { Card card = game.getCard(event.getTargetId()); if (card.getCardType().contains(CardType.CREATURE)) { // TODO: Bestow Card cast as Enchantment probably not handled correctly - CreatureCastWatcher watcher = (CreatureCastWatcher) game.getState().getWatchers().get("CreatureWasCast"); + CreatureWasCastWatcher watcher = (CreatureWasCastWatcher) game.getState().getWatchers().get("CreatureWasCast"); if (watcher != null && !watcher.wasCreatureCastThisTurn(event.getTargetId())) { return true; } @@ -146,51 +132,3 @@ class ContainmentPriestReplacementEffect extends ReplacementEffectImpl { return false; } } - -class CreatureCastWatcher extends Watcher { - - private final Set creaturesCasted = new HashSet<>(); - - public CreatureCastWatcher() { - super("CreatureWasCast", WatcherScope.GAME); - } - - public CreatureCastWatcher(final CreatureCastWatcher watcher) { - super(watcher); - } - - @Override - public void watch(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.SPELL_CAST) { - Spell spell = (Spell) game.getObject(event.getTargetId()); - if (spell != null) { - Card card = game.getCard(spell.getSourceId()); - if (card != null && card.getCardType().contains(CardType.CREATURE)) { - creaturesCasted.add(card.getId()); - } - } - } - if (event.getType() == GameEvent.EventType.ZONE_CHANGE - && ((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD) { - Card card = game.getCard(event.getTargetId()); - if (card != null && card.getCardType().contains(CardType.CREATURE)) { - creaturesCasted.remove(card.getId()); - } - } - } - - public boolean wasCreatureCastThisTurn(UUID creatureSourceId) { - return creaturesCasted.contains(creatureSourceId); - } - - @Override - public void reset() { - super.reset(); - creaturesCasted.clear(); - } - - @Override - public CreatureCastWatcher copy() { - return new CreatureCastWatcher(this); - } -} diff --git a/Mage.Sets/src/mage/sets/magicorigins/ArchangelOfTithes.java b/Mage.Sets/src/mage/sets/magicorigins/ArchangelOfTithes.java new file mode 100644 index 0000000000..f58a35af3a --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/ArchangelOfTithes.java @@ -0,0 +1,131 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.magicorigins; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.combat.CantAttackYouUnlessPayManaAllEffect; +import mage.abilities.effects.common.combat.CantBlockUnlessPayManaAllEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; + +/** + * + * @author LevelX2 + */ +public class ArchangelOfTithes extends CardImpl { + + public ArchangelOfTithes(UUID ownerId) { + super(ownerId, 4, "Archangel of Tithes", Rarity.MYTHIC, new CardType[]{CardType.CREATURE}, "{1}{W}{W}{W}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Angel"); + this.power = new MageInt(3); + this.toughness = new MageInt(5); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // As long as Archangel of Tithes is untapped, creatures can't attack you or a planeswalker you control unless their controller pays {1} for each of those creatures. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ArchangelOfTithesPayManaToAttackAllEffect())); + + // As long as Archangel of Tithes is attacking, creatures can't block unless their controller pays {1} for each of those creatures. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ArchangelOfTithesPayManaToBlockAllEffect())); + } + + public ArchangelOfTithes(final ArchangelOfTithes card) { + super(card); + } + + @Override + public ArchangelOfTithes copy() { + return new ArchangelOfTithes(this); + } +} + +class ArchangelOfTithesPayManaToAttackAllEffect extends CantAttackYouUnlessPayManaAllEffect { + + ArchangelOfTithesPayManaToAttackAllEffect() { + super(new ManaCostsImpl<>("{1}"), true); + staticText = "As long as {this} is untapped, creatures can't attack you or a planeswalker you control unless their controller pays {1} for each of those creatures."; + } + + ArchangelOfTithesPayManaToAttackAllEffect(ArchangelOfTithesPayManaToAttackAllEffect effect) { + super(effect); + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent.isTapped()) { + return false; + } + return super.applies(event, source, game); + } + + @Override + public ArchangelOfTithesPayManaToAttackAllEffect copy() { + return new ArchangelOfTithesPayManaToAttackAllEffect(this); + } + +} + +class ArchangelOfTithesPayManaToBlockAllEffect extends CantBlockUnlessPayManaAllEffect { + + ArchangelOfTithesPayManaToBlockAllEffect() { + super(new ManaCostsImpl<>("{1}"), true); + staticText = "As long as {this} is attacking, creatures can't block unless their controller pays {1} for each of those creatures."; + } + + ArchangelOfTithesPayManaToBlockAllEffect(ArchangelOfTithesPayManaToBlockAllEffect effect) { + super(effect); + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (!permanent.isAttacking()) { + return false; + } + return super.applies(event, source, game); + } + + @Override + public ArchangelOfTithesPayManaToBlockAllEffect copy() { + return new ArchangelOfTithesPayManaToBlockAllEffect(this); + } + +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/ConsulsLieutenant.java b/Mage.Sets/src/mage/sets/magicorigins/ConsulsLieutenant.java new file mode 100644 index 0000000000..26befe1d8f --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/ConsulsLieutenant.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.magicorigins; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.condition.common.RenownCondition; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.RenownAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.filter.common.FilterAttackingCreature; + +/** + * + * @author LevelX2 + */ +public class ConsulsLieutenant extends CardImpl { + + public ConsulsLieutenant(UUID ownerId) { + super(ownerId, 11, "Consul's Lieutenant", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{W}{W}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Human"); + this.subtype.add("Soldier"); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // First strike + this.addAbility(FirstStrikeAbility.getInstance()); + // Renown 1 + this.addAbility(new RenownAbility(1)); + // Whenever Consul's Lieutenant attacks, if it's renowned, other attacking creatures you control get +1/+1 until end of turn. + this.addAbility(new ConditionalTriggeredAbility(new AttacksTriggeredAbility( + new BoostControlledEffect(1, 1, Duration.EndOfTurn, new FilterAttackingCreature("other attacking creatures you control"), true), false), + RenownCondition.getInstance(), + "Whenever Consul's Lieutenant attacks, if it's renowned, other attacking creatures you control get +1/+1 until end of turn.")); + + } + + public ConsulsLieutenant(final ConsulsLieutenant card) { + super(card); + } + + @Override + public ConsulsLieutenant copy() { + return new ConsulsLieutenant(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/HallowedMoonlight.java b/Mage.Sets/src/mage/sets/magicorigins/HallowedMoonlight.java new file mode 100644 index 0000000000..1c2589ac46 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/HallowedMoonlight.java @@ -0,0 +1,136 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.players.Player; +import mage.watchers.common.CreatureWasCastWatcher; + +/** + * + * @author LevelX2 + */ +public class HallowedMoonlight extends CardImpl { + + public HallowedMoonlight(UUID ownerId) { + super(ownerId, 16, "Hallowed Moonlight", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{1}{W}"); + this.expansionSetCode = "ORI"; + + // Until end of turn, if a creature would enter the battlefield and it wasn't cast, exile it instead. + this.getSpellAbility().addEffect(new HallowedMoonlightEffect()); + this.getSpellAbility().addWatcher(new CreatureWasCastWatcher()); + // Draw a card. + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1)); + } + + public HallowedMoonlight(final HallowedMoonlight card) { + super(card); + } + + @Override + public HallowedMoonlight copy() { + return new HallowedMoonlight(this); + } +} + +class HallowedMoonlightEffect extends ReplacementEffectImpl { + + public HallowedMoonlightEffect() { + super(Duration.EndOfTurn, Outcome.Exile); + staticText = "Until end of turn, if a creature would enter the battlefield and it wasn't cast, exile it instead"; + } + + public HallowedMoonlightEffect(final HallowedMoonlightEffect effect) { + super(effect); + } + + @Override + public HallowedMoonlightEffect copy() { + return new HallowedMoonlightEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Player controller = game.getPlayer(source.getControllerId()); + ZoneChangeEvent zEvent = (ZoneChangeEvent) event; + if (controller != null) { + Card card = game.getCard(event.getTargetId()); + if (card != null) { + controller.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, zEvent.getFromZone(), true); + } + return true; + + } + return false; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ZONE_CHANGE || event.getType() == GameEvent.EventType.CREATE_TOKEN; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (event.getType() == GameEvent.EventType.CREATE_TOKEN) { + // TODO: not clear how to check for creature type + // Tokens: Even though you’re probably casting a spell that makes tokens (Lingering Souls, Raise the Alarm, etc), + // the tokens themselves are not cast. As such, Hallowed Moonlight will stop ANY kind of creature tokens + // from entering the battlefield. + return true; + } + if (((ZoneChangeEvent) event).getToZone() == Zone.BATTLEFIELD) { + Card card = game.getCard(event.getTargetId()); + if (card != null && card.getCardType().contains(CardType.CREATURE)) { + // TODO: Bestow Card cast as Enchantment probably not handled correctly + CreatureWasCastWatcher watcher = (CreatureWasCastWatcher) game.getState().getWatchers().get("CreatureWasCast"); + if (watcher != null && !watcher.wasCreatureCastThisTurn(event.getTargetId())) { + return true; + } + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/KytheonsTactics.java b/Mage.Sets/src/mage/sets/magicorigins/KytheonsTactics.java new file mode 100644 index 0000000000..2bf1dbe507 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/KytheonsTactics.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.magicorigins; + +import java.util.UUID; +import mage.abilities.condition.common.SpellMasteryCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class KytheonsTactics extends CardImpl { + + public KytheonsTactics(UUID ownerId) { + super(ownerId, 25, "Kytheon's Tactics", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{1}{W}{W}"); + this.expansionSetCode = "ORI"; + + // Creatures you control get +2/+1 until end of turn. + this.getSpellAbility().addEffect(new BoostControlledEffect(2, 1, Duration.EndOfTurn)); + // Spell mastery — If there are two or more instant and/or sorcery cards in your graveyard, those creatures also gain vigilance until end of turn. + this.getSpellAbility().addEffect(new ConditionalContinuousEffect(new GainAbilityControlledEffect(VigilanceAbility.getInstance(), Duration.EndOfTurn), + SpellMasteryCondition.getInstance(), + "
Spell mastery — If there are two or more instant and/or sorcery cards in your graveyard, those creatures also gain vigilance until end of turn")); + } + + public KytheonsTactics(final KytheonsTactics card) { + super(card); + } + + @Override + public KytheonsTactics copy() { + return new KytheonsTactics(this); + } +} diff --git a/Mage/src/mage/abilities/effects/common/combat/CantAttackYouUnlessPayManaAllEffect.java b/Mage/src/mage/abilities/effects/common/combat/CantAttackYouUnlessPayManaAllEffect.java index 1846384395..4c359b4aa3 100644 --- a/Mage/src/mage/abilities/effects/common/combat/CantAttackYouUnlessPayManaAllEffect.java +++ b/Mage/src/mage/abilities/effects/common/combat/CantAttackYouUnlessPayManaAllEffect.java @@ -1,7 +1,29 @@ /* - * 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. + * 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.combat; diff --git a/Mage/src/mage/abilities/effects/common/combat/CantBlockUnlessPayManaAllEffect.java b/Mage/src/mage/abilities/effects/common/combat/CantBlockUnlessPayManaAllEffect.java new file mode 100644 index 0000000000..f8d42a4c4b --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/combat/CantBlockUnlessPayManaAllEffect.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.abilities.effects.common.combat; + +import mage.abilities.Ability; +import mage.abilities.costs.mana.ManaCosts; +import mage.abilities.effects.PayCostToAttackBlockEffectImpl; +import mage.abilities.effects.PayCostToAttackBlockEffectImpl.RestrictType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; + +/** + * + * @author LevelX2 + */ +public class CantBlockUnlessPayManaAllEffect extends PayCostToAttackBlockEffectImpl { + + private final FilterCreaturePermanent filterCreaturePermanent; + + public CantBlockUnlessPayManaAllEffect(ManaCosts manaCosts) { + this(manaCosts, false); + } + + public CantBlockUnlessPayManaAllEffect(ManaCosts manaCosts, boolean payAlsoForAttackingPlaneswalker) { + this(manaCosts, payAlsoForAttackingPlaneswalker, null); + } + + public CantBlockUnlessPayManaAllEffect(ManaCosts manaCosts, boolean payAlsoForAttackingPlaneswalker, FilterCreaturePermanent filter) { + super(Duration.WhileOnBattlefield, Outcome.Detriment, RestrictType.BLOCK, manaCosts); + this.filterCreaturePermanent = filter; + staticText = (filterCreaturePermanent == null ? "Creatures" : filterCreaturePermanent.getMessage()) + + " can't block " + + "unless their controller pays " + + (manaCosts == null ? "" : manaCosts.getText()) + + " for each blocking creature he or she controls"; + } + + public CantBlockUnlessPayManaAllEffect(CantBlockUnlessPayManaAllEffect effect) { + super(effect); + this.filterCreaturePermanent = effect.filterCreaturePermanent; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + // check if blocking creature fullfills filter criteria + if (filterCreaturePermanent != null) { + Permanent permanent = game.getPermanent(event.getSourceId()); + if (!filterCreaturePermanent.match(permanent, source.getSourceId(), source.getControllerId(), game)) { + return false; + } + } + return true; + } + + @Override + public CantBlockUnlessPayManaAllEffect copy() { + return new CantBlockUnlessPayManaAllEffect(this); + } +} diff --git a/Mage/src/mage/watchers/common/CreatureWasCastWatcher.java b/Mage/src/mage/watchers/common/CreatureWasCastWatcher.java new file mode 100644 index 0000000000..e693a01055 --- /dev/null +++ b/Mage/src/mage/watchers/common/CreatureWasCastWatcher.java @@ -0,0 +1,93 @@ +/* + * 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 java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import mage.cards.Card; +import mage.constants.CardType; +import mage.constants.WatcherScope; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.game.stack.Spell; +import mage.watchers.Watcher; + +/** + * + * @author LevelX2 + */ +public class CreatureWasCastWatcher extends Watcher { + + private final Set creaturesCasted = new HashSet<>(); + + public CreatureWasCastWatcher() { + super("CreatureWasCast", WatcherScope.GAME); + } + + public CreatureWasCastWatcher(final CreatureWasCastWatcher watcher) { + super(watcher); + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.SPELL_CAST) { + Spell spell = (Spell) game.getObject(event.getTargetId()); + if (spell != null) { + Card card = game.getCard(spell.getSourceId()); + if (card != null && card.getCardType().contains(CardType.CREATURE)) { + creaturesCasted.add(card.getId()); + } + } + } + if (event.getType() == GameEvent.EventType.ZONE_CHANGE + && ((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD) { + Card card = game.getCard(event.getTargetId()); + if (card != null && card.getCardType().contains(CardType.CREATURE)) { + creaturesCasted.remove(card.getId()); + } + } + } + + public boolean wasCreatureCastThisTurn(UUID creatureSourceId) { + return creaturesCasted.contains(creatureSourceId); + } + + @Override + public void reset() { + super.reset(); + creaturesCasted.clear(); + } + + @Override + public CreatureWasCastWatcher copy() { + return new CreatureWasCastWatcher(this); + } +}