From a2b6f83a3e52c7c52bea7e02c9800a17efdbc0a1 Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Fri, 23 Feb 2018 13:02:22 +0400 Subject: [PATCH 1/7] Fixed compile error --- .../src/main/java/mage/server/console/ConsolePanel.java | 1 - 1 file changed, 1 deletion(-) diff --git a/Mage.Server.Console/src/main/java/mage/server/console/ConsolePanel.java b/Mage.Server.Console/src/main/java/mage/server/console/ConsolePanel.java index af9afb46662..4b729539d87 100644 --- a/Mage.Server.Console/src/main/java/mage/server/console/ConsolePanel.java +++ b/Mage.Server.Console/src/main/java/mage/server/console/ConsolePanel.java @@ -381,7 +381,6 @@ public class ConsolePanel extends javax.swing.JPanel { JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) { ConsoleFrame.getSession().toggleActivation(userName); return; - } } }//GEN-LAST:event_btnDeActivateActionPerformed From 5b0e71021dccb0cf5590a23e768a59b033856726 Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Fri, 23 Feb 2018 16:15:59 +0400 Subject: [PATCH 2/7] Fixed compile error on getFixedTarget and failed test on new lower names --- Mage.Sets/src/mage/cards/p/Progenitus.java | 5 ----- .../src/mage/cards/t/TeferisProtection.java | 7 +------ .../test/cards/single/lrw/CairnWandererTest.java | 16 ++++++++-------- .../mage/target/targetpointer/FixedTargets.java | 9 +++++++++ .../targetpointer/SecondTargetPointer.java | 1 - 5 files changed, 18 insertions(+), 20 deletions(-) diff --git a/Mage.Sets/src/mage/cards/p/Progenitus.java b/Mage.Sets/src/mage/cards/p/Progenitus.java index ecfc73fa509..afec039d10f 100644 --- a/Mage.Sets/src/mage/cards/p/Progenitus.java +++ b/Mage.Sets/src/mage/cards/p/Progenitus.java @@ -93,11 +93,6 @@ class ProgenitusProtectionAbility extends ProtectionAbility { return new ProgenitusProtectionAbility(this); } - @Override - public String getRule() { - return "Protection from everything"; - } - @Override public boolean canTarget(MageObject source, Game game) { return false; diff --git a/Mage.Sets/src/mage/cards/t/TeferisProtection.java b/Mage.Sets/src/mage/cards/t/TeferisProtection.java index 98701104c96..ec5de97c6b7 100644 --- a/Mage.Sets/src/mage/cards/t/TeferisProtection.java +++ b/Mage.Sets/src/mage/cards/t/TeferisProtection.java @@ -141,12 +141,7 @@ class TeferisProtectionAbility extends ProtectionAbility { public TeferisProtectionAbility copy() { return new TeferisProtectionAbility(this); } - - @Override - public String getRule() { - return "Protection from everything"; - } - + @Override public boolean canTarget(MageObject source, Game game) { return false; diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/lrw/CairnWandererTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/lrw/CairnWandererTest.java index 2f3e6851fe3..6f96643b134 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/lrw/CairnWandererTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/lrw/CairnWandererTest.java @@ -80,28 +80,28 @@ public class CairnWandererTest extends CardTestPlayerBase { addCard(Zone.GRAVEYARD, playerA, "Typhoid Rats"); // Testing HasteAbility. - addCard(Zone.GRAVEYARD, playerA, "Raging Goblin"); + addCard(Zone.GRAVEYARD, playerB, "Raging Goblin"); // Testing LandwalkAbility. - addCard(Zone.GRAVEYARD, playerA, "Zodiac Rooster"); + addCard(Zone.GRAVEYARD, playerB, "Zodiac Rooster"); // Testing LifelinkAbility. - addCard(Zone.GRAVEYARD, playerA, "Trained Caracal"); + addCard(Zone.GRAVEYARD, playerB, "Trained Caracal"); // Testing ProtectionAbility. - addCard(Zone.GRAVEYARD, playerA, "Progenitus"); + addCard(Zone.GRAVEYARD, playerB, "Progenitus"); // Testing ReachAbility. - addCard(Zone.GRAVEYARD, playerA, "Tree Monkey"); + addCard(Zone.GRAVEYARD, playerB, "Tree Monkey"); // Testing TrampleAbility. - addCard(Zone.GRAVEYARD, playerA, "Defiant Elf"); + addCard(Zone.GRAVEYARD, playerB, "Defiant Elf"); // Testing ShroudAbility. - addCard(Zone.GRAVEYARD, playerA, "Elvish Lookout"); + addCard(Zone.GRAVEYARD, playerB, "Elvish Lookout"); // Testing VigilanceAbility. - addCard(Zone.GRAVEYARD, playerA, "Veteran Cavalier"); + addCard(Zone.GRAVEYARD, playerB, "Veteran Cavalier"); execute(); diff --git a/Mage/src/main/java/mage/target/targetpointer/FixedTargets.java b/Mage/src/main/java/mage/target/targetpointer/FixedTargets.java index bb231a51c71..d5c099526b2 100644 --- a/Mage/src/main/java/mage/target/targetpointer/FixedTargets.java +++ b/Mage/src/main/java/mage/target/targetpointer/FixedTargets.java @@ -87,4 +87,13 @@ public class FixedTargets implements TargetPointer { return new FixedTargets(this); } + @Override + public FixedTarget getFixedTarget(Game game, Ability source) { + this.init(game, source); + UUID firstId = getFirst(game, source); + if (firstId != null) { + return new FixedTarget(firstId, game.getState().getZoneChangeCounter(firstId)); + } + return null; + } } diff --git a/Mage/src/main/java/mage/target/targetpointer/SecondTargetPointer.java b/Mage/src/main/java/mage/target/targetpointer/SecondTargetPointer.java index 4917726dfa6..9d2779b4efd 100644 --- a/Mage/src/main/java/mage/target/targetpointer/SecondTargetPointer.java +++ b/Mage/src/main/java/mage/target/targetpointer/SecondTargetPointer.java @@ -80,6 +80,5 @@ public class SecondTargetPointer implements TargetPointer { return new FixedTarget(firstId, game.getState().getZoneChangeCounter(firstId)); } return null; - } } From ecb95db541e5b86554cd1d1d1ed6afc67b9d73be Mon Sep 17 00:00:00 2001 From: L_J Date: Fri, 23 Feb 2018 13:36:23 +0000 Subject: [PATCH 3/7] Eye for an Eye rewrite (fixes #4103) --- Mage.Sets/src/mage/cards/e/EyeForAnEye.java | 103 ++++++++++---------- 1 file changed, 52 insertions(+), 51 deletions(-) diff --git a/Mage.Sets/src/mage/cards/e/EyeForAnEye.java b/Mage.Sets/src/mage/cards/e/EyeForAnEye.java index 08245b25ab3..9c62933fbf9 100644 --- a/Mage.Sets/src/mage/cards/e/EyeForAnEye.java +++ b/Mage.Sets/src/mage/cards/e/EyeForAnEye.java @@ -28,24 +28,22 @@ package mage.cards.e; import java.util.UUID; -import mage.MageObject; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.effects.Effect; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.ReplacementEffectImpl; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.Duration; import mage.constants.Outcome; -import mage.constants.Zone; import mage.game.Game; +import mage.game.events.DamageEvent; import mage.game.events.GameEvent; import mage.players.Player; -import mage.target.targetpointer.FixedTarget; +import mage.target.TargetSource; /** - * - * @author MarcoMarin + * + * @author L_J */ public class EyeForAnEye extends CardImpl { @@ -53,8 +51,7 @@ public class EyeForAnEye extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{W}{W}"); // The next time a source of your choice would deal damage to you this turn, instead that source deals that much damage to you and Eye for an Eye deals that much damage to that source's controller. - this.addAbility(new EyeForAnEyeTriggeredAbility(new EyeForAnEyeEffect())); - + this.getSpellAbility().addEffect(new EyeForAnEyeEffect()); } public EyeForAnEye(final EyeForAnEye card) { @@ -67,48 +64,19 @@ public class EyeForAnEye extends CardImpl { } } -class EyeForAnEyeTriggeredAbility extends TriggeredAbilityImpl { +class EyeForAnEyeEffect extends ReplacementEffectImpl { - public EyeForAnEyeTriggeredAbility(Effect effect) { - super(Zone.BATTLEFIELD, effect); - } - - public EyeForAnEyeTriggeredAbility(final EyeForAnEyeTriggeredAbility ability) { - super(ability); - } - - @Override - public EyeForAnEyeTriggeredAbility copy() { - return new EyeForAnEyeTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - MageObject sourceObject = game.getObject(event.getSourceId()); - this.getEffects().get(0).setValue("damageAmount", event.getAmount()); - this.getEffects().get(0).setTargetPointer(new FixedTarget(game.getControllerId(sourceObject.getId()))); - return true; - } - - @Override - public String getRule() { - return "The next time a source of your choice would deal damage to you this turn, instead that source deals that much damage to you and {this} deals that much damage to that source's controller."; - } -} - -class EyeForAnEyeEffect extends OneShotEffect { + private final TargetSource damageSource; public EyeForAnEyeEffect() { - super(Outcome.Damage); + super(Duration.EndOfTurn, Outcome.RedirectDamage); + staticText = "The next time a source of your choice would deal damage to you this turn, instead that source deals that much damage to you and {this} deals that much damage to that source's controller"; + this.damageSource = new TargetSource(); } public EyeForAnEyeEffect(final EyeForAnEyeEffect effect) { super(effect); + this.damageSource = effect.damageSource.copy(); } @Override @@ -116,15 +84,48 @@ class EyeForAnEyeEffect extends OneShotEffect { return new EyeForAnEyeEffect(this); } + @Override + public void init(Ability source, Game game) { + this.damageSource.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), game); + super.init(source, game); + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGE_PLAYER; + } + @Override public boolean apply(Game game, Ability source) { - Integer damageAmount = (Integer) this.getValue("damageAmount"); - UUID targetId = this.targetPointer.getFirst(game, source); - if (damageAmount != null && targetId != null) { - Player player = game.getPlayer(targetId); - if (player != null) { - player.damage(damageAmount, targetId, game, false, true); + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Player controller = game.getPlayer(source.getControllerId()); + DamageEvent damageEvent = (DamageEvent) event; + if (controller != null) { + controller.damage(damageEvent.getAmount(), damageEvent.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), damageEvent.getAppliedEffects()); + UUID sourceControllerId = game.getControllerId(damageEvent.getSourceId()); + if (sourceControllerId != null) { + Player sourceController = game.getPlayer(sourceControllerId); + if (sourceController != null) { + sourceController.damage(damageEvent.getAmount(), source.getSourceId(), game, false, true); return true; + } + } + } + return false; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + Player controller = game.getPlayer(source.getControllerId()); + DamageEvent damageEvent = (DamageEvent) event; + if (controller != null) { + if (controller.getId() == damageEvent.getTargetId() && damageEvent.getSourceId().equals(damageSource.getFirstTarget())) { + this.discard(); + return true; } } return false; From e5ef545d8f8f3a818386bfbc9d5325d9e75d3bbe Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Fri, 23 Feb 2018 18:21:08 +0400 Subject: [PATCH 4/7] * UI: fixed wrong feedback panel color for non active turn; --- Mage.Client/src/main/java/mage/client/game/FeedbackPanel.java | 1 - Mage.Client/src/main/java/mage/client/game/HelperPanel.java | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Mage.Client/src/main/java/mage/client/game/FeedbackPanel.java b/Mage.Client/src/main/java/mage/client/game/FeedbackPanel.java index 5992f5a424c..de2eb915056 100644 --- a/Mage.Client/src/main/java/mage/client/game/FeedbackPanel.java +++ b/Mage.Client/src/main/java/mage/client/game/FeedbackPanel.java @@ -64,7 +64,6 @@ public class FeedbackPanel extends javax.swing.JPanel { private static final Logger LOGGER = Logger.getLogger(FeedbackPanel.class); public enum FeedbackMode { - INFORM, QUESTION, CONFIRM, CANCEL, SELECT, END } diff --git a/Mage.Client/src/main/java/mage/client/game/HelperPanel.java b/Mage.Client/src/main/java/mage/client/game/HelperPanel.java index 04ccc0db76a..1bd86d7a3da 100644 --- a/Mage.Client/src/main/java/mage/client/game/HelperPanel.java +++ b/Mage.Client/src/main/java/mage/client/game/HelperPanel.java @@ -394,7 +394,7 @@ public class HelperPanel extends JPanel { } } else { // inform about other players - this.setOpaque(false); + this.mainPanel.setOpaque(false); } if (buttons.size() == 0) { From ac09be4b2b6651793e91d96ab60563d414a6cd90 Mon Sep 17 00:00:00 2001 From: L_J Date: Fri, 23 Feb 2018 14:45:01 +0000 Subject: [PATCH 5/7] Fixed Torment of Hailfire interaction with Sigarda (fixes #4452) --- .../src/mage/cards/t/TormentOfHailfire.java | 44 +++++++++++-------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/Mage.Sets/src/mage/cards/t/TormentOfHailfire.java b/Mage.Sets/src/mage/cards/t/TormentOfHailfire.java index 504c68648cc..7855e56b7a3 100644 --- a/Mage.Sets/src/mage/cards/t/TormentOfHailfire.java +++ b/Mage.Sets/src/mage/cards/t/TormentOfHailfire.java @@ -86,31 +86,37 @@ class TormentOfHailfireEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { int repeat = source.getManaCostsToPay().getX(); - for (int i = 0; i < repeat; i++) { + for (int i = 1; i <= repeat; i++) { for (UUID opponentId : game.getOpponents(source.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent != null) { - int permanents = game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT_NON_LAND, opponentId, game); - if (permanents > 0 && opponent.chooseUse(outcome, "Sacrifices a nonland permanent? (Iteration " + i + " of " + repeat + ")", - "Otherwise you have to discard a card or lose 3 life.", "Sacrifice", "Discard or life loss", source, game)) { - Target target = new TargetPermanent(StaticFilters.FILTER_CONTROLLED_PERMANENT_NON_LAND); - if (opponent.choose(outcome, target, source.getSourceId(), game)) { - Permanent permanent = game.getPermanent(target.getFirstTarget()); - if (permanent != null) { - permanent.sacrifice(source.getSourceId(), game); - continue; + boolean hasChosen = false; + while (!hasChosen) { + Player opponent = game.getPlayer(opponentId); + if (opponent != null) { + int permanents = game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT_NON_LAND, opponentId, game); + if (permanents > 0 && opponent.chooseUse(outcome, "Sacrifices a nonland permanent? (Iteration " + i + " of " + repeat + ")", + "Otherwise you have to discard a card or lose 3 life.", "Sacrifice", "Discard or life loss", source, game)) { + Target target = new TargetPermanent(StaticFilters.FILTER_CONTROLLED_PERMANENT_NON_LAND); + if (opponent.choose(outcome, target, source.getSourceId(), game)) { + Permanent permanent = game.getPermanent(target.getFirstTarget()); + if (permanent != null) { + if (permanent.sacrifice(source.getSourceId(), game)) { + hasChosen = true; + continue; + } + } } } + if (!opponent.getHand().isEmpty() && opponent.chooseUse(outcome, "Discard a card? (Iteration " + i + " of " + repeat + ")", + "Otherwise you lose 3 life.", "Discard", "Lose 3 life", source, game)) { + opponent.discardOne(false, source, game); + hasChosen = true; + continue; + } + opponent.loseLife(3, game, false); + hasChosen = true; } - if (!opponent.getHand().isEmpty() && opponent.chooseUse(outcome, "Discard a card? (Iteration " + i + " of " + repeat + ")", - "Otherwise you lose 3 life.", "Discard", "Lose 3 life", source, game)) { - opponent.discardOne(false, source, game); - continue; - } - opponent.loseLife(3, game, false); } } - } return true; } From a98f0f03c7ec4255950036287ff3721401f79b30 Mon Sep 17 00:00:00 2001 From: L_J Date: Fri, 23 Feb 2018 14:46:40 +0000 Subject: [PATCH 6/7] Code cleanup --- .../src/mage/cards/t/TormentOfHailfire.java | 43 ++++++++----------- 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/Mage.Sets/src/mage/cards/t/TormentOfHailfire.java b/Mage.Sets/src/mage/cards/t/TormentOfHailfire.java index 7855e56b7a3..209582a7bf1 100644 --- a/Mage.Sets/src/mage/cards/t/TormentOfHailfire.java +++ b/Mage.Sets/src/mage/cards/t/TormentOfHailfire.java @@ -87,36 +87,31 @@ class TormentOfHailfireEffect extends OneShotEffect { if (controller != null) { int repeat = source.getManaCostsToPay().getX(); for (int i = 1; i <= repeat; i++) { - for (UUID opponentId : game.getOpponents(source.getControllerId())) { - boolean hasChosen = false; - while (!hasChosen) { - Player opponent = game.getPlayer(opponentId); - if (opponent != null) { - int permanents = game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT_NON_LAND, opponentId, game); - if (permanents > 0 && opponent.chooseUse(outcome, "Sacrifices a nonland permanent? (Iteration " + i + " of " + repeat + ")", - "Otherwise you have to discard a card or lose 3 life.", "Sacrifice", "Discard or life loss", source, game)) { - Target target = new TargetPermanent(StaticFilters.FILTER_CONTROLLED_PERMANENT_NON_LAND); - if (opponent.choose(outcome, target, source.getSourceId(), game)) { - Permanent permanent = game.getPermanent(target.getFirstTarget()); - if (permanent != null) { - if (permanent.sacrifice(source.getSourceId(), game)) { - hasChosen = true; - continue; - } + for (UUID opponentId : game.getOpponents(source.getControllerId())) {z + Player opponent = game.getPlayer(opponentId); + if (opponent != null) { + int permanents = game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT_NON_LAND, opponentId, game); + if (permanents > 0 && opponent.chooseUse(outcome, "Sacrifices a nonland permanent? (Iteration " + i + " of " + repeat + ")", + "Otherwise you have to discard a card or lose 3 life.", "Sacrifice", "Discard or life loss", source, game)) { + Target target = new TargetPermanent(StaticFilters.FILTER_CONTROLLED_PERMANENT_NON_LAND); + if (opponent.choose(outcome, target, source.getSourceId(), game)) { + Permanent permanent = game.getPermanent(target.getFirstTarget()); + if (permanent != null) { + if (permanent.sacrifice(source.getSourceId(), game)) { + continue; } } } - if (!opponent.getHand().isEmpty() && opponent.chooseUse(outcome, "Discard a card? (Iteration " + i + " of " + repeat + ")", - "Otherwise you lose 3 life.", "Discard", "Lose 3 life", source, game)) { - opponent.discardOne(false, source, game); - hasChosen = true; - continue; - } - opponent.loseLife(3, game, false); - hasChosen = true; } + if (!opponent.getHand().isEmpty() && opponent.chooseUse(outcome, "Discard a card? (Iteration " + i + " of " + repeat + ")", + "Otherwise you lose 3 life.", "Discard", "Lose 3 life", source, game)) { + opponent.discardOne(false, source, game); + continue; + } + opponent.loseLife(3, game, false); } } + } return true; } From 6c2e66cd57022c2c964d615731f40a2b55636e0c Mon Sep 17 00:00:00 2001 From: L_J Date: Fri, 23 Feb 2018 14:48:08 +0000 Subject: [PATCH 7/7] Typo --- Mage.Sets/src/mage/cards/t/TormentOfHailfire.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/cards/t/TormentOfHailfire.java b/Mage.Sets/src/mage/cards/t/TormentOfHailfire.java index 209582a7bf1..79e9e389ec3 100644 --- a/Mage.Sets/src/mage/cards/t/TormentOfHailfire.java +++ b/Mage.Sets/src/mage/cards/t/TormentOfHailfire.java @@ -87,7 +87,7 @@ class TormentOfHailfireEffect extends OneShotEffect { if (controller != null) { int repeat = source.getManaCostsToPay().getX(); for (int i = 1; i <= repeat; i++) { - for (UUID opponentId : game.getOpponents(source.getControllerId())) {z + for (UUID opponentId : game.getOpponents(source.getControllerId())) { Player opponent = game.getPlayer(opponentId); if (opponent != null) { int permanents = game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT_NON_LAND, opponentId, game);