diff --git a/Mage.Sets/src/mage/cards/b/BalduvianWarlord.java b/Mage.Sets/src/mage/cards/b/BalduvianWarlord.java index e99ae3db823..d04dbc1548f 100644 --- a/Mage.Sets/src/mage/cards/b/BalduvianWarlord.java +++ b/Mage.Sets/src/mage/cards/b/BalduvianWarlord.java @@ -132,7 +132,7 @@ class BalduvianWarlordUnblockEffect extends OneShotEffect { // according to the following mail response from MTG Rules Management about False Orders: // "if Player A attacks Players B and C, Player B's creatures cannot block creatures attacking Player C" // therefore we need to single out creatures attacking the target blocker's controller (disappointing, I know) - + List list = new ArrayList<>(); for (CombatGroup combatGroup : game.getCombat().getGroups()) { if (combatGroup.getDefendingPlayerId().equals(permanent.getControllerId())) { @@ -155,7 +155,7 @@ class BalduvianWarlordUnblockEffect extends OneShotEffect { return true; } Permanent chosenPermanent = game.getPermanent(target.getFirstTarget()); - if (chosenPermanent != null && permanent != null && chosenPermanent.isCreature() && controller != null) { + if (chosenPermanent != null && chosenPermanent.isCreature()) { CombatGroup chosenGroup = game.getCombat().findGroup(chosenPermanent.getId()); if (chosenGroup != null) { // Relevant ruling for Balduvian Warlord: diff --git a/Mage.Sets/src/mage/cards/b/BaronVonCount.java b/Mage.Sets/src/mage/cards/b/BaronVonCount.java index b9fb3afedb0..86f7200b6b9 100644 --- a/Mage.Sets/src/mage/cards/b/BaronVonCount.java +++ b/Mage.Sets/src/mage/cards/b/BaronVonCount.java @@ -59,7 +59,7 @@ import mage.util.CardUtil; public final class BaronVonCount extends CardImpl { public BaronVonCount(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}{R}"); addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.VILLAIN); @@ -152,22 +152,23 @@ class BaronVonCountTriggeredAbility extends TriggeredAbilityImpl { Permanent sourcePermanent = game.getPermanent(getSourceId()); MageObject mageObject = game.getObject(getSourceId()); Spell spell = game.getStack().getSpell(event.getTargetId()); - if (game.getState().getValue(mageObject.getId() + "_doom") == null) { + if (spell == null || sourcePermanent == null || mageObject == null) { return false; } Integer doomNumber = (Integer) game.getState().getValue(mageObject.getId() + "_doom"); - if (spell != null && sourcePermanent != null && mageObject != null && doomNumber > 0) { - if (!spell.isFaceDown(game)) { - String doomString = doomNumber.toString(); - if (spell.getCard().getManaCost().getText().contains(doomString) - || String.valueOf(spell.getPower().getBaseValue()).contains(doomString) - || String.valueOf(spell.getToughness().getBaseValue()).contains(doomString)) { - return true; - } else { - for (String string : spell.getCard().getRules()) { - if (string.contains(doomString)) { - return true; - } + if (doomNumber == null || doomNumber == 0) { + return false; + } + if (!spell.isFaceDown(game)) { + String doomString = doomNumber.toString(); + if (spell.getCard().getManaCost().getText().contains(doomString) + || String.valueOf(spell.getPower().getBaseValue()).contains(doomString) + || String.valueOf(spell.getToughness().getBaseValue()).contains(doomString)) { + return true; + } else { + for (String string : spell.getCard().getRules()) { + if (string.contains(doomString)) { + return true; } } } diff --git a/Mage.Sets/src/mage/cards/b/BloodfireInfusion.java b/Mage.Sets/src/mage/cards/b/BloodfireInfusion.java index 298977aedfe..2c5098eccd8 100644 --- a/Mage.Sets/src/mage/cards/b/BloodfireInfusion.java +++ b/Mage.Sets/src/mage/cards/b/BloodfireInfusion.java @@ -56,7 +56,7 @@ import mage.target.common.TargetControlledCreaturePermanent; public final class BloodfireInfusion extends CardImpl { public BloodfireInfusion(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}"); this.subtype.add(SubType.AURA); // Enchant creature you control @@ -65,14 +65,14 @@ public final class BloodfireInfusion extends CardImpl { this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); Ability ability = new EnchantAbility(auraTarget.getTargetName()); this.addAbility(ability); - + // {R}, Sacrifice enchanted creature: Bloodfire Infusion deals damage equal to the sacrificed creature's power to each creature. Effect effect = new DamageAllEffect(new AttachedPermanentPowerCount(), new FilterCreaturePermanent()); effect.setText("{this} deals damage equal to the sacrificed creature's power to each creature"); Ability ability2 = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{R}")); ability2.addCost(new SacrificeAttachedCost()); this.addAbility(ability2); - + } public BloodfireInfusion(final BloodfireInfusion card) { @@ -90,10 +90,11 @@ class AttachedPermanentPowerCount implements DynamicValue { @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { Permanent attachment = game.getPermanentOrLKIBattlefield(sourceAbility.getSourceId()); + if (attachment == null) { + return 0; + } Permanent permanent = game.getPermanentOrLKIBattlefield(attachment.getAttachedTo()); - if (attachment != null - && permanent != null - && (permanent.getPower().getValue() >= 0)) { + if (permanent != null && (permanent.getPower().getValue() >= 0)) { return permanent.getPower().getValue(); } return 0; diff --git a/Mage.Sets/src/mage/cards/c/CapitalOffense.java b/Mage.Sets/src/mage/cards/c/CapitalOffense.java index 90567f148bd..cf395e0087b 100644 --- a/Mage.Sets/src/mage/cards/c/CapitalOffense.java +++ b/Mage.Sets/src/mage/cards/c/CapitalOffense.java @@ -86,10 +86,12 @@ class NumberOfCapitalsInTextOfTargetCreatureCount implements DynamicValue { if (cards != null) { for (CardInfo cardInfo : cards) { Card dummy = cardInfo != null ? cardInfo.getCard() : null; - for (String line : dummy.getRules()) { - line = line.replaceAll("(?i)", ""); // Ignoring reminder text in italic - line = line.replaceAll("\\{this\\}", permanent.getName()); - capitals += line.length() - line.replaceAll("[A-Z]", "").length(); + if (dummy != null) { + for (String line : dummy.getRules()) { + line = line.replaceAll("(?i)", ""); // Ignoring reminder text in italic + line = line.replaceAll("\\{this\\}", permanent.getName()); + capitals += line.length() - line.replaceAll("[A-Z]", "").length(); + } } return -1 * capitals; } diff --git a/Mage.Sets/src/mage/cards/c/CloneShell.java b/Mage.Sets/src/mage/cards/c/CloneShell.java index f16e568fcae..93ac2a878ce 100644 --- a/Mage.Sets/src/mage/cards/c/CloneShell.java +++ b/Mage.Sets/src/mage/cards/c/CloneShell.java @@ -92,7 +92,7 @@ class CloneShellEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { + if (controller == null) { return false; } Cards cards = new CardsImpl(controller.getLibrary().getTopCards(game, 4)); diff --git a/Mage.Sets/src/mage/cards/c/CrownOfTheAges.java b/Mage.Sets/src/mage/cards/c/CrownOfTheAges.java index 55f5350c17b..5d53c629645 100644 --- a/Mage.Sets/src/mage/cards/c/CrownOfTheAges.java +++ b/Mage.Sets/src/mage/cards/c/CrownOfTheAges.java @@ -103,46 +103,47 @@ class CrownOfTheAgesEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - UUID auraId = getTargetPointer().getFirst(game, source); - Permanent aura = game.getPermanent(auraId); + Permanent aura = game.getPermanent(source.getFirstTarget()); + if (aura == null) { + return false; + } Permanent fromPermanent = game.getPermanent(aura.getAttachedTo()); Player controller = game.getPlayer(source.getControllerId()); - if (fromPermanent != null && controller != null) { - boolean passed = true; - FilterCreaturePermanent filterChoice = new FilterCreaturePermanent("another creature"); - filterChoice.add(Predicates.not(new PermanentIdPredicate(fromPermanent.getId()))); + if (fromPermanent == null || controller == null) { + return false; + } + boolean passed = true; + FilterCreaturePermanent filterChoice = new FilterCreaturePermanent("another creature"); + filterChoice.add(Predicates.not(new PermanentIdPredicate(fromPermanent.getId()))); - Target chosenCreatureToAttachAura = new TargetPermanent(filterChoice); - chosenCreatureToAttachAura.setNotTarget(true); + Target chosenCreatureToAttachAura = new TargetPermanent(filterChoice); + chosenCreatureToAttachAura.setNotTarget(true); - if (chosenCreatureToAttachAura.canChoose(source.getSourceId(), source.getControllerId(), game) - && controller.choose(Outcome.Neutral, chosenCreatureToAttachAura, source.getSourceId(), game)) { - Permanent creatureToAttachAura = game.getPermanent(chosenCreatureToAttachAura.getFirstTarget()); - if (creatureToAttachAura != null) { - if (aura != null && passed) { - // Check the target filter - Target target = aura.getSpellAbility().getTargets().get(0); - if (target instanceof TargetPermanent) { - if (!target.getFilter().match(creatureToAttachAura, game)) { - passed = false; - } - } - // Check for protection - MageObject auraObject = game.getObject(auraId); - if (creatureToAttachAura.cantBeAttachedBy(auraObject, game)) { + if (chosenCreatureToAttachAura.canChoose(source.getSourceId(), source.getControllerId(), game) + && controller.choose(Outcome.Neutral, chosenCreatureToAttachAura, source.getSourceId(), game)) { + Permanent creatureToAttachAura = game.getPermanent(chosenCreatureToAttachAura.getFirstTarget()); + if (creatureToAttachAura != null) { + if (passed) { + // Check the target filter + Target target = aura.getSpellAbility().getTargets().get(0); + if (target instanceof TargetPermanent) { + if (!target.getFilter().match(creatureToAttachAura, game)) { passed = false; } } - if (passed) { - fromPermanent.removeAttachment(aura.getId(), game); - creatureToAttachAura.addAttachment(aura.getId(), game); - return true; + // Check for protection + MageObject auraObject = game.getObject(aura.getId()); + if (creatureToAttachAura.cantBeAttachedBy(auraObject, game)) { + passed = false; } } + if (passed) { + fromPermanent.removeAttachment(aura.getId(), game); + creatureToAttachAura.addAttachment(aura.getId(), game); + return true; + } } - return true; } - - return false; + return true; } } diff --git a/Mage.Sets/src/mage/cards/c/CrypticGateway.java b/Mage.Sets/src/mage/cards/c/CrypticGateway.java index b18c0088c15..9b1f9ef859f 100644 --- a/Mage.Sets/src/mage/cards/c/CrypticGateway.java +++ b/Mage.Sets/src/mage/cards/c/CrypticGateway.java @@ -71,7 +71,7 @@ public final class CrypticGateway extends CardImpl { TargetControlledPermanent target; public CrypticGateway(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{5}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}"); // Tap two untapped creatures you control: You may put a creature card from your hand that shares a creature type with each creature tapped this way onto the battlefield. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new CrypticGatewayEffect(), new CrypticGatewayCost(new TargetControlledPermanent(filter)))); @@ -173,7 +173,7 @@ class CrypticGatewayEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); - if (source == null || source.getCosts() == null) { + if (source.getCosts() == null) { return false; } diff --git a/Mage.Sets/src/mage/cards/d/DrainPower.java b/Mage.Sets/src/mage/cards/d/DrainPower.java index f509bc79528..c336ff64d69 100644 --- a/Mage.Sets/src/mage/cards/d/DrainPower.java +++ b/Mage.Sets/src/mage/cards/d/DrainPower.java @@ -112,7 +112,7 @@ class DrainPowerEffect extends OneShotEffect { for (Ability ability : permanent.getAbilities()) { if (ability instanceof ActivatedAbility && ability.getAbilityType() == AbilityType.MANA) { ActivatedManaAbilityImpl manaAbility = (ActivatedManaAbilityImpl) ability; - if (manaAbility != null && manaAbility.canActivate(targetPlayer.getId(), game).canActivate()) { + if (manaAbility.canActivate(targetPlayer.getId(), game).canActivate()) { // canActivate can't check for mana abilities that require a mana cost, if the payment isn't possible (Cabal Coffers etc) // so it's necessary to filter them out manually - might be buggy in some fringe cases for (ManaCost manaCost : manaAbility.getManaCosts()) { diff --git a/Mage.Sets/src/mage/cards/d/DreamCoat.java b/Mage.Sets/src/mage/cards/d/DreamCoat.java index 87a9e3c5cea..8a3d3789cda 100644 --- a/Mage.Sets/src/mage/cards/d/DreamCoat.java +++ b/Mage.Sets/src/mage/cards/d/DreamCoat.java @@ -98,44 +98,47 @@ class BecomesColorOrColorsEnchantedEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); Permanent enchantment = game.getPermanentOrLKIBattlefield(source.getSourceId()); + if (enchantment == null) { + return false; + } Permanent permanent = game.getPermanent(enchantment.getAttachedTo()); StringBuilder sb = new StringBuilder(); - if (controller != null && enchantment != null && permanent != null) { - for (int i = 0; i < 5; i++) { - if (i > 0) { - if (!controller.chooseUse(Outcome.Neutral, "Do you wish to choose another color?", source, game)) { - break; - } - } - ChoiceColor choiceColor = new ChoiceColor(); - if (!controller.choose(Outcome.Benefit, choiceColor, game)) { - return false; - } - if (!game.isSimulation()) { - game.informPlayers(permanent.getName() + ": " + controller.getLogName() + " has chosen " + choiceColor.getChoice()); - } - if (choiceColor.getColor().isBlack()) { - sb.append('B'); - } else if (choiceColor.getColor().isBlue()) { - sb.append('U'); - } else if (choiceColor.getColor().isRed()) { - sb.append('R'); - } else if (choiceColor.getColor().isGreen()) { - sb.append('G'); - } else if (choiceColor.getColor().isWhite()) { - sb.append('W'); + if (controller == null || permanent == null) { + return false; + } + for (int i = 0; i < 5; i++) { + if (i > 0) { + if (!controller.chooseUse(Outcome.Neutral, "Do you wish to choose another color?", source, game)) { + break; } } - String colors = new String(sb); - ObjectColor chosenColors = new ObjectColor(colors); - ContinuousEffect effect = new BecomesColorTargetEffect(chosenColors, Duration.Custom); - effect.setTargetPointer(new FixedTarget(permanent.getId())); - game.addEffect(effect, source); - - return true; + ChoiceColor choiceColor = new ChoiceColor(); + if (!controller.choose(Outcome.Benefit, choiceColor, game)) { + return false; + } + if (!game.isSimulation()) { + game.informPlayers(permanent.getName() + ": " + controller.getLogName() + " has chosen " + choiceColor.getChoice()); + } + if (choiceColor.getColor().isBlack()) { + sb.append('B'); + } else if (choiceColor.getColor().isBlue()) { + sb.append('U'); + } else if (choiceColor.getColor().isRed()) { + sb.append('R'); + } else if (choiceColor.getColor().isGreen()) { + sb.append('G'); + } else if (choiceColor.getColor().isWhite()) { + sb.append('W'); + } } - return false; + String colors = new String(sb); + ObjectColor chosenColors = new ObjectColor(colors); + ContinuousEffect effect = new BecomesColorTargetEffect(chosenColors, Duration.Custom); + effect.setTargetPointer(new FixedTarget(permanent.getId())); + game.addEffect(effect, source); + + return true; } @Override diff --git a/Mage.Sets/src/mage/cards/f/FalseOrders.java b/Mage.Sets/src/mage/cards/f/FalseOrders.java index 35d218ea252..b69b1a96a1e 100644 --- a/Mage.Sets/src/mage/cards/f/FalseOrders.java +++ b/Mage.Sets/src/mage/cards/f/FalseOrders.java @@ -121,85 +121,87 @@ class FalseOrdersUnblockEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanent(source.getTargets().getFirstTarget()); - if (controller != null && permanent != null) { + if (controller == null || permanent == null) { + return false; + } - // Remove target creature from combat - Effect effect = new RemoveFromCombatTargetEffect(); - effect.apply(game, source); + // Remove target creature from combat + Effect effect = new RemoveFromCombatTargetEffect(); + effect.apply(game, source); - // Make blocked creatures unblocked - BlockedByOnlyOneCreatureThisCombatWatcher watcher = (BlockedByOnlyOneCreatureThisCombatWatcher) game.getState().getWatchers().get(BlockedByOnlyOneCreatureThisCombatWatcher.class.getSimpleName()); - if (watcher != null) { - Set combatGroups = watcher.getBlockedOnlyByCreature(permanent.getId()); - if (combatGroups != null) { - for (CombatGroup combatGroup : combatGroups) { - if (combatGroup != null) { - combatGroup.setBlocked(false, game); - } + // Make blocked creatures unblocked + BlockedByOnlyOneCreatureThisCombatWatcher watcher = (BlockedByOnlyOneCreatureThisCombatWatcher) game.getState().getWatchers().get(BlockedByOnlyOneCreatureThisCombatWatcher.class.getSimpleName()); + if (watcher != null) { + Set combatGroups = watcher.getBlockedOnlyByCreature(permanent.getId()); + if (combatGroups != null) { + for (CombatGroup combatGroup : combatGroups) { + if (combatGroup != null) { + combatGroup.setBlocked(false, game); } } } - - // Choose new creature to block - if (permanent.isCreature()) { - if (controller.chooseUse(Outcome.Benefit, "Do you want " + permanent.getLogName() + " to block an attacking creature?", source, game)) { - // according to the following mail response from MTG Rules Management about False Orders: - // "if Player A attacks Players B and C, Player B's creatures cannot block creatures attacking Player C" - // therefore we need to single out creatures attacking the target blocker's controller (disappointing, I know) - - List list = new ArrayList<>(); - for (CombatGroup combatGroup : game.getCombat().getGroups()) { - if (combatGroup.getDefendingPlayerId().equals(permanent.getControllerId())) { - for (UUID attackingCreatureId : combatGroup.getAttackers()) { - Permanent targetsControllerAttacker = game.getPermanent(attackingCreatureId); - list.add(targetsControllerAttacker); - } - } - } - Player targetsController = game.getPlayer(permanent.getControllerId()); - if (targetsController != null) { - FilterAttackingCreature filter = new FilterAttackingCreature("creature attacking " + targetsController.getLogName()); - filter.add(new PermanentInListPredicate(list)); - TargetAttackingCreature target = new TargetAttackingCreature(1, 1, filter, true); - if (target.canChoose(source.getSourceId(), controller.getId(), game)) { - while (!target.isChosen() && target.canChoose(controller.getId(), game) && controller.canRespond()) { - controller.chooseTarget(outcome, target, source, game); - } - } else { - return true; - } - Permanent chosenPermanent = game.getPermanent(target.getFirstTarget()); - if (chosenPermanent != null && permanent != null && chosenPermanent.isCreature() && controller != null) { - CombatGroup chosenGroup = game.getCombat().findGroup(chosenPermanent.getId()); - if (chosenGroup != null) { - // Relevant ruling for Balduvian Warlord: - // 7/15/2006 If an attacking creature has an ability that triggers “When this creature becomes blocked,” - // it triggers when a creature blocks it due to the Warlord’s ability only if it was unblocked at that point. - boolean notYetBlocked = chosenGroup.getBlockers().isEmpty(); - chosenGroup.addBlockerToGroup(permanent.getId(), controller.getId(), game); - game.getCombat().addBlockingGroup(permanent.getId(), chosenPermanent.getId(), controller.getId(), game); // 702.21h - if (notYetBlocked) { - game.fireEvent(GameEvent.getEvent(GameEvent.EventType.CREATURE_BLOCKED, chosenPermanent.getId(), null)); - for (UUID bandedId : chosenPermanent.getBandedCards()) { - CombatGroup bandedGroup = game.getCombat().findGroup(bandedId); - if (bandedGroup != null && chosenGroup.getBlockers().size() == 1) { - game.fireEvent(GameEvent.getEvent(GameEvent.EventType.CREATURE_BLOCKED, bandedId, null)); - } - } - } - game.fireEvent(GameEvent.getEvent(GameEvent.EventType.BLOCKER_DECLARED, chosenPermanent.getId(), permanent.getId(), permanent.getControllerId())); - } - CombatGroup blockGroup = findBlockingGroup(permanent, game); // a new blockingGroup is formed, so it's necessary to find it again - if (blockGroup != null) { - blockGroup.pickAttackerOrder(permanent.getControllerId(), game); - } - } - } - } - return true; - } } - return false; + + if (!permanent.isCreature() + || !controller.chooseUse(Outcome.Benefit, "Do you want " + permanent.getLogName() + " to block an attacking creature?", source, game)) { + return false; + } + // Choose new creature to block + + // according to the following mail response from MTG Rules Management about False Orders: + // "if Player A attacks Players B and C, Player B's creatures cannot block creatures attacking Player C" + // therefore we need to single out creatures attacking the target blocker's controller (disappointing, I know) + List list = new ArrayList<>(); + for (CombatGroup combatGroup : game.getCombat().getGroups()) { + if (combatGroup.getDefendingPlayerId().equals(permanent.getControllerId())) { + for (UUID attackingCreatureId : combatGroup.getAttackers()) { + Permanent targetsControllerAttacker = game.getPermanent(attackingCreatureId); + list.add(targetsControllerAttacker); + } + } + } + Player targetsController = game.getPlayer(permanent.getControllerId()); + if (targetsController == null) { + return false; + } + FilterAttackingCreature filter = new FilterAttackingCreature("creature attacking " + targetsController.getLogName()); + filter.add(new PermanentInListPredicate(list)); + TargetAttackingCreature target = new TargetAttackingCreature(1, 1, filter, true); + if (target.canChoose(source.getSourceId(), controller.getId(), game)) { + while (!target.isChosen() && target.canChoose(controller.getId(), game) && controller.canRespond()) { + controller.chooseTarget(outcome, target, source, game); + } + } else { + return true; + } + Permanent chosenPermanent = game.getPermanent(target.getFirstTarget()); + if (chosenPermanent == null || !chosenPermanent.isCreature()) { + return false; + } + CombatGroup chosenGroup = game.getCombat().findGroup(chosenPermanent.getId()); + if (chosenGroup != null) { + // Relevant ruling for Balduvian Warlord: + // 7/15/2006 If an attacking creature has an ability that triggers “When this creature becomes blocked,” + // it triggers when a creature blocks it due to the Warlord’s ability only if it was unblocked at that point. + boolean notYetBlocked = chosenGroup.getBlockers().isEmpty(); + chosenGroup.addBlockerToGroup(permanent.getId(), controller.getId(), game); + game.getCombat().addBlockingGroup(permanent.getId(), chosenPermanent.getId(), controller.getId(), game); // 702.21h + if (notYetBlocked) { + game.fireEvent(GameEvent.getEvent(GameEvent.EventType.CREATURE_BLOCKED, chosenPermanent.getId(), null)); + for (UUID bandedId : chosenPermanent.getBandedCards()) { + CombatGroup bandedGroup = game.getCombat().findGroup(bandedId); + if (bandedGroup != null && chosenGroup.getBlockers().size() == 1) { + game.fireEvent(GameEvent.getEvent(GameEvent.EventType.CREATURE_BLOCKED, bandedId, null)); + } + } + } + game.fireEvent(GameEvent.getEvent(GameEvent.EventType.BLOCKER_DECLARED, chosenPermanent.getId(), permanent.getId(), permanent.getControllerId())); + } + CombatGroup blockGroup = findBlockingGroup(permanent, game); // a new blockingGroup is formed, so it's necessary to find it again + if (blockGroup != null) { + blockGroup.pickAttackerOrder(permanent.getControllerId(), game); + } + return true; } private CombatGroup findBlockingGroup(Permanent blocker, Game game) { diff --git a/Mage.Sets/src/mage/cards/g/GildedCerodon.java b/Mage.Sets/src/mage/cards/g/GildedCerodon.java index d171806810f..10e1c2084ea 100644 --- a/Mage.Sets/src/mage/cards/g/GildedCerodon.java +++ b/Mage.Sets/src/mage/cards/g/GildedCerodon.java @@ -51,14 +51,14 @@ import mage.target.common.TargetCreaturePermanent; * @author jeffwadsworth */ public final class GildedCerodon extends CardImpl { - + private static final String rule = "Whenever {this} attacks, if you control a Desert or there is a Desert card in your graveyard, target creature can't block this turn."; public GildedCerodon(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}"); - + this.subtype.add(SubType.BEAST); - + this.power = new MageInt(4); this.toughness = new MageInt(4); @@ -66,7 +66,7 @@ public final class GildedCerodon extends CardImpl { Ability ability = new ConditionalTriggeredAbility(new AttacksTriggeredAbility(new CantBlockTargetEffect(Duration.EndOfTurn), false), new GildedCerodonCondition(), rule); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); - + } public GildedCerodon(final GildedCerodon card) { @@ -80,10 +80,10 @@ public final class GildedCerodon extends CardImpl { } class GildedCerodonCondition implements Condition { - + private static final FilterPermanent filter = new FilterPermanent(); private static final FilterCard filter2 = new FilterCard(); - + static { filter.add(new SubtypePredicate(SubType.DESERT)); filter2.add(new SubtypePredicate(SubType.DESERT)); @@ -93,8 +93,8 @@ class GildedCerodonCondition implements Condition { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null - && !game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game).isEmpty() - || controller.getGraveyard().count(filter2, game) > 0) { + && (!game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game).isEmpty() + || controller.getGraveyard().count(filter2, game) > 0)) { return true; } return false; diff --git a/Mage.Sets/src/mage/cards/g/GlissaSunseeker.java b/Mage.Sets/src/mage/cards/g/GlissaSunseeker.java index 0431fddfb9f..a06b642a3ef 100644 --- a/Mage.Sets/src/mage/cards/g/GlissaSunseeker.java +++ b/Mage.Sets/src/mage/cards/g/GlissaSunseeker.java @@ -98,6 +98,10 @@ class GlissaSunseekerEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (controller == null || permanent == null) { + return false; + } ManaPool pool = controller.getManaPool(); int blackMana = pool.getBlack(); int whiteMana = pool.getWhite(); @@ -106,11 +110,8 @@ class GlissaSunseekerEffect extends OneShotEffect { int redMana = pool.getRed(); int colorlessMana = pool.getColorless(); int manaPoolTotal = blackMana + whiteMana + blueMana + greenMana + redMana + colorlessMana; - Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); - if (controller != null && permanent != null) { - if (permanent.getConvertedManaCost() == manaPoolTotal) { - return permanent.destroy(source.getSourceId(), game, false); - } + if (permanent.getConvertedManaCost() == manaPoolTotal) { + return permanent.destroy(source.getSourceId(), game, false); } return false; } diff --git a/Mage.Sets/src/mage/cards/g/GoblinPsychopath.java b/Mage.Sets/src/mage/cards/g/GoblinPsychopath.java index 87033f84aa8..04805d0abf1 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinPsychopath.java +++ b/Mage.Sets/src/mage/cards/g/GoblinPsychopath.java @@ -51,7 +51,7 @@ import mage.players.Player; public final class GoblinPsychopath extends CardImpl { public GoblinPsychopath(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}"); this.subtype.add(SubType.GOBLIN); this.subtype.add(SubType.MUTANT); this.power = new MageInt(5); @@ -72,7 +72,7 @@ public final class GoblinPsychopath extends CardImpl { } class GoblinPsychopathEffect extends ReplacementEffectImpl { - + private boolean wonFlip; public GoblinPsychopathEffect() { @@ -97,9 +97,9 @@ class GoblinPsychopathEffect extends ReplacementEffectImpl { @Override public boolean checksEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DAMAGE_CREATURE || - event.getType() == GameEvent.EventType.DAMAGE_PLANESWALKER || - event.getType() == GameEvent.EventType.DAMAGE_PLAYER; + return event.getType() == GameEvent.EventType.DAMAGE_CREATURE + || event.getType() == GameEvent.EventType.DAMAGE_PLANESWALKER + || event.getType() == GameEvent.EventType.DAMAGE_PLAYER; } @Override @@ -116,21 +116,19 @@ class GoblinPsychopathEffect extends ReplacementEffectImpl { public boolean replaceEvent(GameEvent event, Ability source, Game game) { MageObject object = game.getObject(event.getSourceId()); Player controller = game.getPlayer(source.getControllerId()); - if (controller != null && object != null) { - if (this.applies(event, source, game) && event instanceof DamageEvent && event.getAmount() > 0) { - DamageEvent damageEvent = (DamageEvent) event; - if (damageEvent.isCombatDamage()) { - if (!wonFlip) { - // TODO: make this redirect damage from all blockers - controller.damage(event.getAmount(), source.getSourceId(), game, false, true); - String sourceLogName = source != null ? game.getObject(source.getSourceId()).getLogName() + ": " : ""; - game.informPlayers(sourceLogName + "Redirected " + event.getAmount() + " damage to " + controller.getLogName()); - this.discard(); - return true; - } - } - } + if (controller == null || object == null + || !(this.applies(event, source, game) && event instanceof DamageEvent && event.getAmount() > 0)) { + return false; } - return false; + DamageEvent damageEvent = (DamageEvent) event; + if (!damageEvent.isCombatDamage() || wonFlip) { + return false; + } + // TODO: make this redirect damage from all blockers + controller.damage(event.getAmount(), source.getSourceId(), game, false, true); + String sourceLogName = game.getObject(source.getSourceId()).getLogName() + ": "; + game.informPlayers(sourceLogName + "Redirected " + event.getAmount() + " damage to " + controller.getLogName()); + this.discard(); + return true; } } diff --git a/Mage.Sets/src/mage/cards/h/Helldozer.java b/Mage.Sets/src/mage/cards/h/Helldozer.java index 811e5e51c3b..c072190f311 100644 --- a/Mage.Sets/src/mage/cards/h/Helldozer.java +++ b/Mage.Sets/src/mage/cards/h/Helldozer.java @@ -51,7 +51,7 @@ import mage.target.common.TargetLandPermanent; public final class Helldozer extends CardImpl { public Helldozer(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}{B}"); this.subtype.add(SubType.ZOMBIE); this.subtype.add(SubType.GIANT); @@ -96,15 +96,14 @@ class HelldozerEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Permanent helldozer = game.getPermanent(source.getSourceId()); Permanent landTarget = game.getPermanent(source.getFirstTarget()); - if (landTarget != null) { - landTarget.destroy(id, game, false); + if (landTarget == null) { + return false; } - Permanent landPermanent = (Permanent) game.getLastKnownInformation(landTarget.getId(), Zone.BATTLEFIELD); - if (landPermanent != null - && !landPermanent.isBasic() - && helldozer != null) { + boolean wasNonBasic = !landTarget.isBasic(); + landTarget.destroy(id, game, false); + if (wasNonBasic && helldozer != null) { return helldozer.untap(game); } return false; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/h/Heroism.java b/Mage.Sets/src/mage/cards/h/Heroism.java index 1c71db92b69..0c135268951 100644 --- a/Mage.Sets/src/mage/cards/h/Heroism.java +++ b/Mage.Sets/src/mage/cards/h/Heroism.java @@ -61,15 +61,16 @@ import mage.target.targetpointer.FixedTarget; public final class Heroism extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("a white creature"); + static { filter.add(new ColorPredicate(ObjectColor.WHITE)); } public Heroism(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{W}"); - + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}"); + // Sacrifice a white creature: For each attacking red creature, prevent all combat damage that would be dealt by that creature this turn unless its controller pays {2}{R}. - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new HeroismEffect(), new SacrificeTargetCost(new TargetControlledCreaturePermanent(1,1, filter, true)))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new HeroismEffect(), new SacrificeTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, true)))); } public Heroism(final Heroism card) { @@ -83,8 +84,9 @@ public final class Heroism extends CardImpl { } class HeroismEffect extends OneShotEffect { - + private static final FilterAttackingCreature filter = new FilterAttackingCreature("attacking red creature"); + static { filter.add(new ColorPredicate(ObjectColor.RED)); } @@ -111,7 +113,7 @@ class HeroismEffect extends OneShotEffect { Player player = game.getPlayer(game.getActivePlayerId()); Cost cost = new ManaCostsImpl("{2}{R}"); List permanentsToPrevent = new ArrayList<>(); - for (Permanent permanent : game.getState().getBattlefield().getAllActivePermanents(filter, player.getId(), game)) { + for (Permanent permanent : game.getState().getBattlefield().getAllActivePermanents(filter, game.getActivePlayerId(), game)) { cost.clearPaid(); String message = "Pay " + cost.getText() + "? If you don't, " + permanent.getLogName() + "'s combat damage will be prevented this turn."; if (player != null && player.chooseUse(Outcome.Neutral, message, source, game)) { diff --git a/Mage.Sets/src/mage/cards/i/ImmortalServitude.java b/Mage.Sets/src/mage/cards/i/ImmortalServitude.java index 5fe8d4249c6..730aaa3afbe 100644 --- a/Mage.Sets/src/mage/cards/i/ImmortalServitude.java +++ b/Mage.Sets/src/mage/cards/i/ImmortalServitude.java @@ -48,12 +48,10 @@ import mage.players.Player; public final class ImmortalServitude extends CardImpl { public ImmortalServitude(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{W/B}{W/B}{W/B}"); - + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{W/B}{W/B}{W/B}"); // Return each creature card with converted mana cost X from your graveyard to the battlefield. this.getSpellAbility().addEffect(new ImmortalServitudeEffect()); - } public ImmortalServitude(final ImmortalServitude card) { @@ -88,11 +86,10 @@ class ImmortalServitudeEffect extends OneShotEffect { int count = source.getManaCostsToPay().getX(); Set cards = you.getGraveyard().getCards(new FilterCreatureCard(), game); for (Card card : cards) { - if (card.getConvertedManaCost() == count - && card != null) { + if (card != null && card.getConvertedManaCost() == count) { card.moveToZone(Zone.BATTLEFIELD, source.getSourceId(), game, false); } } return true; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/i/IronMaiden.java b/Mage.Sets/src/mage/cards/i/IronMaiden.java index 54ce7b9ceac..1e1f4bc8f9f 100644 --- a/Mage.Sets/src/mage/cards/i/IronMaiden.java +++ b/Mage.Sets/src/mage/cards/i/IronMaiden.java @@ -47,7 +47,7 @@ import mage.players.Player; public final class IronMaiden extends CardImpl { public IronMaiden(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); // At the beginning of each opponent's upkeep, Iron Maiden deals X damage to that player, where X is the number of cards in their hand minus 4. Ability ability = new BeginningOfUpkeepTriggeredAbility(new IronMaidenEffect(), TargetController.OPPONENT, false); @@ -62,10 +62,8 @@ public final class IronMaiden extends CardImpl { public IronMaiden copy() { return new IronMaiden(this); } - - -} +} class IronMaidenEffect extends OneShotEffect { @@ -80,16 +78,11 @@ class IronMaidenEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player player = game.getPlayer(targetPointer.getFirst(game, source)); - if(player != null) - { + if (player != null) { int amount = player.getHand().size() - 4; - if(amount > 0) - { - if (player != null) { - player.damage(amount, source.getSourceId(), game, false, true); - return true; - } - + if (amount > 0) { + player.damage(amount, source.getSourceId(), game, false, true); + return true; } } return false; @@ -99,7 +92,7 @@ class IronMaidenEffect extends OneShotEffect { public IronMaidenEffect copy() { return new IronMaidenEffect(this); } - + @Override public String getText(Mode mode) { return "Iron Maiden deals X damage to that player, where X is the number of cards in their hand minus 4"; diff --git a/Mage.Sets/src/mage/cards/i/IronclawCurse.java b/Mage.Sets/src/mage/cards/i/IronclawCurse.java index f364e4ab204..716971c8f21 100644 --- a/Mage.Sets/src/mage/cards/i/IronclawCurse.java +++ b/Mage.Sets/src/mage/cards/i/IronclawCurse.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.i; import java.util.UUID; @@ -55,7 +54,7 @@ import mage.target.common.TargetCreaturePermanent; public final class IronclawCurse extends CardImpl { public IronclawCurse(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{R}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{R}"); this.subtype.add(SubType.AURA); // Enchant creature @@ -67,7 +66,7 @@ public final class IronclawCurse extends CardImpl { // Enchanted creature gets 0/-1. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(0, -1, Duration.WhileOnBattlefield))); - + // Enchanted creature can't block creatures with power equal to or greater than the enchanted creature's toughness. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new IronclawCurseEffect())); } @@ -101,8 +100,11 @@ class IronclawCurseEffect extends CantBlockAttachedEffect { @Override public boolean canBlock(Permanent attacker, Permanent blocker, Ability source, Game game) { Permanent enchantment = game.getPermanentOrLKIBattlefield(source.getSourceId()); + if (enchantment == null) { + return false; + } Permanent enchantedCreature = game.getPermanent(enchantment.getAttachedTo()); - if (enchantment != null && enchantment.getAttachedTo() != null) { + if (enchantment.getAttachedTo() != null) { return !(attacker.getPower().getValue() >= enchantedCreature.getToughness().getValue()); } return true; diff --git a/Mage.Sets/src/mage/cards/k/KarnLiberated.java b/Mage.Sets/src/mage/cards/k/KarnLiberated.java index 41e9a726617..6e237a7e530 100644 --- a/Mage.Sets/src/mage/cards/k/KarnLiberated.java +++ b/Mage.Sets/src/mage/cards/k/KarnLiberated.java @@ -265,15 +265,14 @@ class KarnPlayerExileEffect extends OneShotEffect { if (sourceObject == null) { return false; } - if (player != null) { - TargetCardInHand target = new TargetCardInHand(); - if (target != null - && target.canChoose(source.getSourceId(), player.getId(), game)) { - if (target.chooseTarget(Outcome.Exile, player.getId(), source, game)) { - UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()); - return player.moveCardsToExile(new CardsImpl(target.getTargets()).getCards(game), source, game, true, exileId, sourceObject.getIdName()); - } - } + if (player == null) { + return false; + } + TargetCardInHand target = new TargetCardInHand(); + if (target.canChoose(source.getSourceId(), player.getId(), game) + && target.chooseTarget(Outcome.Exile, player.getId(), source, game)) { + UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()); + return player.moveCardsToExile(new CardsImpl(target.getTargets()).getCards(game), source, game, true, exileId, sourceObject.getIdName()); } return false; } diff --git a/Mage.Sets/src/mage/cards/k/KillingWave.java b/Mage.Sets/src/mage/cards/k/KillingWave.java index 6e9165d15e5..8da49be1437 100644 --- a/Mage.Sets/src/mage/cards/k/KillingWave.java +++ b/Mage.Sets/src/mage/cards/k/KillingWave.java @@ -48,8 +48,7 @@ import java.util.*; public final class KillingWave extends CardImpl { public KillingWave(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{B}"); - + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{B}"); // For each creature, its controller sacrifices it unless he or she pays X life. this.getSpellAbility().addEffect(new KillingWaveEffect()); @@ -96,21 +95,23 @@ class KillingWaveEffect extends OneShotEffect { FilterCreaturePermanent filter = new FilterCreaturePermanent(); for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { Player player = game.getPlayer(playerId); - List creatures = game.getBattlefield().getAllActivePermanents(filter, playerId, game); + if (player != null) { + List creatures = game.getBattlefield().getAllActivePermanents(filter, playerId, game); - int lifePaid = 0; - int playerLife = player.getLife(); - for (Permanent creature : creatures) { - String message = "Pay " + amount + " life? If you don't, " + creature.getName() + " will be sacrificed."; - if (playerLife - amount - lifePaid >= 0 && player != null && player.chooseUse(Outcome.Neutral, message, source, game)) { - game.informPlayers(player.getLogName() + " pays " + amount + " life. He will not sacrifice " + creature.getName()); - lifePaid += amount; - } else { - game.informPlayers(player.getLogName() + " will sacrifice " + creature.getName()); - sacrifices.add(creature); + int lifePaid = 0; + int playerLife = player.getLife(); + for (Permanent creature : creatures) { + String message = "Pay " + amount + " life? If you don't, " + creature.getName() + " will be sacrificed."; + if (playerLife - amount - lifePaid >= 0 && player.chooseUse(Outcome.Neutral, message, source, game)) { + game.informPlayers(player.getLogName() + " pays " + amount + " life. He will not sacrifice " + creature.getName()); + lifePaid += amount; + } else { + game.informPlayers(player.getLogName() + " will sacrifice " + creature.getName()); + sacrifices.add(creature); + } } + lifePaidAmounts.put(playerId, lifePaid); } - lifePaidAmounts.put(playerId, lifePaid); } for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { diff --git a/Mage.Sets/src/mage/cards/l/LastRites.java b/Mage.Sets/src/mage/cards/l/LastRites.java index dbb4b763267..fe7147cbf8d 100644 --- a/Mage.Sets/src/mage/cards/l/LastRites.java +++ b/Mage.Sets/src/mage/cards/l/LastRites.java @@ -57,7 +57,7 @@ import mage.target.targetpointer.FixedTarget; public final class LastRites extends CardImpl { public LastRites(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{B}"); // Discard any number of cards. Target player reveals their hand, then you choose a nonland card from it for each card discarded this way. That player discards those cards. this.getSpellAbility().addEffect(new LastRitesEffect()); @@ -107,16 +107,12 @@ class LastRitesEffect extends OneShotEffect { controller.discard(card, source, game); } } - if (targetPlayer != null) { - FilterCard filter = new FilterCard((discardCount > 1 ? "" : "a") + " nonland card" + (discardCount > 1 ? "s" : "")); - filter.add(Predicates.not(new CardTypePredicate(CardType.LAND))); - StaticValue discardValue = new StaticValue(discardCount); - Effect effect = new DiscardCardYouChooseTargetEffect(discardValue, filter, TargetController.ANY); - effect.setTargetPointer(new FixedTarget(targetPlayer.getId())); - effect.apply(game, source); - } else { - return false; - } + FilterCard filter = new FilterCard((discardCount > 1 ? "" : "a") + " nonland card" + (discardCount > 1 ? "s" : "")); + filter.add(Predicates.not(new CardTypePredicate(CardType.LAND))); + StaticValue discardValue = new StaticValue(discardCount); + Effect effect = new DiscardCardYouChooseTargetEffect(discardValue, filter, TargetController.ANY); + effect.setTargetPointer(new FixedTarget(targetPlayer.getId())); + effect.apply(game, source); } return true; } diff --git a/Mage.Sets/src/mage/cards/l/LudevicNecroAlchemist.java b/Mage.Sets/src/mage/cards/l/LudevicNecroAlchemist.java index d79858bd060..9fa197a2a87 100644 --- a/Mage.Sets/src/mage/cards/l/LudevicNecroAlchemist.java +++ b/Mage.Sets/src/mage/cards/l/LudevicNecroAlchemist.java @@ -76,7 +76,7 @@ public final class LudevicNecroAlchemist extends CardImpl { } class LudevicNecroAlchemistCondition implements Condition { - + @Override public boolean apply(Game game, Ability source) { PlayerLostLifeWatcher watcher = (PlayerLostLifeWatcher) game.getState().getWatchers().get(PlayerLostLifeWatcher.class.getSimpleName()); @@ -85,13 +85,14 @@ class LudevicNecroAlchemistCondition implements Condition { Player currentPlayer = null; UUID sourcePlayerId = source.getControllerId(); Player firstPlayer = null; - if (playerList != null) { - firstPlayer = playerList.getCurrent(game); - currentPlayer = playerList.getNext(game); + if (playerList == null) { + return false; } + firstPlayer = playerList.getCurrent(game); + currentPlayer = playerList.getNext(game); while (watcher != null && currentPlayer != null) { - if (currentPlayer != null && !Objects.equals(currentPlayer.getId(), sourcePlayerId) && watcher.getLiveLost(currentPlayer.getId()) > 0) { + if (!Objects.equals(currentPlayer.getId(), sourcePlayerId) && watcher.getLiveLost(currentPlayer.getId()) > 0) { return true; } if (Objects.equals(currentPlayer, firstPlayer)) { diff --git a/Mage.Sets/src/mage/cards/m/MammothHarness.java b/Mage.Sets/src/mage/cards/m/MammothHarness.java index f4fb01e07c6..49b5c70485b 100644 --- a/Mage.Sets/src/mage/cards/m/MammothHarness.java +++ b/Mage.Sets/src/mage/cards/m/MammothHarness.java @@ -60,7 +60,7 @@ import mage.target.targetpointer.FixedTarget; public final class MammothHarness extends CardImpl { public MammothHarness(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}"); this.subtype.add(SubType.AURA); // Enchant creature @@ -69,7 +69,7 @@ public final class MammothHarness extends CardImpl { this.getSpellAbility().addEffect(new AttachEffect(Outcome.LoseAbility)); Ability ability = new EnchantAbility(auraTarget.getTargetName()); this.addAbility(ability); - + // Enchanted creature loses flying. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new LoseAbilityAttachedEffect(FlyingAbility.getInstance(), AttachmentType.AURA))); @@ -103,20 +103,18 @@ class MammothHarnessTriggeredAbility extends BlocksOrBecomesBlockedTriggeredAbil Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(this.getSourceId()); if (sourcePermanent != null) { Permanent attachedTo = game.getPermanentOrLKIBattlefield(sourcePermanent.getAttachedTo()); - if (sourcePermanent != null) { - if (event.getSourceId().equals(attachedTo.getId())) { - Permanent blocked = game.getPermanent(event.getTargetId()); - if (blocked != null && filter.match(blocked, game)) { - this.getEffects().setTargetPointer(new FixedTarget(event.getTargetId())); - return true; - } + if (event.getSourceId().equals(attachedTo.getId())) { + Permanent blocked = game.getPermanent(event.getTargetId()); + if (blocked != null && filter.match(blocked, game)) { + this.getEffects().setTargetPointer(new FixedTarget(event.getTargetId())); + return true; } - if (event.getTargetId().equals(attachedTo.getId())) { - Permanent blocker = game.getPermanent(event.getSourceId()); - if (blocker != null) { - this.getEffects().setTargetPointer(new FixedTarget(event.getSourceId())); - return true; - } + } + if (event.getTargetId().equals(attachedTo.getId())) { + Permanent blocker = game.getPermanent(event.getSourceId()); + if (blocker != null) { + this.getEffects().setTargetPointer(new FixedTarget(event.getSourceId())); + return true; } } } diff --git a/Mage.Sets/src/mage/cards/m/MaralenOfTheMornsong.java b/Mage.Sets/src/mage/cards/m/MaralenOfTheMornsong.java index 9ba3b1baee6..04a7c3d641b 100644 --- a/Mage.Sets/src/mage/cards/m/MaralenOfTheMornsong.java +++ b/Mage.Sets/src/mage/cards/m/MaralenOfTheMornsong.java @@ -125,14 +125,12 @@ class MaralenOfTheMornsongEffect2 extends OneShotEffect { Player player = game.getPlayer(activePlayerId); if (player != null) { player.loseLife(3, game, false); - if (player != null) { - TargetCardInLibrary target = new TargetCardInLibrary(); - if (player.searchLibrary(target, game)) { - player.moveCards(new CardsImpl(target.getTargets()), Zone.HAND, source, game); - } - player.shuffleLibrary(source, game); - return true; + TargetCardInLibrary target = new TargetCardInLibrary(); + if (player.searchLibrary(target, game)) { + player.moveCards(new CardsImpl(target.getTargets()), Zone.HAND, source, game); } + player.shuffleLibrary(source, game); + return true; } return false; } diff --git a/Mage.Sets/src/mage/cards/p/PerishTheThought.java b/Mage.Sets/src/mage/cards/p/PerishTheThought.java index f4c0d5bb419..8dba84ad93c 100644 --- a/Mage.Sets/src/mage/cards/p/PerishTheThought.java +++ b/Mage.Sets/src/mage/cards/p/PerishTheThought.java @@ -97,10 +97,8 @@ class PerishTheThoughtEffect extends OneShotEffect { if (you.choose(Outcome.Neutral, targetOpponent.getHand(), target, game)) { Card chosenCard = targetOpponent.getHand().get(target.getFirstTarget(), game); if (chosenCard != null) { - if (targetOpponent != null) { - chosenCard.moveToZone(Zone.LIBRARY, source.getSourceId(), game, false); - targetOpponent.shuffleLibrary(source, game); - } + chosenCard.moveToZone(Zone.LIBRARY, source.getSourceId(), game, false); + targetOpponent.shuffleLibrary(source, game); } } return true; diff --git a/Mage.Sets/src/mage/cards/p/PowerLeak.java b/Mage.Sets/src/mage/cards/p/PowerLeak.java index 151d484b862..496be0ab20b 100644 --- a/Mage.Sets/src/mage/cards/p/PowerLeak.java +++ b/Mage.Sets/src/mage/cards/p/PowerLeak.java @@ -60,7 +60,7 @@ import mage.target.targetpointer.FixedTarget; public final class PowerLeak extends CardImpl { public PowerLeak(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}"); this.subtype.add(SubType.AURA); // Enchant enchantment @@ -103,31 +103,31 @@ class PowerLeakEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player player = game.getPlayer(game.getActivePlayerId()); Permanent permanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); - if (player != null && permanent != null) { - ManaCosts cost = new ManaCostsImpl<>("{X}"); - String message = "Pay {X} to prevent X damage from " + permanent.getLogName() + "?"; - int xValue = 0; - if (player != null && player.chooseUse(Outcome.Neutral, message, source, game)) { - xValue = player.announceXMana(0, Integer.MAX_VALUE, "Choose the amount of mana to pay", game, source); - cost.add(new GenericManaCost(xValue)); - if (cost.pay(source, game, source.getSourceId(), player.getId(), false, null)) { - game.informPlayers(player.getLogName() + " paid {" + xValue + "} for " + permanent.getLogName()); - } else { - game.informPlayers(player.getLogName() + " didn't pay {X} for " + permanent.getLogName()); - } + if (player == null || permanent == null) { + return false; + } + ManaCosts cost = new ManaCostsImpl<>("{X}"); + String message = "Pay {X} to prevent X damage from " + permanent.getLogName() + "?"; + int xValue = 0; + if (player.chooseUse(Outcome.Neutral, message, source, game)) { + xValue = player.announceXMana(0, Integer.MAX_VALUE, "Choose the amount of mana to pay", game, source); + cost.add(new GenericManaCost(xValue)); + if (cost.pay(source, game, source.getSourceId(), player.getId(), false, null)) { + game.informPlayers(player.getLogName() + " paid {" + xValue + "} for " + permanent.getLogName()); } else { game.informPlayers(player.getLogName() + " didn't pay {X} for " + permanent.getLogName()); } - - PreventDamageByTargetEffect effect = new PreventDamageByTargetEffect(Duration.OneUse, xValue, false); - if (xValue != 0 && cost.isPaid()) { - effect.setTargetPointer(new FixedTarget(permanent.getId())); - game.addEffect(effect, source); - } - player.damage(2, source.getSourceId(), game, false, true); - effect.discard(); - return true; + } else { + game.informPlayers(player.getLogName() + " didn't pay {X} for " + permanent.getLogName()); } - return false; + + PreventDamageByTargetEffect effect = new PreventDamageByTargetEffect(Duration.OneUse, xValue, false); + if (xValue != 0 && cost.isPaid()) { + effect.setTargetPointer(new FixedTarget(permanent.getId())); + game.addEffect(effect, source); + } + player.damage(2, source.getSourceId(), game, false, true); + effect.discard(); + return true; } } diff --git a/Mage.Sets/src/mage/cards/q/QuietSpeculation.java b/Mage.Sets/src/mage/cards/q/QuietSpeculation.java index 14dbf4773e8..86424c0284d 100644 --- a/Mage.Sets/src/mage/cards/q/QuietSpeculation.java +++ b/Mage.Sets/src/mage/cards/q/QuietSpeculation.java @@ -58,7 +58,7 @@ public final class QuietSpeculation extends CardImpl { } public QuietSpeculation(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{U}"); // Search target player's library for up to three cards with flashback and put them into that player's graveyard. Then the player shuffles their library. TargetCardInLibrary target = new TargetCardInLibrary(0, 3, filterCard); @@ -96,7 +96,10 @@ class SearchLibraryPutInGraveEffect extends SearchEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); UUID targetPlayerID = source.getFirstTarget(); - if (controller != null && targetPlayerID != null && controller.searchLibrary(target, game, targetPlayerID)) { + if (controller == null) { + return false; + } + if (targetPlayerID != null && controller.searchLibrary(target, game, targetPlayerID)) { if (!target.getTargets().isEmpty()) { Cards cards = new CardsImpl(target.getTargets()); controller.revealCards("Quiet Speculation", cards, game); @@ -108,5 +111,4 @@ class SearchLibraryPutInGraveEffect extends SearchEffect { controller.shuffleLibrary(source, game); return false; } - } diff --git a/Mage.Sets/src/mage/cards/r/Recoil.java b/Mage.Sets/src/mage/cards/r/Recoil.java index 33e9794e2bd..4aec6e13740 100644 --- a/Mage.Sets/src/mage/cards/r/Recoil.java +++ b/Mage.Sets/src/mage/cards/r/Recoil.java @@ -47,7 +47,7 @@ import mage.target.TargetPermanent; public final class Recoil extends CardImpl { public Recoil(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}{B}"); // Return target permanent to its owner's hand. Then that player discards a card. this.getSpellAbility().addEffect(new RecoilEffect()); @@ -84,8 +84,11 @@ class RecoilEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Permanent target = game.getPermanent(source.getFirstTarget()); + if (target == null) { + return false; + } Player controller = game.getPlayer(target.getControllerId()); - if (target != null && controller != null) { + if (controller != null) { controller.moveCards(target, Zone.HAND, source, game); controller.discard(1, false, source, game); return true; diff --git a/Mage.Sets/src/mage/cards/s/SavingGrace.java b/Mage.Sets/src/mage/cards/s/SavingGrace.java index 114e29c8a4b..ee4547432cd 100644 --- a/Mage.Sets/src/mage/cards/s/SavingGrace.java +++ b/Mage.Sets/src/mage/cards/s/SavingGrace.java @@ -131,10 +131,10 @@ class SavingGraceReplacementEffect extends ReplacementEffectImpl { public boolean replaceEvent(GameEvent event, Ability source, Game game) { DamageEvent damageEvent = (DamageEvent) event; Permanent sourcePermanent = game.getPermanent(source.getSourceId()); - + if (sourcePermanent != null) { Permanent creature = game.getPermanent(sourcePermanent.getAttachedTo()); - + if (creature == null) { return false; } @@ -157,10 +157,8 @@ class SavingGraceReplacementEffect extends ReplacementEffectImpl { } game.informPlayers(message.toString()); // Redirect damage - if (creature != null) { - creature.damage(damageEvent.getAmount(), damageEvent.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), event.getAppliedEffects()); - return true; - } + creature.damage(damageEvent.getAmount(), damageEvent.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), event.getAppliedEffects()); + return true; } return false; } diff --git a/Mage.Sets/src/mage/cards/s/SerraBestiary.java b/Mage.Sets/src/mage/cards/s/SerraBestiary.java index 0877409aa35..be64902017a 100644 --- a/Mage.Sets/src/mage/cards/s/SerraBestiary.java +++ b/Mage.Sets/src/mage/cards/s/SerraBestiary.java @@ -121,18 +121,22 @@ class SerraBestiaryRuleModifyingEffect extends ContinuousRuleModifyingEffectImpl @Override public boolean applies(GameEvent event, Ability source, Game game) { Permanent enchantment = game.getPermanentOrLKIBattlefield(source.getSourceId()); + if (enchantment == null) { + return false; + } Permanent enchantedCreature = game.getPermanent(enchantment.getAttachedTo()); - if (enchantment != null && enchantment.getAttachedTo() != null) { - MageObject object = game.getObject(event.getSourceId()); - Optional ability = game.getAbility(event.getTargetId(), event.getSourceId()); - if (ability.isPresent() - && object != null - && object.isCreature() - && object.getId().equals(enchantedCreature.getId()) - && game.getState().getPlayersInRange(source.getControllerId(), game).contains(event.getPlayerId())) { - if (ability.get().getCosts().stream().anyMatch((cost) -> (cost instanceof TapSourceCost))) { - return true; - } + if (enchantedCreature == null) { + return false; + } + MageObject object = game.getObject(event.getSourceId()); + Optional ability = game.getAbility(event.getTargetId(), event.getSourceId()); + if (ability.isPresent() + && object != null + && object.isCreature() + && object.getId().equals(enchantedCreature.getId()) + && game.getState().getPlayersInRange(source.getControllerId(), game).contains(event.getPlayerId())) { + if (ability.get().getCosts().stream().anyMatch((cost) -> (cost instanceof TapSourceCost))) { + return true; } } return false; diff --git a/Mage.Sets/src/mage/cards/s/ShadesBreath.java b/Mage.Sets/src/mage/cards/s/ShadesBreath.java index d2677a52782..76fbd0da266 100644 --- a/Mage.Sets/src/mage/cards/s/ShadesBreath.java +++ b/Mage.Sets/src/mage/cards/s/ShadesBreath.java @@ -127,7 +127,7 @@ class ShadesBreathSetSubtypeEffect extends ContinuousEffectImpl { for (Permanent permanent : permanents) { if (permanent != null) { SubTypeList subtype = permanent.getSubtype(game); - if (subtype != null && subtype.size() != 1 || !subtype.contains(SubType.SHADE)) { + if (subtype != null && (subtype.size() != 1 || !subtype.contains(SubType.SHADE))) { subtype.removeAll(SubType.getCreatureTypes(false)); subtype.add(SubType.SHADE); } diff --git a/Mage.Sets/src/mage/cards/s/SlowMotion.java b/Mage.Sets/src/mage/cards/s/SlowMotion.java index 8d6ce701b54..40631f992f9 100644 --- a/Mage.Sets/src/mage/cards/s/SlowMotion.java +++ b/Mage.Sets/src/mage/cards/s/SlowMotion.java @@ -56,10 +56,9 @@ import mage.target.common.TargetCreaturePermanent; public final class SlowMotion extends CardImpl { public SlowMotion(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); this.subtype.add(SubType.AURA); - // Enchant creature TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); @@ -68,7 +67,7 @@ public final class SlowMotion extends CardImpl { this.addAbility(ability); // At the beginning of the upkeep of enchanted creature's controller, that player sacrifices that creature unless he or she pays {2}. - this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SacrificeEquipedUnlessPaysEffect(new GenericManaCost(2)), TargetController.CONTROLLER_ATTACHED_TO, false )); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SacrificeEquipedUnlessPaysEffect(new GenericManaCost(2)), TargetController.CONTROLLER_ATTACHED_TO, false)); // When Slow Motion is put into a graveyard from the battlefield, return Slow Motion to its owner's hand. this.addAbility(new PutIntoGraveFromBattlefieldSourceTriggeredAbility(new ReturnToHandSourceEffect())); @@ -85,13 +84,14 @@ public final class SlowMotion extends CardImpl { } class SacrificeEquipedUnlessPaysEffect extends OneShotEffect { + protected Cost cost; public SacrificeEquipedUnlessPaysEffect(Cost cost) { super(Outcome.Sacrifice); this.cost = cost; staticText = "that player sacrifices that creature unless he or she pays {2}"; - } + } public SacrificeEquipedUnlessPaysEffect(final SacrificeEquipedUnlessPaysEffect effect) { super(effect); @@ -101,25 +101,29 @@ class SacrificeEquipedUnlessPaysEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Permanent equipment = game.getPermanent(source.getSourceId()); - if (equipment != null && equipment.getAttachedTo() != null) { - Permanent equipped = game.getPermanent(equipment.getAttachedTo()); - Player player = game.getPlayer(equipped.getControllerId()); - if (player != null && equipped != null) { - if (player.chooseUse(Outcome.Benefit, "Pay " + cost.getText() + "? (Or " + equipped.getName() + " will be sacrificed.)", source, game)) { - cost.clearPaid(); - if (cost.pay(source, game, source.getSourceId(), equipped.getControllerId(), false, null)) { - return true; - } - } - equipped.sacrifice(source.getSourceId(), game); + if (equipment == null) { + return false; + } + Permanent equipped = game.getPermanent(equipment.getAttachedTo()); + if (equipped == null) { + return false; + } + Player player = game.getPlayer(equipped.getControllerId()); + if (player == null) { + return false; + } + if (player.chooseUse(Outcome.Benefit, "Pay " + cost.getText() + "? (Or " + equipped.getName() + " will be sacrificed.)", source, game)) { + cost.clearPaid(); + if (cost.pay(source, game, source.getSourceId(), equipped.getControllerId(), false, null)) { return true; } } - return false; + equipped.sacrifice(source.getSourceId(), game); + return true; } @Override public SacrificeEquipedUnlessPaysEffect copy() { return new SacrificeEquipedUnlessPaysEffect(this); } - } \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/s/SpikeCannibal.java b/Mage.Sets/src/mage/cards/s/SpikeCannibal.java index e9eeb8df002..1b55c1917a7 100644 --- a/Mage.Sets/src/mage/cards/s/SpikeCannibal.java +++ b/Mage.Sets/src/mage/cards/s/SpikeCannibal.java @@ -114,10 +114,8 @@ class SpikeCannibalEffect extends OneShotEffect { } if (countersRemoved > 0) { - if (sourcePermanent != null) { - sourcePermanent.addCounters(CounterType.P1P1.createInstance(countersRemoved), source, game); - return true; - } + sourcePermanent.addCounters(CounterType.P1P1.createInstance(countersRemoved), source, game); + return true; } } diff --git a/Mage.Sets/src/mage/cards/s/SpyNetwork.java b/Mage.Sets/src/mage/cards/s/SpyNetwork.java index 22131f0e55f..516eb6d67ae 100644 --- a/Mage.Sets/src/mage/cards/s/SpyNetwork.java +++ b/Mage.Sets/src/mage/cards/s/SpyNetwork.java @@ -55,7 +55,7 @@ import mage.target.common.TargetCreaturePermanent; public final class SpyNetwork extends CardImpl { public SpyNetwork(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{U}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}"); // Look at target player's hand, the top card of that player's library, and any face-down creatures he or she controls. Look at the top four cards of your library, then put them back in any order. this.getSpellAbility().addEffect(new SpyNetworkLookAtTargetPlayerHandEffect()); @@ -133,7 +133,7 @@ class SpyNetworkFaceDownEffect extends OneShotEffect { filter.add(new ControllerIdPredicate(player.getId())); TargetCreaturePermanent target = new TargetCreaturePermanent(1, 1, filter, true); if (target.canChoose(source.getSourceId(), controller.getId(), game)) { - while (player != null && controller.chooseUse(outcome, "Look at a face down creature controlled by " + player.getLogName() + "?", source, game)) { + while (controller.chooseUse(outcome, "Look at a face down creature controlled by " + player.getLogName() + "?", source, game)) { target.clearChosen(); while (!target.isChosen() && target.canChoose(controller.getId(), game) && controller.canRespond()) { controller.chooseTarget(outcome, target, source, game); @@ -145,9 +145,7 @@ class SpyNetworkFaceDownEffect extends OneShotEffect { Cards cards = new CardsImpl(); cards.add(copyFaceDown); controller.lookAtCards("face down card - " + mageObject.getName(), cards, game); - if (player != null) { - game.informPlayers(controller.getLogName() + " looks at a face down creature controlled by " + player.getLogName()); - } + game.informPlayers(controller.getLogName() + " looks at a face down creature controlled by " + player.getLogName()); } } } diff --git a/Mage.Sets/src/mage/cards/s/SummonThePack.java b/Mage.Sets/src/mage/cards/s/SummonThePack.java index b770c585fc4..9871557d3f4 100644 --- a/Mage.Sets/src/mage/cards/s/SummonThePack.java +++ b/Mage.Sets/src/mage/cards/s/SummonThePack.java @@ -112,8 +112,8 @@ class SummonThePackEffect extends OneShotEffect { StringBuilder message = new StringBuilder(controller.getLogName()).append(" opened: "); for (Card c : boosterPack) { - message.append(c.getName()).append(" "); if (c != null && c.isCreature()) { + message.append(c.getName()).append(" "); message.append(" (creature card) "); ContinuousEffect effect2 = new BecomesBlackZombieAdditionEffect(false); effect2.setTargetPointer(new FixedTarget(c.getId())); @@ -124,7 +124,7 @@ class SummonThePackEffect extends OneShotEffect { } if (creatureCards.size() > 0) { - Set ccs = new HashSet(creatureCards); + Set ccs = new HashSet<>(creatureCards); game.loadCards(ccs, controller.getId()); controller.moveCards(ccs, Zone.BATTLEFIELD, source, game); } diff --git a/Mage.Sets/src/mage/cards/t/TheBattleOfYavin.java b/Mage.Sets/src/mage/cards/t/TheBattleOfYavin.java index 58ca586b9b5..eac1ad959f3 100644 --- a/Mage.Sets/src/mage/cards/t/TheBattleOfYavin.java +++ b/Mage.Sets/src/mage/cards/t/TheBattleOfYavin.java @@ -50,7 +50,7 @@ import mage.target.common.TargetOpponent; public final class TheBattleOfYavin extends CardImpl { public TheBattleOfYavin(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{B}{B}"); // For each nonland permanent target opponent controls, that player sacrificies it unless he or she pays X life. this.getSpellAbility().addEffect(new TheBattleOfYavinEffect()); @@ -102,7 +102,7 @@ class TheBattleOfYavinEffect extends OneShotEffect { int playerLife = opponent.getLife(); for (Permanent permanent : permanents) { String message = "Pay " + amount + " life? If you don't, " + permanent.getName() + " will be sacrificed."; - if (playerLife - amount - lifePaid >= 0 && opponent != null && opponent.chooseUse(Outcome.Neutral, message, source, game)) { + if (playerLife - amount - lifePaid >= 0 && opponent.chooseUse(Outcome.Neutral, message, source, game)) { game.informPlayers(opponent.getLogName() + " pays " + amount + " life. He will not sacrifice " + permanent.getName()); lifePaid += amount; } else { diff --git a/Mage.Sets/src/mage/cards/t/TidalFlats.java b/Mage.Sets/src/mage/cards/t/TidalFlats.java index 239c74f5e32..ef1f4d3fa15 100644 --- a/Mage.Sets/src/mage/cards/t/TidalFlats.java +++ b/Mage.Sets/src/mage/cards/t/TidalFlats.java @@ -62,8 +62,8 @@ import mage.target.targetpointer.FixedTarget; public final class TidalFlats extends CardImpl { public TidalFlats(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{U}"); - + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{U}"); + // {U}{U}: For each attacking creature without flying, its controller may pay {1}. If he or she doesn't, creatures you control blocking that creature gain first strike until end of turn. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new TidalFlatsEffect(), new ManaCostsImpl("{U}{U}"))); } @@ -79,8 +79,9 @@ public final class TidalFlats extends CardImpl { } class TidalFlatsEffect extends OneShotEffect { - + private static final FilterAttackingCreature filter = new FilterAttackingCreature("attacking creature without flying"); + static { filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class))); } @@ -103,43 +104,45 @@ class TidalFlatsEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { game.getPlayerList(); Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - Player player = game.getPlayer(game.getActivePlayerId()); - Cost cost = new ManaCostsImpl("{1}"); - List affectedPermanents = new ArrayList<>(); - for (Permanent permanent : game.getState().getBattlefield().getAllActivePermanents(filter, player.getId(), game)) { - cost.clearPaid(); - String message = "Pay " + cost.getText() + " for " + permanent.getLogName() + "? If you don't, creatures " + controller.getLogName() + " controls blocking it gain first strike until end of turn."; - if (player != null && player.chooseUse(Outcome.Benefit, message, source, game)) { - if (cost.pay(source, game, source.getSourceId(), player.getId(), false, null)) { - game.informPlayers(player.getLogName() + " paid " + cost.getText() + " for " + permanent.getLogName()); - continue; - } else { - game.informPlayers(player.getLogName() + " didn't pay " + cost.getText() + " for " + permanent.getLogName()); - affectedPermanents.add(permanent); - } + if (controller == null) { + return false; + } + Player player = game.getPlayer(game.getActivePlayerId()); + if (player == null) { + return false; + } + Cost cost = new ManaCostsImpl("{1}"); + List affectedPermanents = new ArrayList<>(); + for (Permanent permanent : game.getState().getBattlefield().getAllActivePermanents(filter, player.getId(), game)) { + cost.clearPaid(); + String message = "Pay " + cost.getText() + " for " + permanent.getLogName() + "? If you don't, creatures " + controller.getLogName() + " controls blocking it gain first strike until end of turn."; + if (player.chooseUse(Outcome.Benefit, message, source, game)) { + if (cost.pay(source, game, source.getSourceId(), player.getId(), false, null)) { + game.informPlayers(player.getLogName() + " paid " + cost.getText() + " for " + permanent.getLogName()); } else { game.informPlayers(player.getLogName() + " didn't pay " + cost.getText() + " for " + permanent.getLogName()); affectedPermanents.add(permanent); } + } else { + game.informPlayers(player.getLogName() + " didn't pay " + cost.getText() + " for " + permanent.getLogName()); + affectedPermanents.add(permanent); } + } - for (Permanent permanent : affectedPermanents) { - CombatGroup group = game.getCombat().findGroup(permanent.getId()); - if (group != null) { - for (UUID blockerId : group.getBlockers()) { - Permanent blocker = game.getPermanent(blockerId); - if (blocker != null && Objects.equals(blocker.getControllerId(), controller.getId())) { - ContinuousEffect effect = new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn); - effect.setTargetPointer(new FixedTarget(blocker.getId())); - game.addEffect(effect, source); - } + for (Permanent permanent : affectedPermanents) { + CombatGroup group = game.getCombat().findGroup(permanent.getId()); + if (group != null) { + for (UUID blockerId : group.getBlockers()) { + Permanent blocker = game.getPermanent(blockerId); + if (blocker != null && Objects.equals(blocker.getControllerId(), controller.getId())) { + ContinuousEffect effect = new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn); + effect.setTargetPointer(new FixedTarget(blocker.getId())); + game.addEffect(effect, source); } } - } - return true; + } - return false; + return true; } } diff --git a/Mage.Sets/src/mage/cards/t/TorrentialGearhulk.java b/Mage.Sets/src/mage/cards/t/TorrentialGearhulk.java index 36cb56f305c..de06ba6f61d 100644 --- a/Mage.Sets/src/mage/cards/t/TorrentialGearhulk.java +++ b/Mage.Sets/src/mage/cards/t/TorrentialGearhulk.java @@ -122,7 +122,7 @@ class TorrentialGearhulkEffect extends OneShotEffect { game.addEffect(effect, source); } } - } else { + } else if (card != null) { Logger.getLogger(TorrentialGearhulkEffect.class).error("Torrential Gearhulk - Instant card without spellAbility : " + card.getName()); return false; } diff --git a/Mage.Sets/src/mage/cards/t/TreacherousLink.java b/Mage.Sets/src/mage/cards/t/TreacherousLink.java index d6208835cbe..346f88a3a09 100644 --- a/Mage.Sets/src/mage/cards/t/TreacherousLink.java +++ b/Mage.Sets/src/mage/cards/t/TreacherousLink.java @@ -55,7 +55,7 @@ import mage.target.common.TargetCreaturePermanent; public final class TreacherousLink extends CardImpl { public TreacherousLink(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}"); this.subtype.add(SubType.AURA); // Enchant creature @@ -109,12 +109,15 @@ class TreacherousLinkEffect extends ReplacementEffectImpl { public boolean replaceEvent(GameEvent event, Ability source, Game game) { DamageEvent damageEvent = (DamageEvent) event; Permanent enchantedCreature = game.getPermanentOrLKIBattlefield(damageEvent.getTargetId()); - Player controller = game.getPlayer(enchantedCreature.getControllerId()); - if (enchantedCreature != null && controller != null) { - controller.damage(damageEvent.getAmount(), damageEvent.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), damageEvent.getAppliedEffects()); - return true; + if (enchantedCreature == null) { + return false; } - return false; + Player controller = game.getPlayer(enchantedCreature.getControllerId()); + if (controller == null) { + return false; + } + controller.damage(damageEvent.getAmount(), damageEvent.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), damageEvent.getAppliedEffects()); + return true; } @Override diff --git a/Mage.Sets/src/mage/cards/w/WallOfPutridFlesh.java b/Mage.Sets/src/mage/cards/w/WallOfPutridFlesh.java index 35d9eb1c27d..010ed30aece 100644 --- a/Mage.Sets/src/mage/cards/w/WallOfPutridFlesh.java +++ b/Mage.Sets/src/mage/cards/w/WallOfPutridFlesh.java @@ -55,7 +55,7 @@ public final class WallOfPutridFlesh extends CardImpl { public WallOfPutridFlesh(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); - + this.subtype.add(SubType.WALL); this.power = new MageInt(2); this.toughness = new MageInt(4); @@ -83,7 +83,7 @@ public final class WallOfPutridFlesh extends CardImpl { class PreventDamageToSourceByEnchantedCreatures extends PreventAllDamageToSourceEffect { - public PreventDamageToSourceByEnchantedCreatures(){ + public PreventDamageToSourceByEnchantedCreatures() { super(Duration.WhileOnBattlefield); } @@ -100,10 +100,10 @@ class PreventDamageToSourceByEnchantedCreatures extends PreventAllDamageToSource } public boolean isEnchantedCreature(MageObject input, Game game) { - if (input != null && !input.isCreature()) { + if (input == null || input.isCreature()) { return false; } - for (UUID attachmentId : ((Permanent)input).getAttachments()) { + for (UUID attachmentId : ((Permanent) input).getAttachments()) { Permanent attachment = game.getPermanent(attachmentId); if (attachment != null && attachment.isEnchantment()) { return true; diff --git a/Mage.Sets/src/mage/cards/w/WheelOfTorture.java b/Mage.Sets/src/mage/cards/w/WheelOfTorture.java index 4a755aa1819..3de6d0549e0 100644 --- a/Mage.Sets/src/mage/cards/w/WheelOfTorture.java +++ b/Mage.Sets/src/mage/cards/w/WheelOfTorture.java @@ -47,7 +47,7 @@ import mage.players.Player; public final class WheelOfTorture extends CardImpl { public WheelOfTorture(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); // At the beginning of each opponent's upkeep, Wheel of Torture deals X damage to that player, where X is 3 minus the number of cards in their hand. Ability ability = new BeginningOfUpkeepTriggeredAbility(new WheelOfTortureEffect(), TargetController.OPPONENT, false); @@ -64,7 +64,6 @@ public final class WheelOfTorture extends CardImpl { } } - class WheelOfTortureEffect extends OneShotEffect { private WheelOfTortureEffect(final WheelOfTortureEffect effect) { @@ -78,16 +77,11 @@ class WheelOfTortureEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player player = game.getPlayer(targetPointer.getFirst(game, source)); - if(player != null) - { + if (player != null) { int amount = 3 - player.getHand().size(); - if(amount > 0) - { - if (player != null) { - player.damage(amount, source.getSourceId(), game, false, true); - return true; - } - + if (amount > 0) { + player.damage(amount, source.getSourceId(), game, false, true); + return true; } } return false; @@ -103,5 +97,4 @@ class WheelOfTortureEffect extends OneShotEffect { return "Wheel of Torture deals X damage to that player, where X is 3 minus the number of cards in their hand"; } - } diff --git a/Mage.Sets/src/mage/cards/w/WretchedBanquet.java b/Mage.Sets/src/mage/cards/w/WretchedBanquet.java index 38160eb03e8..00cec941ed8 100644 --- a/Mage.Sets/src/mage/cards/w/WretchedBanquet.java +++ b/Mage.Sets/src/mage/cards/w/WretchedBanquet.java @@ -83,6 +83,9 @@ class WretchedBanquetEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Permanent targetCreature = game.getPermanent(source.getFirstTarget()); + if (targetCreature == null) { + return false; + } List creatures = game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source.getSourceId(), game); int minPower = targetCreature.getPower().getValue() + 1; @@ -92,7 +95,7 @@ class WretchedBanquetEffect extends OneShotEffect { } } - if (targetCreature != null && targetCreature.getPower().getValue() <= minPower) { + if (targetCreature.getPower().getValue() <= minPower) { targetCreature.destroy(source.getSourceId(), game, false); return true; } diff --git a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java index 2d5c68bc136..344b52e7ea9 100644 --- a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java +++ b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java @@ -1,6 +1,5 @@ package mage.verify; -import javassist.bytecode.SignatureAttribute; import mage.ObjectColor; import mage.cards.*; import mage.cards.basiclands.BasicLand; @@ -352,9 +351,7 @@ public class VerifyCardDataTest { //Assert.assertNotNull("Can't create token by default constructor", token); if (token == null) { Assert.fail("Can't create token by default constructor: " + className); - } - - if (tokDataNamesIndex.getOrDefault(token.getName(), "").isEmpty()) { + } else if (tokDataNamesIndex.getOrDefault(token.getName(), "").isEmpty()) { errorsList.add("error, can't find data in card-pictures-tok.txt for token: " + tokenClass.getName() + " -> " + token.getName()); } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/DoUnlessTargetPlayerOrTargetsControllerPaysEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DoUnlessTargetPlayerOrTargetsControllerPaysEffect.java index 47f064ea6fb..7c820143efb 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DoUnlessTargetPlayerOrTargetsControllerPaysEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DoUnlessTargetPlayerOrTargetsControllerPaysEffect.java @@ -103,7 +103,7 @@ public class DoUnlessTargetPlayerOrTargetsControllerPaysEffect extends OneShotEf } if (targetController != null) { MageObject sourceObject = game.getObject(source.getSourceId()); - if (targetController != null && sourceObject != null) { + if (sourceObject != null) { Cost costToPay; if (cost != null) { costToPay = cost.copy(); @@ -120,7 +120,7 @@ public class DoUnlessTargetPlayerOrTargetsControllerPaysEffect extends OneShotEf message = CardUtil.replaceSourceName(message, sourceObject.getName()); boolean result = true; boolean doEffect = true; - + // check if targetController is willing to pay if (costToPay.canPay(source, source.getSourceId(), targetController.getId(), game) && targetController.chooseUse(Outcome.Detriment, message, source, game)) { costToPay.clearPaid(); @@ -128,10 +128,10 @@ public class DoUnlessTargetPlayerOrTargetsControllerPaysEffect extends OneShotEf if (!game.isSimulation()) { game.informPlayers(targetController.getLogName() + " pays the cost to prevent the effect"); } - doEffect = false; + doEffect = false; } } - + // do the effects if not paid if (doEffect) { for (Effect effect : executingEffects) {