diff --git a/Mage.Sets/src/mage/cards/b/BattleHymn.java b/Mage.Sets/src/mage/cards/b/BattleHymn.java index 0cf3de42420..4d730d9409a 100644 --- a/Mage.Sets/src/mage/cards/b/BattleHymn.java +++ b/Mage.Sets/src/mage/cards/b/BattleHymn.java @@ -34,7 +34,7 @@ import mage.abilities.effects.common.DynamicManaEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.StaticFilters; /** * @@ -43,11 +43,10 @@ import mage.filter.common.FilterControlledCreaturePermanent; public class BattleHymn extends CardImpl { public BattleHymn(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{R}"); - + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{R}"); // Add {R} to your mana pool for each creature you control. - this.getSpellAbility().addEffect(new DynamicManaEffect(Mana.RedMana(1), new PermanentsOnBattlefieldCount(new FilterControlledCreaturePermanent()))); + this.getSpellAbility().addEffect(new DynamicManaEffect(Mana.RedMana(1), new PermanentsOnBattlefieldCount(StaticFilters.FILTER_CONTROLLED_CREATURE))); } public BattleHymn(final BattleHymn card) { diff --git a/Mage.Sets/src/mage/cards/g/GhaltaPrimalHunger.java b/Mage.Sets/src/mage/cards/g/GhaltaPrimalHunger.java new file mode 100644 index 00000000000..4475fd1c4e3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GhaltaPrimalHunger.java @@ -0,0 +1,125 @@ +/* + * 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.g; + +import java.util.UUID; +import mage.MageInt; +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.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.CostModificationType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledArtifactPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.util.CardUtil; + +/** + * + * @author LevelX2 + */ +public class GhaltaPrimalHunger extends CardImpl { + + public GhaltaPrimalHunger(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{10}{G}{G}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.ELDER); + this.subtype.add(SubType.DINOSAUR); + this.power = new MageInt(12); + this.toughness = new MageInt(12); + + // Ghalta, Primal Hunger costs {X} less to cast, where X is the total power of creatures you control. + this.addAbility(new SimpleStaticAbility(Zone.STACK, new GhaltaPrimalHungerCostReductionEffect())); + // Trample + this.addAbility(TrampleAbility.getInstance()); + + } + + public GhaltaPrimalHunger(final GhaltaPrimalHunger card) { + super(card); + } + + @Override + public GhaltaPrimalHunger copy() { + return new GhaltaPrimalHunger(this); + } +} + +class GhaltaPrimalHungerCostReductionEffect extends CostModificationEffectImpl { + + private static final FilterPermanent filter = new FilterControlledArtifactPermanent("noncreature artifacts you control"); + + static { + filter.add(Predicates.not(new CardTypePredicate(CardType.CREATURE))); + } + + GhaltaPrimalHungerCostReductionEffect() { + super(Duration.Custom, Outcome.Benefit, CostModificationType.REDUCE_COST); + staticText = "{this} costs {X} less to cast, where X is the total power of creatures you control"; + } + + GhaltaPrimalHungerCostReductionEffect(final GhaltaPrimalHungerCostReductionEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source, Ability abilityToModify) { + int totalPower = 0; + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(source.getControllerId())) { + if (permanent.isCreature()) { + totalPower += permanent.getPower().getValue(); + } + + } + CardUtil.reduceCost(abilityToModify, totalPower); + return true; + } + + @Override + public boolean applies(Ability abilityToModify, Ability source, Game game) { + return abilityToModify.getSourceId().equals(source.getSourceId()) && (abilityToModify instanceof SpellAbility); + } + + @Override + public GhaltaPrimalHungerCostReductionEffect copy() { + return new GhaltaPrimalHungerCostReductionEffect(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GrowingRitesOfItlimoc.java b/Mage.Sets/src/mage/cards/g/GrowingRitesOfItlimoc.java index bd78168fff7..0e3a1cb05ff 100644 --- a/Mage.Sets/src/mage/cards/g/GrowingRitesOfItlimoc.java +++ b/Mage.Sets/src/mage/cards/g/GrowingRitesOfItlimoc.java @@ -45,7 +45,7 @@ import mage.constants.SuperType; import mage.constants.TargetController; import mage.constants.Zone; import mage.filter.FilterCard; -import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.StaticFilters; import mage.filter.predicate.mageobject.CardTypePredicate; /** @@ -62,7 +62,7 @@ public class GrowingRitesOfItlimoc extends CardImpl { public GrowingRitesOfItlimoc(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}"); - + this.addSuperType(SuperType.LEGENDARY); this.transformable = true; @@ -77,7 +77,7 @@ public class GrowingRitesOfItlimoc extends CardImpl { this.addAbility(new TransformAbility()); this.addAbility(new ConditionalTriggeredAbility( new BeginningOfEndStepTriggeredAbility(new TransformSourceEffect(true), TargetController.YOU, false), - new PermanentsOnTheBattlefieldCondition(new FilterControlledCreaturePermanent(), ComparisonType.MORE_THAN, 3), + new PermanentsOnTheBattlefieldCondition(StaticFilters.FILTER_CONTROLLED_A_CREATURE, ComparisonType.MORE_THAN, 3), "At the beginning of your end step, if you control four or more creatures, transform {this}")); } diff --git a/Mage.Sets/src/mage/cards/n/NaturesWill.java b/Mage.Sets/src/mage/cards/n/NaturesWill.java index 48c70b9c444..215999aa9be 100644 --- a/Mage.Sets/src/mage/cards/n/NaturesWill.java +++ b/Mage.Sets/src/mage/cards/n/NaturesWill.java @@ -32,19 +32,14 @@ import java.util.List; import java.util.Set; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.effects.Effect; +import mage.abilities.common.ControlledCreaturesDealCombatDamagePlayerTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; -import mage.constants.Zone; import mage.filter.StaticFilters; import mage.game.Game; -import mage.game.events.DamagedPlayerEvent; -import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; /** @@ -54,11 +49,10 @@ import mage.game.permanent.Permanent; public class NaturesWill extends CardImpl { public NaturesWill(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{G}{G}"); - + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}{G}"); // Whenever one or more creatures you control deal combat damage to a player, tap all lands that player controls and untap all lands you control. - this.addAbility(new NaturesWillTriggeredAbility()); + this.addAbility(new ControlledCreaturesDealCombatDamagePlayerTriggeredAbility(new NaturesWillEffect())); } public NaturesWill(final NaturesWill card) { @@ -71,63 +65,6 @@ public class NaturesWill extends CardImpl { } } -class NaturesWillTriggeredAbility extends TriggeredAbilityImpl { - - private boolean madeDamge = false; - private Set damagedPlayers = new HashSet<>(); - - public NaturesWillTriggeredAbility() { - super(Zone.BATTLEFIELD, new NaturesWillEffect(), false); - } - - public NaturesWillTriggeredAbility(final NaturesWillTriggeredAbility ability) { - super(ability); - this.madeDamge = ability.madeDamge; - this.damagedPlayers = new HashSet<>(); - this.damagedPlayers.addAll(ability.damagedPlayers); - } - - @Override - public NaturesWillTriggeredAbility copy() { - return new NaturesWillTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == EventType.DAMAGED_PLAYER || event.getType() == EventType.COMBAT_DAMAGE_STEP_POST; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType() == EventType.DAMAGED_PLAYER) { - DamagedPlayerEvent damageEvent = (DamagedPlayerEvent) event; - Permanent p = game.getPermanent(event.getSourceId()); - if (damageEvent.isCombatDamage() && p != null && p.getControllerId().equals(this.getControllerId())) { - madeDamge = true; - damagedPlayers.add(event.getPlayerId()); - } - } - if (event.getType() == EventType.COMBAT_DAMAGE_STEP_POST) { - if (madeDamge) { - Set damagedPlayersCopy = new HashSet<>(); - damagedPlayersCopy.addAll(damagedPlayers); - for(Effect effect: this.getEffects()) { - effect.setValue("damagedPlayers", damagedPlayersCopy); - } - damagedPlayers.clear(); - madeDamge = false; - return true; - } - } - return false; - } - - @Override - public String getRule() { - return "Whenever one or more creatures you control deal combat damage to a player, " + super.getRule(); - } -} - class NaturesWillEffect extends OneShotEffect { public NaturesWillEffect() { @@ -160,7 +97,6 @@ class NaturesWillEffect extends OneShotEffect { } } - return false; } } diff --git a/Mage.Sets/src/mage/cards/o/OngoingInvestigation.java b/Mage.Sets/src/mage/cards/o/OngoingInvestigation.java index 1dd5bef22fa..fcf6569d42f 100644 --- a/Mage.Sets/src/mage/cards/o/OngoingInvestigation.java +++ b/Mage.Sets/src/mage/cards/o/OngoingInvestigation.java @@ -27,11 +27,9 @@ */ package mage.cards.o; -import java.util.ArrayList; -import java.util.List; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.ControlledCreaturesDealCombatDamagePlayerTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.ExileFromGraveCost; import mage.abilities.costs.mana.ManaCostsImpl; @@ -42,10 +40,6 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Zone; import mage.filter.common.FilterCreatureCard; -import mage.game.Game; -import mage.game.events.DamagedPlayerEvent; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; import mage.target.common.TargetCardInYourGraveyard; /** @@ -58,7 +52,7 @@ public class OngoingInvestigation extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}"); // Whenever one or more creatures you control deal combat damage to a player, investigate. - this.addAbility(new OngoingInvestigationTriggeredAbility()); + this.addAbility(new ControlledCreaturesDealCombatDamagePlayerTriggeredAbility(new InvestigateEffect())); // {1}{G}, Exile a creature card from your graveyard: Investigate. You gain 2 life. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new InvestigateEffect(), new ManaCostsImpl("{1}{G}")); @@ -76,50 +70,3 @@ public class OngoingInvestigation extends CardImpl { return new OngoingInvestigation(this); } } - -class OngoingInvestigationTriggeredAbility extends TriggeredAbilityImpl { - - List damagedPlayerIds = new ArrayList<>(); - - public OngoingInvestigationTriggeredAbility() { - super(Zone.BATTLEFIELD, new InvestigateEffect(), false); - } - - public OngoingInvestigationTriggeredAbility(final OngoingInvestigationTriggeredAbility ability) { - super(ability); - } - - @Override - public OngoingInvestigationTriggeredAbility copy() { - return new OngoingInvestigationTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DAMAGED_PLAYER - || event.getType() == GameEvent.EventType.END_COMBAT_STEP_POST; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.DAMAGED_PLAYER) { - if (((DamagedPlayerEvent) event).isCombatDamage()) { - Permanent creature = game.getPermanent(event.getSourceId()); - if (creature != null && creature.getControllerId().equals(controllerId) - && !damagedPlayerIds.contains(event.getTargetId())) { - damagedPlayerIds.add(event.getTargetId()); - return true; - } - } - } - if (event.getType() == GameEvent.EventType.END_COMBAT_STEP_POST) { - damagedPlayerIds.clear(); - } - return false; - } - - @Override - public String getRule() { - return "Whenever one or more creatures you control deal combat damage to a player, investigate"; - } -} diff --git a/Mage.Sets/src/mage/cards/p/PyrewildShaman.java b/Mage.Sets/src/mage/cards/p/PyrewildShaman.java index d8e6d15213f..72fa8612714 100644 --- a/Mage.Sets/src/mage/cards/p/PyrewildShaman.java +++ b/Mage.Sets/src/mage/cards/p/PyrewildShaman.java @@ -25,14 +25,11 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.cards.p; -import java.util.ArrayList; -import java.util.List; import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.ControlledCreaturesDealCombatDamagePlayerTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.ReturnToHandSourceEffect; @@ -41,22 +38,14 @@ import mage.abilities.keyword.BloodrushAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; +import mage.constants.SubType; import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.DamagedEvent; -import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; -import mage.game.events.ZoneChangeEvent; -import mage.game.permanent.Permanent; - - public class PyrewildShaman extends CardImpl { - public PyrewildShaman (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}"); + public PyrewildShaman(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); this.subtype.add(SubType.GOBLIN); this.subtype.add(SubType.SHAMAN); @@ -64,14 +53,16 @@ public class PyrewildShaman extends CardImpl { this.toughness = new MageInt(1); // Bloodrush — {1}{R}, Discard Pyrewild Shaman: Target attacking creature gets +3/+1 until end of turn. - this.addAbility(new BloodrushAbility("{1}{R}", new BoostTargetEffect(3,1,Duration.EndOfTurn))); + this.addAbility(new BloodrushAbility("{1}{R}", new BoostTargetEffect(3, 1, Duration.EndOfTurn))); // Whenever one or more creatures you control deal combat damage to a player, if Pyrewild Shaman is in your graveyard, you may pay {3}. If you do, return Pyrewild Shaman to your hand. - this.addAbility(new PyrewildShamanTriggeredAbility()); + this.addAbility(new ControlledCreaturesDealCombatDamagePlayerTriggeredAbility(Zone.GRAVEYARD, + new DoIfCostPaid(new ReturnToHandSourceEffect(), new ManaCostsImpl("{3}")) + .setText("if {this} is in your graveyard, you may pay {3}. If you do, return {this} to your hand"))); } - public PyrewildShaman (final PyrewildShaman card) { + public PyrewildShaman(final PyrewildShaman card) { super(card); } @@ -81,56 +72,3 @@ public class PyrewildShaman extends CardImpl { } } - -class PyrewildShamanTriggeredAbility extends TriggeredAbilityImpl { - - List damagedPlayerIds = new ArrayList<>(); - - public PyrewildShamanTriggeredAbility() { - super(Zone.GRAVEYARD, new DoIfCostPaid(new ReturnToHandSourceEffect(), new ManaCostsImpl("{3}")), false); - } - - public PyrewildShamanTriggeredAbility(final PyrewildShamanTriggeredAbility ability) { - super(ability); - } - - @Override - public PyrewildShamanTriggeredAbility copy() { - return new PyrewildShamanTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == EventType.DAMAGED_PLAYER - || event.getType() == EventType.END_COMBAT_STEP_POST - || event.getType() == EventType.ZONE_CHANGE; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.DAMAGED_PLAYER) { - if (((DamagedEvent) event).isCombatDamage()) { - Permanent creature = game.getPermanent(event.getSourceId()); - if (creature != null && creature.getControllerId().equals(controllerId) && !damagedPlayerIds.contains(event.getTargetId())) { - damagedPlayerIds.add(event.getTargetId()); - return true; - } - } - } - if (event.getType() == EventType.END_COMBAT_STEP_POST){ - damagedPlayerIds.clear(); - } - if (event.getType() == EventType.ZONE_CHANGE && event.getTargetId().equals(getSourceId())){ - ZoneChangeEvent zEvent = (ZoneChangeEvent) event; - if (zEvent.getFromZone() == Zone.GRAVEYARD) { - damagedPlayerIds.clear(); - } - } - return false; - } - - @Override - public String getRule() { - return "Whenever one or more creatures you control deal combat damage to a player, if {this} is in your graveyard, you may pay {3}. If you do, return {this} to your hand."; - } -} diff --git a/Mage.Sets/src/mage/cards/s/StormTheVault.java b/Mage.Sets/src/mage/cards/s/StormTheVault.java new file mode 100644 index 00000000000..4a1647230fe --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/StormTheVault.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.cards.s; + +import java.util.UUID; +import mage.abilities.common.BeginningOfEndStepTriggeredAbility; +import mage.abilities.common.ControlledCreaturesDealCombatDamagePlayerTriggeredAbility; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.TransformSourceEffect; +import mage.abilities.keyword.TransformAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.v.VaultOfCatlacan; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.SuperType; +import mage.constants.TargetController; +import mage.filter.StaticFilters; +import mage.game.permanent.token.TreasureToken; + +/** + * + * @author LevelX2 + */ +public class StormTheVault extends CardImpl { + + public StormTheVault(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}{R}"); + + this.addSuperType(SuperType.LEGENDARY); + + this.transformable = true; + this.secondSideCardClazz = VaultOfCatlacan.class; + + // Whenever one or more creatures you control deal combat damage to a player, create a colorless Treasure artifact token with "{T}, Sacrifice this artifact: Add one mana of any color to your mana pool." + this.addAbility(new ControlledCreaturesDealCombatDamagePlayerTriggeredAbility(new CreateTokenEffect(new TreasureToken()))); + + // At the beginning of your end step, if you control five or more artifacts, transform Storm the Vault. + this.addAbility(new TransformAbility()); + this.addAbility(new ConditionalTriggeredAbility( + new BeginningOfEndStepTriggeredAbility(new TransformSourceEffect(true), TargetController.YOU, false), + new PermanentsOnTheBattlefieldCondition(StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT, ComparisonType.MORE_THAN, 4), + "At the beginning of your end step, if you control five or more artifacts, transform {this}")); + + } + + public StormTheVault(final StormTheVault card) { + super(card); + } + + @Override + public StormTheVault copy() { + return new StormTheVault(this); + } +} diff --git a/Mage.Sets/src/mage/cards/v/VaultOfCatlacan.java b/Mage.Sets/src/mage/cards/v/VaultOfCatlacan.java new file mode 100644 index 00000000000..372ba6e1dab --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VaultOfCatlacan.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.cards.v; + +import java.util.UUID; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.common.DynamicManaEffect; +import mage.abilities.effects.common.InfoEffect; +import mage.abilities.mana.AnyColorManaAbility; +import mage.abilities.mana.SimpleManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SuperType; +import mage.constants.Zone; +import mage.filter.StaticFilters; + +/** + * + * @author LevelX2 + */ +public class VaultOfCatlacan extends CardImpl { + + public VaultOfCatlacan(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + this.addSuperType(SuperType.LEGENDARY); + this.nightCard = true; + + // (Transforms from Storm the Vault.) + Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new InfoEffect("(Transforms from Storm the Vault.)")); + ability.setRuleAtTheTop(true); + this.addAbility(ability); + + // {T}: Add one mana of any color to your mana pool. + this.addAbility(new AnyColorManaAbility()); + + // {T}: Add {U} to your mana pool for each artifact you control. + this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, + new DynamicManaEffect(Mana.BlueMana(1), new PermanentsOnBattlefieldCount(StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT)), + new TapSourceCost())); + + } + + public VaultOfCatlacan(final VaultOfCatlacan card) { + super(card); + } + + @Override + public VaultOfCatlacan copy() { + return new VaultOfCatlacan(this); + } +} diff --git a/Mage.Sets/src/mage/sets/RivalsOfIxalan.java b/Mage.Sets/src/mage/sets/RivalsOfIxalan.java index 6e42595562a..4d6cce9b6d8 100644 --- a/Mage.Sets/src/mage/sets/RivalsOfIxalan.java +++ b/Mage.Sets/src/mage/sets/RivalsOfIxalan.java @@ -28,6 +28,7 @@ package mage.sets; import mage.cards.ExpansionSet; +import mage.constants.Rarity; import mage.constants.SetType; /** @@ -53,5 +54,10 @@ public class RivalsOfIxalan extends ExpansionSet { this.numBoosterUncommon = 3; this.numBoosterRare = 1; this.ratioBoosterMythic = 8; + + cards.add(new SetCardInfo("Ghalta, Primal Hunger", 130, Rarity.RARE, mage.cards.g.GhaltaPrimalHunger.class)); + cards.add(new SetCardInfo("Silvergill Adept", 53, Rarity.UNCOMMON, mage.cards.s.SilvergillAdept.class)); + cards.add(new SetCardInfo("Storm the Vault", 173, Rarity.RARE, mage.cards.s.StormTheVault.class)); + cards.add(new SetCardInfo("Vault of Catlacan", 173, Rarity.RARE, mage.cards.v.VaultOfCatlacan.class)); } } diff --git a/Mage/src/main/java/mage/abilities/common/ControlledCreaturesDealCombatDamagePlayerTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/ControlledCreaturesDealCombatDamagePlayerTriggeredAbility.java new file mode 100644 index 00000000000..0dff8b8c01b --- /dev/null +++ b/Mage/src/main/java/mage/abilities/common/ControlledCreaturesDealCombatDamagePlayerTriggeredAbility.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.abilities.common; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.DamagedPlayerEvent; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; + +/** + * + * @author LevelX2 + */ +public class ControlledCreaturesDealCombatDamagePlayerTriggeredAbility extends TriggeredAbilityImpl { + + private boolean madeDamage = false; + private Set damagedPlayerIds = new HashSet<>(); + + public ControlledCreaturesDealCombatDamagePlayerTriggeredAbility(Effect effect) { + this(Zone.BATTLEFIELD, effect); + } + + public ControlledCreaturesDealCombatDamagePlayerTriggeredAbility(Zone zone, Effect effect) { + super(zone, effect, false); + } + + public ControlledCreaturesDealCombatDamagePlayerTriggeredAbility(final ControlledCreaturesDealCombatDamagePlayerTriggeredAbility ability) { + super(ability); + this.madeDamage = ability.madeDamage; + this.damagedPlayerIds = new HashSet<>(); + this.damagedPlayerIds.addAll(ability.damagedPlayerIds); + } + + @Override + public ControlledCreaturesDealCombatDamagePlayerTriggeredAbility copy() { + return new ControlledCreaturesDealCombatDamagePlayerTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == EventType.DAMAGED_PLAYER + || event.getType() == EventType.END_COMBAT_STEP_POST + || event.getType() == EventType.ZONE_CHANGE; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType() == EventType.DAMAGED_PLAYER) { + DamagedPlayerEvent damageEvent = (DamagedPlayerEvent) event; + Permanent p = game.getPermanent(event.getSourceId()); + if (damageEvent.isCombatDamage() && p != null && p.getControllerId().equals(this.getControllerId())) { + madeDamage = true; + damagedPlayerIds.add(event.getPlayerId()); + } + } + if (event.getType() == EventType.END_COMBAT_STEP_POST) { + if (madeDamage) { + Set damagedPlayersCopy = new HashSet<>(); + damagedPlayersCopy.addAll(damagedPlayerIds); + for (Effect effect : this.getEffects()) { + effect.setValue("damagedPlayers", damagedPlayersCopy); + } + damagedPlayerIds.clear(); + madeDamage = false; + return true; + } + } + if (event.getType() == EventType.ZONE_CHANGE && event.getTargetId().equals(getSourceId())) { + ZoneChangeEvent zEvent = (ZoneChangeEvent) event; + if (zEvent.getFromZone() == Zone.GRAVEYARD) { + damagedPlayerIds.clear(); + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever one or more creatures you control deal combat damage to a player, " + super.getRule(); + } +} diff --git a/Mage/src/main/java/mage/filter/StaticFilters.java b/Mage/src/main/java/mage/filter/StaticFilters.java index 84695fd94f9..e2fb79b74ea 100644 --- a/Mage/src/main/java/mage/filter/StaticFilters.java +++ b/Mage/src/main/java/mage/filter/StaticFilters.java @@ -48,6 +48,7 @@ public final class StaticFilters { public static final FilterPermanent FILTER_OPPONENTS_PERMANENT_ARTIFACT = new FilterPermanent("artifact an opponent controls"); public static final FilterPermanent FILTER_OPPONENTS_PERMANENT_ARTIFACT_OR_CREATURE = new FilterPermanent("artifact or creature an opponent controls"); + public static final FilterPermanent FILTER_CONTROLLED_CREATURE = new FilterControlledCreaturePermanent(); public static final FilterPermanent FILTER_CONTROLLED_A_CREATURE = new FilterControlledCreaturePermanent("a creature you control"); public static final FilterControlledCreaturePermanent FILTER_CONTROLLED_ANOTHER_CREATURE = new FilterControlledCreaturePermanent("another creature"); public static final FilterControlledPermanent FILTER_CONTROLLED_PERMANENT_NON_LAND = new FilterControlledPermanent("nonland permanent"); diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 1152e94dc2b..73f297ad8f9 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -32696,3 +32696,9 @@ Forest|Duel Decks: Mind vs. Might|65|L||Basic Land - Forest|||{T}: Add {G} to yo Chandra, Gremlin Wrangler|Heroes of the Realm|1|M|{2}{R}{R}|Legendary Planeswalker - Chandra|3||+1: Create a 2/2 red Gremlin creature token.$-2:Chandra, Gremlin Wrangler deals X damage to target creature or player, where X is the number of Gremlins you control.| Dungeon Master|Heroes of the Realm|1|M|{2}{W}{U}|Legendary Planeswalker - Dungeon Master|||+1: Target opponent creates a 1/1 black Skeleton creature token with “When this creature dies, each opponent loses 2 life.”$+1: Roll a d20. If you roll a 1, skip your next turn. If you roll a 12 or higher, draw a card.$-6: You get an adventuring party. (Your party is a 3/3 red Fighter with first strike, a 1/1 white Cleric with lifelink, a 2/2 black Rogue with hexproof, and a 1/1 blue Wizard with flying.)| Nira, Hellkite Duelist|Heroes of the Realm|3|M|{W}{U}{B}{R}{G}|Legendary Creature — Dragon|6|6|Flash$Flying, trample, haste$When Nira, Hellkite Duelist enters the battlefield, the next time you would lose the game this turn, instead draw three cards and your life total becomes 5.| +Silvergill Adept|Rivals of Ixalan|53|U|{1}{U}|Creature - Merfolk Wizard|2|1|As an additional cost to cast Silvergill Adept, reveal a Merfolk card from your hand or pay {3}.$When Silvergill Adept enters the battlefield, draw a card.| +Tetzimoc, Primal Death|Rivals of Ixalan|86|R|{4}{B}{B}|Legendary Creature - Elder Dinosaur|6|6|Deathtouch${B}, Reveal Tetzimoc, Primal Death from your hand: Put a prey counter on target creature. Activate this ability only during your turn.$When Tetzimoc, Primal Death enters the battlefield, destroy each creature your opponents control with a prey counter on it.| +Ghalta, Primal Hunger|Rivals of Ixalan|130|R|{10}{G}{G}|Legendary Creature - Elder Dinosaur|12|12|Ghalta, Primal Hunger costs {X} less to cast, where X is the total power of creatures you control.$Trample| +Storm the Vault|Rivals of Ixalan|173|R|{2}{U}{R}|Legendary Enchantment|||Whenever one or more creatures you control deal combat damage to a player, create a colorless Treasure artifact token with "{T}, Sacrifice this artifact: Add one mana of any color to your mana pool."$At the beginning of your end step, if you control five or more artifacts, transform Storm the Vault.| +Vault of Catlacan|Rivals of Ixalan|173|R||Legendary Land|||(Transforms from Storm the Vault.)${T}: Add one mana of any color to your mana pool.${T}: Add {U} to your mana pool for each artifact you control.| +The Immortal Sun|Rivals of Ixalan|180|M|{6}|Legendary Artifact|||Players can't activate loyalty abilities of planeswalkers.$At the beginning of your draw step, draw an additional card.$Spells you cast cost {1} less to cast.$Creatures you control get +1/+1.| \ No newline at end of file