From 724b0ef33d0d7a3827e7cdd6af72421f8f0d3fe0 Mon Sep 17 00:00:00 2001 From: Daniel Bomar Date: Sun, 10 Jan 2021 16:15:59 -0600 Subject: [PATCH 01/20] [KHM] Fixed rarity for snow basics (was causing build errors) --- Mage.Sets/src/mage/sets/Kaldheim.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Mage.Sets/src/mage/sets/Kaldheim.java b/Mage.Sets/src/mage/sets/Kaldheim.java index c2eb3dbf206..71aabb538b5 100644 --- a/Mage.Sets/src/mage/sets/Kaldheim.java +++ b/Mage.Sets/src/mage/sets/Kaldheim.java @@ -105,11 +105,11 @@ public final class Kaldheim extends ExpansionSet { cards.add(new SetCardInfo("Seize the Spoils", 149, Rarity.COMMON, mage.cards.s.SeizeTheSpoils.class)); cards.add(new SetCardInfo("Showdown of the Skalds", 229, Rarity.RARE, mage.cards.s.ShowdownOfTheSkalds.class)); cards.add(new SetCardInfo("Sigrid, God-Favored", 29, Rarity.RARE, mage.cards.s.SigridGodFavored.class)); - cards.add(new SetCardInfo("Snow-Covered Forest", 284, Rarity.COMMON, mage.cards.s.SnowCoveredForest.class)); - cards.add(new SetCardInfo("Snow-Covered Island", 278, Rarity.COMMON, mage.cards.s.SnowCoveredIsland.class)); - cards.add(new SetCardInfo("Snow-Covered Mountain", 282, Rarity.COMMON, mage.cards.s.SnowCoveredMountain.class)); - cards.add(new SetCardInfo("Snow-Covered Plains", 276, Rarity.COMMON, mage.cards.s.SnowCoveredPlains.class)); - cards.add(new SetCardInfo("Snow-Covered Swamp", 280, Rarity.COMMON, mage.cards.s.SnowCoveredSwamp.class)); + cards.add(new SetCardInfo("Snow-Covered Forest", 284, Rarity.LAND, mage.cards.s.SnowCoveredForest.class)); + cards.add(new SetCardInfo("Snow-Covered Island", 278, Rarity.LAND, mage.cards.s.SnowCoveredIsland.class)); + cards.add(new SetCardInfo("Snow-Covered Mountain", 282, Rarity.LAND, mage.cards.s.SnowCoveredMountain.class)); + cards.add(new SetCardInfo("Snow-Covered Plains", 276, Rarity.LAND, mage.cards.s.SnowCoveredPlains.class)); + cards.add(new SetCardInfo("Snow-Covered Swamp", 280, Rarity.LAND, mage.cards.s.SnowCoveredSwamp.class)); cards.add(new SetCardInfo("Snowfield Sinkhole", 269, Rarity.COMMON, mage.cards.s.SnowfieldSinkhole.class)); cards.add(new SetCardInfo("Starnheim Aspirant", 380, Rarity.UNCOMMON, mage.cards.s.StarnheimAspirant.class)); cards.add(new SetCardInfo("Sulfurous Mine", 270, Rarity.COMMON, mage.cards.s.SulfurousMine.class)); From 6cb89b00ed8667f82cbb0d2cef688600d732f8e1 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Sun, 10 Jan 2021 14:47:04 -0500 Subject: [PATCH 02/20] [KHM] Implemented Spirit of the Aldergard --- .../mage/cards/s/SpiritOfTheAldergard.java | 72 +++++++++++++++++++ Mage.Sets/src/mage/sets/Kaldheim.java | 1 + 2 files changed, 73 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/SpiritOfTheAldergard.java diff --git a/Mage.Sets/src/mage/cards/s/SpiritOfTheAldergard.java b/Mage.Sets/src/mage/cards/s/SpiritOfTheAldergard.java new file mode 100644 index 00000000000..e35eaf6b360 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SpiritOfTheAldergard.java @@ -0,0 +1,72 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.FilterCard; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.common.FilterLandCard; +import mage.filter.predicate.permanent.AnotherPredicate; +import mage.target.common.TargetCardInLibrary; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SpiritOfTheAldergard extends CardImpl { + + private static final FilterCard filter + = new FilterLandCard("a snow land card"); + private static final FilterPermanent filter2 + = new FilterControlledPermanent("other snow permanent you control"); + + static { + filter.add(SuperType.SNOW.getPredicate()); + filter2.add(SuperType.SNOW.getPredicate()); + filter2.add(AnotherPredicate.instance); + } + + private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter2); + + public SpiritOfTheAldergard(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}"); + + this.addSuperType(SuperType.SNOW); + this.subtype.add(SubType.BEAR); + this.subtype.add(SubType.SPIRIT); + this.power = new MageInt(0); + this.toughness = new MageInt(4); + + // When Spirit of the Aldergard enters the battlefield, search your library for a snow land card, reveal it, put it into your hand, then shuffle your library. + this.addAbility(new EntersBattlefieldTriggeredAbility( + new SearchLibraryPutInHandEffect(new TargetCardInLibrary(filter), true) + )); + + // Spirit of the Aldergard gets +1/+0 for each other snow permanent you control. + this.addAbility(new SimpleStaticAbility(new BoostSourceEffect( + xValue, StaticValue.get(0), Duration.WhileOnBattlefield + ))); + } + + private SpiritOfTheAldergard(final SpiritOfTheAldergard card) { + super(card); + } + + @Override + public SpiritOfTheAldergard copy() { + return new SpiritOfTheAldergard(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Kaldheim.java b/Mage.Sets/src/mage/sets/Kaldheim.java index 71aabb538b5..be7bd0de9bb 100644 --- a/Mage.Sets/src/mage/sets/Kaldheim.java +++ b/Mage.Sets/src/mage/sets/Kaldheim.java @@ -111,6 +111,7 @@ public final class Kaldheim extends ExpansionSet { cards.add(new SetCardInfo("Snow-Covered Plains", 276, Rarity.LAND, mage.cards.s.SnowCoveredPlains.class)); cards.add(new SetCardInfo("Snow-Covered Swamp", 280, Rarity.LAND, mage.cards.s.SnowCoveredSwamp.class)); cards.add(new SetCardInfo("Snowfield Sinkhole", 269, Rarity.COMMON, mage.cards.s.SnowfieldSinkhole.class)); + cards.add(new SetCardInfo("Spirit of the Aldergard", 195, Rarity.UNCOMMON, mage.cards.s.SpiritOfTheAldergard.class)); cards.add(new SetCardInfo("Starnheim Aspirant", 380, Rarity.UNCOMMON, mage.cards.s.StarnheimAspirant.class)); cards.add(new SetCardInfo("Sulfurous Mine", 270, Rarity.COMMON, mage.cards.s.SulfurousMine.class)); cards.add(new SetCardInfo("Surtland Elementalist", 375, Rarity.RARE, mage.cards.s.SurtlandElementalist.class)); From 01261575a80dc4e00dfbabf7fee13de6785e13ea Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Sun, 10 Jan 2021 15:24:42 -0500 Subject: [PATCH 03/20] [KHM] Niko Aris --- Mage.Sets/src/mage/cards/n/NikoAris.java | 180 ++++++++++++++++++ Mage.Sets/src/mage/sets/Kaldheim.java | 1 + .../src/main/java/mage/constants/SubType.java | 2 + .../mage/game/permanent/token/ShardToken.java | 39 ++++ 4 files changed, 222 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/n/NikoAris.java create mode 100644 Mage/src/main/java/mage/game/permanent/token/ShardToken.java diff --git a/Mage.Sets/src/mage/cards/n/NikoAris.java b/Mage.Sets/src/mage/cards/n/NikoAris.java new file mode 100644 index 00000000000..d6240a7374f --- /dev/null +++ b/Mage.Sets/src/mage/cards/n/NikoAris.java @@ -0,0 +1,180 @@ +package mage.cards.n; + +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.MultipliedValue; +import mage.abilities.dynamicvalue.common.CardsDrawnThisTurnDynamicValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.abilities.effects.common.combat.CantBeBlockedTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.token.ShardToken; +import mage.game.stack.Spell; +import mage.target.TargetPermanent; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.watchers.Watcher; +import mage.watchers.common.CardsDrawnThisTurnWatcher; + +import java.util.Objects; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class NikoAris extends CardImpl { + + private static final FilterPermanent filter = new FilterCreaturePermanent("tapped creature"); + + static { + filter.add(TappedPredicate.instance); + } + + private static final DynamicValue xValue = new MultipliedValue(CardsDrawnThisTurnDynamicValue.instance, 2); + + public NikoAris(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{X}{W}{U}{U}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.NIKO); + this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(3)); + + // When Niko Aris enters the battlefield, create X Shard tokens. + this.addAbility(new EntersBattlefieldTriggeredAbility( + new CreateTokenEffect(new ShardToken(), NikoArisValue.instance) + ), new NikoArisWatcher()); + + // +1: Up to one target creature you control can't be blocked this turn. Whenever that creature deals damage this turn, return it to its owner's hand. + Ability ability = new LoyaltyAbility(new CantBeBlockedTargetEffect(Duration.EndOfTurn), 1); + ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new NikoArisDamageTriggeredAbility())); + ability.addTarget(new TargetControlledCreaturePermanent(0, 1)); + this.addAbility(ability); + + // −1: Niko Aris deals 2 damage to target tapped creature for each card you've drawn this turn. + ability = new LoyaltyAbility(new DamageTargetEffect(xValue).setText( + "{this} deals 2 damage to target tapped creature for each card you've drawn this turn" + ), -1); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability, new CardsDrawnThisTurnWatcher()); + + // −1: Create a Shard token. + this.addAbility(new LoyaltyAbility(new CreateTokenEffect(new ShardToken()), -1)); + } + + private NikoAris(final NikoAris card) { + super(card); + } + + @Override + public NikoAris copy() { + return new NikoAris(this); + } +} + +enum NikoArisValue implements DynamicValue { + instance; + + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + NikoArisWatcher watcher = game.getState().getWatcher(NikoArisWatcher.class, sourceAbility.getSourceId()); + if (watcher == null) { + return 0; + } + if (game.getState().getValue(sourceAbility.getSourceId().toString() + "xValue") == null) { + return 0; + } + return (Integer) game.getState().getValue(sourceAbility.getSourceId().toString() + "xValue"); + } + + @Override + public DynamicValue copy() { + return instance; + } + + @Override + public String toString() { + return "X"; + } + + @Override + public String getMessage() { + return ""; + } +} + +class NikoArisWatcher extends Watcher { + + NikoArisWatcher() { + super(WatcherScope.CARD); + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() != GameEvent.EventType.SPELL_CAST) { + return; + } + Spell spell = game.getSpellOrLKIStack(event.getTargetId()); + if (spell == null || spell.getSourceId() != super.getSourceId()) { + return; + } + game.getState().setValue( + spell.getSourceId().toString() + "xValue", + spell.getSpellAbility().getManaCostsToPay().getX() + ); + } +} + +class NikoArisDamageTriggeredAbility extends DelayedTriggeredAbility { + + NikoArisDamageTriggeredAbility() { + super(new ReturnToHandTargetEffect(), Duration.EndOfTurn, false); + } + + private NikoArisDamageTriggeredAbility(final NikoArisDamageTriggeredAbility ability) { + super(ability); + } + + @Override + public NikoArisDamageTriggeredAbility copy() { + return new NikoArisDamageTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + switch (event.getType()) { + case DAMAGED_PLAYER: + case DAMAGED_CREATURE: + case DAMAGED_PLANESWALKER: + return true; + } + return false; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return this.getEffects() + .stream() + .filter(Objects::nonNull) + .map(Effect::getTargetPointer) + .map(targetPointer -> targetPointer.getFirst(game, this)) + .anyMatch(event.getSourceId()::equals); + } + + @Override + public String getRule() { + return "Whenever that creature deals damage this turn, return it to its owner's hand."; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/Kaldheim.java b/Mage.Sets/src/mage/sets/Kaldheim.java index be7bd0de9bb..3e180e84b8e 100644 --- a/Mage.Sets/src/mage/sets/Kaldheim.java +++ b/Mage.Sets/src/mage/sets/Kaldheim.java @@ -91,6 +91,7 @@ public final class Kaldheim extends ExpansionSet { cards.add(new SetCardInfo("Koma's Faithful", 102, Rarity.COMMON, mage.cards.k.KomasFaithful.class)); cards.add(new SetCardInfo("Magda, Brazen Outlaw", 142, Rarity.RARE, mage.cards.m.MagdaBrazenOutlaw.class)); cards.add(new SetCardInfo("Masked Vandal", 184, Rarity.COMMON, mage.cards.m.MaskedVandal.class)); + cards.add(new SetCardInfo("Niko Aris", 225, Rarity.MYTHIC, mage.cards.n.NikoAris.class)); cards.add(new SetCardInfo("Pyre of Heroes", 241, Rarity.RARE, mage.cards.p.PyreOfHeroes.class)); cards.add(new SetCardInfo("Rampage of the Valkyries", 393, Rarity.UNCOMMON, mage.cards.r.RampageOfTheValkyries.class)); cards.add(new SetCardInfo("Ravenform", 72, Rarity.COMMON, mage.cards.r.Ravenform.class)); diff --git a/Mage/src/main/java/mage/constants/SubType.java b/Mage/src/main/java/mage/constants/SubType.java index 4682c8bda60..4f355e2a232 100644 --- a/Mage/src/main/java/mage/constants/SubType.java +++ b/Mage/src/main/java/mage/constants/SubType.java @@ -33,6 +33,7 @@ public enum SubType { CARTOUCHE("Cartouche", SubTypeSet.EnchantmentType), CURSE("Curse", SubTypeSet.EnchantmentType), SAGA("Saga", SubTypeSet.EnchantmentType), + SHARD("Shard", SubTypeSet.EnchantmentType), SHRINE("Shrine", SubTypeSet.EnchantmentType), // 205.3g: Artifacts have their own unique set of subtypes; these subtypes are called artifact types. CLUE("Clue", SubTypeSet.ArtifactType), @@ -415,6 +416,7 @@ public enum SubType { LUKKA("Lukka", SubTypeSet.PlaneswalkerType), NAHIRI("Nahiri", SubTypeSet.PlaneswalkerType), NARSET("Narset", SubTypeSet.PlaneswalkerType), + NIKO("Niko", SubTypeSet.PlaneswalkerType), NISSA("Nissa", SubTypeSet.PlaneswalkerType), NIXILIS("Nixilis", SubTypeSet.PlaneswalkerType), OBI_WAN("Obi-Wan", SubTypeSet.PlaneswalkerType, true), // Star Wars diff --git a/Mage/src/main/java/mage/game/permanent/token/ShardToken.java b/Mage/src/main/java/mage/game/permanent/token/ShardToken.java new file mode 100644 index 00000000000..9c075b815dc --- /dev/null +++ b/Mage/src/main/java/mage/game/permanent/token/ShardToken.java @@ -0,0 +1,39 @@ +package mage.game.permanent.token; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.keyword.ScryEffect; +import mage.constants.CardType; +import mage.constants.SubType; + +/** + * @author TheElk801 + */ + +public final class ShardToken extends TokenImpl { + + public ShardToken() { + super("Shard", "Shard token"); + cardType.add(CardType.ENCHANTMENT); + subtype.add(SubType.SHARD); + + // {2}, Sacrifice this enchantment: Scry 1, then draw a card. + Ability ability = new SimpleActivatedAbility(new ScryEffect(1), new GenericManaCost(2)); + ability.addEffect(new DrawCardSourceControllerEffect(1).concatBy(", then")); + SacrificeSourceCost cost = new SacrificeSourceCost(); + cost.setText("Sacrifice this enchantment"); + ability.addCost(cost); + this.addAbility(ability); + } + + public ShardToken(final ShardToken token) { + super(token); + } + + public ShardToken copy() { + return new ShardToken(this); + } +} From dcf3a8a88f24433c114e187bd1fc468d46b1d194 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Sun, 10 Jan 2021 18:04:19 -0500 Subject: [PATCH 04/20] [KHM] updated spoiler and reprints --- Mage.Sets/src/mage/sets/Kaldheim.java | 2 ++ Utils/mtg-cards-data.txt | 10 +++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/Kaldheim.java b/Mage.Sets/src/mage/sets/Kaldheim.java index 3e180e84b8e..8ce95361075 100644 --- a/Mage.Sets/src/mage/sets/Kaldheim.java +++ b/Mage.Sets/src/mage/sets/Kaldheim.java @@ -19,6 +19,7 @@ public final class Kaldheim extends ExpansionSet { "Cosmos Charger", "Doomskar Oracle", "Gods' Hall Guardian", + "Kaya's Onslaught", "Quakebringer", "Ranar the Ever-Watchful", "Ravenform", @@ -48,6 +49,7 @@ public final class Kaldheim extends ExpansionSet { cards.add(new SetCardInfo("Absorb Identity", 383, Rarity.UNCOMMON, mage.cards.a.AbsorbIdentity.class)); cards.add(new SetCardInfo("Alpine Meadow", 248, Rarity.COMMON, mage.cards.a.AlpineMeadow.class)); cards.add(new SetCardInfo("Alrund's Epiphany", 41, Rarity.MYTHIC, mage.cards.a.AlrundsEpiphany.class)); + cards.add(new SetCardInfo("Annul", 42, Rarity.COMMON, mage.cards.a.Annul.class)); cards.add(new SetCardInfo("Arctic Treeline", 249, Rarity.COMMON, mage.cards.a.ArcticTreeline.class)); cards.add(new SetCardInfo("Armed and Armored", 379, Rarity.UNCOMMON, mage.cards.a.ArmedAndArmored.class)); cards.add(new SetCardInfo("Augury Raven", 44, Rarity.COMMON, mage.cards.a.AuguryRaven.class)); diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 40fccf28173..4d671fae8b4 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -40023,10 +40023,12 @@ Doomskar Oracle|Kaldheim|10|C|{2}{W}|Creature - Human Cleric|3|2|Whenever you ca Gods' Hall Guardian|Kaldheim|13|C|{5}{W}|Creature - Cat|3|6|Vigilance$Foretell {3}{W}| Halvar, God of Battle|Kaldheim|15|M|{2}{W}{W}|Legendary Creature - God|4|4|Creatures you control that are enchanted or equipped have double strike.$At the beginning of each combat, you may attach target Aura or Equipment attached to a creature you control to target creature you control.| Sword of the Realms|Kaldheim|15|M|{1}{W}|Legendary Artifact - Equipment|||Equipped creature gets +2/+0 and has vigilance.$Whenever equipped creature dies, return it to its owner's hand.$Equip {1}{W}| +Kaya's Onslaught|Kaldheim|18|U|{2}{W}|Instant|||Target creature gets +1/+1 and gains double strike until end of turn.$Foretell {W}| Sigrid, God-Favored|Kaldheim|29|R|{1}{W}{W}|Legendary Creature - Human Warrior|2|2|Flash$First strike, protection from God creatures$When Sigrid, God-Favored enters the battlefield, exile up to one target attacking or blocking creature until Sigrid leaves the battlefield.| Alrund, God of the Cosmos|Kaldheim|40|M|{3}{U}{U}|Legendary Creature - God|1|1|Alrund gets +1/+1 for each card in your hand and each foretold card you own in exile.$At the beginning of your end step, choose a card type, then reveal the top two cards of your library. Put all cards of the chosen type into your hand and the rest on the bottom of your library in any order.| Hakka, Whispering Raven|Kaldheim|40|M|{1}{U}|Legendary Creature - Bird|2|3|Flying$Whenever Hakka, Whispering Raven deals combat damage to a player, return it to its owner's hand, then scry 2.| Alrund's Epiphany|Kaldheim|41|M|{5}{U}{U}|Sorcery|||Create two 1/1 blue Bird creature tokens with flying. Take an extra turn after this one. Exile Alrund's Epiphany.$Foretell {4}{U}{U}| +Annul|Kaldheim|42|C|{U}|Instant|||Counter target artifact or enchantment spell.| Augury Raven|Kaldheim|44|C|{3}{U}|Creature - Bird|3|3|Flying$Foretell {1}{U}| Behold the Multiverse|Kaldheim|46|C|{3}{U}|Instant|||Scry 2, then draw two cards.$Foretell {1}{U}| Cosmos Charger|Kaldheim|51|R|{3}{U}|Creature - Horse Spirit|3|3|Flash$Flying$Foretelling cards from your hand costs {1} less and can be done on any player's turn.$Foretell {2}{U}| @@ -40037,6 +40039,8 @@ Ravenform|Kaldheim|72|C|{2}{U}|Sorcery|||Exile target artifact or creature. Its Reflections of Littjara|Kaldheim|73|R|{4}{U}|Enchantment|||As Reflections of Littjara enters the battlefield, choose a creature type.$Whenever you cast a spell of the chosen type, copy that spell.| Saw It Coming|Kaldheim|76|U|{1}{U}{U}|Instant|||Counter target spell.$Foretell {1}{U}| Undersea Invader|Kaldheim|78|C|{4}{U}{U}|Creature - Giant Rogue|5|6|Flash$Undersea Invader enters the battlefield tapped.| +Draugr Necromancer|Kaldheim|86|R|{3}{B}|Snow Creature - Zombie Cleric|4|4|If a nontoken creature an opponent controls would die, exile that card with an ice counter on it instead.$You may cast spells from among cards in exile your opponents own with ice counters on them, and you may spend mana from snow sources as through it were mana of any color to cast those spells.| +Eradicator Valkyrie|Kaldheim|94|M|{2}{B}{B}|Creature - Angel Berserker|4|3|Flying, lifelink, hexproof from planeswalkers$Boast — {1}{B}, Sacrifice a creature: Each opponent sacrifices a creature or planeswalker| Hailstorm Valkyrie|Kaldheim|97|U|{3}{B}|Snow Creature - Angel Wizard|2|2|Flying, trample${S}{S}: Hailstorm Valkyrie gets +2/+2 until end of turn.| Koma's Faithful|Kaldheim|102|C|{2}{B}|Creature - Elf Cleric|3|1|Lifelink$When Koma's Faithful dies, each player mills three cards.| Tergrid's Lantern|Kaldheim|112|R|{3}{B}|Legendary Artifact|||{T}: Target player loses 3 life unless they sacrifice a nonland permanent or discard a card.${3}{B}: Untap Tergrid's Lantern.| @@ -40048,9 +40052,10 @@ Village Rites|Kaldheim|117|C|{B}|Instant|||As an additional cost to cast this sp Calamity Bearer|Kaldheim|125|R|{2}{R}{R}|Creature - Giant Berserker|3|4|If a Giant source you control would deal damage to a permanent or player, it deals double that damage to that permanent or player instead.| Frost Bite|Kaldheim|138|C|{R}|Snow Instant|||Frost Bite deals 2 damage to target creature or planeswalker. If you control three or more snow permanents, it deals 3 damage instead.| Goldspan Dragon|Kaldheim|139|M|{3}{R}{R}|Creature - Dragon|4|4|Flying, haste$Whenever Goldspan Dragon attacks or becomes the target of a spell, create a Treasure token.$Treasures you control have "{T}, Sacrifice this artifact: Add two mana of any one color."| +Hagi Mob|Kaldheim|140|C|{4}{R}|Creature - Troll Berserker|5|4|Boast — {1}{R}: Hagi Mob deals 1 damage to any target.| Magda, Brazen Outlaw|Kaldheim|142|R|{1}{R}|Legendary Creature - Dwarf Berserker|2|1|Other Dwarves you control get +1/+0.$Whenever a Dwarf you control becomes tapped, create a Treasure token.$Sacrifice five Treasures: Search your library for an artifact or Dragon card, put that card onto the battlefield, then shuffle your library.| Quakebringer|Kaldheim|145|M|{3}{R}{R}|Creature - Giant Berserker|5|4|Your opponents can't gain life.$At the beginning of your upkeep, Quakebringer deals 2 damage to each opponent. This ability triggers only if Quakebringer is on the battlefield or if Quakebringer is in your graveyard and you control a Giant.$Foretell {2}{R}{R}| -Reckless Crew|Kaldheim|148|R|{3}{R}|Sorcery|||Create X 2/1 red Dwarf creature tokens,where X is the number of Vehicles you control plus the number of Equipment you control.$For each of those tokens, You may attach an Equipment you control to it.| +Reckless Crew|Kaldheim|148|R|{3}{R}|Sorcery|||Create X 2/1 red Dwarf creature tokens, where X is the number of Vehicles you control plus the number of Equipments you control. For each of those tokens, you may attach an Equipment you control to it.| Seize the Spoils|Kaldheim|149|C|{2}{R}|Sorcery|||As an additional cost to cast this spell, discard a card.$Draw two cards and create a Treasure token.| Broken Wings|Kaldheim|164|C|{2}{G}|Instant|||Destroy target artifact, enchantment, or creature with flying.| Elvish Warmaster|Kaldheim|167|R|{1}{G}|Creature - Elf Warrior|2|2|Whenever one or more other Elves enters the battlefield under your control, create a 1/1 green Elf Warrior creature token. This ability triggers only once each turn.${5}{G}{G}: Elves you control get +2/+2 and gain deathtouch until end of turn.| @@ -40065,6 +40070,7 @@ Path to the World Tree|Kaldheim|186|U|{1}{G}|Enchantment|||When Path to the Worl Realmwalker|Kaldheim|188|R|{2}{G}|Creature - Shapeshifter|2|3|Changeling$As Realmwalker enters the battlefield, choose a creature type.$You may look at the top card of your library any time.$You may cast creature spells of the chosen type from the top of your library.| Sarulf's Packmate|Kaldheim|192|C|{3}{G}|Creature - Wolf|3|3|When Sarulf's Packmate enters the battlefield, draw a card.$Foretell {1}{G}| Sculptor of Winter|Kaldheim|193|C|{1}{G}|Snow Creature - Elf Rogue|2|2|{T}: Untap target snow land.| +Snakeskin Veil|Kaldheim|194|C|{G}|Instant|||Put a +1/+1 counter on target creature you control. It gains hexproof until end of turn.| Spirit of the Aldergard|Kaldheim|195|U|{3}{G}|Snow Creature - Bear Spirit|0|4|When Spirit of the Aldergard enters the battlefield, search your library for a snow land card, reveal it, put it into your hand, then shuffle your library.$Spirit of the Aldergard gets +1/+0 for each other snow permanent you control.| Toski, Bearer of Secrets|Kaldheim|197|R|{3}{G}|Legendary Creature - Squirrel|1|1|This spell can't be countered.$Indestructible$Toski, Bearer of Secrets attacks each combat if able.$Whenever a creature you control deals combat damage to a player, draw a card.| Vorinclex, Monstrous Raider|Kaldheim|199|M|{4}{G}{G}|Legendary Creature - Phyrexian Praetor|6|6|Trample, haste$If you would put one or more counters on a permanent or player, put twice that many of each of those kinds of counters on that permanent or player instead.$If an opponent would put one or more counters on a permanent or player, they put half that many of each of those kinds of counters on that permanent or player instead, rounded down.| @@ -40080,6 +40086,7 @@ Sarulf, Realm Eater|Kaldheim|228|R|{1}{B}{G}|Legendary Creature - Wolf|3|3|Whene Showdown of the Skalds|Kaldheim|229|R|{2}{R}{W}|Enchantment - Saga|||(As this Saga enters and after your draw step, add a lore counter. Sacrifice after III.)$I — Exile the top four cards of your library. Until the end of your next turn, you may play those cards.$II, III — Whenever you cast a spell this turn, put a +1/+1 counter on target creature you control.| The Trickster-God's Heist|Kaldheim|232|U|{2}{U}{B}|Enchantment - Saga|||(As this Saga enters and after your draw step, add a lore counter. Sacrifice after III.)$I — You may exchange control of two target creatures.$II — You may exchange control of two target nonbasic, noncreature permanents that share a card type.$III — Target player loses 3 life and you gain 3 life.| Vega, the Watcher|Kaldheim|233|U|{1}{W}{U}|Legendary Creature - Bird Spirit|2|2|Flying$Whenever you cast a spell from anywhere other than your hand, draw a card.| +Maskwood Nexus|Kaldheim|240|R|{4}|Artifact|||Creatures you control are every creature type. The same is true for creature spells you control and creature cards you own that aren't on the battlefield.${3}, {T}: Create a 2/2 blue Shapeshifter creature token with changeling.| Pyre of Heroes|Kaldheim|241|R|{2}|Artifact|||{2}, {T}, Sacrifice a creature: Search your library for a creature card that shares a creature type with the sacrificed creature and has converted mana cost equal to 1 plus that creature's converted mana cost. Put that card onto the battlefield, then shuffle your library. Activate this ability only any time you could cast a sorcery.| Replicating Ring|Kaldheim|244|U|{3}|Snow Artifact|||{T}: Add one mana of any color.$At the beginning of your upkeep, put a night counter on Replicating Ring. Then if it has eight or more night counters on it, remove all of them and create eight colorless snow artifact tokens named Replicated Ring with "{T}: Add one mana of any color."| Alpine Meadow|Kaldheim|248|C||Snow Land - Mountain Plains|||({T}: Add {R} or {W}.)$Alpine Meadow enters the battlefield tapped.| @@ -40091,6 +40098,7 @@ Searstep Pathway|Kaldheim|252|R||Land|||{T}: Add {R}.| Bretagard Stronghold|Kaldheim|253|U||Land|||Bretagard Stronghold enters the battlefield tapped.${T}: Add {G}.${G}{W}{W}, {T}, Sacrifice Bretagard Stronghold: Put a +1/+1 counter on each of up to two target creatures you control. They gain vigilance and lifelink until end of turn. Activate this ability only any time you cast a sorcery.| Darkbore Pathway|Kaldheim|254|R||Land|||{T}: Add {B}.| Slitherbore Pathway|Kaldheim|254|R||Land|||{T}: Add {G}.| +Faceless Haven|Kaldheim|255|R||Snow Land|||{T}: Add {C}.${S}{S}{S}: Faceless Haven becomes a 4/3 creature with vigilance and all creature types until end of turn. It's still a land.| Glacial Floodplain|Kaldheim|257|C||Snow Land - Plains Island|||({T}: Add {W} or {U}.)$Glacial Floodplain enters the battlefield tapped.| Hengegate Pathway|Kaldheim|260|R||Land|||{T}: Add {W}.| Mistgate Pathway|Kaldheim|260|R||Land|||{T}: Add {U}.| From bb9a7ccc40b99e162adb15cab047288fcd020d57 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Sun, 10 Jan 2021 18:07:20 -0500 Subject: [PATCH 05/20] [KHM] Implemented Hagi Mob --- Mage.Sets/src/mage/cards/h/HagiMob.java | 43 +++++++++++++++++++++++++ Mage.Sets/src/mage/sets/Kaldheim.java | 1 + 2 files changed, 44 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/h/HagiMob.java diff --git a/Mage.Sets/src/mage/cards/h/HagiMob.java b/Mage.Sets/src/mage/cards/h/HagiMob.java new file mode 100644 index 00000000000..eec65407ac8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HagiMob.java @@ -0,0 +1,43 @@ +package mage.cards.h; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.keyword.BoastAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.target.common.TargetAnyTarget; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class HagiMob extends CardImpl { + + public HagiMob(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}"); + + this.subtype.add(SubType.TROLL); + this.subtype.add(SubType.BERSERKER); + this.power = new MageInt(5); + this.toughness = new MageInt(4); + + // Boast — {1}{R}: Hagi Mob deals 1 damage to any target. + Ability ability = new BoastAbility(new DamageTargetEffect(1), new ManaCostsImpl("{1}{R}")); + ability.addTarget(new TargetAnyTarget()); + this.addAbility(ability); + } + + private HagiMob(final HagiMob card) { + super(card); + } + + @Override + public HagiMob copy() { + return new HagiMob(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Kaldheim.java b/Mage.Sets/src/mage/sets/Kaldheim.java index 8ce95361075..72b5caabf80 100644 --- a/Mage.Sets/src/mage/sets/Kaldheim.java +++ b/Mage.Sets/src/mage/sets/Kaldheim.java @@ -81,6 +81,7 @@ public final class Kaldheim extends ExpansionSet { cards.add(new SetCardInfo("Gladewalker Ritualist", 392, Rarity.UNCOMMON, mage.cards.g.GladewalkerRitualist.class)); cards.add(new SetCardInfo("Gods' Hall Guardian", 13, Rarity.COMMON, mage.cards.g.GodsHallGuardian.class)); cards.add(new SetCardInfo("Goldspan Dragon", 139, Rarity.MYTHIC, mage.cards.g.GoldspanDragon.class)); + cards.add(new SetCardInfo("Hagi Mob", 140, Rarity.COMMON, mage.cards.h.HagiMob.class)); cards.add(new SetCardInfo("Hailstorm Valkyrie", 97, Rarity.UNCOMMON, mage.cards.h.HailstormValkyrie.class)); cards.add(new SetCardInfo("Halvar, God of Battle", 15, Rarity.MYTHIC, mage.cards.h.HalvarGodOfBattle.class)); cards.add(new SetCardInfo("Hengegate Pathway", 260, Rarity.RARE, mage.cards.h.HengegatePathway.class)); From 63c2f1493a08fe0a3e5f92d39be5d63103c19d87 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Sun, 10 Jan 2021 18:10:18 -0500 Subject: [PATCH 06/20] [KHM] Implemented Kaya's Onslaught --- .../src/mage/cards/k/KayasOnslaught.java | 44 +++++++++++++++++++ Mage.Sets/src/mage/sets/Kaldheim.java | 1 + 2 files changed, 45 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/k/KayasOnslaught.java diff --git a/Mage.Sets/src/mage/cards/k/KayasOnslaught.java b/Mage.Sets/src/mage/cards/k/KayasOnslaught.java new file mode 100644 index 00000000000..78adaf4b53a --- /dev/null +++ b/Mage.Sets/src/mage/cards/k/KayasOnslaught.java @@ -0,0 +1,44 @@ +package mage.cards.k; + +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.DoubleStrikeAbility; +import mage.abilities.keyword.ForetellAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class KayasOnslaught extends CardImpl { + + public KayasOnslaught(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}"); + + // Target creature gets +1/+1 and gains double strike until end of turn. + this.getSpellAbility().addEffect(new BoostTargetEffect( + 1, 1, Duration.EndOfTurn + ).setText("target creature gets +1/+1")); + this.getSpellAbility().addEffect(new GainAbilityTargetEffect( + DoubleStrikeAbility.getInstance(), Duration.EndOfTurn + ).setText("and gains double strike until end of turn")); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + + // Foretell {W} + this.addAbility(new ForetellAbility(this, "{W}")); + } + + private KayasOnslaught(final KayasOnslaught card) { + super(card); + } + + @Override + public KayasOnslaught copy() { + return new KayasOnslaught(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Kaldheim.java b/Mage.Sets/src/mage/sets/Kaldheim.java index 72b5caabf80..dd216071eaf 100644 --- a/Mage.Sets/src/mage/sets/Kaldheim.java +++ b/Mage.Sets/src/mage/sets/Kaldheim.java @@ -90,6 +90,7 @@ public final class Kaldheim extends ExpansionSet { cards.add(new SetCardInfo("Inga Rune-Eyes", 64, Rarity.UNCOMMON, mage.cards.i.IngaRuneEyes.class)); cards.add(new SetCardInfo("Invasion of the Giants", 215, Rarity.UNCOMMON, mage.cards.i.InvasionOfTheGiants.class)); cards.add(new SetCardInfo("Kaya the Inexorable", 218, Rarity.MYTHIC, mage.cards.k.KayaTheInexorable.class)); + cards.add(new SetCardInfo("Kaya's Onslaught", 18, Rarity.UNCOMMON, mage.cards.k.KayasOnslaught.class)); cards.add(new SetCardInfo("Koll, the Forgemaster", 220, Rarity.UNCOMMON, mage.cards.k.KollTheForgemaster.class)); cards.add(new SetCardInfo("Koma's Faithful", 102, Rarity.COMMON, mage.cards.k.KomasFaithful.class)); cards.add(new SetCardInfo("Magda, Brazen Outlaw", 142, Rarity.RARE, mage.cards.m.MagdaBrazenOutlaw.class)); From 2b5bb92bc6b2b7a3ca30a1d49ee4bfed00c2d17a Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Sun, 10 Jan 2021 18:12:46 -0500 Subject: [PATCH 07/20] [KHM] Implemented Snakeskin Veil --- Mage.Sets/src/mage/cards/s/SnakeskinVeil.java | 39 +++++++++++++++++++ Mage.Sets/src/mage/sets/Kaldheim.java | 1 + 2 files changed, 40 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/SnakeskinVeil.java diff --git a/Mage.Sets/src/mage/cards/s/SnakeskinVeil.java b/Mage.Sets/src/mage/cards/s/SnakeskinVeil.java new file mode 100644 index 00000000000..f021fc85ad9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SnakeskinVeil.java @@ -0,0 +1,39 @@ +package mage.cards.s; + +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.keyword.HexproofAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.counters.CounterType; +import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SnakeskinVeil extends CardImpl { + + public SnakeskinVeil(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{G}"); + + // Put a +1/+1 counter on target creature you control. It gains hexproof until end of turn. + this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.P1P1.createInstance())); + this.getSpellAbility().addEffect(new GainAbilityTargetEffect( + HexproofAbility.getInstance(), Duration.EndOfTurn + ).setText("It gains hexproof until end of turn")); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); + } + + private SnakeskinVeil(final SnakeskinVeil card) { + super(card); + } + + @Override + public SnakeskinVeil copy() { + return new SnakeskinVeil(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Kaldheim.java b/Mage.Sets/src/mage/sets/Kaldheim.java index dd216071eaf..58bf12b1332 100644 --- a/Mage.Sets/src/mage/sets/Kaldheim.java +++ b/Mage.Sets/src/mage/sets/Kaldheim.java @@ -110,6 +110,7 @@ public final class Kaldheim extends ExpansionSet { cards.add(new SetCardInfo("Seize the Spoils", 149, Rarity.COMMON, mage.cards.s.SeizeTheSpoils.class)); cards.add(new SetCardInfo("Showdown of the Skalds", 229, Rarity.RARE, mage.cards.s.ShowdownOfTheSkalds.class)); cards.add(new SetCardInfo("Sigrid, God-Favored", 29, Rarity.RARE, mage.cards.s.SigridGodFavored.class)); + cards.add(new SetCardInfo("Snakeskin Veil", 194, Rarity.COMMON, mage.cards.s.SnakeskinVeil.class)); cards.add(new SetCardInfo("Snow-Covered Forest", 284, Rarity.LAND, mage.cards.s.SnowCoveredForest.class)); cards.add(new SetCardInfo("Snow-Covered Island", 278, Rarity.LAND, mage.cards.s.SnowCoveredIsland.class)); cards.add(new SetCardInfo("Snow-Covered Mountain", 282, Rarity.LAND, mage.cards.s.SnowCoveredMountain.class)); From 99faeb6d1a66fac6ebec4253440defecee521f1f Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Sun, 10 Jan 2021 19:14:02 -0500 Subject: [PATCH 08/20] [KHM] updates spoiler --- Utils/mtg-cards-data.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 4d671fae8b4..32854c4b376 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -40035,12 +40035,13 @@ Cosmos Charger|Kaldheim|51|R|{3}{U}|Creature - Horse Spirit|3|3|Flash$Flying$For Giant's Amulet|Kaldheim|59|U|{U}|Artifact - Equipment|||When Giant's Amulet enters the battlefield, you may pay {3}{U}. If you do, create a 4/4 blue Giant Wizard creature token, then attach Giant's Amulet to it.$Equipped creature gets +0/+1 and has "This creature has hexproof as long as it's untapped."$Equip {2}| Glimpse the Cosmos|Kaldheim|60|U|{1}{U}|Sorcery|||Look at the top three cards of your library. Put one of them into your hand and the rest on the bottom of your library in any order.$As long as you control a Giant, you may cast Glimpse the Cosmos from your graveyard by paying {U} rather than paying its mana cost. If you cast Glimpse the Cosmos this way and it would be put into your graveyard, exile it instead.| Inga Rune-Eyes|Kaldheim|64|U|{3}{U}|Legendary Creature - Human Wizard|3|3|When Inga Rune-Eyes enters the battlefield, scry 3.$When Inga Rune-Eyes dies, draw three cards if three or more creatures died this turn.| +Littjara Kinseekers|Kaldheim|66|C|{3}{U}|Creature - Shapeshifter|2|4|Changeling (This card is every creature type.$When Littjara Kinseekers enters the battlefield, if you control three or more creatures that share a creature type, put a +1/+1 counter on Littjara Kinseekers, then scry 1.| Ravenform|Kaldheim|72|C|{2}{U}|Sorcery|||Exile target artifact or creature. Its controller creates a 1/1 blue Bird creature token with flying.$Foretell {U}| Reflections of Littjara|Kaldheim|73|R|{4}{U}|Enchantment|||As Reflections of Littjara enters the battlefield, choose a creature type.$Whenever you cast a spell of the chosen type, copy that spell.| Saw It Coming|Kaldheim|76|U|{1}{U}{U}|Instant|||Counter target spell.$Foretell {1}{U}| Undersea Invader|Kaldheim|78|C|{4}{U}{U}|Creature - Giant Rogue|5|6|Flash$Undersea Invader enters the battlefield tapped.| -Draugr Necromancer|Kaldheim|86|R|{3}{B}|Snow Creature - Zombie Cleric|4|4|If a nontoken creature an opponent controls would die, exile that card with an ice counter on it instead.$You may cast spells from among cards in exile your opponents own with ice counters on them, and you may spend mana from snow sources as through it were mana of any color to cast those spells.| -Eradicator Valkyrie|Kaldheim|94|M|{2}{B}{B}|Creature - Angel Berserker|4|3|Flying, lifelink, hexproof from planeswalkers$Boast — {1}{B}, Sacrifice a creature: Each opponent sacrifices a creature or planeswalker| +Draugr Necromancer|Kaldheim|86|R|{3}{B}|Snow Creature - Zombie Cleric|4|4|If a nontoken creature an opponent controls would die, exile that card with an ice counter on it instead.$You may cast spells from among cards in exile your opponents own with ice counters on them, and you may spend mana from snow sources as though it were mana of any color to cast those spells.| +Eradicator Valkyrie|Kaldheim|94|M|{2}{B}{B}|Creature - Angel Berserker|4|3|Flying, lifelink, hexproof from planeswalkers$Boast — {1}{B}, Sacrifice a creature: Each opponent sacrifices a creature or planeswalker.| Hailstorm Valkyrie|Kaldheim|97|U|{3}{B}|Snow Creature - Angel Wizard|2|2|Flying, trample${S}{S}: Hailstorm Valkyrie gets +2/+2 until end of turn.| Koma's Faithful|Kaldheim|102|C|{2}{B}|Creature - Elf Cleric|3|1|Lifelink$When Koma's Faithful dies, each player mills three cards.| Tergrid's Lantern|Kaldheim|112|R|{3}{B}|Legendary Artifact|||{T}: Target player loses 3 life unless they sacrifice a nonland permanent or discard a card.${3}{B}: Untap Tergrid's Lantern.| @@ -40062,6 +40063,7 @@ Elvish Warmaster|Kaldheim|167|R|{1}{G}|Creature - Elf Warrior|2|2|Whenever one o Esika, God of the Tree|Kaldheim|168|M|{1}{G}{G}|Legendary Creature - God|1|4|Vigilance${T}: Add one mana of any color.$Other legendary creatures you control have vigilance and "{T}: Add one mana of any color."| The Prismatic Bridge|Kaldheim|168|M|{W}{U}{B}{R}{G}|Legendary Enchantment|||At the beginning of your upkeep, reveal cards from the top of your library until you reveal a creature or planeswalker card. Put that card onto the battlefield and the rest on the bottom of your library in a random order.| Esika's Chariot|Kaldheim|169|R|{3}{G}|Legendary Artifact - Vehicle|4|4|When Esika's Chariot enters the battlefield, create two 2/2 green Cat creature tokens.$Whenever Esika's Chariot attacks, create a token that's a copy of target token you control.$Crew 4| +Guardian Gladewalker|Kaldheim|174|C|{1}{G}|Creature - Shapeshifter|1|1|Changeling$When Guardian Gladewalker enters the battlefield, put a +1/+1 counter on target creature.| Kolvori, God of Kinship|Kaldheim|181|R|{2}{G}{G}|Legendary Creature - God|2|4|As long as you control three or more legendary creatures, Kolvori, God of Kinship gets +4/+2 and has vigilance.${1}{G}, {T}: Look at the top six cards of your library. You may reveal a legendary creature card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.| The Ringheart Crest|Kaldheim|181|R|{1}{G}|Legendary Artifact|||As The Ringheart Crest enters the battlefield, choose a creature type.${T}: Add {G}. Spend this mana only to cast a creature spell of the chosen type or a legendary creature spell.| Masked Vandal|Kaldheim|184|C|{1}{G}|Creature - Shapeshifter|1|3|Changeling$When Masked Vandal enters the battlefield, you may exile a creature card from your graveyard. If you do, exile target artifact or enchantment an opponent controls.| @@ -40086,6 +40088,7 @@ Sarulf, Realm Eater|Kaldheim|228|R|{1}{B}{G}|Legendary Creature - Wolf|3|3|Whene Showdown of the Skalds|Kaldheim|229|R|{2}{R}{W}|Enchantment - Saga|||(As this Saga enters and after your draw step, add a lore counter. Sacrifice after III.)$I — Exile the top four cards of your library. Until the end of your next turn, you may play those cards.$II, III — Whenever you cast a spell this turn, put a +1/+1 counter on target creature you control.| The Trickster-God's Heist|Kaldheim|232|U|{2}{U}{B}|Enchantment - Saga|||(As this Saga enters and after your draw step, add a lore counter. Sacrifice after III.)$I — You may exchange control of two target creatures.$II — You may exchange control of two target nonbasic, noncreature permanents that share a card type.$III — Target player loses 3 life and you gain 3 life.| Vega, the Watcher|Kaldheim|233|U|{1}{W}{U}|Legendary Creature - Bird Spirit|2|2|Flying$Whenever you cast a spell from anywhere other than your hand, draw a card.| +Bloodline Pretender|Kaldheim|235|U|{3}|Artifact Creature - Shapeshifter|2|2|Changeling$As Bloodline Pretender enters the battlefield, choose a creature type.$Whenever another creature of the chosen type enters the battlefield under your control, put a +1/+1 counter on Bloodline Pretender.| Maskwood Nexus|Kaldheim|240|R|{4}|Artifact|||Creatures you control are every creature type. The same is true for creature spells you control and creature cards you own that aren't on the battlefield.${3}, {T}: Create a 2/2 blue Shapeshifter creature token with changeling.| Pyre of Heroes|Kaldheim|241|R|{2}|Artifact|||{2}, {T}, Sacrifice a creature: Search your library for a creature card that shares a creature type with the sacrificed creature and has converted mana cost equal to 1 plus that creature's converted mana cost. Put that card onto the battlefield, then shuffle your library. Activate this ability only any time you could cast a sorcery.| Replicating Ring|Kaldheim|244|U|{3}|Snow Artifact|||{T}: Add one mana of any color.$At the beginning of your upkeep, put a night counter on Replicating Ring. Then if it has eight or more night counters on it, remove all of them and create eight colorless snow artifact tokens named Replicated Ring with "{T}: Add one mana of any color."| From 746c20356596fa12b411382dc3f47d85f7ef03a6 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Sun, 10 Jan 2021 19:19:34 -0500 Subject: [PATCH 09/20] [KHM] Implemented Guardian Gladewalker --- .../src/mage/cards/g/GuardianGladewalker.java | 49 +++++++++++++++++++ Mage.Sets/src/mage/sets/Kaldheim.java | 1 + 2 files changed, 50 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/g/GuardianGladewalker.java diff --git a/Mage.Sets/src/mage/cards/g/GuardianGladewalker.java b/Mage.Sets/src/mage/cards/g/GuardianGladewalker.java new file mode 100644 index 00000000000..5a31053888f --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GuardianGladewalker.java @@ -0,0 +1,49 @@ +package mage.cards.g; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.keyword.ChangelingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.counters.CounterType; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class GuardianGladewalker extends CardImpl { + + public GuardianGladewalker(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); + + this.subtype.add(SubType.SHAPESHIFTER); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Changeling + this.isAllCreatureTypes(); + this.addAbility(ChangelingAbility.getInstance()); + + // When Guardian Gladewalker enters the battlefield, put a +1/+1 counter on target creature. + Ability ability = new EntersBattlefieldTriggeredAbility( + new AddCountersTargetEffect(CounterType.P1P1.createInstance()) + ); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + private GuardianGladewalker(final GuardianGladewalker card) { + super(card); + } + + @Override + public GuardianGladewalker copy() { + return new GuardianGladewalker(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Kaldheim.java b/Mage.Sets/src/mage/sets/Kaldheim.java index 58bf12b1332..f0145504ccd 100644 --- a/Mage.Sets/src/mage/sets/Kaldheim.java +++ b/Mage.Sets/src/mage/sets/Kaldheim.java @@ -81,6 +81,7 @@ public final class Kaldheim extends ExpansionSet { cards.add(new SetCardInfo("Gladewalker Ritualist", 392, Rarity.UNCOMMON, mage.cards.g.GladewalkerRitualist.class)); cards.add(new SetCardInfo("Gods' Hall Guardian", 13, Rarity.COMMON, mage.cards.g.GodsHallGuardian.class)); cards.add(new SetCardInfo("Goldspan Dragon", 139, Rarity.MYTHIC, mage.cards.g.GoldspanDragon.class)); + cards.add(new SetCardInfo("Guardian Gladewalker", 174, Rarity.COMMON, mage.cards.g.GuardianGladewalker.class)); cards.add(new SetCardInfo("Hagi Mob", 140, Rarity.COMMON, mage.cards.h.HagiMob.class)); cards.add(new SetCardInfo("Hailstorm Valkyrie", 97, Rarity.UNCOMMON, mage.cards.h.HailstormValkyrie.class)); cards.add(new SetCardInfo("Halvar, God of Battle", 15, Rarity.MYTHIC, mage.cards.h.HalvarGodOfBattle.class)); From 6d91ee69d42eabaa6241da39f3ee7114f7845379 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Sun, 10 Jan 2021 19:24:29 -0500 Subject: [PATCH 10/20] added test to check for changeling cards having isAllCreatureTypes set to true --- Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java index 05a53c95aec..8e1bc2b7f60 100644 --- a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java +++ b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java @@ -1301,6 +1301,10 @@ public class VerifyCardDataTest { if (card.getAbilities().toArray().length == 1) { // all cards have 1 inner ability to cast fail(card, "abilities", "card's abilities is empty, but ref have text"); } + + if (card.getAbilities().contains(ChangelingAbility.getInstance()) && !card.isAllCreatureTypes()) { + fail(card, "abilities", "card has changeling ability but doesn't have isAllCreatureTypes"); + } } private void checkWrongSymbolsInRules(Card card) { From 0943ae1bb7cf075cab76e10d9e3efaf1c8c281d6 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Sun, 10 Jan 2021 19:38:48 -0500 Subject: [PATCH 11/20] Revert "added test to check for changeling cards having isAllCreatureTypes set to true" This reverts commit 6d91ee69d42eabaa6241da39f3ee7114f7845379. --- Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java index 8e1bc2b7f60..05a53c95aec 100644 --- a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java +++ b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java @@ -1301,10 +1301,6 @@ public class VerifyCardDataTest { if (card.getAbilities().toArray().length == 1) { // all cards have 1 inner ability to cast fail(card, "abilities", "card's abilities is empty, but ref have text"); } - - if (card.getAbilities().contains(ChangelingAbility.getInstance()) && !card.isAllCreatureTypes()) { - fail(card, "abilities", "card has changeling ability but doesn't have isAllCreatureTypes"); - } } private void checkWrongSymbolsInRules(Card card) { From e7a557f287206d0601934d33197599e133848779 Mon Sep 17 00:00:00 2001 From: Daniel Bomar Date: Sun, 10 Jan 2021 19:36:32 -0600 Subject: [PATCH 12/20] [KHM] Implemented Vega, the Watcher (#7366) --- .../src/mage/cards/v/VegaTheWatcher.java | 70 +++++++++++++++++++ Mage.Sets/src/mage/sets/Kaldheim.java | 1 + .../SpellCastControllerTriggeredAbility.java | 4 +- 3 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/v/VegaTheWatcher.java diff --git a/Mage.Sets/src/mage/cards/v/VegaTheWatcher.java b/Mage.Sets/src/mage/cards/v/VegaTheWatcher.java new file mode 100644 index 00000000000..3ea2d993e05 --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VegaTheWatcher.java @@ -0,0 +1,70 @@ +package mage.cards.v; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; + +/** + * + * @author weirddan455 + */ +public final class VegaTheWatcher extends CardImpl { + + public VegaTheWatcher(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{U}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.BIRD); + this.subtype.add(SubType.SPIRIT); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Whenever you cast a spell from anywhere other than your hand, draw a card. + this.addAbility(new VegaTheWatcherTriggeredAbility(new DrawCardSourceControllerEffect(1), false)); + } + + private VegaTheWatcher(final VegaTheWatcher card) { + super(card); + } + + @Override + public VegaTheWatcher copy() { + return new VegaTheWatcher(this); + } +} + +class VegaTheWatcherTriggeredAbility extends SpellCastControllerTriggeredAbility { + + public VegaTheWatcherTriggeredAbility(Effect effect, boolean optional) { + super(effect, optional); + this.rule = "Whenever you cast a spell from anywhere other than your hand, draw a card."; + } + + public VegaTheWatcherTriggeredAbility(final VegaTheWatcherTriggeredAbility ability) { + super(ability); + } + + @Override + public VegaTheWatcherTriggeredAbility copy() { + return new VegaTheWatcherTriggeredAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return event.getZone() != Zone.HAND && super.checkTrigger(event, game); + } +} diff --git a/Mage.Sets/src/mage/sets/Kaldheim.java b/Mage.Sets/src/mage/sets/Kaldheim.java index f0145504ccd..a44b52d43b3 100644 --- a/Mage.Sets/src/mage/sets/Kaldheim.java +++ b/Mage.Sets/src/mage/sets/Kaldheim.java @@ -130,6 +130,7 @@ public final class Kaldheim extends ExpansionSet { cards.add(new SetCardInfo("Undersea Invader", 78, Rarity.COMMON, mage.cards.u.UnderseaInvader.class)); cards.add(new SetCardInfo("Valkyrie Harbinger", 374, Rarity.RARE, mage.cards.v.ValkyrieHarbinger.class)); cards.add(new SetCardInfo("Varragoth, Bloodsky Sire", 115, Rarity.RARE, mage.cards.v.VarragothBloodskySire.class)); + cards.add(new SetCardInfo("Vega, the Watcher", 233, Rarity.UNCOMMON, mage.cards.v.VegaTheWatcher.class)); cards.add(new SetCardInfo("Village Rites", 117, Rarity.COMMON, mage.cards.v.VillageRites.class)); cards.add(new SetCardInfo("Volatile Fjord", 273, Rarity.COMMON, mage.cards.v.VolatileFjord.class)); cards.add(new SetCardInfo("Warchanter Skald", 381, Rarity.UNCOMMON, mage.cards.w.WarchanterSkald.class)); diff --git a/Mage/src/main/java/mage/abilities/common/SpellCastControllerTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/SpellCastControllerTriggeredAbility.java index c4b34b53d56..4816d97da35 100644 --- a/Mage/src/main/java/mage/abilities/common/SpellCastControllerTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/SpellCastControllerTriggeredAbility.java @@ -4,6 +4,7 @@ import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.Effect; import mage.constants.Zone; import mage.filter.FilterSpell; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.stack.Spell; @@ -14,7 +15,6 @@ import mage.target.targetpointer.FixedTarget; */ public class SpellCastControllerTriggeredAbility extends TriggeredAbilityImpl { - private static final FilterSpell spellCard = new FilterSpell("a spell"); protected FilterSpell filter; protected String rule; @@ -25,7 +25,7 @@ public class SpellCastControllerTriggeredAbility extends TriggeredAbilityImpl { protected boolean rememberSource = false; public SpellCastControllerTriggeredAbility(Effect effect, boolean optional) { - this(Zone.BATTLEFIELD, effect, spellCard, optional, false); + this(Zone.BATTLEFIELD, effect, StaticFilters.FILTER_SPELL_A, optional, false); } public SpellCastControllerTriggeredAbility(Effect effect, FilterSpell filter, boolean optional) { From 065dc3da0e87570e3471ffb11bedfb2f86296f4a Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Sun, 10 Jan 2021 21:33:14 -0500 Subject: [PATCH 13/20] [KHM] Implemented Maskwood Nexus --- Mage.Sets/src/mage/cards/m/MaskwoodNexus.java | 147 ++++++++++++++++++ Mage.Sets/src/mage/sets/Kaldheim.java | 1 + .../token/ShapeshifterBlueToken.java | 31 ++++ 3 files changed, 179 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/m/MaskwoodNexus.java create mode 100644 Mage/src/main/java/mage/game/permanent/token/ShapeshifterBlueToken.java diff --git a/Mage.Sets/src/mage/cards/m/MaskwoodNexus.java b/Mage.Sets/src/mage/cards/m/MaskwoodNexus.java new file mode 100644 index 00000000000..e65c52e16a4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MaskwoodNexus.java @@ -0,0 +1,147 @@ +package mage.cards.m; + +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.GenericManaCost; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.game.Game; +import mage.game.command.CommandObject; +import mage.game.command.Commander; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.ShapeshifterBlueToken; +import mage.game.stack.Spell; +import mage.game.stack.StackObject; +import mage.players.Player; + +import java.util.Iterator; +import java.util.List; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class MaskwoodNexus extends CardImpl { + + public MaskwoodNexus(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); + + // Creatures you control are every creature type. The same is true for creature spells you control and creature cards you own that aren't on the battlefield. + this.addAbility(new SimpleStaticAbility(new MaskwoodNexusEffect())); + + // {3}, {T}: Create a 2/2 blue Shapeshifter creature token with changeling. + Ability ability = new SimpleActivatedAbility( + new CreateTokenEffect(new ShapeshifterBlueToken()), new GenericManaCost(3) + ); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + } + + private MaskwoodNexus(final MaskwoodNexus card) { + super(card); + } + + @Override + public MaskwoodNexus copy() { + return new MaskwoodNexus(this); + } +} + +class MaskwoodNexusEffect extends ContinuousEffectImpl { + + MaskwoodNexusEffect() { + super(Duration.WhileOnBattlefield, Outcome.Benefit); + staticText = "Creatures you control are every creature type. " + + "The same is true for creature spells you control " + + "and creature cards you own that aren't on the battlefield."; + } + + private MaskwoodNexusEffect(final MaskwoodNexusEffect effect) { + super(effect); + } + + @Override + public MaskwoodNexusEffect copy() { + return new MaskwoodNexusEffect(this); + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + // Creature cards you own that aren't on the battlefield + // in graveyard + for (UUID cardId : controller.getGraveyard()) { + Card card = game.getCard(cardId); + if (card != null && card.isCreature()) { + card.setIsAllCreatureTypes(true); + } + } + // on Hand + for (UUID cardId : controller.getHand()) { + Card card = game.getCard(cardId); + if (card != null && card.isCreature()) { + card.setIsAllCreatureTypes(true); + } + } + // in Exile + for (Card card : game.getState().getExile().getAllCards(game)) { + if (card.isCreature() && card.isOwnedBy(controller.getId())) { + card.setIsAllCreatureTypes(true); + } + } + // in Library (e.g. for Mystical Teachings) + for (Card card : controller.getLibrary().getCards(game)) { + if (card.isOwnedBy(controller.getId()) && card.isCreature()) { + card.setIsAllCreatureTypes(true); + } + } + // commander in command zone + for (CommandObject commandObject : game.getState().getCommand()) { + if (!(commandObject instanceof Commander)) { + continue; + } + Card card = game.getCard(((Commander) commandObject).getId()); + if (card != null + && card.isOwnedBy(controller.getId()) + && card.isCreature()) { + card.setIsAllCreatureTypes(true); + } + } + // creature spells you control + for (Iterator iterator = game.getStack().iterator(); iterator.hasNext(); ) { + StackObject stackObject = iterator.next(); + if (stackObject instanceof Spell + && stackObject.isControlledBy(source.getControllerId()) + && stackObject.isCreature()) { + Card card = ((Spell) stackObject).getCard(); + card.setIsAllCreatureTypes(true); + } + } + // creatures you control + List creatures = game.getBattlefield().getAllActivePermanents( + new FilterControlledCreaturePermanent(), source.getControllerId(), game); + for (Permanent creature : creatures) { + if (creature != null) { + creature.setIsAllCreatureTypes(true); + } + } + return true; + + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + +} diff --git a/Mage.Sets/src/mage/sets/Kaldheim.java b/Mage.Sets/src/mage/sets/Kaldheim.java index a44b52d43b3..4f2b23ec025 100644 --- a/Mage.Sets/src/mage/sets/Kaldheim.java +++ b/Mage.Sets/src/mage/sets/Kaldheim.java @@ -96,6 +96,7 @@ public final class Kaldheim extends ExpansionSet { cards.add(new SetCardInfo("Koma's Faithful", 102, Rarity.COMMON, mage.cards.k.KomasFaithful.class)); cards.add(new SetCardInfo("Magda, Brazen Outlaw", 142, Rarity.RARE, mage.cards.m.MagdaBrazenOutlaw.class)); cards.add(new SetCardInfo("Masked Vandal", 184, Rarity.COMMON, mage.cards.m.MaskedVandal.class)); + cards.add(new SetCardInfo("Maskwood Nexus", 240, Rarity.RARE, mage.cards.m.MaskwoodNexus.class)); cards.add(new SetCardInfo("Niko Aris", 225, Rarity.MYTHIC, mage.cards.n.NikoAris.class)); cards.add(new SetCardInfo("Pyre of Heroes", 241, Rarity.RARE, mage.cards.p.PyreOfHeroes.class)); cards.add(new SetCardInfo("Rampage of the Valkyries", 393, Rarity.UNCOMMON, mage.cards.r.RampageOfTheValkyries.class)); diff --git a/Mage/src/main/java/mage/game/permanent/token/ShapeshifterBlueToken.java b/Mage/src/main/java/mage/game/permanent/token/ShapeshifterBlueToken.java new file mode 100644 index 00000000000..67bddeb14ef --- /dev/null +++ b/Mage/src/main/java/mage/game/permanent/token/ShapeshifterBlueToken.java @@ -0,0 +1,31 @@ +package mage.game.permanent.token; + +import mage.MageInt; +import mage.abilities.keyword.ChangelingAbility; +import mage.constants.CardType; +import mage.constants.SubType; + +/** + * @author TheElk801 + */ +public final class ShapeshifterBlueToken extends TokenImpl { + + public ShapeshifterBlueToken() { + super("Shapeshifter", "2/2 blue Shapeshifter creature token with changeling"); + cardType.add(CardType.CREATURE); + subtype.add(SubType.SHAPESHIFTER); + color.setBlue(true); + power = new MageInt(2); + toughness = new MageInt(2); + setIsAllCreatureTypes(true); + addAbility(ChangelingAbility.getInstance()); + } + + private ShapeshifterBlueToken(final ShapeshifterBlueToken token) { + super(token); + } + + public ShapeshifterBlueToken copy() { + return new ShapeshifterBlueToken(this); + } +} From bec613cb8d2fc871b50fea827d451841afba0c28 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Sun, 10 Jan 2021 21:40:36 -0500 Subject: [PATCH 14/20] [KHM] Implemented Bloodline Pretender --- .../src/mage/cards/b/BloodlinePretender.java | 63 +++++++++++++++++++ Mage.Sets/src/mage/sets/Kaldheim.java | 1 + 2 files changed, 64 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/b/BloodlinePretender.java diff --git a/Mage.Sets/src/mage/cards/b/BloodlinePretender.java b/Mage.Sets/src/mage/cards/b/BloodlinePretender.java new file mode 100644 index 00000000000..839c75de853 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BloodlinePretender.java @@ -0,0 +1,63 @@ +package mage.cards.b; + +import mage.MageInt; +import mage.abilities.common.AsEntersBattlefieldAbility; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.effects.common.ChooseCreatureTypeEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.ChangelingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.ChosenSubtypePredicate; +import mage.filter.predicate.permanent.AnotherPredicate; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BloodlinePretender extends CardImpl { + + private static final FilterPermanent filter + = new FilterCreaturePermanent("another creature of the chosen type"); + + static { + filter.add(AnotherPredicate.instance); + filter.add(ChosenSubtypePredicate.instance); + } + + public BloodlinePretender(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}"); + + this.subtype.add(SubType.SHAPESHIFTER); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Changeling + this.setIsAllCreatureTypes(true); + this.addAbility(ChangelingAbility.getInstance()); + + // As Bloodline Pretender enters the battlefield, choose a creature type. + this.addAbility(new AsEntersBattlefieldAbility(new ChooseCreatureTypeEffect(Outcome.BoostCreature))); + + // Whenever another creature of the chosen type enters the battlefield under your control, put a +1/+1 counter on Bloodline Pretender. + this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + new AddCountersSourceEffect(CounterType.P1P1.createInstance()), filter + )); + } + + private BloodlinePretender(final BloodlinePretender card) { + super(card); + } + + @Override + public BloodlinePretender copy() { + return new BloodlinePretender(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Kaldheim.java b/Mage.Sets/src/mage/sets/Kaldheim.java index 4f2b23ec025..0755ecc794b 100644 --- a/Mage.Sets/src/mage/sets/Kaldheim.java +++ b/Mage.Sets/src/mage/sets/Kaldheim.java @@ -58,6 +58,7 @@ public final class Kaldheim extends ExpansionSet { cards.add(new SetCardInfo("Behold the Multiverse", 46, Rarity.COMMON, mage.cards.b.BeholdTheMultiverse.class)); cards.add(new SetCardInfo("Binding the Old Gods", 206, Rarity.UNCOMMON, mage.cards.b.BindingTheOldGods.class)); cards.add(new SetCardInfo("Blightstep Pathway", 252, Rarity.RARE, mage.cards.b.BlightstepPathway.class)); + cards.add(new SetCardInfo("Bloodline Pretender", 235, Rarity.UNCOMMON, mage.cards.b.BloodlinePretender.class)); cards.add(new SetCardInfo("Bretagard Stronghold", 253, Rarity.UNCOMMON, mage.cards.b.BretagardStronghold.class)); cards.add(new SetCardInfo("Broken Wings", 164, Rarity.COMMON, mage.cards.b.BrokenWings.class)); cards.add(new SetCardInfo("Calamity Bearer", 125, Rarity.RARE, mage.cards.c.CalamityBearer.class)); From 4f4ea502e16bb655c3bbc7123806dbad59efad6d Mon Sep 17 00:00:00 2001 From: Daniel Bomar Date: Sun, 10 Jan 2021 21:07:18 -0600 Subject: [PATCH 15/20] [KHM] Implemented Eradicator Valkyrie (#7367) --- .../src/mage/cards/e/EradicatorValkyrie.java | 64 +++++++++++++++++++ Mage.Sets/src/mage/sets/Kaldheim.java | 1 + .../HexproofFromPlaneswalkersAbility.java | 47 ++++++++++++++ 3 files changed, 112 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/e/EradicatorValkyrie.java create mode 100644 Mage/src/main/java/mage/abilities/keyword/HexproofFromPlaneswalkersAbility.java diff --git a/Mage.Sets/src/mage/cards/e/EradicatorValkyrie.java b/Mage.Sets/src/mage/cards/e/EradicatorValkyrie.java new file mode 100644 index 00000000000..850bcb9a354 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EradicatorValkyrie.java @@ -0,0 +1,64 @@ +package mage.cards.e; + +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.common.SacrificeOpponentsEffect; +import mage.abilities.keyword.BoastAbility; +import mage.abilities.keyword.HexproofFromPlaneswalkersAbility; +import mage.constants.SubType; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.LifelinkAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.FilterPermanent; +import mage.filter.predicate.Predicates; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author weirddan455 + */ +public final class EradicatorValkyrie extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("creature or planeswalker"); + + static { + filter.add(Predicates.or(CardType.CREATURE.getPredicate(), CardType.PLANESWALKER.getPredicate())); + } + + public EradicatorValkyrie(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{B}"); + + this.subtype.add(SubType.ANGEL); + this.subtype.add(SubType.BERSERKER); + this.power = new MageInt(4); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Lifelink + this.addAbility(LifelinkAbility.getInstance()); + + // Hexproof from planeswalkers + this.addAbility(HexproofFromPlaneswalkersAbility.getInstance()); + + // Boast — {1}{B}, Sacrifice a creature: Each opponent sacrifices a creature or planeswalker. + Ability ability = new BoastAbility(new SacrificeOpponentsEffect(filter), new ManaCostsImpl("{1}{B}")); + ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent())); + this.addAbility(ability); + } + + private EradicatorValkyrie(final EradicatorValkyrie card) { + super(card); + } + + @Override + public EradicatorValkyrie copy() { + return new EradicatorValkyrie(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Kaldheim.java b/Mage.Sets/src/mage/sets/Kaldheim.java index 0755ecc794b..9165750d0bd 100644 --- a/Mage.Sets/src/mage/sets/Kaldheim.java +++ b/Mage.Sets/src/mage/sets/Kaldheim.java @@ -69,6 +69,7 @@ public final class Kaldheim extends ExpansionSet { cards.add(new SetCardInfo("Elderfang Ritualist", 385, Rarity.UNCOMMON, mage.cards.e.ElderfangRitualist.class)); cards.add(new SetCardInfo("Elven Ambush", 391, Rarity.UNCOMMON, mage.cards.e.ElvenAmbush.class)); cards.add(new SetCardInfo("Elvish Warmaster", 167, Rarity.RARE, mage.cards.e.ElvishWarmaster.class)); + cards.add(new SetCardInfo("Eradicator Valkyrie", 94, Rarity.MYTHIC, mage.cards.e.EradicatorValkyrie.class)); cards.add(new SetCardInfo("Esika's Chariot", 169, Rarity.RARE, mage.cards.e.EsikasChariot.class)); cards.add(new SetCardInfo("Esika, God of the Tree", 168, Rarity.MYTHIC, mage.cards.e.EsikaGodOfTheTree.class)); cards.add(new SetCardInfo("Fire Giant's Fury", 389, Rarity.UNCOMMON, mage.cards.f.FireGiantsFury.class)); diff --git a/Mage/src/main/java/mage/abilities/keyword/HexproofFromPlaneswalkersAbility.java b/Mage/src/main/java/mage/abilities/keyword/HexproofFromPlaneswalkersAbility.java new file mode 100644 index 00000000000..1cbb997ed00 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/keyword/HexproofFromPlaneswalkersAbility.java @@ -0,0 +1,47 @@ +package mage.abilities.keyword; + +import mage.MageObject; +import mage.game.Game; + +import java.io.ObjectStreamException; + +/** + * Hexproof from planesalkers + * + * @author weirddan455 + */ +public class HexproofFromPlaneswalkersAbility extends HexproofBaseAbility { + + private static final HexproofFromPlaneswalkersAbility instance; + + static { + instance = new HexproofFromPlaneswalkersAbility(); + } + + private Object readResolve() throws ObjectStreamException { + return instance; + } + + public static HexproofFromPlaneswalkersAbility getInstance() { + return instance; + } + + private HexproofFromPlaneswalkersAbility() { + super(); + } + + @Override + public boolean checkObject(MageObject source, Game game) { + return source.isPlaneswalker(); + } + + @Override + public HexproofFromPlaneswalkersAbility copy() { + return instance; + } + + @Override + public String getRule() { + return "hexproof from planeswalkers"; + } +} From e966b760fbe442878d21cc2b88c72f8fa3fd6d19 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Mon, 11 Jan 2021 08:54:26 -0500 Subject: [PATCH 16/20] [KHM] Implemented Littjara Kinseekers --- .../src/mage/cards/l/LittjaraKinseekers.java | 88 +++++++++++++++++++ Mage.Sets/src/mage/sets/Kaldheim.java | 1 + Utils/mtg-cards-data.txt | 2 +- 3 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 Mage.Sets/src/mage/cards/l/LittjaraKinseekers.java diff --git a/Mage.Sets/src/mage/cards/l/LittjaraKinseekers.java b/Mage.Sets/src/mage/cards/l/LittjaraKinseekers.java new file mode 100644 index 00000000000..928b0edfb40 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LittjaraKinseekers.java @@ -0,0 +1,88 @@ +package mage.cards.l; + +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.effects.keyword.ScryEffect; +import mage.abilities.keyword.ChangelingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.counters.CounterType; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; + +import java.util.*; + +/** + * @author TheElk801 + */ +public final class LittjaraKinseekers extends CardImpl { + + public LittjaraKinseekers(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); + + this.subtype.add(SubType.SHAPESHIFTER); + this.power = new MageInt(2); + this.toughness = new MageInt(4); + + // Changeling + this.setIsAllCreatureTypes(true); + this.addAbility(ChangelingAbility.getInstance()); + + // When Littjara Kinseekers enters the battlefield, if you control three or more creatures that share a creature type, put a +1/+1 counter on Littjara Kinseekers, then scry 1. + Ability ability = new ConditionalInterveningIfTriggeredAbility( + new EntersBattlefieldTriggeredAbility( + new AddCountersSourceEffect(CounterType.P1P1.createInstance()) + ), LittjaraKinseekersCondition.instance, "When {this} enters the battlefield, " + + "if you control three or more creatures that share a creature type, " + + "put a +1/+1 counter on {this}, then scry 1." + ); + ability.addEffect(new ScryEffect(1)); + this.addAbility(ability); + } + + private LittjaraKinseekers(final LittjaraKinseekers card) { + super(card); + } + + @Override + public LittjaraKinseekers copy() { + return new LittjaraKinseekers(this); + } +} + +enum LittjaraKinseekersCondition implements Condition { + instance; + + @Override + public boolean apply(Game game, Ability source) { + List permanentList = game.getBattlefield().getActivePermanents( + StaticFilters.FILTER_CONTROLLED_CREATURE, + source.getControllerId(), source.getSourceId(), game + ); + permanentList.removeIf(Objects::isNull); + long changelings = permanentList + .stream() + .filter(Objects::nonNull) + .filter(MageObject::isAllCreatureTypes) + .count(); + if (changelings > 2) { + return true; + } + permanentList.removeIf(MageObject::isAllCreatureTypes); + Map typeMap = new HashMap<>(); + return permanentList + .stream() + .map(permanent -> permanent.getSubtype(game)) + .flatMap(Collection::stream) + .mapToInt(subType -> typeMap.compute(subType, (s, i) -> i == null ? 1 : Integer.sum(i, 1))) + .anyMatch(x -> x + changelings > 2); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/Kaldheim.java b/Mage.Sets/src/mage/sets/Kaldheim.java index 9165750d0bd..341ef9cca39 100644 --- a/Mage.Sets/src/mage/sets/Kaldheim.java +++ b/Mage.Sets/src/mage/sets/Kaldheim.java @@ -96,6 +96,7 @@ public final class Kaldheim extends ExpansionSet { cards.add(new SetCardInfo("Kaya's Onslaught", 18, Rarity.UNCOMMON, mage.cards.k.KayasOnslaught.class)); cards.add(new SetCardInfo("Koll, the Forgemaster", 220, Rarity.UNCOMMON, mage.cards.k.KollTheForgemaster.class)); cards.add(new SetCardInfo("Koma's Faithful", 102, Rarity.COMMON, mage.cards.k.KomasFaithful.class)); + cards.add(new SetCardInfo("Littjara Kinseekers", 66, Rarity.COMMON, mage.cards.l.LittjaraKinseekers.class)); cards.add(new SetCardInfo("Magda, Brazen Outlaw", 142, Rarity.RARE, mage.cards.m.MagdaBrazenOutlaw.class)); cards.add(new SetCardInfo("Masked Vandal", 184, Rarity.COMMON, mage.cards.m.MaskedVandal.class)); cards.add(new SetCardInfo("Maskwood Nexus", 240, Rarity.RARE, mage.cards.m.MaskwoodNexus.class)); diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 32854c4b376..a7ec6b5189c 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -40035,7 +40035,7 @@ Cosmos Charger|Kaldheim|51|R|{3}{U}|Creature - Horse Spirit|3|3|Flash$Flying$For Giant's Amulet|Kaldheim|59|U|{U}|Artifact - Equipment|||When Giant's Amulet enters the battlefield, you may pay {3}{U}. If you do, create a 4/4 blue Giant Wizard creature token, then attach Giant's Amulet to it.$Equipped creature gets +0/+1 and has "This creature has hexproof as long as it's untapped."$Equip {2}| Glimpse the Cosmos|Kaldheim|60|U|{1}{U}|Sorcery|||Look at the top three cards of your library. Put one of them into your hand and the rest on the bottom of your library in any order.$As long as you control a Giant, you may cast Glimpse the Cosmos from your graveyard by paying {U} rather than paying its mana cost. If you cast Glimpse the Cosmos this way and it would be put into your graveyard, exile it instead.| Inga Rune-Eyes|Kaldheim|64|U|{3}{U}|Legendary Creature - Human Wizard|3|3|When Inga Rune-Eyes enters the battlefield, scry 3.$When Inga Rune-Eyes dies, draw three cards if three or more creatures died this turn.| -Littjara Kinseekers|Kaldheim|66|C|{3}{U}|Creature - Shapeshifter|2|4|Changeling (This card is every creature type.$When Littjara Kinseekers enters the battlefield, if you control three or more creatures that share a creature type, put a +1/+1 counter on Littjara Kinseekers, then scry 1.| +Littjara Kinseekers|Kaldheim|66|C|{3}{U}|Creature - Shapeshifter|2|4|Changeling$When Littjara Kinseekers enters the battlefield, if you control three or more creatures that share a creature type, put a +1/+1 counter on Littjara Kinseekers, then scry 1.| Ravenform|Kaldheim|72|C|{2}{U}|Sorcery|||Exile target artifact or creature. Its controller creates a 1/1 blue Bird creature token with flying.$Foretell {U}| Reflections of Littjara|Kaldheim|73|R|{4}{U}|Enchantment|||As Reflections of Littjara enters the battlefield, choose a creature type.$Whenever you cast a spell of the chosen type, copy that spell.| Saw It Coming|Kaldheim|76|U|{1}{U}{U}|Instant|||Counter target spell.$Foretell {1}{U}| From 1e0ce2a8c2abdbb8e05b831a6144408c77183b06 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Mon, 11 Jan 2021 09:07:41 -0500 Subject: [PATCH 17/20] [KHM] Implemented Path to the World Tree --- .../src/mage/cards/p/PathToTheWorldTree.java | 103 ++++++++++++++++++ Mage.Sets/src/mage/sets/Kaldheim.java | 1 + 2 files changed, 104 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/p/PathToTheWorldTree.java diff --git a/Mage.Sets/src/mage/cards/p/PathToTheWorldTree.java b/Mage.Sets/src/mage/cards/p/PathToTheWorldTree.java new file mode 100644 index 00000000000..b398d8868d5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PathToTheWorldTree.java @@ -0,0 +1,103 @@ +package mage.cards.p; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +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.common.search.SearchLibraryPutInHandEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.BearToken; +import mage.players.Player; +import mage.target.Target; +import mage.target.common.TargetCardInLibrary; +import mage.target.common.TargetCreaturePermanent; +import mage.target.common.TargetOpponent; + +import java.util.Collection; +import java.util.UUID; +import java.util.stream.Collectors; + +/** + * @author TheElk801 + */ +public final class PathToTheWorldTree extends CardImpl { + + public PathToTheWorldTree(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}"); + + // When Path to the World Tree enters the battlefield, search your library for a basic land card, reveal it, put it into your hand, then shuffle your library. + this.addAbility(new EntersBattlefieldTriggeredAbility(new SearchLibraryPutInHandEffect( + new TargetCardInLibrary(StaticFilters.FILTER_CARD_BASIC_LAND), true + ))); + + // {2}{W}{U}{B}{R}{G}, Sacrifice Path to the World Tree: You gain 2 life and draw two cards. Target opponent loses 2 life. Path to the World Tree deals 2 damage to up to one target creature. You create a 2/2 green Bear creature token. + Ability ability = new SimpleActivatedAbility( + new PathToTheWorldTreeEffect(), new ManaCostsImpl("{2}{W}{U}{B}{R}{G}") + ); + ability.addCost(new SacrificeSourceCost()); + ability.addTarget(new TargetOpponent()); + ability.addTarget(new TargetCreaturePermanent(0, 1)); + this.addAbility(ability); + } + + private PathToTheWorldTree(final PathToTheWorldTree card) { + super(card); + } + + @Override + public PathToTheWorldTree copy() { + return new PathToTheWorldTree(this); + } +} + +class PathToTheWorldTreeEffect extends OneShotEffect { + + PathToTheWorldTreeEffect() { + super(Outcome.Benefit); + staticText = "You gain 2 life and draw two cards. Target opponent loses 2 life. " + + "{this} deals 2 damage to up to one target creature. You create a 2/2 green Bear creature token."; + } + + private PathToTheWorldTreeEffect(final PathToTheWorldTreeEffect effect) { + super(effect); + } + + @Override + public PathToTheWorldTreeEffect copy() { + return new PathToTheWorldTreeEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + controller.gainLife(2, game, source); + controller.drawCards(2, source, game); + } + for (UUID targetId : source + .getTargets() + .stream() + .map(Target::getTargets) + .flatMap(Collection::stream) + .collect(Collectors.toList())) { + Player player = game.getPlayer(targetId); + if (player != null) { + player.loseLife(2, game, source, false); + } + Permanent permanent = game.getPermanent(targetId); + if (permanent != null) { + permanent.damage(2, source.getSourceId(), source, game); + } + } + new BearToken().putOntoBattlefield(1, game, source, source.getControllerId()); + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/Kaldheim.java b/Mage.Sets/src/mage/sets/Kaldheim.java index 341ef9cca39..05fe8af2b65 100644 --- a/Mage.Sets/src/mage/sets/Kaldheim.java +++ b/Mage.Sets/src/mage/sets/Kaldheim.java @@ -101,6 +101,7 @@ public final class Kaldheim extends ExpansionSet { cards.add(new SetCardInfo("Masked Vandal", 184, Rarity.COMMON, mage.cards.m.MaskedVandal.class)); cards.add(new SetCardInfo("Maskwood Nexus", 240, Rarity.RARE, mage.cards.m.MaskwoodNexus.class)); cards.add(new SetCardInfo("Niko Aris", 225, Rarity.MYTHIC, mage.cards.n.NikoAris.class)); + cards.add(new SetCardInfo("Path to the World Tree", 186, Rarity.UNCOMMON, mage.cards.p.PathToTheWorldTree.class)); cards.add(new SetCardInfo("Pyre of Heroes", 241, Rarity.RARE, mage.cards.p.PyreOfHeroes.class)); cards.add(new SetCardInfo("Rampage of the Valkyries", 393, Rarity.UNCOMMON, mage.cards.r.RampageOfTheValkyries.class)); cards.add(new SetCardInfo("Ravenform", 72, Rarity.COMMON, mage.cards.r.Ravenform.class)); From eb51aa63daad06273e44eee0daa75d5c19ae7ac1 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Mon, 11 Jan 2021 09:10:38 -0500 Subject: [PATCH 18/20] [KHM] Implemented Faceless Haven --- Mage.Sets/src/mage/cards/f/FacelessHaven.java | 65 +++++++++++++++++++ Mage.Sets/src/mage/sets/Kaldheim.java | 1 + 2 files changed, 66 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/f/FacelessHaven.java diff --git a/Mage.Sets/src/mage/cards/f/FacelessHaven.java b/Mage.Sets/src/mage/cards/f/FacelessHaven.java new file mode 100644 index 00000000000..41906500c0e --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FacelessHaven.java @@ -0,0 +1,65 @@ +package mage.cards.f; + +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; +import mage.abilities.keyword.VigilanceAbility; +import mage.abilities.mana.ColorlessManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SuperType; +import mage.game.permanent.token.TokenImpl; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class FacelessHaven extends CardImpl { + + public FacelessHaven(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + this.addSuperType(SuperType.SNOW); + + // {T}: Add {C}. + this.addAbility(new ColorlessManaAbility()); + + // {S}{S}{S}: Faceless Haven becomes a 4/3 creature with vigilance and all creature types until end of turn. It's still a land. + this.addAbility(new SimpleActivatedAbility(new BecomesCreatureSourceEffect( + new FacelessHavenToken(), "land", Duration.EndOfTurn + ), new ManaCostsImpl("{S}{S}{S}"))); + } + + private FacelessHaven(final FacelessHaven card) { + super(card); + } + + @Override + public FacelessHaven copy() { + return new FacelessHaven(this); + } +} + +class FacelessHavenToken extends TokenImpl { + + FacelessHavenToken() { + super("", "4/3 creature with vigilance and all creature types"); + cardType.add(CardType.CREATURE); + setIsAllCreatureTypes(true); + power = new MageInt(4); + toughness = new MageInt(3); + addAbility(VigilanceAbility.getInstance()); + } + + private FacelessHavenToken(final FacelessHavenToken token) { + super(token); + } + + public FacelessHavenToken copy() { + return new FacelessHavenToken(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Kaldheim.java b/Mage.Sets/src/mage/sets/Kaldheim.java index 05fe8af2b65..bb656ae059c 100644 --- a/Mage.Sets/src/mage/sets/Kaldheim.java +++ b/Mage.Sets/src/mage/sets/Kaldheim.java @@ -72,6 +72,7 @@ public final class Kaldheim extends ExpansionSet { cards.add(new SetCardInfo("Eradicator Valkyrie", 94, Rarity.MYTHIC, mage.cards.e.EradicatorValkyrie.class)); cards.add(new SetCardInfo("Esika's Chariot", 169, Rarity.RARE, mage.cards.e.EsikasChariot.class)); cards.add(new SetCardInfo("Esika, God of the Tree", 168, Rarity.MYTHIC, mage.cards.e.EsikaGodOfTheTree.class)); + cards.add(new SetCardInfo("Faceless Haven", 255, Rarity.RARE, mage.cards.f.FacelessHaven.class)); cards.add(new SetCardInfo("Fire Giant's Fury", 389, Rarity.UNCOMMON, mage.cards.f.FireGiantsFury.class)); cards.add(new SetCardInfo("Firja, Judge of Valor", 209, Rarity.UNCOMMON, mage.cards.f.FirjaJudgeOfValor.class)); cards.add(new SetCardInfo("Forging the Tyrite Sword", 211, Rarity.UNCOMMON, mage.cards.f.ForgingTheTyriteSword.class)); From 1b80ecb7b45a2cae1d8d6efcfce4547d5a6db0aa Mon Sep 17 00:00:00 2001 From: jeffwadsworth Date: Mon, 11 Jan 2021 10:58:31 -0600 Subject: [PATCH 19/20] - Fixed the Outcome of Blightning --- Mage.Sets/src/mage/cards/b/Blightning.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/cards/b/Blightning.java b/Mage.Sets/src/mage/cards/b/Blightning.java index 397629a8d54..4a588167398 100644 --- a/Mage.Sets/src/mage/cards/b/Blightning.java +++ b/Mage.Sets/src/mage/cards/b/Blightning.java @@ -1,4 +1,3 @@ - package mage.cards.b; import java.util.UUID; @@ -44,7 +43,7 @@ public final class Blightning extends CardImpl { class BlightningEffect extends OneShotEffect { BlightningEffect() { - super(Outcome.Benefit); + super(Outcome.Detriment); this.staticText = "That player or that planeswalker's controller discards two cards."; } From ed1133c338fe135b1c0524784ab01810924c1ed7 Mon Sep 17 00:00:00 2001 From: Daniel Bomar Date: Mon, 11 Jan 2021 18:28:26 -0600 Subject: [PATCH 20/20] Removed redundant CantBeCounteredAbility (#7373) --- .../src/mage/cards/c/CragplateBaloth.java | 4 +-- .../common/CantBeCounteredAbility.java | 32 ------------------- 2 files changed, 2 insertions(+), 34 deletions(-) delete mode 100644 Mage/src/main/java/mage/abilities/common/CantBeCounteredAbility.java diff --git a/Mage.Sets/src/mage/cards/c/CragplateBaloth.java b/Mage.Sets/src/mage/cards/c/CragplateBaloth.java index c4bdcb2f50f..97a4da84daa 100644 --- a/Mage.Sets/src/mage/cards/c/CragplateBaloth.java +++ b/Mage.Sets/src/mage/cards/c/CragplateBaloth.java @@ -1,7 +1,7 @@ package mage.cards.c; import mage.MageInt; -import mage.abilities.common.CantBeCounteredAbility; +import mage.abilities.common.CantBeCounteredSourceAbility; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.condition.common.KickedCondition; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -32,7 +32,7 @@ public final class CragplateBaloth extends CardImpl { this.addAbility(new KickerAbility("{2}{G}")); // This spell can't be countered. - this.addAbility(new CantBeCounteredAbility()); + this.addAbility(new CantBeCounteredSourceAbility()); // Hexproof this.addAbility(HexproofAbility.getInstance()); diff --git a/Mage/src/main/java/mage/abilities/common/CantBeCounteredAbility.java b/Mage/src/main/java/mage/abilities/common/CantBeCounteredAbility.java deleted file mode 100644 index 7aaab64c222..00000000000 --- a/Mage/src/main/java/mage/abilities/common/CantBeCounteredAbility.java +++ /dev/null @@ -1,32 +0,0 @@ - - -package mage.abilities.common; - -import mage.abilities.StaticAbility; -import mage.abilities.effects.common.CantBeCounteredSourceEffect; -import mage.constants.Zone; - -/** - * - * @author BetaSteward_at_googlemail.com - */ -public class CantBeCounteredAbility extends StaticAbility { - - public CantBeCounteredAbility() { - super(Zone.STACK, new CantBeCounteredSourceEffect()); - } - - public CantBeCounteredAbility(CantBeCounteredAbility ability) { - super(ability); - } - - @Override - public String getRule() { - return "This spell can't be countered."; - } - - @Override - public CantBeCounteredAbility copy() { - return new CantBeCounteredAbility(this); - } -}