From fbf874fdc5f77e51535e84a6ac4d2fec3eb418a2 Mon Sep 17 00:00:00 2001 From: theelk801 <theelk801@gmail.com> Date: Mon, 17 Apr 2023 19:53:32 -0400 Subject: [PATCH] [MOM] Implement Drana and Linvala --- .../src/mage/cards/d/DranaAndLinvala.java | 182 ++++++++++++++++++ .../src/mage/sets/MarchOfTheMachine.java | 1 + .../java/mage/game/permanent/Permanent.java | 2 +- .../mage/game/permanent/PermanentImpl.java | 4 +- 4 files changed, 187 insertions(+), 2 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/d/DranaAndLinvala.java diff --git a/Mage.Sets/src/mage/cards/d/DranaAndLinvala.java b/Mage.Sets/src/mage/cards/d/DranaAndLinvala.java new file mode 100644 index 0000000000..340bfefe3b --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DranaAndLinvala.java @@ -0,0 +1,182 @@ +package mage.cards.d; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.AsThoughEffectImpl; +import mage.abilities.effects.AsThoughManaEffect; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.RestrictionEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.ManaPoolItem; +import mage.util.CardUtil; + +import java.util.Collection; +import java.util.Objects; +import java.util.UUID; +import java.util.stream.Collectors; + +/** + * @author TheElk801 + */ +public final class DranaAndLinvala extends CardImpl { + + public DranaAndLinvala(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{W}{B}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.VAMPIRE); + this.subtype.add(SubType.ANGEL); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + // Activated abilities of creatures your opponents control can't be activated. + this.addAbility(new SimpleStaticAbility(new DranaAndLinvalaCantActivateEffect())); + + // Drana and Linvala has all activated abilities of all creatures your opponents control. You may spend mana as though it were mana of any color to activate those abilities. + Ability ability = new SimpleStaticAbility(new DranaAndLinvalaGainAbilitiesEffect()); + ability.addEffect(new DranaAndLinvalaManaEffect()); + this.addAbility(ability); + } + + private DranaAndLinvala(final DranaAndLinvala card) { + super(card); + } + + @Override + public DranaAndLinvala copy() { + return new DranaAndLinvala(this); + } +} + +class DranaAndLinvalaCantActivateEffect extends RestrictionEffect { + + DranaAndLinvalaCantActivateEffect() { + super(Duration.WhileOnBattlefield); + staticText = "activated abilities of creatures your opponents control can't be activated"; + } + + private DranaAndLinvalaCantActivateEffect(final DranaAndLinvalaCantActivateEffect effect) { + super(effect); + } + + @Override + public boolean applies(Permanent permanent, Ability source, Game game) { + return permanent.isCreature(game) + && game + .getOpponents(source.getControllerId()) + .contains(permanent.getControllerId()); + } + + @Override + public boolean canUseActivatedAbilities(Permanent permanent, Ability source, Game game, boolean canUseChooseDialogs) { + return false; + } + + @Override + public DranaAndLinvalaCantActivateEffect copy() { + return new DranaAndLinvalaCantActivateEffect(this); + } +} + +class DranaAndLinvalaGainAbilitiesEffect extends ContinuousEffectImpl { + + DranaAndLinvalaGainAbilitiesEffect() { + super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); + staticText = "{this} has all activated abilities of all creatures your opponents control"; + this.addDependencyType(DependencyType.AddingAbility); + } + + private DranaAndLinvalaGainAbilitiesEffect(final DranaAndLinvalaGainAbilitiesEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent perm = source.getSourcePermanentIfItStillExists(game); + if (perm == null) { + return false; + } + for (Ability ability : game + .getBattlefield() + .getActivePermanents( + StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE, + source.getControllerId(), source, game + ) + .stream() + .map(permanent -> permanent.getAbilities(game)) + .flatMap(Collection::stream) + .filter(Objects::nonNull) + .filter(ability -> ability.getAbilityType() == AbilityType.ACTIVATED + || ability.getAbilityType() == AbilityType.MANA) + .collect(Collectors.toList())) { + Ability addedAbility = perm.addAbility(ability, source.getSourceId(), game); + addedAbility.getEffects().setValue("dranaLinvalaFlag", true); + } + return true; + } + + @Override + public DranaAndLinvalaGainAbilitiesEffect copy() { + return new DranaAndLinvalaGainAbilitiesEffect(this); + } +} + +class DranaAndLinvalaManaEffect extends AsThoughEffectImpl implements AsThoughManaEffect { + + DranaAndLinvalaManaEffect() { + super(AsThoughEffectType.SPEND_OTHER_MANA, Duration.WhileOnBattlefield, Outcome.Benefit); + staticText = "You may spend mana as though it were mana of any color to activate those abilities"; + } + + private DranaAndLinvalaManaEffect(final DranaAndLinvalaManaEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public DranaAndLinvalaManaEffect copy() { + return new DranaAndLinvalaManaEffect(this); + } + + @Override + public boolean applies(UUID objectId, Ability affectedAbility, Ability source, Game game, UUID playerId) { + return CardUtil + .getMainCardId(game, objectId) + .equals(source.getSourceId()) + && affectedAbility + .getEffects() + .stream() + .map(effect -> effect.getValue("dranaLinvalaFlag")) + .filter(Boolean.class::isInstance) + .anyMatch(Boolean.class::cast) + && source.isControlledBy(playerId); + } + + @Override + public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { + return false; + } + + @Override + public ManaType getAsThoughManaType(ManaType manaType, ManaPoolItem mana, UUID affectedControllerId, Ability source, Game game) { + return mana.getFirstAvailable(); + } +} diff --git a/Mage.Sets/src/mage/sets/MarchOfTheMachine.java b/Mage.Sets/src/mage/sets/MarchOfTheMachine.java index 0120f21968..b37c0585f8 100644 --- a/Mage.Sets/src/mage/sets/MarchOfTheMachine.java +++ b/Mage.Sets/src/mage/sets/MarchOfTheMachine.java @@ -97,6 +97,7 @@ public final class MarchOfTheMachine extends ExpansionSet { cards.add(new SetCardInfo("Disturbing Conversion", 54, Rarity.COMMON, mage.cards.d.DisturbingConversion.class)); cards.add(new SetCardInfo("Djeru and Hazoret", 221, Rarity.RARE, mage.cards.d.DjeruAndHazoret.class)); cards.add(new SetCardInfo("Doomskar Warrior", 185, Rarity.RARE, mage.cards.d.DoomskarWarrior.class)); + cards.add(new SetCardInfo("Drana and Linvala", 222, Rarity.RARE, mage.cards.d.DranaAndLinvala.class)); cards.add(new SetCardInfo("Dreg Recycler", 100, Rarity.COMMON, mage.cards.d.DregRecycler.class)); cards.add(new SetCardInfo("Dusk Legion Duelist", 11, Rarity.RARE, mage.cards.d.DuskLegionDuelist.class)); cards.add(new SetCardInfo("Elesh Norn", 12, Rarity.MYTHIC, mage.cards.e.EleshNorn.class)); diff --git a/Mage/src/main/java/mage/game/permanent/Permanent.java b/Mage/src/main/java/mage/game/permanent/Permanent.java index a410eb0a96..4026dc42bc 100644 --- a/Mage/src/main/java/mage/game/permanent/Permanent.java +++ b/Mage/src/main/java/mage/game/permanent/Permanent.java @@ -212,7 +212,7 @@ public interface Permanent extends Card, Controllable { * @param sourceId * @param game */ - void addAbility(Ability ability, UUID sourceId, Game game); + Ability addAbility(Ability ability, UUID sourceId, Game game); void removeAllAbilities(UUID sourceId, Game game); diff --git a/Mage/src/main/java/mage/game/permanent/PermanentImpl.java b/Mage/src/main/java/mage/game/permanent/PermanentImpl.java index 045c0c12cb..912dc2b1df 100644 --- a/Mage/src/main/java/mage/game/permanent/PermanentImpl.java +++ b/Mage/src/main/java/mage/game/permanent/PermanentImpl.java @@ -381,7 +381,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { } @Override - public void addAbility(Ability ability, UUID sourceId, Game game) { + public Ability addAbility(Ability ability, UUID sourceId, Game game) { // singleton abilities -- only one instance // other abilities -- any amount of instances if (!abilities.containsKey(ability.getId())) { @@ -397,7 +397,9 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { } abilities.add(copyAbility); abilities.addAll(ability.getSubAbilities()); + return copyAbility; } + return null; } @Override