diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java index 7101c48e3d..357033b4f3 100644 --- a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java @@ -44,6 +44,7 @@ import mage.game.tournament.Tournament; import mage.player.ai.simulators.CombatGroupSimulator; import mage.player.ai.simulators.CombatSimulator; import mage.player.ai.simulators.CreatureSimulator; +import mage.players.ManaPoolItem; import mage.players.Player; import mage.players.PlayerImpl; import mage.players.net.UserData; @@ -1423,6 +1424,9 @@ public class ComputerPlayer extends PlayerImpl implements Player { if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) { continue; } + if (approvingObject != null && !canUseAsThoughManaToPayManaCost(cost, ability, netMana, manaAbility, mageObject, game)) { + continue; + } if (activateAbility(manaAbility, game)) { return true; } @@ -1441,6 +1445,9 @@ public class ComputerPlayer extends PlayerImpl implements Player { if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) { continue; } + if (approvingObject != null && !canUseAsThoughManaToPayManaCost(cost, ability, netMana, manaAbility, mageObject, game)) { + continue; + } if (activateAbility(manaAbility, game)) { return true; } @@ -1456,6 +1463,9 @@ public class ComputerPlayer extends PlayerImpl implements Player { if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) { continue; } + if (approvingObject != null && !canUseAsThoughManaToPayManaCost(cost, ability, netMana, manaAbility, mageObject, game)) { + continue; + } if (activateAbility(manaAbility, game)) { return true; } @@ -1471,6 +1481,9 @@ public class ComputerPlayer extends PlayerImpl implements Player { if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) { continue; } + if (approvingObject != null && !canUseAsThoughManaToPayManaCost(cost, ability, netMana, manaAbility, mageObject, game)) { + continue; + } if (activateAbility(manaAbility, game)) { return true; } @@ -1486,6 +1499,9 @@ public class ComputerPlayer extends PlayerImpl implements Player { if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) { continue; } + if (approvingObject != null && !canUseAsThoughManaToPayManaCost(cost, ability, netMana, manaAbility, mageObject, game)) { + continue; + } if (activateAbility(manaAbility, game)) { return true; } @@ -1501,6 +1517,9 @@ public class ComputerPlayer extends PlayerImpl implements Player { if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) { continue; } + if (approvingObject != null && !canUseAsThoughManaToPayManaCost(cost, ability, netMana, manaAbility, mageObject, game)) { + continue; + } if (activateAbility(manaAbility, game)) { return true; } @@ -1516,6 +1535,9 @@ public class ComputerPlayer extends PlayerImpl implements Player { if (netMana instanceof ConditionalMana && !((ConditionalMana) netMana).apply(ability, game, getId(), cost)) { continue; } + if (approvingObject != null && !canUseAsThoughManaToPayManaCost(cost, ability, netMana, manaAbility, mageObject, game)) { + continue; + } if (activateAbility(manaAbility, game)) { return true; } @@ -1555,6 +1577,56 @@ public class ComputerPlayer extends PlayerImpl implements Player { return false; } + boolean canUseAsThoughManaToPayManaCost(ManaCost checkCost, Ability abilityToPay, Mana manaOption, Ability manaAbility, MageObject manaProducer, Game game) { + // asThoughMana can change producing mana type, so you must check it here + // cause some effects adds additional checks in getAsThoughManaType (example: Draugr Necromancer with snow mana sources) + + // simulate real asThoughMana usage + ManaPoolItem possiblePoolItem; + if (manaOption instanceof ConditionalMana) { + ConditionalMana conditionalNetMana = (ConditionalMana) manaOption; + possiblePoolItem = new ManaPoolItem( + conditionalNetMana, + manaAbility.getSourceObject(game), + conditionalNetMana.getManaProducerOriginalId() != null ? conditionalNetMana.getManaProducerOriginalId() : manaAbility.getOriginalId() + ); + } else { + possiblePoolItem = new ManaPoolItem( + manaOption.getRed(), + manaOption.getGreen(), + manaOption.getBlue(), + manaOption.getWhite(), + manaOption.getBlack(), + manaOption.getGeneric() + manaOption.getColorless(), + manaProducer, + manaAbility.getOriginalId(), + manaOption.getFlag() + ); + } + + // cost can contains multiple mana types, must check each type (is it possible to pay a cost) + for (ManaType checkType : ManaUtil.getManaTypesInCost(checkCost)) { + // affected asThoughMana effect must fit a checkType with pool mana + ManaType possibleAsThoughPoolManaType = game.getContinuousEffects().asThoughMana(checkType, possiblePoolItem, abilityToPay.getSourceId(), abilityToPay, abilityToPay.getControllerId(), game); + if (possibleAsThoughPoolManaType == null) { + continue; // no affected asThough effects + } + boolean canPay; + if (possibleAsThoughPoolManaType == ManaType.COLORLESS) { + // colorless can be payed by any color from the pool + canPay = possiblePoolItem.count() > 0; + } else { + // colored must be payed by specific color from the pool (AsThough already changed it to fit with mana pool) + canPay = possiblePoolItem.get(possibleAsThoughPoolManaType) > 0; + } + if (canPay) { + return true; + } + } + + return false; + } + private Abilities getManaAbilitiesSortedByManaCount(MageObject mageObject, final Game game) { Abilities manaAbilities = mageObject.getAbilities().getAvailableActivatedManaAbilities(Zone.BATTLEFIELD, playerId, game); if (manaAbilities.size() > 1) { diff --git a/Mage.Sets/src/mage/cards/c/CelestialDawn.java b/Mage.Sets/src/mage/cards/c/CelestialDawn.java index 4b7f53b729..26fe0d830b 100644 --- a/Mage.Sets/src/mage/cards/c/CelestialDawn.java +++ b/Mage.Sets/src/mage/cards/c/CelestialDawn.java @@ -88,7 +88,7 @@ class CelestialDawnToPlainsEffect extends ContinuousEffectImpl { land.addAbility(new WhiteManaAbility(), source.getSourceId(), game); break; case TypeChangingEffects_4: - land.removeAllSubTypes(game,SubTypeSet.NonBasicLandType); + land.removeAllSubTypes(game, SubTypeSet.NonBasicLandType); land.addSubType(game, SubType.PLAINS); break; } @@ -241,7 +241,9 @@ class CelestialDawnSpendColorlessManaEffect extends AsThoughEffectImpl implement public ManaType getAsThoughManaType(ManaType manaType, ManaPoolItem mana, UUID affectedControllerId, Ability source, Game game) { if (mana.getWhite() == 0) { return ManaType.COLORLESS; + } else { + // must return manaType cause applied all the time + return manaType; } - return manaType; } } diff --git a/Mage.Sets/src/mage/cards/d/DraugrNecromancer.java b/Mage.Sets/src/mage/cards/d/DraugrNecromancer.java index fe94d0dff5..6204f78cdc 100644 --- a/Mage.Sets/src/mage/cards/d/DraugrNecromancer.java +++ b/Mage.Sets/src/mage/cards/d/DraugrNecromancer.java @@ -6,9 +6,7 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.AsThoughManaEffect; import mage.abilities.effects.ReplacementEffectImpl; -import mage.cards.Card; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; +import mage.cards.*; import mage.constants.*; import mage.counters.CounterType; import mage.game.CardState; @@ -19,7 +17,6 @@ import mage.game.permanent.Permanent; import mage.game.permanent.PermanentToken; import mage.players.ManaPoolItem; import mage.players.Player; -import mage.util.CardUtil; import java.util.UUID; @@ -167,14 +164,32 @@ class DraugrNecromancerSpendAnyManaEffect extends AsThoughEffectImpl implements || !game.getOpponents(game.getOwnerId(sourceId)).contains(source.getControllerId())) { return false; } + Card card = game.getCard(sourceId); - if (card != null - && game.getState().getZone(card.getId()) == Zone.EXILED - && card.getMainCard().getCounters(game).getCount(CounterType.ICE) > 0) { - return true; + if (card == null) { + return false; + } + card = card.getMainCard(); + + // card can be in exile or stack zones + if (game.getState().getZone(card.getId()) == Zone.EXILED) { + // exile zone + return card.getCounters(game).getCount(CounterType.ICE) > 0; + } else { + // stack zone + // you must look at exile zone (use LKI to see ice counters from the past) + CardState cardState; + if (card instanceof SplitCard) { + cardState = game.getLastKnownInformationCard(card.getId(), Zone.EXILED); + } else if (card instanceof AdventureCard) { + cardState = game.getLastKnownInformationCard(card.getId(), Zone.EXILED); + } else if (card instanceof ModalDoubleFacesCard) { + cardState = game.getLastKnownInformationCard(((ModalDoubleFacesCard) card).getLeftHalfCard().getId(), Zone.EXILED); + } else { + cardState = game.getLastKnownInformationCard(card.getId(), Zone.EXILED); + } + return cardState != null && cardState.getCounters().getCount(CounterType.ICE) > 0; } - CardState cardState = game.getLastKnownInformationCard(CardUtil.getMainCardId(game, sourceId), Zone.EXILED); - return cardState != null && cardState.getCounters().getCount(CounterType.ICE) > 0; } @Override @@ -182,6 +197,6 @@ class DraugrNecromancerSpendAnyManaEffect extends AsThoughEffectImpl implements if (mana.getSourceObject().isSnow()) { return mana.getFirstAvailable(); } - return manaType; + return null; } } diff --git a/Mage.Sets/src/mage/cards/s/SunglassesOfUrza.java b/Mage.Sets/src/mage/cards/s/SunglassesOfUrza.java index 7b5458a7d1..d60f2ef88b 100644 --- a/Mage.Sets/src/mage/cards/s/SunglassesOfUrza.java +++ b/Mage.Sets/src/mage/cards/s/SunglassesOfUrza.java @@ -1,30 +1,24 @@ - package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.AsThoughManaEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.AsThoughEffectType; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.ManaType; -import mage.constants.Outcome; -import mage.constants.Zone; +import mage.constants.*; import mage.game.Game; import mage.players.ManaPoolItem; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class SunglassesOfUrza extends CardImpl { public SunglassesOfUrza(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); // You may spend white mana as though it were red mana. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SunglassesOfUrzaManaAsThoughtEffect())); @@ -62,7 +56,7 @@ class SunglassesOfUrzaManaAsThoughtEffect extends AsThoughEffectImpl implements if (mana.getWhite() > 0 && ManaType.RED == manaType) { return ManaType.WHITE; } - return manaType; + return null; } @Override diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/asthough/AsThoughManaAndAITest.java b/Mage.Tests/src/test/java/org/mage/test/cards/asthough/AsThoughManaAndAITest.java new file mode 100644 index 0000000000..b9c376a726 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/asthough/AsThoughManaAndAITest.java @@ -0,0 +1,34 @@ +package org.mage.test.cards.asthough; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author JayDi85 + */ +public class AsThoughManaAndAITest extends CardTestPlayerBase { + + @Test + public void test_AutoPaymentMustUseAsThoughMana() { + // possible bug: AI auto-payment uses first mana ability from the mana source, so multi-colored lands can be broken + + // You may spend white mana as though it were red mana. + addCard(Zone.BATTLEFIELD, playerA, "Sunglasses of Urza", 1); + // + // {T}: Add {U} or {W}. + addCard(Zone.BATTLEFIELD, playerA, "Sea of Clouds", 1); + addCard(Zone.HAND, playerA, "Lightning Bolt", 1); // {R} + + checkPlayableAbility("before", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Lightning Bolt", true); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertLife(playerB, 20 - 3); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/khm/DraugrNecromancerTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/khm/DraugrNecromancerTest.java index 3d6a51742b..4c188d7bcb 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/khm/DraugrNecromancerTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/khm/DraugrNecromancerTest.java @@ -3,7 +3,6 @@ package org.mage.test.cards.single.khm; import mage.constants.PhaseStep; import mage.constants.Zone; import mage.counters.CounterType; -import org.junit.Ignore; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; @@ -186,16 +185,16 @@ public class DraugrNecromancerTest extends CardTestPlayerBase { @Test public void testCastMDFCFrontFromExile() { addCard(Zone.BATTLEFIELD, playerA, necromancer); - addCard(Zone.BATTLEFIELD, playerA, "Badlands", 6); + addCard(Zone.BATTLEFIELD, playerA, "Badlands", 6); // {B} or {R} addCard(Zone.HAND, playerA, murder); addCard(Zone.HAND, playerB, birgi); addCard(Zone.BATTLEFIELD, playerB, "Mountain", 3); castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, birgi); - castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, murder, birgi); + castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, murder, birgi); // {1}{B}{B} - castSpell(3, PhaseStep.POSTCOMBAT_MAIN, playerA, birgi); + castSpell(3, PhaseStep.POSTCOMBAT_MAIN, playerA, birgi); // {2}{R} setStrictChooseMode(true); setStopAt(3, PhaseStep.END_TURN); @@ -232,7 +231,6 @@ public class DraugrNecromancerTest extends CardTestPlayerBase { assertExileCount(playerB, birgi, 0); } - @Ignore @Test public void testCastMDFCFrontFromExileWithSnow() { addCard(Zone.BATTLEFIELD, playerA, necromancer); @@ -257,7 +255,6 @@ public class DraugrNecromancerTest extends CardTestPlayerBase { assertExileCount(playerB, birgi, 0); } - @Ignore @Test public void testCastMDFCBackFromExileWithSnow() { addCard(Zone.BATTLEFIELD, playerA, necromancer); diff --git a/Mage/src/main/java/mage/abilities/effects/AsThoughManaEffect.java b/Mage/src/main/java/mage/abilities/effects/AsThoughManaEffect.java index 54ac888207..4f8e7e773b 100644 --- a/Mage/src/main/java/mage/abilities/effects/AsThoughManaEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/AsThoughManaEffect.java @@ -1,27 +1,30 @@ - package mage.abilities.effects; -import java.util.UUID; import mage.abilities.Ability; import mage.constants.ManaType; import mage.game.Game; import mage.players.ManaPoolItem; +import java.util.UUID; + /** - * * @author LevelX2 */ public interface AsThoughManaEffect extends AsThoughEffect { - // return a mana type that can be used to pay a mana cost instead of the normally needed mana type /** + * Return a mana type that can be used to pay a mana cost instead of the normally needed mana type + *

+ * Usage instructions: + * - on non applied effect: must return null (example: basic object applied, by you need to check a mana source too, see Draugr Necromancer); + * - on applied effect: must return compatible manaType with ManaPoolItem (e.g. return mana.getFirstAvailable) * - * @param manaType type of mana with which the player wants to pay the cost - * @param mana mana pool item to pay from the cost + * @param manaType type of mana with which the player wants to pay the cost + * @param mana mana pool item to pay from the cost * @param affectedControllerId * @param source * @param game - * @return + * @return null on non applied effect */ ManaType getAsThoughManaType(ManaType manaType, ManaPoolItem mana, UUID affectedControllerId, Ability source, Game game); diff --git a/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java b/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java index 0708a510c4..5560e5fa3c 100644 --- a/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java +++ b/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java @@ -612,6 +612,23 @@ public class ContinuousEffects implements Serializable { return null; } + /** + * Fit paying mana type with current mana pool (if asThoughMana affected) + *

+ * Example: + * - you need to pay {R} as cost + * - asThoughMana effect allows to use {G} as any color; + * - asThoughMana effect must change/fit paying mana type from {R} to {G} + * - after that you can pay {G} as cost + * + * @param manaType paying mana type + * @param mana checking pool item + * @param objectId paying ability's source object + * @param affectedAbility paying ability + * @param controllerId controller who pay + * @param game + * @return corrected paying mana type (same if no asThough effects and different on applied asThough effect) + */ public ManaType asThoughMana(ManaType manaType, ManaPoolItem mana, UUID objectId, Ability affectedAbility, UUID controllerId, Game game) { // First check existing only effects List asThoughEffectsList = getApplicableAsThoughEffects(AsThoughEffectType.SPEND_ONLY_MANA, game); diff --git a/Mage/src/main/java/mage/cards/ModalDoubleFacesCard.java b/Mage/src/main/java/mage/cards/ModalDoubleFacesCard.java index dda16ba35f..34ae3def46 100644 --- a/Mage/src/main/java/mage/cards/ModalDoubleFacesCard.java +++ b/Mage/src/main/java/mage/cards/ModalDoubleFacesCard.java @@ -7,6 +7,7 @@ import mage.abilities.*; import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.ManaCosts; import mage.constants.*; +import mage.counters.Counter; import mage.counters.Counters; import mage.game.Game; import mage.game.GameState; @@ -123,6 +124,16 @@ public abstract class ModalDoubleFacesCard extends CardImpl { return state.getCardState(leftHalfCard.getId()).getCounters(); } + @Override + public boolean addCounters(Counter counter, UUID playerAddingCounters, Ability source, Game game, List appliedEffects, boolean isEffect) { + return leftHalfCard.addCounters(counter, playerAddingCounters, source, game, appliedEffects, isEffect); + } + + @Override + public void removeCounters(String name, int amount, Ability source, Game game) { + leftHalfCard.removeCounters(name, amount, source, game); + } + @Override public boolean cast(Game game, Zone fromZone, SpellAbility ability, UUID controllerId) { switch (ability.getSpellAbilityType()) { diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index c73a583fd8..98b1e439fa 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -2985,39 +2985,25 @@ public abstract class GameImpl implements Game, Serializable { if (object instanceof Permanent || object instanceof StackObject) { MageObject copy = object.copy(); - Map lkiMap = lki.get(zone); - if (lkiMap != null) { - lkiMap.put(objectId, copy); - } else { - Map newMap = new HashMap<>(); - newMap.put(objectId, copy); - lki.put(zone, newMap); - } + Map lkiMap = lki.computeIfAbsent(zone, k -> new HashMap<>()); + lkiMap.put(objectId, copy); + // remembers if a object was in a zone during the resolution of an effect // e.g. Wrath destroys all and you the question is is the replacement effect to apply because the source was also moved by the same effect // because it happens all at the same time the replacement effect has still to be applied Set idSet = shortLivingLKI.computeIfAbsent(zone, k -> new HashSet<>()); idSet.add(objectId); if (object instanceof Permanent) { - Map lkiExtendedMap = lkiExtended.get(objectId); - if (lkiExtendedMap != null) { - lkiExtendedMap.put(object.getZoneChangeCounter(this), copy); - } else { - lkiExtendedMap = new HashMap<>(); - lkiExtendedMap.put(object.getZoneChangeCounter(this), copy); - lkiExtended.put(objectId, lkiExtendedMap); - } + Map lkiExtendedMap = lkiExtended.computeIfAbsent(objectId, k -> new HashMap<>()); + lkiExtendedMap.put(object.getZoneChangeCounter(this), copy); } } else if (zone.isPublicZone()) { // Remember card state in this public zone (mainly removed/gained abilities) - Map lkiMap = lkiCardState.get(zone); - if (lkiMap != null) { - lkiMap.put(objectId, getState().getCardState(objectId)); - } else { - Map newMap = new HashMap<>(); - newMap.put(objectId, getState().getCardState(objectId).copy()); - lkiCardState.put(zone, newMap); - } + // Must save all card parts (mdf, split) + CardUtil.getObjectParts(object).forEach(partId -> { + Map lkiMap = lkiCardState.computeIfAbsent(zone, k -> new HashMap<>()); + lkiMap.put(partId, getState().getCardState(partId).copy()); + }); } } diff --git a/Mage/src/main/java/mage/players/ManaPool.java b/Mage/src/main/java/mage/players/ManaPool.java index 67b87e73ed..187c65f126 100644 --- a/Mage/src/main/java/mage/players/ManaPool.java +++ b/Mage/src/main/java/mage/players/ManaPool.java @@ -339,15 +339,28 @@ public class ManaPool implements Serializable { Mana mana = manaToAdd.copy(); if (!game.replaceEvent(new ManaEvent(EventType.ADD_MANA, source.getId(), source, playerId, mana))) { if (mana instanceof ConditionalMana) { - ManaPoolItem item = new ManaPoolItem((ConditionalMana) mana, source.getSourceObject(game), - ((ConditionalMana) mana).getManaProducerOriginalId() != null - ? ((ConditionalMana) mana).getManaProducerOriginalId() : source.getOriginalId()); + ConditionalMana conditionalMana = (ConditionalMana) mana; + ManaPoolItem item = new ManaPoolItem( + conditionalMana, + source.getSourceObject(game), + conditionalMana.getManaProducerOriginalId() != null ? conditionalMana.getManaProducerOriginalId() : source.getOriginalId() + ); if (emptyOnTurnsEnd) { item.setDuration(Duration.EndOfTurn); } this.manaItems.add(item); } else { - ManaPoolItem item = new ManaPoolItem(mana.getRed(), mana.getGreen(), mana.getBlue(), mana.getWhite(), mana.getBlack(), mana.getGeneric() + mana.getColorless(), source.getSourceObject(game), source.getOriginalId(), mana.getFlag()); + ManaPoolItem item = new ManaPoolItem( + mana.getRed(), + mana.getGreen(), + mana.getBlue(), + mana.getWhite(), + mana.getBlack(), + mana.getGeneric() + mana.getColorless(), + source.getSourceObject(game), + source.getOriginalId(), + mana.getFlag() + ); if (emptyOnTurnsEnd) { item.setDuration(Duration.EndOfTurn); } diff --git a/Mage/src/main/java/mage/util/ManaUtil.java b/Mage/src/main/java/mage/util/ManaUtil.java index 1f7ccddba5..14998a5eb0 100644 --- a/Mage/src/main/java/mage/util/ManaUtil.java +++ b/Mage/src/main/java/mage/util/ManaUtil.java @@ -18,6 +18,7 @@ import mage.cards.ModalDoubleFacesCard; import mage.cards.SplitCard; import mage.choices.Choice; import mage.constants.ColoredManaSymbol; +import mage.constants.ManaType; import mage.filter.FilterMana; import mage.game.Game; import mage.players.Player; @@ -699,6 +700,23 @@ public final class ManaUtil { } else { return 0; } + } + /** + * Find all used mana types in mana cost (wubrg + colorless) + * + * @return + */ + public static List getManaTypesInCost(ManaCost cost) { + List res = new ArrayList<>(); + for (Mana mana : cost.getManaOptions()) { + if (mana.getWhite() > 0) res.add(ManaType.WHITE); + if (mana.getBlue() > 0) res.add(ManaType.BLUE); + if (mana.getBlack() > 0) res.add(ManaType.BLACK); + if (mana.getRed() > 0) res.add(ManaType.RED); + if (mana.getGreen() > 0) res.add(ManaType.GREEN); + if (mana.getColorless() > 0 || mana.getGeneric() > 0 || mana.getAny() > 0) res.add(ManaType.COLORLESS); + } + return res; } }