Merge origin/master

This commit is contained in:
LevelX2 2015-09-29 11:25:28 +02:00
commit 6ec008c58b
10 changed files with 213 additions and 144 deletions

View file

@ -64,11 +64,12 @@ public class DuelCommander extends Commander {
banned.add("Mox Pearl");
banned.add("Mox Ruby");
banned.add("Mox Sapphire");
banned.add("Mystical Tutor"); // banned effective July 17, 2015
banned.add("Mystical Tutor");
banned.add("Natural Order");
banned.add("Necropotence");
banned.add("Oath of Druids");
banned.add("Protean Hulk");
banned.add("Sensei's Divining Top");
banned.add("Serra Ascendant");
banned.add("Shahrazad");
banned.add("Sol Ring");

View file

@ -46,7 +46,6 @@ public class Legacy extends Constructed {
banned.add("Balance");
banned.add("Bazaar of Baghdad");
banned.add("Black Lotus");
banned.add("Black Vise");
banned.add("Brago's Favor");
banned.add("Bronze Tablet");
banned.add("Channel");
@ -56,6 +55,7 @@ public class Legacy extends Constructed {
banned.add("Demonic Attorney");
banned.add("Demonic Consultation");
banned.add("Demonic Tutor");
banned.add("Dig Through Time");
banned.add("Double Stroke");
banned.add("Earthcraft");
banned.add("Falling Star");
@ -104,7 +104,7 @@ public class Legacy extends Constructed {
banned.add("Timmerian Fiends");
banned.add("Tinker");
banned.add("Tolarian Academy");
banned.add("Treasure Cruise"); // banned effective January 23, 2015
banned.add("Treasure Cruise");
banned.add("Unexpected Potential");
banned.add("Vampiric Tutor");
banned.add("Wheel of Fortune");

View file

@ -70,8 +70,10 @@ public class Vintage extends Constructed {
restricted.add("Black Lotus");
restricted.add("Brainstorm");
restricted.add("Channel");
restricted.add("Chalice of the Void");
restricted.add("Demonic Consultation");
restricted.add("Demonic Tutor");
restricted.add("Dig Through Time");
restricted.add("Fastbond");
restricted.add("Flash");
restricted.add("Imperial Seal");
@ -93,13 +95,12 @@ public class Vintage extends Constructed {
restricted.add("Ponder");
restricted.add("Sol Ring");
restricted.add("Strip Mine");
restricted.add("Thirst for Knowledge");
restricted.add("Time Vault");
restricted.add("Time Walk");
restricted.add("Timetwister");
restricted.add("Tinker");
restricted.add("Tolarian Academy");
restricted.add("Treasure Cruise"); // banned effective January 23, 2015
restricted.add("Treasure Cruise");
restricted.add("Trinisphere");
restricted.add("Vampiric Tutor");
restricted.add("Wheel of Fortune");

View file

@ -27,21 +27,28 @@
*/
package mage.sets.alarareborn;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.keyword.CascadeAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.SubLayer;
import mage.constants.WatcherScope;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.stack.Spell;
import mage.target.targetpointer.FixedTarget;
import mage.game.stack.StackObject;
import mage.players.Player;
import mage.watchers.Watcher;
/**
@ -55,7 +62,7 @@ public class MaelstromNexus extends CardImpl {
this.expansionSetCode = "ARB";
// The first spell you cast each turn has cascade.
this.addAbility(new MaelstromNexusTriggeredAbility(), new FirstSpellCastThisTurnWatcher());
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MaelstromNexusGainCascadeFirstSpellEffect()), new FirstSpellCastThisTurnWatcher());
}
@ -69,52 +76,51 @@ public class MaelstromNexus extends CardImpl {
}
}
class MaelstromNexusTriggeredAbility extends TriggeredAbilityImpl {
class MaelstromNexusGainCascadeFirstSpellEffect extends ContinuousEffectImpl {
public MaelstromNexusTriggeredAbility() {
super(Zone.BATTLEFIELD, new CascadeEffect());
private Ability cascadeAbility = new CascadeAbility();
public MaelstromNexusGainCascadeFirstSpellEffect() {
super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility);
staticText = "The first spell you cast each turn has cascade";
}
public MaelstromNexusTriggeredAbility(MaelstromNexusTriggeredAbility ability) {
super(ability);
public MaelstromNexusGainCascadeFirstSpellEffect(final MaelstromNexusGainCascadeFirstSpellEffect effect) {
super(effect);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.SPELL_CAST;
public MaelstromNexusGainCascadeFirstSpellEffect copy() {
return new MaelstromNexusGainCascadeFirstSpellEffect(this);
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Spell spell = game.getStack().getSpell(event.getTargetId());
FirstSpellCastThisTurnWatcher watcher = (FirstSpellCastThisTurnWatcher) game.getState().getWatchers().get("FirstSpellCastThisTurn", this.getSourceId());
if (spell != null
&& watcher != null
&& watcher.conditionMet()) {
this.getEffects().get(0).setTargetPointer(new FixedTarget(spell.getSourceId()));
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
for (StackObject stackObject : game.getStack()) {
// only spells cast, so no copies of spells
if ((stackObject instanceof Spell) && !stackObject.isCopy() && stackObject.getControllerId().equals(source.getControllerId())) {
Spell spell = (Spell) stackObject;
FirstSpellCastThisTurnWatcher watcher = (FirstSpellCastThisTurnWatcher) game.getState().getWatchers().get("FirstSpellCastThisTurn");
if (watcher != null && spell.getId().equals(watcher.getIdOfFirstCastSpell(source.getControllerId()))) {
game.getState().addOtherAbility(spell.getCard(), cascadeAbility);
}
}
}
return true;
}
return false;
}
@Override
public MaelstromNexusTriggeredAbility copy() {
return new MaelstromNexusTriggeredAbility(this);
}
@Override
public String getRule() {
return "The first spell you cast each turn has cascade.";
}
}
class FirstSpellCastThisTurnWatcher extends Watcher {
int spellCount = 0;
Map<UUID, UUID> playerFirstSpellCast = new HashMap<>();
Map<UUID, UUID> playerFirstCastSpell = new HashMap<>();
public FirstSpellCastThisTurnWatcher() {
super("FirstSpellCastThisTurn", WatcherScope.CARD);
super("FirstSpellCastThisTurn", WatcherScope.GAME);
}
public FirstSpellCastThisTurnWatcher(final FirstSpellCastThisTurnWatcher watcher) {
@ -123,16 +129,18 @@ class FirstSpellCastThisTurnWatcher extends Watcher {
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.SPELL_CAST && event.getPlayerId() == controllerId) {
Spell spell = (Spell) game.getObject(event.getTargetId());
if (spell != null) {
spellCount++;
if (spellCount == 1) {
condition = true;
} else {
condition = false;
switch (event.getType()) {
case SPELL_CAST:
case CAST_SPELL:
Spell spell = (Spell) game.getObject(event.getTargetId());
if (spell != null && !playerFirstSpellCast.containsKey(spell.getControllerId())) {
if (event.getType().equals(EventType.SPELL_CAST)) {
playerFirstSpellCast.put(spell.getControllerId(), spell.getId());
} else if (event.getType().equals(EventType.CAST_SPELL)) {
playerFirstCastSpell.put(spell.getControllerId(), spell.getId());
}
}
}
}
}
@ -144,28 +152,15 @@ class FirstSpellCastThisTurnWatcher extends Watcher {
@Override
public void reset() {
super.reset();
spellCount = 0;
playerFirstSpellCast.clear();
playerFirstCastSpell.clear();
}
public UUID getIdOfFirstCastSpell(UUID playerId) {
if (playerFirstSpellCast.get(playerId) == null) {
return playerFirstCastSpell.get(playerId);
} else {
return playerFirstSpellCast.get(playerId);
}
}
}
class CascadeEffect extends OneShotEffect {
public CascadeEffect() {
super(Outcome.PutCardInPlay);
}
public CascadeEffect(CascadeEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
return CascadeAbility.applyCascade(outcome, game, source);
}
@Override
public CascadeEffect copy() {
return new CascadeEffect(this);
}
}

View file

@ -102,12 +102,15 @@ class ZadaHedronGrinderTriggeredAbility extends TriggeredAbilityImpl {
Spell spell = game.getStack().getSpell(event.getTargetId());
if (isControlledInstantOrSorcery(spell)) {
boolean targetsSource = false;
for (Target target : spell.getSpellAbility().getTargets()) {
for (UUID targetId : target.getTargets()) {
if (targetId.equals(getSourceId())) {
targetsSource = true;
} else {
return false;
for (UUID modeId : spell.getSpellAbility().getModes().getSelectedModes()) {
spell.getSpellAbility().getModes().setActiveMode(modeId);
for (Target target : spell.getSpellAbility().getTargets()) {
for (UUID targetId : target.getTargets()) {
if (targetId.equals(getSourceId())) {
targetsSource = true;
} else {
return false;
}
}
}
}
@ -157,10 +160,15 @@ class ZadaHedronGrinderEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
if (spell != null && controller != null) {
Target usedTarget = null;
for (Target target : spell.getSpellAbility().getTargets()) {
if (target.getFirstTarget().equals(source.getSourceId())) {
usedTarget = target.copy();
usedTarget.clearChosen();
setUsedTarget:
for (UUID modeId : spell.getSpellAbility().getModes().getSelectedModes()) {
spell.getSpellAbility().getModes().setActiveMode(modeId);
for (Target target : spell.getSpellAbility().getTargets()) {
if (target.getFirstTarget().equals(source.getSourceId())) {
usedTarget = target.copy();
usedTarget.clearChosen();
break setUsedTarget;
}
}
}
if (usedTarget == null) {
@ -169,11 +177,15 @@ class ZadaHedronGrinderEffect extends OneShotEffect {
for (Permanent creature : game.getState().getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), game)) {
if (!creature.getId().equals(source.getSourceId()) && usedTarget.canTarget(source.getControllerId(), creature.getId(), source, game)) {
Spell copy = spell.copySpell();
for (Target target : spell.getSpellAbility().getTargets()) {
if (target.getClass().equals(usedTarget.getClass()) && target.getMessage().equals(usedTarget.getMessage())) {
target.clearChosen();
target.add(creature.getId(), game);
break;
setTarget:
for (UUID modeId : spell.getSpellAbility().getModes().getSelectedModes()) {
copy.getSpellAbility().getModes().setActiveMode(modeId);
for (Target target : copy.getSpellAbility().getTargets()) {
if (target.getClass().equals(usedTarget.getClass()) && target.getMessage().equals(usedTarget.getMessage())) {
target.clearChosen();
target.add(creature.getId(), game);
break setTarget;
}
}
}
copy.setControllerId(source.getControllerId());

View file

@ -28,12 +28,12 @@
package mage.sets.mirrodinbesieged;
import java.util.UUID;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.cards.CardImpl;
import mage.filter.FilterPermanent;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.filter.common.FilterArtifactPermanent;
import mage.target.TargetPermanent;
/**
@ -42,20 +42,15 @@ import mage.target.TargetPermanent;
*/
public class IntoTheCore extends CardImpl {
private static final FilterPermanent filter = new FilterPermanent("artifact");
static {
filter.add(new CardTypePredicate(CardType.ARTIFACT));
}
public IntoTheCore(UUID ownerId) {
super(ownerId, 67, "Into the Core", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{2}{R}{R}");
this.expansionSetCode = "MBS";
this.getSpellAbility().addTarget(new TargetPermanent(filter));
this.getSpellAbility().addTarget(new TargetPermanent(filter));
this.getSpellAbility().addEffect(new ExileTargetEffect());
// Exile two target artifacts.
this.getSpellAbility().addTarget(new TargetPermanent(2, 2, new FilterArtifactPermanent("artifacts"), false));
Effect effect = new ExileTargetEffect();
effect.setText("Exile two target artifacts");
this.getSpellAbility().addEffect(effect);
}
public IntoTheCore(final IntoTheCore card) {

View file

@ -27,6 +27,7 @@
*/
package org.mage.test.cards.copy;
import mage.abilities.keyword.FlyingAbility;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
@ -61,4 +62,61 @@ public class CopySpellTest extends CardTestPlayerBase {
assertHandCount(playerA, "Silvercoat Lion", 1);
}
@Test
public void ZadaHedronGrinderBoost() {
// Target creature gets +3/+3 and gains flying until end of turn.
addCard(Zone.HAND, playerA, "Angelic Blessing", 1); // {2}{W}
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
// Whenever you cast an instant or sorcery spell that targets only Zada, Hedron Grinder, copy that spell for each other creature you control that the spell could target. Each copy targets a different one of those creatures.
addCard(Zone.BATTLEFIELD, playerA, "Zada, Hedron Grinder", 1);
addCard(Zone.BATTLEFIELD, playerA, "Pillarfield Ox", 1);
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Angelic Blessing", "Zada, Hedron Grinder");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerA, "Angelic Blessing", 1);
assertPowerToughness(playerA, "Pillarfield Ox", 5, 7);
assertAbility(playerA, "Pillarfield Ox", FlyingAbility.getInstance(), true);
assertPowerToughness(playerA, "Zada, Hedron Grinder", 6, 6);
assertAbility(playerA, "Zada, Hedron Grinder", FlyingAbility.getInstance(), true);
assertPowerToughness(playerB, "Silvercoat Lion", 2, 2);
assertAbility(playerB, "Silvercoat Lion", FlyingAbility.getInstance(), false);
}
@Test
public void ZadaHedronGrinderBoostWithCharm() {
// Choose two -
// Counter target spell.
// Return target permanent to its owner's hand.
// Tap all creatures your opponents control.
// Draw a card.
addCard(Zone.HAND, playerA, "Cryptic Command", 1); // {2}{U}{U}{U}
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
// Whenever you cast an instant or sorcery spell that targets only Zada, Hedron Grinder, copy that spell for each other creature you control that the spell could target. Each copy targets a different one of those creatures.
addCard(Zone.BATTLEFIELD, playerA, "Zada, Hedron Grinder", 1);
addCard(Zone.BATTLEFIELD, playerA, "Pillarfield Ox", 1);
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cryptic Command", "mode=2Zada, Hedron Grinder");
setModeChoice(playerA, "2"); // Return target permanent to its owner's hand
setModeChoice(playerA, "4"); // Draw a card
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPowerToughness(playerB, "Silvercoat Lion", 2, 2);
assertGraveyardCount(playerA, "Cryptic Command", 1);
assertPermanentCount(playerA, "Zada, Hedron Grinder", 0);
assertPermanentCount(playerA, "Pillarfield Ox", 0);
assertHandCount(playerA, 4); // 2 draw + 2 creatures returned to hand
}
}

View file

@ -1,37 +1,38 @@
/*
* 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.
*/
* 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.abilities.keyword;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
@ -74,10 +75,7 @@ public class CascadeAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Spell spell = game.getStack().getSpell(event.getTargetId());
if (spell != null && spell.getSourceId().equals(this.getSourceId())) {
return true;
}
return false;
return spell != null && spell.getSourceId().equals(this.getSourceId());
}
@Override
@ -95,7 +93,6 @@ public class CascadeAbility extends TriggeredAbilityImpl {
}
// moved to static method because it's called also from class {link} MaelstromNexus
public static boolean applyCascade(Outcome outcome, Game game, Ability source) {
Card card;
Player player = game.getPlayer(source.getControllerId());
@ -109,31 +106,33 @@ public class CascadeAbility extends TriggeredAbilityImpl {
if (card == null) {
break;
}
player.moveCardToExileWithInfo(card, exile.getId(), exile.getName(), source.getSourceId(), game, Zone.LIBRARY, true);
player.moveCardsToExile(card, source, game, true, exile.getId(), exile.getName());
} while (player.isInGame() && card.getCardType().contains(CardType.LAND) || card.getManaCost().convertedManaCost() >= sourceCost);
player.getLibrary().reset();
if (card != null) {
if (player.chooseUse(outcome, "Use cascade effect on " + card.getName() + "?", source, game)) {
if(player.cast(card.getSpellAbility(), game, true)){
if (player.chooseUse(outcome, "Use cascade effect on " + card.getLogName() + "?", source, game)) {
if (player.cast(card.getSpellAbility(), game, true)) {
exile.remove(card.getId());
}
}
}
while (exile.size() > 0) {
card = exile.getRandom(game);
exile.remove(card.getId());
player.moveCardToLibraryWithInfo(card, source.getSourceId(), game, Zone.EXILED, false, false);
// Mobe the remaining cards to the buttom of the libraray in a random order
Cards cardsFromExile = new CardsImpl();
Cards cardsToLibrary = new CardsImpl();
cardsFromExile.addAll(exile);
while (cardsFromExile.size() > 0) {
card = cardsFromExile.getRandom(game);
cardsFromExile.remove(card.getId());
cardsToLibrary.add(card);
}
player.putCardsOnBottomOfLibrary(cardsToLibrary, game, source, true);
return true;
}
}
// !!! Changes to the cascade effect here have to be copied to the cascadeEffect of Maelstrom Nexus card eventually.
// There is a functional copy of this effect
class CascadeEffect extends OneShotEffect {
public CascadeEffect() {
@ -185,5 +184,3 @@ class CascadeEffect extends OneShotEffect {
}
}

View file

@ -525,6 +525,10 @@ public class Combat implements Serializable, Copyable<Combat> {
// has cost to block to pay so remove this attacker
continue;
}
if (!getDefendingPlayerId(attackingCreatureId, game).equals(possibleBlocker.getControllerId())) {
// Creature can't block if not the controller or a planeswalker of the controller of the possible blocker is attacked
continue;
}
if (creatureMustBlockAttackers.containsKey(possibleBlocker.getId())) {
creatureMustBlockAttackers.get(possibleBlocker.getId()).add(attackingCreatureId);
} else {
@ -729,6 +733,10 @@ public class Combat implements Serializable, Copyable<Combat> {
if (creatureForcedToBlock == null) {
break;
}
if (!creatureForcedToBlock.getControllerId().equals(player.getId())) {
// ignore creatures controlled by other players
continue;
}
// // check if creature has to pay a cost to block so it's not mandatory to block
// boolean removedAttacker = false;
@ -1133,10 +1141,10 @@ public class Combat implements Serializable, Copyable<Combat> {
return defenderId;
}
public UUID getDefendingPlayerId(UUID attackerId, Game game) {
public UUID getDefendingPlayerId(UUID attackingCreatureId, Game game) {
UUID defenderId = null;
for (CombatGroup group : groups) {
if (group.getAttackers().contains(attackerId)) {
if (group.getAttackers().contains(attackingCreatureId)) {
defenderId = group.getDefenderId();
if (group.defenderIsPlaneswalker) {
Permanent permanent = game.getPermanent(defenderId);

View file

@ -962,8 +962,10 @@ public abstract class PlayerImpl implements Player, Serializable {
}
}
setCastSourceIdWithAlternateMana(null, null);
GameEvent event = GameEvent.getEvent(GameEvent.EventType.CAST_SPELL, spell.getSpellAbility().getId(), spell.getSpellAbility().getSourceId(), playerId);
game.fireEvent(event);
if (spell.activate(game, noMana)) {
GameEvent event = GameEvent.getEvent(GameEvent.EventType.SPELL_CAST, spell.getSpellAbility().getId(), spell.getSpellAbility().getSourceId(), playerId);
event = GameEvent.getEvent(GameEvent.EventType.SPELL_CAST, spell.getSpellAbility().getId(), spell.getSpellAbility().getSourceId(), playerId);
event.setZone(fromZone);
game.fireEvent(event);
if (!game.isSimulation()) {