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