diff --git a/Mage.Sets/src/mage/cards/b/BottleCapBlast.java b/Mage.Sets/src/mage/cards/b/BottleCapBlast.java index 6d9d536f495..1b19927a649 100644 --- a/Mage.Sets/src/mage/cards/b/BottleCapBlast.java +++ b/Mage.Sets/src/mage/cards/b/BottleCapBlast.java @@ -62,8 +62,8 @@ class BottleCapBlastEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - UUID target = getTargetPointer().getFirst(game, source); - Player player = game.getPlayer(target); + UUID targetId = getTargetPointer().getFirst(game, source); + Player player = game.getPlayer(targetId); if (player != null) { player.damage(5, source, game); return true; @@ -72,11 +72,10 @@ class BottleCapBlastEffect extends OneShotEffect { if (permanent == null) { return false; } - int lethal = Math.min(permanent.getLethalDamage(source.getSourceId(), game), 5); - permanent.damage(5, source.getSourceId(), source, game); - if (lethal < 5) { + int excess = permanent.damageWithExcess(5, source, game); + if (excess > 0) { new TreasureToken().putOntoBattlefield( - 5 - lethal, game, source, source.getControllerId(), true, false + excess, game, source, source.getControllerId(), true, false ); } return true; diff --git a/Mage.Sets/src/mage/cards/c/ContestOfClaws.java b/Mage.Sets/src/mage/cards/c/ContestOfClaws.java index 530b4a9847e..afa5f2dc6d4 100644 --- a/Mage.Sets/src/mage/cards/c/ContestOfClaws.java +++ b/Mage.Sets/src/mage/cards/c/ContestOfClaws.java @@ -1,7 +1,5 @@ package mage.cards.c; -import java.util.UUID; - import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.keyword.DiscoverEffect; @@ -9,34 +7,29 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; -import mage.filter.StaticFilters; +import mage.game.Controllable; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.players.Player; -import mage.target.Target; import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; -import mage.target.common.TargetCreaturePermanent; + +import java.util.Optional; +import java.util.UUID; import static mage.filter.StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2; /** - * * @author jimga150 */ public final class ContestOfClaws extends CardImpl { public ContestOfClaws(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{G}"); - // Target creature you control deals damage equal to its power to another target creature. If excess damage was dealt this way, discover X, where X is that excess damage. this.getSpellAbility().addEffect(new ContestOfClawsDamageEffect()); - Target target = new TargetControlledCreaturePermanent().setTargetTag(1); - this.getSpellAbility().addTarget(target); - - Target target2 = new TargetPermanent(FILTER_ANOTHER_CREATURE_TARGET_2).setTargetTag(2); - this.getSpellAbility().addTarget(target2); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent().setTargetTag(1)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_ANOTHER_CREATURE_TARGET_2).setTargetTag(2)); } private ContestOfClaws(final ContestOfClaws card) { @@ -74,22 +67,13 @@ class ContestOfClawsDamageEffect extends OneShotEffect { if (ownCreature == null || targetCreature == null) { return false; } - int damage = ownCreature.getPower().getValue(); - int lethalDamage = targetCreature.getLethalDamage(source.getSourceId(), game); - targetCreature.damage(damage, ownCreature.getId(), source, game, false, true); - - if (damage < lethalDamage){ - return true; + int excess = targetCreature.damageWithExcess( ownCreature.getPower().getValue(), ownCreature.getId(), source, game); + if (excess > 0) { + Optional.ofNullable(source) + .map(Controllable::getControllerId) + .map(game::getPlayer) + .ifPresent(player -> DiscoverEffect.doDiscover(player, excess, game, source)); } - int discoverValue = damage - lethalDamage; - Player player = game.getPlayer(source.getControllerId()); - - if (player == null){ - // If somehow this case is hit, the damage still technically happened, so i guess it applied? - return true; - } - DiscoverEffect.doDiscover(player, discoverValue, game, source); - return true; } } diff --git a/Mage.Sets/src/mage/cards/g/GoblinNegotiation.java b/Mage.Sets/src/mage/cards/g/GoblinNegotiation.java index 368eb608eab..538d9976e60 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinNegotiation.java +++ b/Mage.Sets/src/mage/cards/g/GoblinNegotiation.java @@ -15,7 +15,6 @@ import mage.util.CardUtil; import java.util.UUID; /** - * * @author ciaccona007 */ public final class GoblinNegotiation extends CardImpl { @@ -62,14 +61,12 @@ class GoblinNegotiationEffect extends OneShotEffect { if (permanent == null) { return false; } - int damage = CardUtil.getSourceCostsTag(game, source, "X", 0); - int lethal = Math.min(permanent.getLethalDamage(source.getSourceId(), game), damage); - permanent.damage(damage, source.getSourceId(), source, game); - if (damage > lethal) { - new GoblinToken().putOntoBattlefield( - damage - lethal, game, source, source.getControllerId() - ); + int excess = permanent.damageWithExcess( + CardUtil.getSourceCostsTag(game, source, "X", 0), source, game + ); + if (excess > 0) { + new GoblinToken().putOntoBattlefield(excess, game, source); } return true; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/h/HellToPay.java b/Mage.Sets/src/mage/cards/h/HellToPay.java index 640b2be38b8..8b3e35e9589 100644 --- a/Mage.Sets/src/mage/cards/h/HellToPay.java +++ b/Mage.Sets/src/mage/cards/h/HellToPay.java @@ -60,13 +60,11 @@ class HellToPayEffect extends OneShotEffect { if (permanent == null) { return false; } - int damage = CardUtil.getSourceCostsTag(game, source, "X", 0); - int lethal = Math.min(permanent.getLethalDamage(source.getSourceId(), game), damage); - permanent.damage(damage, source.getSourceId(), source, game); - if (damage > lethal) { - new TreasureToken().putOntoBattlefield( - damage - lethal, game, source, source.getControllerId(), true, false - ); + int excess = permanent.damageWithExcess( + CardUtil.getSourceCostsTag(game, source, "X", 0), source, game + ); + if (excess > 0) { + new TreasureToken().putOntoBattlefield(excess, game, source, source.getControllerId(), true, false); } return true; } diff --git a/Mage.Sets/src/mage/cards/l/LacerateFlesh.java b/Mage.Sets/src/mage/cards/l/LacerateFlesh.java index 0d4f8c4eea3..9e060e65cd7 100644 --- a/Mage.Sets/src/mage/cards/l/LacerateFlesh.java +++ b/Mage.Sets/src/mage/cards/l/LacerateFlesh.java @@ -55,14 +55,13 @@ class LacerateFleshEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getFirstTarget()); + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); if (permanent == null) { return false; } - int lethal = Math.min(permanent.getLethalDamage(source.getSourceId(), game), 4); - permanent.damage(4, source.getSourceId(), source, game); - if (lethal < 4) { - new BloodToken().putOntoBattlefield(4 - lethal, game, source); + int excess = permanent.damageWithExcess(4, source, game); + if (excess > 0) { + new BloodToken().putOntoBattlefield(excess, game, source); } return true; } diff --git a/Mage.Sets/src/mage/cards/m/MegatronDestructiveForce.java b/Mage.Sets/src/mage/cards/m/MegatronDestructiveForce.java index 2badfb10257..7b718d6efbd 100644 --- a/Mage.Sets/src/mage/cards/m/MegatronDestructiveForce.java +++ b/Mage.Sets/src/mage/cards/m/MegatronDestructiveForce.java @@ -79,7 +79,7 @@ class MegatronDestructiveForceEffect extends OneShotEffect { return false; } TargetSacrifice target = new TargetSacrifice( - 0, 1, StaticFilters.FILTER_CONTROLLED_ANOTHER_ARTIFACT + 0, 1, StaticFilters.FILTER_CONTROLLED_ANOTHER_ARTIFACT ); player.choose(outcome, target, source, game); Permanent permanent = game.getPermanent(target.getFirstTarget()); @@ -93,7 +93,7 @@ class MegatronDestructiveForceEffect extends OneShotEffect { } ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility( - new MegatronDestructiveForceReflexiveEffect(manaValue), false + new MegatronDestructiveForceReflexiveEffect(manaValue), false ); ability.addHint(new StaticHint("Sacrificed artifact mana value: " + manaValue)); ability.addTarget(new TargetCreaturePermanent()); @@ -109,8 +109,8 @@ class MegatronDestructiveForceReflexiveEffect extends OneShotEffect { MegatronDestructiveForceReflexiveEffect(int value) { super(Outcome.Damage); staticText = "{this} deals damage equal to the sacrificed artifact's mana value to target " + - "creature. If excess damage would be dealt to that creature this way, instead that damage " + - "is dealt to that creature's controller and you convert {this}."; + "creature. If excess damage would be dealt to that creature this way, instead that damage " + + "is dealt to that creature's controller and you convert {this}."; this.value = value; } @@ -126,36 +126,22 @@ class MegatronDestructiveForceReflexiveEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent sourcePermanent = source.getSourcePermanentOrLKI(game); - if (sourcePermanent == null) { - return false; - } - if (value < 1) { return false; } - Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); if (permanent == null) { return false; } - - int lethal = permanent.getLethalDamage(source.getSourceId(), game); - int excess = value - lethal; - if (excess <= 0) { - // no excess damage. - permanent.damage(value, source.getSourceId(), source, game); + int excess = permanent.damageWithExcess(value, source, game); + if (excess < 1) { return true; } - - // excess damage. dealing excess to controller's instead. And convert Megatron. - permanent.damage(lethal, source.getSourceId(), source, game); Player player = game.getPlayer(permanent.getControllerId()); if (player != null) { player.damage(excess, source, game); } new TransformSourceEffect().apply(game, source); - return true; } } diff --git a/Mage.Sets/src/mage/cards/n/NahirisWarcrafting.java b/Mage.Sets/src/mage/cards/n/NahirisWarcrafting.java index cd5f2e4ceab..c170893bc2d 100644 --- a/Mage.Sets/src/mage/cards/n/NahirisWarcrafting.java +++ b/Mage.Sets/src/mage/cards/n/NahirisWarcrafting.java @@ -80,9 +80,8 @@ class NahirisWarcraftingEffect extends OneShotEffect { if (player == null || permanent == null) { return false; } - int lethal = permanent.getLethalDamage(source.getSourceId(), game); - int excess = permanent.damage(5, source, game) - lethal; - if (excess <= 0) { + int excess = permanent.damageWithExcess(5, source, game); + if (excess < 1) { return true; } Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, excess)); diff --git a/Mage.Sets/src/mage/cards/o/OrbitalPlunge.java b/Mage.Sets/src/mage/cards/o/OrbitalPlunge.java index e5238585a3d..a7436dcb122 100644 --- a/Mage.Sets/src/mage/cards/o/OrbitalPlunge.java +++ b/Mage.Sets/src/mage/cards/o/OrbitalPlunge.java @@ -2,7 +2,6 @@ package mage.cards.o; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -61,10 +60,8 @@ class OrbitalPlungeEffect extends OneShotEffect { if (permanent == null) { return false; } - int lethal = permanent.getLethalDamage(source.getSourceId(), game); - permanent.damage(6, source.getSourceId(), source, game); - if (lethal < 6) { - new CreateTokenEffect(new LanderToken()).apply(game, source); + if (permanent.damageWithExcess(6, source, game) > 0) { + new LanderToken().putOntoBattlefield(1, game, source); } return true; } diff --git a/Mage.Sets/src/mage/cards/r/RamThrough.java b/Mage.Sets/src/mage/cards/r/RamThrough.java index 582f0ccb988..18bac9209d1 100644 --- a/Mage.Sets/src/mage/cards/r/RamThrough.java +++ b/Mage.Sets/src/mage/cards/r/RamThrough.java @@ -7,15 +7,18 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; -import mage.filter.StaticFilters; +import mage.game.Controllable; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; -import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.EachTargetPointer; +import java.util.List; +import java.util.Objects; +import java.util.Optional; import java.util.UUID; +import java.util.stream.Collectors; import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; @@ -47,6 +50,7 @@ class RamThroughEffect extends OneShotEffect { RamThroughEffect() { super(Outcome.Benefit); + this.setTargetPointer(new EachTargetPointer()); staticText = "Target creature you control deals damage equal to its power to target creature you don't control. " + "If the creature you control has trample, excess damage is dealt to that creature's controller instead."; } @@ -62,29 +66,31 @@ class RamThroughEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - if (source.getTargets().size() != 2) { - throw new IllegalStateException("It must have two targets, but found " + source.getTargets().size()); - } - - Permanent myPermanent = game.getPermanent(getTargetPointer().getFirst(game, source)); - Permanent anotherPermanent = game.getPermanent(source.getTargets().get(1).getFirstTarget()); - - if (myPermanent == null || anotherPermanent == null) { + List permanents = this + .getTargetPointer() + .getTargets(game, source) + .stream() + .map(game::getPermanent) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + if (permanents.size() < 2) { return false; } - int power = myPermanent.getPower().getValue(); + Permanent permanent = permanents.get(0); + int power = permanent.getPower().getValue(); if (power < 1) { return false; } - if (!myPermanent.getAbilities().containsKey(TrampleAbility.getInstance().getId())) { - return anotherPermanent.damage(power, myPermanent.getId(), source, game, false, true) > 0; + Permanent creature = permanents.get(1); + if (!permanent.hasAbility(TrampleAbility.getInstance(), game)) { + return creature.damage(power, permanent.getId(), source, game) > 0; } - int lethal = anotherPermanent.getLethalDamage(myPermanent.getId(), game); - lethal = Math.min(lethal, power); - anotherPermanent.damage(lethal, myPermanent.getId(), source, game); - Player player = game.getPlayer(anotherPermanent.getControllerId()); - if (player != null && lethal < power) { - player.damage(power - lethal, myPermanent.getId(), source, game); + int excess = creature.damageWithExcess(power, permanent.getId(), source, game); + if (excess > 0) { + Optional.ofNullable(creature) + .map(Controllable::getControllerId) + .map(game::getPlayer) + .ifPresent(player -> player.damage(excess, permanent.getId(), source, game)); } return true; } diff --git a/Mage.Sets/src/mage/cards/r/RazorRings.java b/Mage.Sets/src/mage/cards/r/RazorRings.java new file mode 100644 index 00000000000..de184c5311d --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RazorRings.java @@ -0,0 +1,72 @@ +package mage.cards.r; + +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.game.Controllable; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetAttackingOrBlockingCreature; + +import java.util.Optional; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class RazorRings extends CardImpl { + + public RazorRings(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}"); + + // Razor Rings deals 4 damage to target attacking or blocking creature. You gain life equal to the excess damage dealt this way. + this.getSpellAbility().addEffect(new RazorRingsEffect()); + this.getSpellAbility().addTarget(new TargetAttackingOrBlockingCreature()); + } + + private RazorRings(final RazorRings card) { + super(card); + } + + @Override + public RazorRings copy() { + return new RazorRings(this); + } +} + +class RazorRingsEffect extends OneShotEffect { + + RazorRingsEffect() { + super(Outcome.Benefit); + staticText = "{this} deals 4 damage to target attacking or blocking creature. " + + "You gain life equal to the excess damage dealt this way"; + } + + private RazorRingsEffect(final RazorRingsEffect effect) { + super(effect); + } + + @Override + public RazorRingsEffect copy() { + return new RazorRingsEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (permanent == null) { + return false; + } + int excess = permanent.damageWithExcess(4, source, game); + if (excess > 0) { + Optional.ofNullable(source) + .map(Controllable::getControllerId) + .map(game::getPlayer) + .ifPresent(player -> player.gainLife(excess, game, source)); + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/t/TorchTheWitness.java b/Mage.Sets/src/mage/cards/t/TorchTheWitness.java index 283c3409be3..da1d98ac6e1 100644 --- a/Mage.Sets/src/mage/cards/t/TorchTheWitness.java +++ b/Mage.Sets/src/mage/cards/t/TorchTheWitness.java @@ -60,8 +60,7 @@ class TorchTheWitnessEffect extends OneShotEffect { if (permanent == null) { return false; } - int lethal = permanent.getLethalDamage(source.getSourceId(), game); - if (lethal < permanent.damage(2 * CardUtil.getSourceCostsTag(game, source, "X", 0), source, game)) { + if (permanent.damageWithExcess(2 * CardUtil.getSourceCostsTag(game, source, "X", 0), source, game) > 0) { InvestigateEffect.doInvestigate(source.getControllerId(), 1, game, source); } return true; diff --git a/Mage.Sets/src/mage/cards/u/UnleashTheInferno.java b/Mage.Sets/src/mage/cards/u/UnleashTheInferno.java index 33ccf27b203..a2df1217059 100644 --- a/Mage.Sets/src/mage/cards/u/UnleashTheInferno.java +++ b/Mage.Sets/src/mage/cards/u/UnleashTheInferno.java @@ -67,19 +67,18 @@ class UnleashTheInfernoEffect extends OneShotEffect { if (permanent == null) { return false; } - int lethal = Math.min(permanent.getLethalDamage(source.getSourceId(), game), 7); - permanent.damage(7, source, game); - int excess = 7 - lethal; - if (excess > 0) { - ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(new DestroyTargetEffect(), false); - FilterPermanent filter = new FilterArtifactOrEnchantmentPermanent( - "artifact or enchantment an opponent controls with mana value less than or equal to " + excess - ); - filter.add(TargetController.OPPONENT.getControllerPredicate()); - filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, excess + 1)); - ability.addTarget(new TargetPermanent(filter)); - game.fireReflexiveTriggeredAbility(ability, source); + int excess = permanent.damageWithExcess(7, source, game); + if (excess < 1) { + return true; } + ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(new DestroyTargetEffect(), false); + FilterPermanent filter = new FilterArtifactOrEnchantmentPermanent( + "artifact or enchantment an opponent controls with mana value less than or equal to " + excess + ); + filter.add(TargetController.OPPONENT.getControllerPredicate()); + filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, excess + 1)); + ability.addTarget(new TargetPermanent(filter)); + game.fireReflexiveTriggeredAbility(ability, source); return true; } } diff --git a/Mage.Sets/src/mage/cards/v/VikyaScorchingStalwart.java b/Mage.Sets/src/mage/cards/v/VikyaScorchingStalwart.java index 8fa03b3c406..bd59aeb7c9b 100644 --- a/Mage.Sets/src/mage/cards/v/VikyaScorchingStalwart.java +++ b/Mage.Sets/src/mage/cards/v/VikyaScorchingStalwart.java @@ -14,11 +14,13 @@ import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SubType; import mage.constants.SuperType; +import mage.game.Controllable; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetAnyTarget; +import java.util.Optional; import java.util.UUID; /** @@ -91,14 +93,11 @@ class VikyaScorchingStalwartEffect extends OneShotEffect { if (!permanent.isCreature(game)) { return permanent.damage(amount, source, game) > 0; } - int lethal = permanent.getLethalDamage(source.getSourceId(), game); - permanent.damage(amount, source.getSourceId(), source, game); - if (lethal >= amount) { - return true; - } - Player player = game.getPlayer(source.getControllerId()); - if (player != null) { - player.drawCards(1, source, game); + if (permanent.damageWithExcess(amount, source, game) > 0) { + Optional.ofNullable(source) + .map(Controllable::getControllerId) + .map(game::getPlayer) + .ifPresent(player -> player.drawCards(1, source, game)); } return true; } diff --git a/Mage.Sets/src/mage/cards/w/WindswiftSlice.java b/Mage.Sets/src/mage/cards/w/WindswiftSlice.java index 0c9751e1c7a..59cb03ca713 100644 --- a/Mage.Sets/src/mage/cards/w/WindswiftSlice.java +++ b/Mage.Sets/src/mage/cards/w/WindswiftSlice.java @@ -1,32 +1,33 @@ package mage.cards.w; -import java.util.UUID; - import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; -import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.token.ElfWarriorToken; import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; -import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.EachTargetPointer; + +import java.util.List; +import java.util.Objects; +import java.util.UUID; +import java.util.stream.Collectors; import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; /** - * * @author bwsinger */ public final class WindswiftSlice extends CardImpl { public WindswiftSlice(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{G}"); - + // Target creature you control deals damage equal to its power to target creature you don't control. Create a number of 1/1 green Elf Warrior creature tokens equal to the amount of excess damage dealt this way. this.getSpellAbility().addEffect(new WindswiftSliceEffect()); @@ -48,6 +49,7 @@ class WindswiftSliceEffect extends OneShotEffect { WindswiftSliceEffect() { super(Outcome.Benefit); + this.setTargetPointer(new EachTargetPointer()); staticText = "Target creature you control deals damage equal to its power to target " + "creature you don't control. Create a number of 1/1 green Elf Warrior creature " + "tokens equal to the amount of excess damage dealt this way."; @@ -64,27 +66,26 @@ class WindswiftSliceEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent myPermanent = game.getPermanent(getTargetPointer().getFirst(game, source)); - Permanent anotherPermanent = game.getPermanent(source.getTargets().get(1).getFirstTarget()); - - if (myPermanent == null || anotherPermanent == null) { + List permanents = this + .getTargetPointer() + .getTargets(game, source) + .stream() + .map(game::getPermanent) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + if (permanents.size() < 2) { return false; } - - int power = myPermanent.getPower().getValue(); + Permanent permanent = permanents.get(0); + int power = permanent.getPower().getValue(); if (power < 1) { return false; } - - int lethal = anotherPermanent.getLethalDamage(myPermanent.getId(), game); - lethal = Math.min(lethal, power); - - anotherPermanent.damage(power, myPermanent.getId(), source, game); - - if (lethal < power) { - new ElfWarriorToken().putOntoBattlefield(power - lethal, game, source, source.getControllerId()); + Permanent creature = permanents.get(1); + int excess = creature.damageWithExcess(power, permanent.getId(), source, game); + if (excess > 0) { + new ElfWarriorToken().putOntoBattlefield(excess, game, source); } - return true; } } diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java index 28effa48995..4c3fd56748c 100644 --- a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -98,6 +98,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet { cards.add(new SetCardInfo("Pretending Poxbearers", 237, Rarity.COMMON, mage.cards.p.PretendingPoxbearers.class)); cards.add(new SetCardInfo("Rabaroo Troop", 32, Rarity.COMMON, mage.cards.r.RabarooTroop.class)); cards.add(new SetCardInfo("Raucous Audience", 190, Rarity.COMMON, mage.cards.r.RaucousAudience.class)); + cards.add(new SetCardInfo("Razor Rings", 33, Rarity.COMMON, mage.cards.r.RazorRings.class)); cards.add(new SetCardInfo("Rebellious Captives", 191, Rarity.COMMON, mage.cards.r.RebelliousCaptives.class)); cards.add(new SetCardInfo("Redirect Lightning", 151, Rarity.RARE, mage.cards.r.RedirectLightning.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Redirect Lightning", 343, Rarity.RARE, mage.cards.r.RedirectLightning.class, NON_FULL_USE_VARIOUS)); diff --git a/Mage/src/main/java/mage/abilities/effects/common/DamageWithExcessEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DamageWithExcessEffect.java index 84721c6224f..2df5d3a11cd 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DamageWithExcessEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DamageWithExcessEffect.java @@ -6,9 +6,11 @@ import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.OneShotEffect; import mage.constants.Outcome; +import mage.game.Controllable; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.players.Player; + +import java.util.Optional; /** * @author TheElk801 @@ -47,12 +49,12 @@ public class DamageWithExcessEffect extends OneShotEffect { return false; } int damage = amount.calculate(game, source, this); - int lethal = permanent.getLethalDamage(source.getSourceId(), game); - lethal = Math.min(lethal, damage); - permanent.damage(lethal, source.getSourceId(), source, game); - Player player = game.getPlayer(permanent.getControllerId()); - if (player != null && lethal < damage) { - player.damage(damage - lethal, source.getSourceId(), source, game); + int excess = permanent.damageWithExcess(damage, source, game); + if (excess > 0) { + Optional.ofNullable(permanent) + .map(Controllable::getControllerId) + .map(game::getPlayer) + .ifPresent(player -> player.damage(excess, source, game)); } return true; } diff --git a/Mage/src/main/java/mage/game/permanent/Permanent.java b/Mage/src/main/java/mage/game/permanent/Permanent.java index 1447879b362..73075f8f663 100644 --- a/Mage/src/main/java/mage/game/permanent/Permanent.java +++ b/Mage/src/main/java/mage/game/permanent/Permanent.java @@ -8,6 +8,7 @@ import mage.constants.Zone; import mage.game.Controllable; import mage.game.Game; import mage.game.GameState; +import mage.util.CardUtil; import java.util.List; import java.util.Set; @@ -177,6 +178,23 @@ public interface Permanent extends Card, Controllable { int getLethalDamage(UUID attackerId, Game game); + /** + * Same arguments as regular damage method, but returns the amount of excess damage dealt instead + * + * @return + */ + default int damageWithExcess(int damage, Ability source, Game game) { + return this.damageWithExcess(damage, source.getSourceId(), source, game); + } + + default int damageWithExcess(int damage, UUID attackerId, Ability source, Game game) { + int lethal = getLethalDamage(attackerId, game); + int excess = Math.max(CardUtil.overflowDec(damage, lethal), 0); + int dealt = Math.min(lethal, damage); + this.damage(dealt, attackerId, source, game); + return excess; + } + void removeAllDamage(Game game); void reset(Game game);