Merge pull request #7 from magefree/master

Merge
This commit is contained in:
theelk801 2017-07-30 17:47:46 -04:00 committed by GitHub
commit 32226c886a
10 changed files with 107 additions and 57 deletions

View file

@ -1281,7 +1281,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
hideTables(); hideTables();
SessionHandler.disconnect(false); SessionHandler.disconnect(false);
if (errorCall) { if (errorCall) {
UserRequestMessage message = new UserRequestMessage("Connection lost", "The connection to server was lost. Reconnect to " + currentConnection.getHost() + '?'); UserRequestMessage message = new UserRequestMessage("Connection lost", "The connection to server was lost. Reconnect?");
message.setButton1("No", null); message.setButton1("No", null);
message.setButton2("Yes", PlayerAction.CLIENT_RECONNECT); message.setButton2("Yes", PlayerAction.CLIENT_RECONNECT);
showUserRequestDialog(message); showUserRequestDialog(message);

View file

@ -188,7 +188,6 @@ public class HumanPlayer extends PlayerImpl {
synchronized (response) { synchronized (response) {
try { try {
response.wait(); response.wait();
logger.info("Got response from player: " + response.toString());
} catch (InterruptedException ex) { } catch (InterruptedException ex) {
logger.error("Response error for player " + getName() + " gameId: " + game.getId(), ex); logger.error("Response error for player " + getName() + " gameId: " + game.getId(), ex);
} finally { } finally {

View file

@ -29,6 +29,7 @@ package mage.cards.d;
import java.util.UUID; import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.Mode; import mage.abilities.Mode;
import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility;
@ -101,13 +102,13 @@ class DuplicantExileTargetEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(targetPointer.getFirst(game, source)); Permanent permanent = game.getPermanent(targetPointer.getFirst(game, source));
Permanent sourcePermananent = game.getPermanent(source.getSourceId()); MageObject sourceObject = source.getSourceObject(game);
if (permanent != null) { if (permanent != null && sourceObject instanceof Permanent) {
if (sourcePermananent != null) { if (permanent.moveToExile(null, null, source.getSourceId(), game)) {
sourcePermananent.imprint(permanent.getId(), game); ((Permanent) sourceObject).imprint(permanent.getId(), game);
sourcePermananent.addInfo("imprint", new StringBuilder("[Imprinted card - ").append(permanent.getName()).append(']').toString(), game); ((Permanent) sourceObject).addInfo("imprint", "[Imprinted card - " + permanent.getName() + ']', game);
} }
return permanent.moveToExile(null, null, source.getSourceId(), game); return true;
} }
return false; return false;

View file

@ -31,6 +31,7 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility;
@ -43,6 +44,7 @@ import mage.constants.CardType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.SuperType; import mage.constants.SuperType;
import mage.constants.WatcherScope; import mage.constants.WatcherScope;
import mage.constants.Zone;
import mage.filter.common.FilterInstantOrSorceryCard; import mage.filter.common.FilterInstantOrSorceryCard;
import mage.game.ExileZone; import mage.game.ExileZone;
import mage.game.Game; import mage.game.Game;
@ -61,7 +63,7 @@ import mage.watchers.Watcher;
public class JelevaNephaliasScourge extends CardImpl { public class JelevaNephaliasScourge extends CardImpl {
public JelevaNephaliasScourge(UUID ownerId, CardSetInfo setInfo) { public JelevaNephaliasScourge(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}{B}{R}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{B}{R}");
addSuperType(SuperType.LEGENDARY); addSuperType(SuperType.LEGENDARY);
this.subtype.add("Vampire"); this.subtype.add("Vampire");
this.subtype.add("Wizard"); this.subtype.add("Wizard");
@ -107,27 +109,19 @@ class JelevaNephaliasScourgeEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId()); Player controller = game.getPlayer(source.getControllerId());
Card sourceCard = game.getCard(source.getSourceId()); MageObject sourceObject = source.getSourceObject(game);
if (controller != null && sourceCard != null) { JelevaNephaliasWatcher watcher = (JelevaNephaliasWatcher) game.getState().getWatchers().get(JelevaNephaliasWatcher.class.getSimpleName());
JelevaNephaliasWatcher watcher = (JelevaNephaliasWatcher) game.getState().getWatchers().get(JelevaNephaliasWatcher.class.getSimpleName(), source.getSourceId()); if (controller != null && sourceObject != null && watcher != null) {
if (watcher != null) { int xValue = watcher.getManaSpentToCastLastTime(sourceObject.getId(), sourceObject.getZoneChangeCounter(game) - 1);
int xValue = watcher.getManaSpentToCastLastTime(sourceCard.getZoneChangeCounter(game) - 1); if (xValue > 0) {
if (xValue > 0) { for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { Player player = game.getPlayer(playerId);
Player player = game.getPlayer(playerId); if (player != null) {
if (player != null) { player.moveCards(player.getLibrary().getTopCards(game, xValue), Zone.EXILED, source, game);
int cardsToExile = Math.min(player.getLibrary().size(), xValue);
for (int i = 0; i < cardsToExile; i++) {
Card card = player.getLibrary().removeFromTop(game);
if (card != null) {
card.moveToExile(CardUtil.getCardExileZoneId(game, source), sourceCard.getIdName(), source.getSourceId(), game);
}
}
}
} }
} }
return true;
} }
return true;
} }
return false; return false;
} }
@ -173,10 +167,10 @@ class JelevaNephaliasCastEffect extends OneShotEffect {
class JelevaNephaliasWatcher extends Watcher { class JelevaNephaliasWatcher extends Watcher {
private final Map<Integer, Integer> manaSpendToCast = new HashMap<>(); // cast private final Map<String, Integer> manaSpendToCast = new HashMap<>(); // cast
public JelevaNephaliasWatcher() { public JelevaNephaliasWatcher() {
super(JelevaNephaliasWatcher.class.getSimpleName(), WatcherScope.CARD); super(JelevaNephaliasWatcher.class.getSimpleName(), WatcherScope.GAME);
} }
public JelevaNephaliasWatcher(final JelevaNephaliasWatcher watcher) { public JelevaNephaliasWatcher(final JelevaNephaliasWatcher watcher) {
@ -190,22 +184,22 @@ class JelevaNephaliasWatcher extends Watcher {
@Override @Override
public void watch(GameEvent event, Game game) { public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.SPELL_CAST && event.getSourceId().equals(sourceId)) { // Watcher saves all casts becaus of possible Clone cards that copy Jeleva
if (event.getType() == GameEvent.EventType.SPELL_CAST) {
if (!game.getStack().isEmpty()) { if (!game.getStack().isEmpty()) {
for (StackObject stackObject : game.getStack()) { for (StackObject stackObject : game.getStack()) {
if (stackObject instanceof Spell && ((Spell) stackObject).getSourceId().equals(sourceId)) { if (stackObject instanceof Spell) {
Card card = game.getCard(sourceId); Spell spell = (Spell) stackObject;
if (!manaSpendToCast.containsValue(card.getZoneChangeCounter(game))) { manaSpendToCast.putIfAbsent(spell.getSourceId().toString() + spell.getCard().getZoneChangeCounter(game),
manaSpendToCast.put(card.getZoneChangeCounter(game), ((Spell) stackObject).getSpellAbility().getManaCostsToPay().convertedManaCost()); spell.getSpellAbility().getManaCostsToPay().convertedManaCost());
}
} }
} }
} }
} }
} }
public int getManaSpentToCastLastTime(int zoneChangeCounter) { public int getManaSpentToCastLastTime(UUID sourceId, int zoneChangeCounter) {
return manaSpendToCast.getOrDefault(zoneChangeCounter, 0); return manaSpendToCast.getOrDefault(sourceId.toString() + zoneChangeCounter, 0);
} }
@Override @Override

View file

@ -47,8 +47,7 @@ import mage.players.Player;
public class MindsAglow extends CardImpl { public class MindsAglow extends CardImpl {
public MindsAglow(UUID ownerId, CardSetInfo setInfo) { public MindsAglow(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{U}"); super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{U}");
// Join forces - Starting with you, each player may pay any amount of mana. Each player draws X cards, where X is the total amount of mana paid this way. // Join forces - Starting with you, each player may pay any amount of mana. Each player draws X cards, where X is the total amount of mana paid this way.
this.getSpellAbility().addEffect(new MindsAglowEffect()); this.getSpellAbility().addEffect(new MindsAglowEffect());
@ -66,44 +65,44 @@ public class MindsAglow extends CardImpl {
} }
class MindsAglowEffect extends OneShotEffect { class MindsAglowEffect extends OneShotEffect {
public MindsAglowEffect() { public MindsAglowEffect() {
super(Outcome.Detriment); super(Outcome.Detriment);
this.staticText = "<i>Join forces</i> - Starting with you, each player may pay any amount of mana. Each player draws X cards, where X is the total amount of mana paid this way"; this.staticText = "<i>Join forces</i> - Starting with you, each player may pay any amount of mana. Each player draws X cards, where X is the total amount of mana paid this way";
} }
public MindsAglowEffect(final MindsAglowEffect effect) { public MindsAglowEffect(final MindsAglowEffect effect) {
super(effect); super(effect);
} }
@Override @Override
public MindsAglowEffect copy() { public MindsAglowEffect copy() {
return new MindsAglowEffect(this); return new MindsAglowEffect(this);
} }
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId()); Player controller = game.getPlayer(source.getControllerId());
if (controller != null) { if (controller != null) {
int xSum = 0; int xSum = 0;
xSum += playerPaysXGenericMana(controller, source, game); xSum += playerPaysXGenericMana(controller, source, game);
for(UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
if (!Objects.equals(playerId, controller.getId())) { if (!Objects.equals(playerId, controller.getId())) {
Player player = game.getPlayer(playerId); Player player = game.getPlayer(playerId);
if (player != null) { if (player != null) {
xSum += playerPaysXGenericMana(player, source, game); xSum += playerPaysXGenericMana(player, source, game);
} }
} }
} }
if (xSum > 0) { if (xSum > 0) {
for(UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
Player player = game.getPlayer(playerId); Player player = game.getPlayer(playerId);
if (player != null) { if (player != null) {
player.drawCards(xSum, game); player.drawCards(xSum, game);
} }
} }
} }
// prevent undo // prevent undo
controller.resetStoredBookmark(game); controller.resetStoredBookmark(game);
@ -120,6 +119,9 @@ class MindsAglowEffect extends OneShotEffect {
if (xValue > 0) { if (xValue > 0) {
Cost cost = new GenericManaCost(xValue); Cost cost = new GenericManaCost(xValue);
payed = cost.pay(source, game, source.getSourceId(), player.getId(), false, null); payed = cost.pay(source, game, source.getSourceId(), player.getId(), false, null);
if (!payed) {
game.undo(player.getId());
}
} else { } else {
payed = true; payed = true;
} }

View file

@ -122,8 +122,8 @@ class OathOfNissaEffect extends OneShotEffect {
topCards.remove(card); topCards.remove(card);
} }
} }
controller.putCardsOnBottomOfLibrary(topCards, game, source, true);
} }
controller.putCardsOnBottomOfLibrary(topCards, game, source, true);
} }
return true; return true;
} }

View file

@ -85,4 +85,54 @@ public class FracturingGustTest extends CardTestPlayerBase {
assertLife(playerB, 20); assertLife(playerB, 20);
} }
@Test
public void testWithIndestructible() {
addCard(Zone.BATTLEFIELD, playerA, "Forest", 5);
// Destroy all artifacts and enchantments. You gain 2 life for each permanent destroyed this way.
addCard(Zone.HAND, playerA, "Fracturing Gust", 1);
// Flying
// Indestructible (Damage and effects that say "destroy" don't destroy this creature.)
addCard(Zone.BATTLEFIELD, playerB, "Darksteel Gargoyle", 1); // Artifact Creature - Gargoyle
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Fracturing Gust");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerA, "Fracturing Gust", 1);
assertPermanentCount(playerB, "Darksteel Gargoyle", 1);
// No life because Darksteel Gargoyle is Indestructible
assertLife(playerA, 20);
assertLife(playerB, 20);
}
@Test
public void testWithRestInPeace() {
addCard(Zone.BATTLEFIELD, playerA, "Forest", 5);
// Destroy all artifacts and enchantments. You gain 2 life for each permanent destroyed this way.
addCard(Zone.HAND, playerA, "Fracturing Gust", 1);
addCard(Zone.BATTLEFIELD, playerB, "Ornithopter", 1); // Artifact Creature 2/2
// When Rest in Peace enters the battlefield, exile all cards from all graveyards.
// If a card or token would be put into a graveyard from anywhere, exile it instead.
addCard(Zone.BATTLEFIELD, playerB, "Rest in Peace"); // Artifact
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Fracturing Gust");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerA, "Fracturing Gust", 1);
assertGraveyardCount(playerB, "Ornithopter", 0);
assertExileCount(playerB, "Ornithopter", 1);
assertLife(playerA, 24);
assertLife(playerB, 20);
}
} }

View file

@ -59,7 +59,8 @@ public class CommanderReplaceEffectTest extends CardTestCommanderDuelBase {
addCard(Zone.HAND, playerB, "Phyrexian Rebirth", 1); addCard(Zone.HAND, playerB, "Phyrexian Rebirth", 1);
// Daxos of Meletis can't be blocked by creatures with power 3 or greater. // Daxos of Meletis can't be blocked by creatures with power 3 or greater.
// Whenever Daxos of Meletis deals combat damage to a player, exile the top card of that player's library. You gain life equal to that card's converted mana cost. Until end of turn, you may cast that card and you may spend mana as though it were mana of any color to cast it. // Whenever Daxos of Meletis deals combat damage to a player, exile the top card of that player's library. You gain life equal to that card's converted mana cost.
// Until end of turn, you may cast that card and you may spend mana as though it were mana of any color to cast it.
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Daxos of Meletis"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Daxos of Meletis");
// Destroy all creatures, then put an X/X colorless Horror artifact creature token onto the battlefield, where X is the number of creatures destroyed this way. // Destroy all creatures, then put an X/X colorless Horror artifact creature token onto the battlefield, where X is the number of creatures destroyed this way.

View file

@ -27,6 +27,7 @@
*/ */
package mage.game.permanent; package mage.game.permanent;
import java.util.*;
import mage.MageObject; import mage.MageObject;
import mage.MageObjectReference; import mage.MageObjectReference;
import mage.ObjectColor; import mage.ObjectColor;
@ -55,8 +56,6 @@ import mage.players.Player;
import mage.util.GameLog; import mage.util.GameLog;
import mage.util.ThreadLocalStringBuilder; import mage.util.ThreadLocalStringBuilder;
import java.util.*;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
@ -972,8 +971,8 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
} }
} }
game.fireEvent(GameEvent.getEvent(EventType.DESTROYED_PERMANENT, objectId, sourceId, controllerId)); game.fireEvent(GameEvent.getEvent(EventType.DESTROYED_PERMANENT, objectId, sourceId, controllerId));
return true;
} }
return true;
} }
return false; return false;
} }

View file

@ -69,8 +69,8 @@ import mage.util.SubTypeList;
*/ */
public class Spell extends StackObjImpl implements Card { public class Spell extends StackObjImpl implements Card {
private final List<Card> spellCards = new ArrayList<>();
private final List<SpellAbility> spellAbilities = new ArrayList<>(); private final List<SpellAbility> spellAbilities = new ArrayList<>();
private final List<Card> spellCards = new ArrayList<>();
private final Card card; private final Card card;
private final ObjectColor color; private final ObjectColor color;
@ -108,7 +108,6 @@ public class Spell extends StackObjImpl implements Card {
this.controllerId = controllerId; this.controllerId = controllerId;
this.fromZone = fromZone; this.fromZone = fromZone;
this.countered = false; this.countered = false;
this.doneActivatingManaAbilities = false;
} }
public Spell(final Spell spell) { public Spell(final Spell spell) {
@ -129,13 +128,18 @@ public class Spell extends StackObjImpl implements Card {
} else { } else {
this.card = spell.card.copy(); this.card = spell.card.copy();
} }
this.controllerId = spell.controllerId;
this.fromZone = spell.fromZone; this.fromZone = spell.fromZone;
this.copiedSpell = spell.copiedSpell;
this.faceDown = spell.faceDown;
this.color = spell.color.copy(); this.color = spell.color.copy();
this.frameColor = spell.color.copy(); this.frameColor = spell.color.copy();
this.frameStyle = spell.frameStyle; this.frameStyle = spell.frameStyle;
this.controllerId = spell.controllerId;
this.copiedSpell = spell.copiedSpell;
this.faceDown = spell.faceDown;
this.countered = spell.countered;
this.resolving = spell.resolving;
this.doneActivatingManaAbilities = spell.doneActivatingManaAbilities; this.doneActivatingManaAbilities = spell.doneActivatingManaAbilities;
} }