mirror of
https://github.com/correl/mage.git
synced 2025-01-12 03:00:13 +00:00
* returned UUID of used THOUGHT AS effect instead of boolean.
This commit is contained in:
parent
968b10bd79
commit
92793327f3
19 changed files with 351 additions and 318 deletions
|
@ -108,16 +108,16 @@ public class DeckGeneratorDialog {
|
|||
mainPanel.add(formatSetText, c);
|
||||
|
||||
// Format/set dropdown with search button
|
||||
JPanel setPanel = new JPanel();
|
||||
JPanel setPanel = new JPanel();
|
||||
setPanel.setLayout(new javax.swing.BoxLayout(setPanel, javax.swing.BoxLayout.LINE_AXIS));
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
c.gridx = 1;
|
||||
c.gridy = 1;
|
||||
c.ipadx = 30;
|
||||
c.insets = new Insets(5, 10, 0, 10);
|
||||
c.weightx = 0.80;
|
||||
c.weightx = 0.80;
|
||||
mainPanel.add(setPanel, c);
|
||||
|
||||
|
||||
cbSets = new JComboBox<>(ConstructedFormats.getTypes());
|
||||
cbSets.setSelectedIndex(0);
|
||||
cbSets.setAlignmentX(0.0F);
|
||||
|
@ -127,13 +127,14 @@ public class DeckGeneratorDialog {
|
|||
if (prefSet != null) {
|
||||
cbSets.setSelectedItem(prefSet);
|
||||
}
|
||||
|
||||
|
||||
JButton btn = new JButton();
|
||||
btn.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/search_32.png")));
|
||||
btn.setToolTipText(FastSearchUtil.DEFAULT_EXPANSION_TOOLTIP_MESSAGE);
|
||||
btn.setAlignmentX(1.0F);
|
||||
btn.setPreferredSize(new java.awt.Dimension(32, 32));
|
||||
btn.setAlignmentX(1.0F);
|
||||
btn.setPreferredSize(new java.awt.Dimension(32, 32));
|
||||
btn.addActionListener(new java.awt.event.ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
FastSearchUtil.showFastSearchForStringComboBox(cbSets, FastSearchUtil.DEFAULT_EXPANSION_SEARCH_MESSAGE);
|
||||
}
|
||||
|
|
|
@ -1243,7 +1243,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
|
||||
protected boolean playManaHandling(Ability ability, ManaCost unpaid, Game game) {
|
||||
// log.info("paying for " + unpaid.getText());
|
||||
boolean spendAnyMana = game.getContinuousEffects().asThough(ability.getSourceId(), AsThoughEffectType.SPEND_OTHER_MANA, ability, ability.getControllerId(), game);
|
||||
UUID spendAnyManaId = game.getContinuousEffects().asThough(ability.getSourceId(), AsThoughEffectType.SPEND_OTHER_MANA, ability, ability.getControllerId(), game);
|
||||
ManaCost cost;
|
||||
List<MageObject> producers;
|
||||
if (unpaid instanceof ManaCosts) {
|
||||
|
@ -1285,7 +1285,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
for (ActivatedManaAbilityImpl manaAbility : mageObject.getAbilities().getAvailableActivatedManaAbilities(Zone.BATTLEFIELD, game)) {
|
||||
if (cost instanceof ColoredManaCost) {
|
||||
for (Mana netMana : manaAbility.getNetMana(game)) {
|
||||
if (cost.testPay(netMana) || spendAnyMana) {
|
||||
if (cost.testPay(netMana) || spendAnyManaId != null) {
|
||||
if (activateAbility(manaAbility, game)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -1297,7 +1297,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
for (ActivatedManaAbilityImpl manaAbility : mageObject.getAbilities().getAvailableActivatedManaAbilities(Zone.BATTLEFIELD, game)) {
|
||||
if (cost instanceof SnowManaCost) {
|
||||
for (Mana netMana : manaAbility.getNetMana(game)) {
|
||||
if (cost.testPay(netMana) || spendAnyMana) {
|
||||
if (cost.testPay(netMana) || spendAnyManaId != null) {
|
||||
if (activateAbility(manaAbility, game)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -1309,7 +1309,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
for (ActivatedManaAbilityImpl manaAbility : mageObject.getAbilities().getAvailableActivatedManaAbilities(Zone.BATTLEFIELD, game)) {
|
||||
if (cost instanceof HybridManaCost) {
|
||||
for (Mana netMana : manaAbility.getNetMana(game)) {
|
||||
if (cost.testPay(netMana) || spendAnyMana) {
|
||||
if (cost.testPay(netMana) || spendAnyManaId != null) {
|
||||
if (activateAbility(manaAbility, game)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -1321,7 +1321,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
for (ActivatedManaAbilityImpl manaAbility : mageObject.getAbilities().getAvailableActivatedManaAbilities(Zone.BATTLEFIELD, game)) {
|
||||
if (cost instanceof MonoHybridManaCost) {
|
||||
for (Mana netMana : manaAbility.getNetMana(game)) {
|
||||
if (cost.testPay(netMana) || spendAnyMana) {
|
||||
if (cost.testPay(netMana) || spendAnyManaId != null) {
|
||||
if (activateAbility(manaAbility, game)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -1333,7 +1333,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
for (ActivatedManaAbilityImpl manaAbility : mageObject.getAbilities().getAvailableActivatedManaAbilities(Zone.BATTLEFIELD, game)) {
|
||||
if (cost instanceof ColorlessManaCost) {
|
||||
for (Mana netMana : manaAbility.getNetMana(game)) {
|
||||
if (cost.testPay(netMana) || spendAnyMana) {
|
||||
if (cost.testPay(netMana) || spendAnyManaId != null) {
|
||||
if (activateAbility(manaAbility, game)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -1345,7 +1345,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
for (ActivatedManaAbilityImpl manaAbility : mageObject.getAbilities().getAvailableActivatedManaAbilities(Zone.BATTLEFIELD, game)) {
|
||||
if (cost instanceof GenericManaCost) {
|
||||
for (Mana netMana : manaAbility.getNetMana(game)) {
|
||||
if (cost.testPay(netMana) || spendAnyMana) {
|
||||
if (cost.testPay(netMana) || spendAnyManaId != null) {
|
||||
if (activateAbility(manaAbility, game)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -1356,7 +1356,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
}
|
||||
// pay phyrexian life costs
|
||||
if (cost instanceof PhyrexianManaCost) {
|
||||
if (cost.pay(null, game, null, playerId, false, null) || spendAnyMana) {
|
||||
if (cost.pay(null, game, null, playerId, false, null) || spendAnyManaId != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ package mage.cards.a;
|
|||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.DelayedTriggeredAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
|
@ -46,7 +47,7 @@ import mage.game.Game;
|
|||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.target.Target;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
|
@ -76,8 +77,8 @@ public class AdarkarValkyrie extends CardImpl {
|
|||
this.addAbility(VigilanceAbility.getInstance());
|
||||
// {T}: When target creature other than Adarkar Valkyrie dies this turn, return that card to the battlefield under your control.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AdarkarValkyrieEffect(), new TapSourceCost());
|
||||
Target target = new TargetCreaturePermanent(filter);
|
||||
ability.addTarget(target);
|
||||
|
||||
ability.addTarget(new TargetCreaturePermanent(filter));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
|
@ -109,25 +110,28 @@ class AdarkarValkyrieEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
DelayedTriggeredAbility delayedAbility = new AdarkarValkyrieDelayedTriggeredAbility(getTargetPointer().getFixedTarget(game, source));
|
||||
game.addDelayedTriggeredAbility(delayedAbility, source);
|
||||
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (permanent != null) {
|
||||
DelayedTriggeredAbility delayedAbility = new AdarkarValkyrieDelayedTriggeredAbility(new MageObjectReference(permanent, game));
|
||||
game.addDelayedTriggeredAbility(delayedAbility, source);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class AdarkarValkyrieDelayedTriggeredAbility extends DelayedTriggeredAbility {
|
||||
|
||||
protected FixedTarget fixedTarget;
|
||||
protected MageObjectReference mor;
|
||||
|
||||
public AdarkarValkyrieDelayedTriggeredAbility(FixedTarget fixedTarget) {
|
||||
public AdarkarValkyrieDelayedTriggeredAbility(MageObjectReference mor) {
|
||||
super(new ReturnToBattlefieldUnderYourControlTargetEffect(), Duration.EndOfTurn);
|
||||
this.getEffects().get(0).setTargetPointer(fixedTarget);
|
||||
this.fixedTarget = fixedTarget;
|
||||
this.mor = mor;
|
||||
}
|
||||
|
||||
public AdarkarValkyrieDelayedTriggeredAbility(final AdarkarValkyrieDelayedTriggeredAbility ability) {
|
||||
super(ability);
|
||||
this.fixedTarget = ability.fixedTarget;
|
||||
this.mor = ability.mor;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -142,10 +146,11 @@ class AdarkarValkyrieDelayedTriggeredAbility extends DelayedTriggeredAbility {
|
|||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (((ZoneChangeEvent) event).isDiesEvent()) {
|
||||
if (fixedTarget.getFirst(game, this).equals(event.getTargetId())) {
|
||||
return true;
|
||||
}
|
||||
if (((ZoneChangeEvent) event).isDiesEvent()
|
||||
&& mor.refersTo(((ZoneChangeEvent) event).getTarget(), game)) {
|
||||
getEffects().setTargetPointer(new FixedTarget(event.getTargetId(), game));
|
||||
return true;
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1,230 +1,240 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.cards.m;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.AsThoughEffectImpl;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.choices.Choice;
|
||||
import mage.choices.ChoiceImpl;
|
||||
import mage.constants.AsThoughEffectType;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.players.Player;
|
||||
import mage.watchers.Watcher;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class MuldrothaTheGravetide extends CardImpl {
|
||||
|
||||
public MuldrothaTheGravetide(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{G}{U}");
|
||||
|
||||
this.addSuperType(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.ELEMENTAL);
|
||||
this.subtype.add(SubType.AVATAR);
|
||||
this.power = new MageInt(6);
|
||||
this.toughness = new MageInt(6);
|
||||
|
||||
// During each of your turns, you may play up to one permanent card of each permanent type from your graveyard.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MuldrothaTheGravetideCastFromGraveyardEffect()), new MuldrothaTheGravetideWatcher());
|
||||
}
|
||||
|
||||
public MuldrothaTheGravetide(final MuldrothaTheGravetide card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MuldrothaTheGravetide copy() {
|
||||
return new MuldrothaTheGravetide(this);
|
||||
}
|
||||
}
|
||||
|
||||
class MuldrothaTheGravetideCastFromGraveyardEffect extends AsThoughEffectImpl {
|
||||
|
||||
public MuldrothaTheGravetideCastFromGraveyardEffect() {
|
||||
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.WhileOnBattlefield, Outcome.Benefit);
|
||||
staticText = "During each of your turns, you may play up to one permanent card of each permanent type from your graveyard. "
|
||||
+ "<i>(If a card has multiple permanent types, choose one as you play it.)</i>";
|
||||
}
|
||||
|
||||
public MuldrothaTheGravetideCastFromGraveyardEffect(final MuldrothaTheGravetideCastFromGraveyardEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MuldrothaTheGravetideCastFromGraveyardEffect copy() {
|
||||
return new MuldrothaTheGravetideCastFromGraveyardEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
||||
if (source.getControllerId().equals(affectedControllerId) && Zone.GRAVEYARD.equals(game.getState().getZone(objectId))) {
|
||||
MuldrothaTheGravetideWatcher watcher = (MuldrothaTheGravetideWatcher) game.getState().getWatchers().get(MuldrothaTheGravetideWatcher.class.getSimpleName());
|
||||
MageObject mageObject = game.getObject(objectId);
|
||||
if (mageObject != null && watcher != null) {
|
||||
for (CardType cardType : mageObject.getCardType()) {
|
||||
if (cardType.isPermanentType()) {
|
||||
if (!watcher.permanentTypePlayedFromGraveyard(affectedControllerId, cardType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class MuldrothaTheGravetideWatcher extends Watcher {
|
||||
|
||||
final HashMap<UUID, Set<CardType>> playerPlayedPermanentTypes = new HashMap<>(); // player that played permanent types from graveyard
|
||||
private Zone fromZone;
|
||||
|
||||
public MuldrothaTheGravetideWatcher() {
|
||||
super(MuldrothaTheGravetideWatcher.class.getSimpleName(), WatcherScope.GAME);
|
||||
}
|
||||
|
||||
public MuldrothaTheGravetideWatcher(final MuldrothaTheGravetideWatcher watcher) {
|
||||
super(watcher);
|
||||
playerPlayedPermanentTypes.putAll(watcher.playerPlayedPermanentTypes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MuldrothaTheGravetideWatcher copy() {
|
||||
return new MuldrothaTheGravetideWatcher(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (event.getType() == GameEvent.EventType.PLAY_LAND) {
|
||||
fromZone = game.getState().getZone(event.getTargetId()); // Remember the Zone the land came from
|
||||
}
|
||||
if (event.getType() == GameEvent.EventType.LAND_PLAYED && fromZone.equals(Zone.GRAVEYARD)) {
|
||||
addPermanentTypes(game.getPermanentOrLKIBattlefield(event.getTargetId()), game);
|
||||
}
|
||||
|
||||
if (event.getType() == GameEvent.EventType.SPELL_CAST) {
|
||||
Spell spell = (Spell) game.getObject(event.getTargetId());
|
||||
if (spell.getFromZone().equals(Zone.GRAVEYARD)) {
|
||||
addPermanentTypes(spell, game);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addPermanentTypes(Card mageObject, Game game) {
|
||||
if (mageObject != null) {
|
||||
UUID playerId = null;
|
||||
if (mageObject instanceof Spell) {
|
||||
playerId = ((Spell) mageObject).getControllerId();
|
||||
} else if (mageObject instanceof Permanent) {
|
||||
playerId = ((Permanent) mageObject).getControllerId();
|
||||
}
|
||||
if (playerId != null) {
|
||||
Set<CardType> permanentTypes = playerPlayedPermanentTypes.get(playerId);
|
||||
if (permanentTypes == null) {
|
||||
permanentTypes = EnumSet.noneOf(CardType.class);
|
||||
playerPlayedPermanentTypes.put(playerId, permanentTypes);
|
||||
}
|
||||
Set<CardType> typesNotCast = EnumSet.noneOf(CardType.class);
|
||||
for (CardType cardType : mageObject.getCardType()) {
|
||||
if (cardType.isPermanentType()) {
|
||||
if (!permanentTypes.contains(cardType)) {
|
||||
typesNotCast.add(cardType);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (typesNotCast.size() <= 1) {
|
||||
permanentTypes.addAll(typesNotCast);
|
||||
} else {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null) {
|
||||
Choice typeChoice = new ChoiceImpl(true);
|
||||
typeChoice.setMessage("Choose permanent type you consume for casting from graveyard.");
|
||||
for (CardType cardType : typesNotCast) {
|
||||
typeChoice.getChoices().add(cardType.toString());
|
||||
}
|
||||
if (player.choose(Outcome.Detriment, typeChoice, game)) {
|
||||
String typeName = typeChoice.getChoice();
|
||||
CardType chosenType = null;
|
||||
for (CardType cardType : CardType.values()) {
|
||||
if (cardType.toString().equals(typeName)) {
|
||||
chosenType = cardType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (chosenType != null) {
|
||||
permanentTypes.add(chosenType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
playerPlayedPermanentTypes.clear();
|
||||
super.reset();
|
||||
}
|
||||
|
||||
public boolean permanentTypePlayedFromGraveyard(UUID playerId, CardType cardType) {
|
||||
Set<CardType> permanentTypes = playerPlayedPermanentTypes.get(playerId);
|
||||
if (permanentTypes != null) {
|
||||
return permanentTypes.contains(cardType);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.cards.m;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.AsThoughEffectImpl;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.choices.Choice;
|
||||
import mage.choices.ChoiceImpl;
|
||||
import mage.constants.AsThoughEffectType;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.players.Player;
|
||||
import mage.watchers.Watcher;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class MuldrothaTheGravetide extends CardImpl {
|
||||
|
||||
public MuldrothaTheGravetide(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{G}{U}");
|
||||
|
||||
this.addSuperType(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.ELEMENTAL);
|
||||
this.subtype.add(SubType.AVATAR);
|
||||
this.power = new MageInt(6);
|
||||
this.toughness = new MageInt(6);
|
||||
|
||||
// During each of your turns, you may play up to one permanent card of each permanent type from your graveyard.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MuldrothaTheGravetideCastFromGraveyardEffect()), new MuldrothaTheGravetideWatcher());
|
||||
}
|
||||
|
||||
public MuldrothaTheGravetide(final MuldrothaTheGravetide card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MuldrothaTheGravetide copy() {
|
||||
return new MuldrothaTheGravetide(this);
|
||||
}
|
||||
}
|
||||
|
||||
class MuldrothaTheGravetideCastFromGraveyardEffect extends AsThoughEffectImpl {
|
||||
|
||||
public MuldrothaTheGravetideCastFromGraveyardEffect() {
|
||||
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.WhileOnBattlefield, Outcome.Benefit);
|
||||
staticText = "During each of your turns, you may play up to one permanent card of each permanent type from your graveyard. "
|
||||
+ "<i>(If a card has multiple permanent types, choose one as you play it.)</i>";
|
||||
}
|
||||
|
||||
public MuldrothaTheGravetideCastFromGraveyardEffect(final MuldrothaTheGravetideCastFromGraveyardEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MuldrothaTheGravetideCastFromGraveyardEffect copy() {
|
||||
return new MuldrothaTheGravetideCastFromGraveyardEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
||||
if (source.getControllerId().equals(affectedControllerId)
|
||||
&& affectedControllerId.equals(game.getActivePlayerId()) // only during your turns (e.g. prevent flash creatures)
|
||||
&& Zone.GRAVEYARD.equals(game.getState().getZone(objectId))) {
|
||||
MuldrothaTheGravetideWatcher watcher = (MuldrothaTheGravetideWatcher) game.getState().getWatchers().get(MuldrothaTheGravetideWatcher.class.getSimpleName());
|
||||
MageObject mageObject = game.getObject(objectId);
|
||||
if (mageObject != null && watcher != null) {
|
||||
for (CardType cardType : mageObject.getCardType()) {
|
||||
if (cardType.isPermanentType()) {
|
||||
if (!watcher.permanentTypePlayedFromGraveyard(affectedControllerId, cardType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds track of the consumed types of each permission giving source
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
class MuldrothaTheGravetideWatcher extends Watcher {
|
||||
|
||||
// final HashMap<MageObjectReference, Set<CardType>> playerPlayedPermanentTypes = new HashMap<>(); // source that played permanent types from graveyard
|
||||
final HashMap<UUID, Set<CardType>> playerPlayedPermanentTypes = new HashMap<>(); // player that played permanent types from graveyard
|
||||
// 4/27/2018 If multiple effects allow you to play a card from your graveyard, such as those of Gisa and Geralf and Karador,
|
||||
// Ghost Chieftain, you must announce which permission you’re using as you begin to play the card.
|
||||
private Zone fromZone;
|
||||
|
||||
public MuldrothaTheGravetideWatcher() {
|
||||
super(MuldrothaTheGravetideWatcher.class.getSimpleName(), WatcherScope.GAME);
|
||||
}
|
||||
|
||||
public MuldrothaTheGravetideWatcher(final MuldrothaTheGravetideWatcher watcher) {
|
||||
super(watcher);
|
||||
playerPlayedPermanentTypes.putAll(watcher.playerPlayedPermanentTypes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MuldrothaTheGravetideWatcher copy() {
|
||||
return new MuldrothaTheGravetideWatcher(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (event.getType() == GameEvent.EventType.PLAY_LAND) {
|
||||
fromZone = game.getState().getZone(event.getTargetId()); // Remember the Zone the land came from
|
||||
}
|
||||
if (event.getType() == GameEvent.EventType.LAND_PLAYED && fromZone.equals(Zone.GRAVEYARD)) {
|
||||
addPermanentTypes(event, game.getPermanentOrLKIBattlefield(event.getTargetId()), game);
|
||||
}
|
||||
|
||||
if (event.getType() == GameEvent.EventType.SPELL_CAST) {
|
||||
Spell spell = (Spell) game.getObject(event.getTargetId());
|
||||
if (spell.getFromZone().equals(Zone.GRAVEYARD)) {
|
||||
addPermanentTypes(event, spell, game);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addPermanentTypes(GameEvent event, Card mageObject, Game game) {
|
||||
if (mageObject != null) {
|
||||
UUID playerId = null;
|
||||
if (mageObject instanceof Spell) {
|
||||
playerId = ((Spell) mageObject).getControllerId();
|
||||
} else if (mageObject instanceof Permanent) {
|
||||
playerId = ((Permanent) mageObject).getControllerId();
|
||||
}
|
||||
if (playerId != null) {
|
||||
Set<CardType> permanentTypes = playerPlayedPermanentTypes.get(playerId);
|
||||
if (permanentTypes == null) {
|
||||
permanentTypes = EnumSet.noneOf(CardType.class);
|
||||
playerPlayedPermanentTypes.put(playerId, permanentTypes);
|
||||
}
|
||||
Set<CardType> typesNotCast = EnumSet.noneOf(CardType.class);
|
||||
for (CardType cardType : mageObject.getCardType()) {
|
||||
if (cardType.isPermanentType()) {
|
||||
if (!permanentTypes.contains(cardType)) {
|
||||
typesNotCast.add(cardType);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (typesNotCast.size() <= 1) {
|
||||
permanentTypes.addAll(typesNotCast);
|
||||
} else {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null) {
|
||||
Choice typeChoice = new ChoiceImpl(true);
|
||||
typeChoice.setMessage("Choose permanent type you consume for casting from graveyard.");
|
||||
for (CardType cardType : typesNotCast) {
|
||||
typeChoice.getChoices().add(cardType.toString());
|
||||
}
|
||||
if (player.choose(Outcome.Detriment, typeChoice, game)) {
|
||||
String typeName = typeChoice.getChoice();
|
||||
CardType chosenType = null;
|
||||
for (CardType cardType : CardType.values()) {
|
||||
if (cardType.toString().equals(typeName)) {
|
||||
chosenType = cardType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (chosenType != null) {
|
||||
permanentTypes.add(chosenType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
playerPlayedPermanentTypes.clear();
|
||||
super.reset();
|
||||
}
|
||||
|
||||
public boolean permanentTypePlayedFromGraveyard(UUID playerId, CardType cardType) {
|
||||
Set<CardType> permanentTypes = playerPlayedPermanentTypes.get(playerId);
|
||||
if (permanentTypes != null) {
|
||||
return permanentTypes.contains(cardType);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ class CantBeBlockedUnlessAllEffect extends RestrictionEffect {
|
|||
// check if all creatures of defender are able to block this permanent
|
||||
// permanent.canBlock() can't be used because causing recursive call
|
||||
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, blocker.getControllerId(), game)) {
|
||||
if (permanent.isTapped() && !game.getState().getContinuousEffects().asThough(this.getId(), AsThoughEffectType.BLOCK_TAPPED, source, blocker.getControllerId(), game)) {
|
||||
if (permanent.isTapped() && null == game.getState().getContinuousEffects().asThough(this.getId(), AsThoughEffectType.BLOCK_TAPPED, source, blocker.getControllerId(), game)) {
|
||||
return false;
|
||||
}
|
||||
// check blocker restrictions
|
||||
|
|
|
@ -220,7 +220,7 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa
|
|||
}
|
||||
//20091005 - 602.5d/602.5e
|
||||
if (timing == TimingRule.INSTANT || game.canPlaySorcery(playerId)
|
||||
|| game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.ACTIVATE_AS_INSTANT, this, controllerId, game)) {
|
||||
|| null != game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.ACTIVATE_AS_INSTANT, this, controllerId, game)) {
|
||||
if (costs.canPay(this, sourceId, playerId, game) && canChooseTarget(game)) {
|
||||
this.activatorId = playerId;
|
||||
return true;
|
||||
|
|
|
@ -52,7 +52,7 @@ public class PlayLandAbility extends ActivatedAbilityImpl {
|
|||
@Override
|
||||
public boolean canActivate(UUID playerId, Game game) {
|
||||
if (!controlsAbility(playerId, game)
|
||||
&& !game.getContinuousEffects().asThough(getSourceId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, playerId, game)) {
|
||||
&& null == game.getContinuousEffects().asThough(getSourceId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, playerId, game)) {
|
||||
return false;
|
||||
}
|
||||
//20091005 - 114.2a
|
||||
|
|
|
@ -92,13 +92,13 @@ public class SpellAbility extends ActivatedAbilityImpl {
|
|||
|
||||
@Override
|
||||
public boolean canActivate(UUID playerId, Game game) {
|
||||
if (game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.CAST_AS_INSTANT, this, playerId, game) // check this first to allow Offering in main phase
|
||||
if (null != game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.CAST_AS_INSTANT, this, playerId, game) // check this first to allow Offering in main phase
|
||||
|| this.spellCanBeActivatedRegularlyNow(playerId, game)) {
|
||||
if (spellAbilityType == SpellAbilityType.SPLIT || spellAbilityType == SpellAbilityType.SPLIT_AFTERMATH) {
|
||||
return false;
|
||||
}
|
||||
// fix for Gitaxian Probe and casting opponent's spells
|
||||
if (!game.getContinuousEffects().asThough(getSourceId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, playerId, game)) {
|
||||
if (null == game.getContinuousEffects().asThough(getSourceId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, playerId, game)) {
|
||||
Card card = game.getCard(sourceId);
|
||||
if (!(card != null && card.getOwnerId().equals(playerId))) {
|
||||
return false;
|
||||
|
|
|
@ -24,8 +24,7 @@
|
|||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
*/
|
||||
package mage.abilities.costs.common;
|
||||
|
||||
import java.util.UUID;
|
||||
|
@ -63,8 +62,8 @@ public class TapSourceCost extends CostImpl {
|
|||
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
|
||||
Permanent permanent = game.getPermanent(sourceId);
|
||||
if (permanent != null) {
|
||||
return !permanent.isTapped() &&
|
||||
(permanent.canTap() || game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.ACTIVATE_HASTE, controllerId, game));
|
||||
return !permanent.isTapped()
|
||||
&& (permanent.canTap() || null != game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.ACTIVATE_HASTE, controllerId, game));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ public class UntapSourceCost extends CostImpl {
|
|||
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
|
||||
Permanent permanent = game.getPermanent(sourceId);
|
||||
if (permanent != null) {
|
||||
return permanent.isTapped() && (permanent.canTap() || game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.ACTIVATE_HASTE, controllerId, game));
|
||||
return permanent.isTapped() && (permanent.canTap() || null != game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.ACTIVATE_HASTE, controllerId, game));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -500,25 +500,44 @@ public class ContinuousEffects implements Serializable {
|
|||
return spliceEffects;
|
||||
}
|
||||
|
||||
public boolean asThough(UUID objectId, AsThoughEffectType type, UUID controllerId, Game game) {
|
||||
/**
|
||||
*
|
||||
* @param objectId
|
||||
* @param type
|
||||
* @param controllerId
|
||||
* @param game
|
||||
* @return sourceId of the permitting effect if any exists otherwise returns
|
||||
* null
|
||||
*/
|
||||
public UUID asThough(UUID objectId, AsThoughEffectType type, UUID controllerId, Game game) {
|
||||
return asThough(objectId, type, null, controllerId, game);
|
||||
}
|
||||
|
||||
public boolean asThough(UUID objectId, AsThoughEffectType type, Ability affectedAbility, UUID controllerId, Game game) {
|
||||
/**
|
||||
*
|
||||
* @param objectId
|
||||
* @param type
|
||||
* @param affectedAbility
|
||||
* @param controllerId
|
||||
* @param game
|
||||
* @return sourceId of the permitting effect if any exists otherwise returns
|
||||
* null
|
||||
*/
|
||||
public UUID asThough(UUID objectId, AsThoughEffectType type, Ability affectedAbility, UUID controllerId, Game game) {
|
||||
List<AsThoughEffect> asThoughEffectsList = getApplicableAsThoughEffects(type, game);
|
||||
for (AsThoughEffect effect : asThoughEffectsList) {
|
||||
Set<Ability> abilities = asThoughEffectsMap.get(type).getAbility(effect.getId());
|
||||
for (Ability ability : abilities) {
|
||||
if (affectedAbility == null) {
|
||||
if (effect.applies(objectId, ability, controllerId, game)) {
|
||||
return true;
|
||||
return ability.getSourceId();
|
||||
}
|
||||
} else if (effect.applies(objectId, affectedAbility, ability, game)) {
|
||||
return true;
|
||||
return ability.getSourceId();
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
|
@ -754,7 +773,7 @@ public class ContinuousEffects implements Serializable {
|
|||
// Remove all consumed effects (ability dependant)
|
||||
for (Iterator<ReplacementEffect> it1 = rEffects.keySet().iterator(); it1.hasNext();) {
|
||||
ReplacementEffect entry = it1.next();
|
||||
if (consumed.containsKey(entry.getId()) /*&& !(entry instanceof CommanderReplacementEffect) */) { // 903.9.
|
||||
if (consumed.containsKey(entry.getId()) /*&& !(entry instanceof CommanderReplacementEffect) */) { // 903.9.
|
||||
Set<UUID> consumedAbilitiesIds = consumed.get(entry.getId());
|
||||
if (rEffects.get(entry) == null || consumedAbilitiesIds.size() == rEffects.get(entry).size()) {
|
||||
it1.remove();
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
*/
|
||||
package mage.abilities.keyword;
|
||||
|
||||
import java.io.ObjectStreamException;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.EvasionAbility;
|
||||
import mage.abilities.MageSingleton;
|
||||
|
@ -37,8 +38,6 @@ import mage.constants.SubType;
|
|||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.io.ObjectStreamException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
@ -90,7 +89,8 @@ class FlyingEffect extends RestrictionEffect implements MageSingleton {
|
|||
public boolean canBeBlocked(Permanent attacker, Permanent blocker, Ability source, Game game) {
|
||||
return blocker.getAbilities().containsKey(FlyingAbility.getInstance().getId())
|
||||
|| blocker.getAbilities().containsKey(ReachAbility.getInstance().getId())
|
||||
|| (game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_DRAGON, source, blocker.getControllerId(), game) && attacker.hasSubtype(SubType.DRAGON, game));
|
||||
|| (null != game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_DRAGON, source, blocker.getControllerId(), game)
|
||||
&& attacker.hasSubtype(SubType.DRAGON, game));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -88,21 +88,21 @@ class LandwalkEffect extends RestrictionEffect {
|
|||
@Override
|
||||
public boolean canBeBlocked(Permanent attacker, Permanent blocker, Ability source, Game game) {
|
||||
if (game.getBattlefield().contains(filter, blocker.getControllerId(), 1, game)
|
||||
&& !game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_LANDWALK, source, blocker.getControllerId(), game)) {
|
||||
&& null == game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_LANDWALK, source, blocker.getControllerId(), game)) {
|
||||
switch (filter.getMessage()) {
|
||||
case "plains":
|
||||
return game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_PLAINSWALK, source, blocker.getControllerId(), game);
|
||||
return null != game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_PLAINSWALK, source, blocker.getControllerId(), game);
|
||||
case "island":
|
||||
return game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_ISLANDWALK, source, blocker.getControllerId(), game);
|
||||
return null != game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_ISLANDWALK, source, blocker.getControllerId(), game);
|
||||
case "swamp":
|
||||
return game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_SWAMPWALK, source, blocker.getControllerId(), game);
|
||||
return null != game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_SWAMPWALK, source, blocker.getControllerId(), game);
|
||||
case "mountain":
|
||||
return game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_MOUNTAINWALK, source, blocker.getControllerId(), game);
|
||||
return null != game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_MOUNTAINWALK, source, blocker.getControllerId(), game);
|
||||
case "forest":
|
||||
return game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_FORESTWALK, source, blocker.getControllerId(), game);
|
||||
return null != game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_FORESTWALK, source, blocker.getControllerId(), game);
|
||||
default:
|
||||
return false;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -66,7 +66,7 @@ class ShadowEffect extends RestrictionEffect implements MageSingleton {
|
|||
@Override
|
||||
public boolean canBeBlocked(Permanent attacker, Permanent blocker, Ability source, Game game) {
|
||||
return blocker.getAbilities().containsKey(ShadowAbility.getInstance().getId())
|
||||
|| game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_SHADOW, source, blocker.getControllerId(), game);
|
||||
|| null != game.getContinuousEffects().asThough(blocker.getId(), AsThoughEffectType.BLOCK_SHADOW, source, blocker.getControllerId(), game);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
*/
|
||||
package mage.abilities.keyword;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpecialAction;
|
||||
|
@ -50,10 +53,6 @@ import mage.game.permanent.Permanent;
|
|||
import mage.players.Player;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* 502.59. Suspend
|
||||
|
@ -120,10 +119,10 @@ import java.util.UUID;
|
|||
* card involves an additional cost, the card's owner must pay that cost if
|
||||
* able. If he or she can't, the card remains removed from the game. If the
|
||||
* additional cost includes mana, the situation is more complex. If the player
|
||||
* has enough mana in their mana pool to pay the cost, that player must do
|
||||
* so. If the player can't possibly pay the cost, the card remains removed from
|
||||
* the game. However, if the player has the means to produce enough mana to pay
|
||||
* the cost, then he or she has a choice: The player may play the spell, produce
|
||||
* has enough mana in their mana pool to pay the cost, that player must do so.
|
||||
* If the player can't possibly pay the cost, the card remains removed from the
|
||||
* game. However, if the player has the means to produce enough mana to pay the
|
||||
* cost, then he or she has a choice: The player may play the spell, produce
|
||||
* mana, and pay the cost. Or the player may choose to play no mana abilities,
|
||||
* thus making the card impossible to play because the additional mana can't be
|
||||
* paid.
|
||||
|
@ -237,7 +236,7 @@ public class SuspendAbility extends SpecialAction {
|
|||
MageObject object = game.getObject(sourceId);
|
||||
return (object.isInstant()
|
||||
|| object.hasAbility(FlashAbility.getInstance().getId(), game)
|
||||
|| game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.CAST_AS_INSTANT, this, playerId, game)
|
||||
|| null != game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.CAST_AS_INSTANT, this, playerId, game)
|
||||
|| game.canPlaySorcery(playerId));
|
||||
}
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ public abstract class ActivatedManaAbilityImpl extends ActivatedAbilityImpl impl
|
|||
}
|
||||
if (timing == TimingRule.SORCERY
|
||||
&& !game.canPlaySorcery(playerId)
|
||||
&& !game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.ACTIVATE_AS_INSTANT, this, controllerId, game)) {
|
||||
&& null == game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.ACTIVATE_AS_INSTANT, this, controllerId, game)) {
|
||||
return false;
|
||||
}
|
||||
// check if player is in the process of playing spell costs and he is no longer allowed to use activated mana abilities (e.g. because he started to use improvise)
|
||||
|
|
|
@ -24,8 +24,7 @@
|
|||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
*/
|
||||
package mage.filter.common;
|
||||
|
||||
import mage.constants.AsThoughEffectType;
|
||||
|
@ -61,8 +60,8 @@ public class FilterCreatureForCombatBlock extends FilterCreatureForCombatBase {
|
|||
class BlockTappedPredicate implements Predicate<Permanent> {
|
||||
|
||||
@Override
|
||||
public boolean apply(Permanent input, Game game) {
|
||||
return !input.isTapped() || game.getState().getContinuousEffects().asThough(input.getId(), AsThoughEffectType.BLOCK_TAPPED, input.getControllerId(), game);
|
||||
public boolean apply(Permanent input, Game game) {
|
||||
return !input.isTapped() || null != game.getState().getContinuousEffects().asThough(input.getId(), AsThoughEffectType.BLOCK_TAPPED, input.getControllerId(), game);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -935,20 +935,20 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
public boolean canBeTargetedBy(MageObject source, UUID sourceControllerId, Game game) {
|
||||
if (source != null) {
|
||||
if (abilities.containsKey(ShroudAbility.getInstance().getId())) {
|
||||
if (!game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.SHROUD, sourceControllerId, game)) {
|
||||
if (null == game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.SHROUD, sourceControllerId, game)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (abilities.containsKey(HexproofAbility.getInstance().getId())) {
|
||||
if (game.getPlayer(this.getControllerId()).hasOpponent(sourceControllerId, game)
|
||||
&& !game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.HEXPROOF, sourceControllerId, game)) {
|
||||
&& null == game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.HEXPROOF, sourceControllerId, game)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (abilities.containsKey(HexproofFromBlackAbility.getInstance().getId())) {
|
||||
if (game.getPlayer(this.getControllerId()).hasOpponent(sourceControllerId, game)
|
||||
&& !game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.HEXPROOF, sourceControllerId, game)
|
||||
&& null == game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.HEXPROOF, sourceControllerId, game)
|
||||
&& source.getColor(game).isBlack()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -956,7 +956,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
|
||||
if (abilities.containsKey(HexproofFromWhiteAbility.getInstance().getId())) {
|
||||
if (game.getPlayer(this.getControllerId()).hasOpponent(sourceControllerId, game)
|
||||
&& !game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.HEXPROOF, sourceControllerId, game)
|
||||
&& null == game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.HEXPROOF, sourceControllerId, game)
|
||||
&& source.getColor(game).isWhite()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1095,7 +1095,8 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
|
||||
@Override
|
||||
public boolean canAttackInPrinciple(UUID defenderId, Game game) {
|
||||
if (hasSummoningSickness() && !game.getContinuousEffects().asThough(this.objectId, AsThoughEffectType.ATTACK_AS_HASTE, this.getControllerId(), game)) {
|
||||
if (hasSummoningSickness()
|
||||
&& null == game.getContinuousEffects().asThough(this.objectId, AsThoughEffectType.ATTACK_AS_HASTE, this.getControllerId(), game)) {
|
||||
return false;
|
||||
}
|
||||
//20101001 - 508.1c
|
||||
|
@ -1115,7 +1116,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
}
|
||||
|
||||
return !abilities.containsKey(DefenderAbility.getInstance().getId())
|
||||
|| game.getContinuousEffects().asThough(this.objectId, AsThoughEffectType.ATTACK, this.getControllerId(), game);
|
||||
|| null != game.getContinuousEffects().asThough(this.objectId, AsThoughEffectType.ATTACK, this.getControllerId(), game);
|
||||
}
|
||||
|
||||
private boolean canAttackCheckRestrictionEffects(UUID defenderId, Game game) {
|
||||
|
@ -1135,7 +1136,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
|
||||
@Override
|
||||
public boolean canBlock(UUID attackerId, Game game) {
|
||||
if (tapped && !game.getState().getContinuousEffects().asThough(this.getId(), AsThoughEffectType.BLOCK_TAPPED, this.getControllerId(), game)) {
|
||||
if (tapped && null == game.getState().getContinuousEffects().asThough(this.getId(), AsThoughEffectType.BLOCK_TAPPED, this.getControllerId(), game)) {
|
||||
return false;
|
||||
}
|
||||
Permanent attacker = game.getPermanent(attackerId);
|
||||
|
@ -1168,7 +1169,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
|
||||
@Override
|
||||
public boolean canBlockAny(Game game) {
|
||||
if (tapped && !game.getState().getContinuousEffects().asThough(this.getId(), AsThoughEffectType.BLOCK_TAPPED, this.getControllerId(), game)) {
|
||||
if (tapped && null == game.getState().getContinuousEffects().asThough(this.getId(), AsThoughEffectType.BLOCK_TAPPED, this.getControllerId(), game)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,6 @@ import java.io.Serializable;
|
|||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import static jdk.nashorn.internal.objects.NativeRegExp.source;
|
||||
import mage.ConditionalMana;
|
||||
import mage.MageObject;
|
||||
import mage.Mana;
|
||||
|
@ -610,7 +609,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
}
|
||||
if (abilities.containsKey(HexproofAbility.getInstance().getId())) {
|
||||
if (sourceControllerId != null && this.hasOpponent(sourceControllerId, game)
|
||||
&& !game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.HEXPROOF, this.getId(), game)) {
|
||||
&& null == game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.HEXPROOF, this.getId(), game)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1356,7 +1355,8 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (zone != Zone.BATTLEFIELD && game.getContinuousEffects().asThough(object.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, this.getId(), game)) {
|
||||
if (zone != Zone.BATTLEFIELD
|
||||
&& null != game.getContinuousEffects().asThough(object.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, this.getId(), game)) {
|
||||
for (Ability ability : candidateAbilites) {
|
||||
if (canUse || ability.getAbilityType() == AbilityType.SPECIAL_ACTION) {
|
||||
ability.setControllerId(this.getId());
|
||||
|
@ -2706,10 +2706,10 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
if (available == null) {
|
||||
return true;
|
||||
}
|
||||
boolean spendAnyMana = game.getContinuousEffects().asThough(ability.getSourceId(), AsThoughEffectType.SPEND_OTHER_MANA, ability, ability.getControllerId(), game);
|
||||
UUID spendAnyManaSourceId = game.getContinuousEffects().asThough(ability.getSourceId(), AsThoughEffectType.SPEND_OTHER_MANA, ability, ability.getControllerId(), game);
|
||||
for (Mana mana : abilityOptions) {
|
||||
for (Mana avail : available) {
|
||||
if (spendAnyMana && mana.count() <= avail.count()) {
|
||||
if (spendAnyManaSourceId != null && mana.count() <= avail.count()) {
|
||||
return true;
|
||||
}
|
||||
if (mana.enough(avail)) { // here we need to check if spend mana as though allow to pay the mana cost
|
||||
|
@ -2834,13 +2834,13 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
}
|
||||
|
||||
private void getPlayableFromGraveyardCard(Game game, Card card, Abilities<Ability> candidateAbilities, ManaOptions availableMana, List<Ability> output) {
|
||||
boolean asThoughtCast = game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, this.getId(), game);
|
||||
UUID asThoughtCastSourceId = game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, this.getId(), game);
|
||||
for (ActivatedAbility ability : candidateAbilities.getActivatedAbilities(Zone.ALL)) {
|
||||
boolean possible = false;
|
||||
if (ability.getZone().match(Zone.GRAVEYARD)) {
|
||||
possible = true;
|
||||
} else if (ability.getZone().match(Zone.HAND) && (ability instanceof SpellAbility || ability instanceof PlayLandAbility)) {
|
||||
if (asThoughtCast || canPlayCardsFromGraveyard()) {
|
||||
if (asThoughtCastSourceId != null || canPlayCardsFromGraveyard()) {
|
||||
possible = true;
|
||||
}
|
||||
}
|
||||
|
@ -2909,7 +2909,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
}
|
||||
for (ExileZone exile : game.getExile().getExileZones()) {
|
||||
for (Card card : exile.getCards(game)) {
|
||||
if (game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, this.getId(), game)) {
|
||||
if (null != game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, this.getId(), game)) {
|
||||
for (Ability ability : card.getAbilities()) {
|
||||
if (ability.getZone().match(Zone.HAND)) {
|
||||
ability.setControllerId(this.getId()); // controller must be set for case owner != caster
|
||||
|
@ -2927,7 +2927,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
// Check to play revealed cards
|
||||
for (Cards cards : game.getState().getRevealed().values()) {
|
||||
for (Card card : cards.getCards(game)) {
|
||||
if (game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, this.getId(), game)) {
|
||||
if (null != game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, this.getId(), game)) {
|
||||
for (ActivatedAbility ability : card.getAbilities().getActivatedAbilities(Zone.HAND)) {
|
||||
if (ability instanceof SpellAbility || ability instanceof PlayLandAbility) {
|
||||
playable.add(ability);
|
||||
|
@ -2942,7 +2942,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
if (player != null) {
|
||||
if (/*player.isTopCardRevealed() &&*/player.getLibrary().hasCards()) {
|
||||
Card card = player.getLibrary().getFromTop(game);
|
||||
if (game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, getId(), game)) {
|
||||
if (null != game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, getId(), game)) {
|
||||
for (ActivatedAbility ability : card.getAbilities().getActivatedAbilities(Zone.HAND)) {
|
||||
if (ability instanceof SpellAbility || ability instanceof PlayLandAbility) {
|
||||
playable.add(ability);
|
||||
|
@ -3295,7 +3295,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
@Override
|
||||
public boolean lookAtFaceDownCard(Card card, Game game
|
||||
) {
|
||||
if (game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.LOOK_AT_FACE_DOWN, this.getId(), game)) {
|
||||
if (null != game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.LOOK_AT_FACE_DOWN, this.getId(), game)) {
|
||||
if (chooseUse(Outcome.Benefit, "Look at that card?", null, game)) {
|
||||
Cards cards = new CardsImpl(card);
|
||||
this.lookAtCards(getName() + " - " + sdf.format(System.currentTimeMillis()), cards, game);
|
||||
|
|
Loading…
Reference in a new issue