diff --git a/Mage.Sets/src/mage/cards/m/MyrBattlesphere.java b/Mage.Sets/src/mage/cards/m/MyrBattlesphere.java index 923d1f6a541..03a8a691cce 100644 --- a/Mage.Sets/src/mage/cards/m/MyrBattlesphere.java +++ b/Mage.Sets/src/mage/cards/m/MyrBattlesphere.java @@ -25,7 +25,6 @@ * 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.io.Serializable; @@ -50,9 +49,11 @@ import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.SubtypePredicate; import mage.filter.predicate.permanent.TappedPredicate; import mage.game.Game; +import mage.game.permanent.Permanent; import mage.game.permanent.token.MyrToken; import mage.players.Player; import mage.target.TargetPermanent; +import mage.watchers.common.CreatureAttackedWhichPlayerWatcher; /** * @@ -61,7 +62,7 @@ import mage.target.TargetPermanent; public class MyrBattlesphere extends CardImpl { public MyrBattlesphere(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{7}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{7}"); this.subtype.add(SubType.MYR); this.subtype.add(SubType.CONSTRUCT); this.power = new MageInt(4); @@ -71,7 +72,8 @@ public class MyrBattlesphere extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new MyrToken(), 4), false)); // Whenever Myr Battlesphere attacks, you may tap X untapped Myr you control. If you do, Myr Battlesphere gets +X/+0 until end of turn and deals X damage to defending player. - this.addAbility(new AttacksTriggeredAbility(new MyrBattlesphereEffect(), true)); + this.addAbility(new AttacksTriggeredAbility(new MyrBattlesphereEffect(), true), new CreatureAttackedWhichPlayerWatcher()); + } public MyrBattlesphere(final MyrBattlesphere card) { @@ -107,42 +109,46 @@ class MyrBattlesphereEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - int tappedAmount = 0; - TargetPermanent target = new TargetPermanent(0,1,filter, false); - while (true && controller.canRespond()) { - target.clearChosen(); - if (target.canChoose(source.getControllerId(), game)) { - Map options = new HashMap<>(); - options.put("UI.right.btn.text", "Myr tapping complete"); - controller.choose(outcome, target, source.getControllerId(), game, options); - if (!target.getTargets().isEmpty()) { - UUID creature = target.getFirstTarget(); - if (creature != null) { - game.getPermanent(creature).tap(game); - tappedAmount++; + CreatureAttackedWhichPlayerWatcher watcher = (CreatureAttackedWhichPlayerWatcher) game.getState().getWatchers().get(CreatureAttackedWhichPlayerWatcher.class.getSimpleName()); + if (watcher != null) { + // even if the Myr Battlesphere is off the battlefield, it still does damage to the defender + Permanent myr = game.getPermanentOrLKIBattlefield(source.getSourceId()); + UUID defenderId = watcher.getPlayerAttackedThisTurnByCreature(myr.getId()); + Player defender = game.getPlayer(defenderId); + int tappedAmount = 0; + TargetPermanent target = new TargetPermanent(0, 1, filter, false); + while (true && controller.canRespond()) { + target.clearChosen(); + if (target.canChoose(source.getControllerId(), game)) { + Map options = new HashMap<>(); + options.put("UI.right.btn.text", "Myr tapping complete"); + controller.choose(outcome, target, source.getControllerId(), game, options); + if (!target.getTargets().isEmpty()) { + UUID creature = target.getFirstTarget(); + if (creature != null) { + game.getPermanent(creature).tap(game); + tappedAmount++; + } + } else { + break; } } else { break; } } - else { - break; - } - } - if (tappedAmount > 0) { - game.informPlayers(new StringBuilder(controller.getLogName()).append(" taps ").append(tappedAmount).append(" Myrs").toString()); - // boost effect - game.addEffect(new BoostSourceEffect(tappedAmount, 0, Duration.EndOfTurn), source); - // damage to defender - UUID defenderId = game.getCombat().getDefendingPlayerId(source.getSourceId(), game); - Player defender = game.getPlayer(defenderId); - if (defender != null) { - defender.damage(tappedAmount, source.getSourceId(), game, false, true); - return true; - } + if (tappedAmount > 0) { + game.informPlayers(new StringBuilder(controller.getLogName()).append(" taps ").append(tappedAmount).append(" Myrs").toString()); + // boost effect + game.addEffect(new BoostSourceEffect(tappedAmount, 0, Duration.EndOfTurn), source); + // damage to defender + if (defender != null) { + defender.damage(tappedAmount, myr.getId(), game, false, true); + return true; + } + } + return true; } - return true; } return false; } diff --git a/Mage/src/main/java/mage/watchers/common/CreatureAttackedWhichPlayerWatcher.java b/Mage/src/main/java/mage/watchers/common/CreatureAttackedWhichPlayerWatcher.java new file mode 100644 index 00000000000..7d519e6e043 --- /dev/null +++ b/Mage/src/main/java/mage/watchers/common/CreatureAttackedWhichPlayerWatcher.java @@ -0,0 +1,84 @@ +/* + * 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.watchers.common; + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.UUID; +import mage.constants.WatcherScope; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.watchers.Watcher; + +/** + * @author jeffwadsworth + * + * Return the last player that was attacked by specified creature this turn + */ +public class CreatureAttackedWhichPlayerWatcher extends Watcher { + + private final Map getPlayerAttackedThisTurnByCreature = new HashMap<>(); + + public CreatureAttackedWhichPlayerWatcher() { + super(CreatureAttackedWhichPlayerWatcher.class.getSimpleName(), WatcherScope.GAME); + } + + public CreatureAttackedWhichPlayerWatcher(final CreatureAttackedWhichPlayerWatcher watcher) { + super(watcher); + for (Entry entry : watcher.getPlayerAttackedThisTurnByCreature.entrySet()) { + getPlayerAttackedThisTurnByCreature.put(entry.getKey(), entry.getValue()); + } + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.ATTACKER_DECLARED) { + UUID creatureId = event.getSourceId(); + UUID playerId = event.getTargetId(); + if (playerId != null + && creatureId != null) { + getPlayerAttackedThisTurnByCreature.putIfAbsent(creatureId, playerId); + } + } + } + + public UUID getPlayerAttackedThisTurnByCreature(UUID creatureId) { + return getPlayerAttackedThisTurnByCreature.getOrDefault(creatureId, null); + } + + @Override + public void reset() { + getPlayerAttackedThisTurnByCreature.clear(); + } + + @Override + public CreatureAttackedWhichPlayerWatcher copy() { + return new CreatureAttackedWhichPlayerWatcher(this); + } +}