diff --git a/Mage.Sets/src/mage/cards/s/StreetwiseNegotiator.java b/Mage.Sets/src/mage/cards/s/StreetwiseNegotiator.java index 22c12baa315..bdbd0602960 100644 --- a/Mage.Sets/src/mage/cards/s/StreetwiseNegotiator.java +++ b/Mage.Sets/src/mage/cards/s/StreetwiseNegotiator.java @@ -26,9 +26,9 @@ public final class StreetwiseNegotiator extends CardImpl { // Backup 1 BackupAbility backupAbility = new BackupAbility(this, 1); - // This creature assigns combat damage equal to its toughness rather than its power. - backupAbility.addAbility(new SimpleStaticAbility(new CombatDamageByToughnessSourceEffect(Duration.EndOfTurn) + // This creature assigns combat damage equal to its toughness rather than its power. + backupAbility.addAbility(new SimpleStaticAbility(new CombatDamageByToughnessSourceEffect(Duration.EndOfGame) .setText("this creature assigns combat damage equal to its toughness rather than its power"))); this.addAbility(backupAbility); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/BackupTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/BackupTest.java index 9b4f52de738..e542231ad9c 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/BackupTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/BackupTest.java @@ -22,7 +22,7 @@ public class BackupTest extends CardTestPlayerBase { addTarget(playerA, "Raging Goblin");//Now a 4/4 attack(1, playerA, "Raging Goblin"); - block(1,playerB,"Memnite","Raging Goblin"); + block(1, playerB, "Memnite", "Raging Goblin"); setStrictChooseMode(false); //auto-stack triggers setStopAt(1, PhaseStep.END_TURN); @@ -33,6 +33,7 @@ public class BackupTest extends CardTestPlayerBase { assertPermanentCount(playerA, "Conclave Sledge-Captain", 1); assertPowerToughness(playerA, "Conclave Sledge-Captain", 4, 4); } + @Test public void ConclaveSledgeCaptainSelfTest() { addCard(Zone.BATTLEFIELD, playerA, "Forest", 6); @@ -49,6 +50,7 @@ public class BackupTest extends CardTestPlayerBase { assertPermanentCount(playerA, "Conclave Sledge-Captain", 1); assertPowerToughness(playerA, "Conclave Sledge-Captain", 14, 14); } + @Test public void ConclaveSledgeCaptainSplitTest() { addCard(Zone.BATTLEFIELD, playerA, "Forest", 6); @@ -75,6 +77,7 @@ public class BackupTest extends CardTestPlayerBase { assertPowerToughness(playerA, "Raging Minotaur", 8, 8); assertPowerToughness(playerA, "Conclave Sledge-Captain", 4, 4); } + @Test public void MirrorShieldHopliteStrictTest() { addCard(Zone.BATTLEFIELD, playerA, "Mirror-Shield Hoplite"); @@ -83,7 +86,7 @@ public class BackupTest extends CardTestPlayerBase { castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Consuming Aetherborn"); addTarget(playerA, "Consuming Aetherborn"); - setChoice(playerA,true); + setChoice(playerA, true); addTarget(playerA, "Mirror-Shield Hoplite"); setStrictChooseMode(true); @@ -92,6 +95,7 @@ public class BackupTest extends CardTestPlayerBase { assertPowerToughness(playerA, "Mirror-Shield Hoplite", 3, 3); assertPowerToughness(playerA, "Consuming Aetherborn", 3, 3); } + @Test public void MirrorShieldHopliteTriggeredTest() { addCard(Zone.BATTLEFIELD, playerA, "Mirror-Shield Hoplite"); @@ -102,7 +106,7 @@ public class BackupTest extends CardTestPlayerBase { castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Enduring Bondwarden"); addTarget(playerA, "Mirror-Shield Hoplite"); - setChoice(playerA,false); //2 +1/+1 counters + setChoice(playerA, false); //2 +1/+1 counters waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Murder", "Mirror-Shield Hoplite"); @@ -113,6 +117,7 @@ public class BackupTest extends CardTestPlayerBase { execute(); assertPowerToughness(playerA, "Enduring Bondwarden", 4, 5); } + @Test public void MirrorShieldHopliteSourceTest() { addCard(Zone.BATTLEFIELD, playerA, "Mirror-Shield Hoplite"); @@ -123,7 +128,7 @@ public class BackupTest extends CardTestPlayerBase { castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Enduring Bondwarden"); addTarget(playerA, "Mirror-Shield Hoplite"); - setChoice(playerA,true); + setChoice(playerA, true); addTarget(playerA, "Enduring Bondwarden"); //The source of the copy is the same as the source of the original backup ability. //So the Bondwarden shouldn't gain the ability again @@ -140,19 +145,25 @@ public class BackupTest extends CardTestPlayerBase { @Test public void StreetwiseNegotiatorTest() { - addCard(Zone.BATTLEFIELD, playerA, "Aegis Turtle"); + addCard(Zone.BATTLEFIELD, playerA, "Air-Cult Elemental"); // 2/5 addCard(Zone.BATTLEFIELD, playerA, "Forest", 2); - addCard(Zone.HAND, playerA, "Streetwise Negotiator", 1); + addCard(Zone.HAND, playerA, "Streetwise Negotiator", 1); // 0/2 castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Streetwise Negotiator"); - addTarget(playerA, "Aegis Turtle"); - // Should deal 6 damage - attack(1, playerA, "Aegis Turtle"); + addTarget(playerA, "Air-Cult Elemental"); + + // turn 1 - counter + active backup + attack(1, playerA, "Air-Cult Elemental"); // deals 1 + 5 damage due backup + checkLife("after 1", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, 20 - 1 - 5); + + // turn 3 - counter only + attack(3, playerA, "Air-Cult Elemental"); // deals 1 + 2 damage + attack(3, playerA, "Streetwise Negotiator"); // deals 2 damage due static ability - setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); setStrictChooseMode(true); + setStopAt(3, PhaseStep.POSTCOMBAT_MAIN); execute(); - assertLife(playerB, 14); + assertLife(playerB, 20 - (1 + 5) - (1 + 2 + 2)); } } diff --git a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java index d56bec26e1c..7d50fbee52d 100644 --- a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java +++ b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java @@ -2646,6 +2646,7 @@ public class VerifyCardDataTest { setInfo.getCardNumber(), setInfo.getRarity(), setInfo.getGraphicInfo())); if (card == null) { errorsList.add("Error: broken constructor " + setInfo.getCardClass()); + continue; } if (!card.getExpansionSetCode().equals(set.getCode())) { errorsList.add("Error: card constructor have custom expansionSetCode, must be removed " + setInfo.getCardClass()); diff --git a/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CombatDamageByToughnessSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CombatDamageByToughnessSourceEffect.java index 3403370a19f..ffbd8c9476a 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CombatDamageByToughnessSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/CombatDamageByToughnessSourceEffect.java @@ -31,7 +31,6 @@ public class CombatDamageByToughnessSourceEffect extends ContinuousEffectImpl { public boolean apply(Game game, Ability source) { Permanent permanent = source.getSourcePermanentIfItStillExists(game); if (permanent == null) { - discard(); return false; } diff --git a/Mage/src/main/java/mage/abilities/keyword/BackupAbility.java b/Mage/src/main/java/mage/abilities/keyword/BackupAbility.java index d88691e9247..78fda570d13 100644 --- a/Mage/src/main/java/mage/abilities/keyword/BackupAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/BackupAbility.java @@ -1,10 +1,14 @@ package mage.abilities.keyword; import mage.abilities.Ability; +import mage.abilities.StaticAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.cards.Card; +import mage.constants.Duration; import mage.constants.Outcome; import mage.counters.CounterType; import mage.game.Game; @@ -85,12 +89,25 @@ public class BackupAbility extends EntersBattlefieldTriggeredAbility { } /** - * * @param ability * @param watcher * @param dontAddToCard use it on multiple instances of backups (example: Conclave Sledge-Captain) */ public void addAbility(Ability ability, Watcher watcher, boolean dontAddToCard) { + // runtime/verify check: wrong duration in backup's static effects + if (ability instanceof StaticAbility) { + Effect wrongEffect = ability.getEffects().stream() + .filter(effect -> effect instanceof ContinuousEffect) + .map(effect -> (ContinuousEffect) effect) + .filter(effect -> effect.getDuration().equals(Duration.EndOfTurn)) + .findFirst() + .orElse(null); + if (wrongEffect != null) { + // how-to fix: add effect with Duration.EndOfGame (backup's abilities for permanent controls by GainAbility) + throw new IllegalArgumentException("Wrong code usage. Backup ability and source card must contains static effects. Wrong effect: " + wrongEffect.getClass().getName()); + } + } + if (watcher != null) { ability.addWatcher(watcher); }