mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 02:30:08 -08:00
[TLA] Implement Razor Rings, rework excess damage (#13910)
* [TLA] Implement Razor Rings * add overflow protection
This commit is contained in:
parent
96dbfc757e
commit
b64f1dce45
17 changed files with 209 additions and 153 deletions
|
|
@ -62,8 +62,8 @@ class BottleCapBlastEffect extends OneShotEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
UUID target = getTargetPointer().getFirst(game, source);
|
UUID targetId = getTargetPointer().getFirst(game, source);
|
||||||
Player player = game.getPlayer(target);
|
Player player = game.getPlayer(targetId);
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
player.damage(5, source, game);
|
player.damage(5, source, game);
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -72,11 +72,10 @@ class BottleCapBlastEffect extends OneShotEffect {
|
||||||
if (permanent == null) {
|
if (permanent == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int lethal = Math.min(permanent.getLethalDamage(source.getSourceId(), game), 5);
|
int excess = permanent.damageWithExcess(5, source, game);
|
||||||
permanent.damage(5, source.getSourceId(), source, game);
|
if (excess > 0) {
|
||||||
if (lethal < 5) {
|
|
||||||
new TreasureToken().putOntoBattlefield(
|
new TreasureToken().putOntoBattlefield(
|
||||||
5 - lethal, game, source, source.getControllerId(), true, false
|
excess, game, source, source.getControllerId(), true, false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
package mage.cards.c;
|
package mage.cards.c;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.keyword.DiscoverEffect;
|
import mage.abilities.effects.keyword.DiscoverEffect;
|
||||||
|
|
@ -9,34 +7,29 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.filter.StaticFilters;
|
import mage.game.Controllable;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.players.Player;
|
|
||||||
import mage.target.Target;
|
|
||||||
import mage.target.TargetPermanent;
|
import mage.target.TargetPermanent;
|
||||||
import mage.target.common.TargetControlledCreaturePermanent;
|
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;
|
import static mage.filter.StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author jimga150
|
* @author jimga150
|
||||||
*/
|
*/
|
||||||
public final class ContestOfClaws extends CardImpl {
|
public final class ContestOfClaws extends CardImpl {
|
||||||
|
|
||||||
public ContestOfClaws(UUID ownerId, CardSetInfo setInfo) {
|
public ContestOfClaws(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{G}");
|
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.
|
// 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());
|
this.getSpellAbility().addEffect(new ContestOfClawsDamageEffect());
|
||||||
Target target = new TargetControlledCreaturePermanent().setTargetTag(1);
|
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent().setTargetTag(1));
|
||||||
this.getSpellAbility().addTarget(target);
|
this.getSpellAbility().addTarget(new TargetPermanent(FILTER_ANOTHER_CREATURE_TARGET_2).setTargetTag(2));
|
||||||
|
|
||||||
Target target2 = new TargetPermanent(FILTER_ANOTHER_CREATURE_TARGET_2).setTargetTag(2);
|
|
||||||
this.getSpellAbility().addTarget(target2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ContestOfClaws(final ContestOfClaws card) {
|
private ContestOfClaws(final ContestOfClaws card) {
|
||||||
|
|
@ -74,22 +67,13 @@ class ContestOfClawsDamageEffect extends OneShotEffect {
|
||||||
if (ownCreature == null || targetCreature == null) {
|
if (ownCreature == null || targetCreature == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int damage = ownCreature.getPower().getValue();
|
int excess = targetCreature.damageWithExcess( ownCreature.getPower().getValue(), ownCreature.getId(), source, game);
|
||||||
int lethalDamage = targetCreature.getLethalDamage(source.getSourceId(), game);
|
if (excess > 0) {
|
||||||
targetCreature.damage(damage, ownCreature.getId(), source, game, false, true);
|
Optional.ofNullable(source)
|
||||||
|
.map(Controllable::getControllerId)
|
||||||
if (damage < lethalDamage){
|
.map(game::getPlayer)
|
||||||
return true;
|
.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;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ import mage.util.CardUtil;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author ciaccona007
|
* @author ciaccona007
|
||||||
*/
|
*/
|
||||||
public final class GoblinNegotiation extends CardImpl {
|
public final class GoblinNegotiation extends CardImpl {
|
||||||
|
|
@ -62,14 +61,12 @@ class GoblinNegotiationEffect extends OneShotEffect {
|
||||||
if (permanent == null) {
|
if (permanent == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int damage = CardUtil.getSourceCostsTag(game, source, "X", 0);
|
int excess = permanent.damageWithExcess(
|
||||||
int lethal = Math.min(permanent.getLethalDamage(source.getSourceId(), game), damage);
|
CardUtil.getSourceCostsTag(game, source, "X", 0), source, game
|
||||||
permanent.damage(damage, source.getSourceId(), source, game);
|
);
|
||||||
if (damage > lethal) {
|
if (excess > 0) {
|
||||||
new GoblinToken().putOntoBattlefield(
|
new GoblinToken().putOntoBattlefield(excess, game, source);
|
||||||
damage - lethal, game, source, source.getControllerId()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,13 +60,11 @@ class HellToPayEffect extends OneShotEffect {
|
||||||
if (permanent == null) {
|
if (permanent == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int damage = CardUtil.getSourceCostsTag(game, source, "X", 0);
|
int excess = permanent.damageWithExcess(
|
||||||
int lethal = Math.min(permanent.getLethalDamage(source.getSourceId(), game), damage);
|
CardUtil.getSourceCostsTag(game, source, "X", 0), source, game
|
||||||
permanent.damage(damage, source.getSourceId(), source, game);
|
);
|
||||||
if (damage > lethal) {
|
if (excess > 0) {
|
||||||
new TreasureToken().putOntoBattlefield(
|
new TreasureToken().putOntoBattlefield(excess, game, source, source.getControllerId(), true, false);
|
||||||
damage - lethal, game, source, source.getControllerId(), true, false
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,14 +55,13 @@ class LacerateFleshEffect extends OneShotEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Permanent permanent = game.getPermanent(source.getFirstTarget());
|
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||||
if (permanent == null) {
|
if (permanent == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int lethal = Math.min(permanent.getLethalDamage(source.getSourceId(), game), 4);
|
int excess = permanent.damageWithExcess(4, source, game);
|
||||||
permanent.damage(4, source.getSourceId(), source, game);
|
if (excess > 0) {
|
||||||
if (lethal < 4) {
|
new BloodToken().putOntoBattlefield(excess, game, source);
|
||||||
new BloodToken().putOntoBattlefield(4 - lethal, game, source);
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ class MegatronDestructiveForceEffect extends OneShotEffect {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
TargetSacrifice target = new TargetSacrifice(
|
TargetSacrifice target = new TargetSacrifice(
|
||||||
0, 1, StaticFilters.FILTER_CONTROLLED_ANOTHER_ARTIFACT
|
0, 1, StaticFilters.FILTER_CONTROLLED_ANOTHER_ARTIFACT
|
||||||
);
|
);
|
||||||
player.choose(outcome, target, source, game);
|
player.choose(outcome, target, source, game);
|
||||||
Permanent permanent = game.getPermanent(target.getFirstTarget());
|
Permanent permanent = game.getPermanent(target.getFirstTarget());
|
||||||
|
|
@ -93,7 +93,7 @@ class MegatronDestructiveForceEffect extends OneShotEffect {
|
||||||
}
|
}
|
||||||
|
|
||||||
ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(
|
ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(
|
||||||
new MegatronDestructiveForceReflexiveEffect(manaValue), false
|
new MegatronDestructiveForceReflexiveEffect(manaValue), false
|
||||||
);
|
);
|
||||||
ability.addHint(new StaticHint("Sacrificed artifact mana value: " + manaValue));
|
ability.addHint(new StaticHint("Sacrificed artifact mana value: " + manaValue));
|
||||||
ability.addTarget(new TargetCreaturePermanent());
|
ability.addTarget(new TargetCreaturePermanent());
|
||||||
|
|
@ -109,8 +109,8 @@ class MegatronDestructiveForceReflexiveEffect extends OneShotEffect {
|
||||||
MegatronDestructiveForceReflexiveEffect(int value) {
|
MegatronDestructiveForceReflexiveEffect(int value) {
|
||||||
super(Outcome.Damage);
|
super(Outcome.Damage);
|
||||||
staticText = "{this} deals damage equal to the sacrificed artifact's mana value to target " +
|
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 " +
|
"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}.";
|
"is dealt to that creature's controller and you convert {this}.";
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -126,36 +126,22 @@ class MegatronDestructiveForceReflexiveEffect extends OneShotEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Permanent sourcePermanent = source.getSourcePermanentOrLKI(game);
|
|
||||||
if (sourcePermanent == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value < 1) {
|
if (value < 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||||
if (permanent == null) {
|
if (permanent == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
int excess = permanent.damageWithExcess(value, source, game);
|
||||||
int lethal = permanent.getLethalDamage(source.getSourceId(), game);
|
if (excess < 1) {
|
||||||
int excess = value - lethal;
|
|
||||||
if (excess <= 0) {
|
|
||||||
// no excess damage.
|
|
||||||
permanent.damage(value, source.getSourceId(), source, game);
|
|
||||||
return true;
|
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());
|
Player player = game.getPlayer(permanent.getControllerId());
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
player.damage(excess, source, game);
|
player.damage(excess, source, game);
|
||||||
}
|
}
|
||||||
new TransformSourceEffect().apply(game, source);
|
new TransformSourceEffect().apply(game, source);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -80,9 +80,8 @@ class NahirisWarcraftingEffect extends OneShotEffect {
|
||||||
if (player == null || permanent == null) {
|
if (player == null || permanent == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int lethal = permanent.getLethalDamage(source.getSourceId(), game);
|
int excess = permanent.damageWithExcess(5, source, game);
|
||||||
int excess = permanent.damage(5, source, game) - lethal;
|
if (excess < 1) {
|
||||||
if (excess <= 0) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, excess));
|
Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, excess));
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ package mage.cards.o;
|
||||||
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.CreateTokenEffect;
|
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
|
|
@ -61,10 +60,8 @@ class OrbitalPlungeEffect extends OneShotEffect {
|
||||||
if (permanent == null) {
|
if (permanent == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int lethal = permanent.getLethalDamage(source.getSourceId(), game);
|
if (permanent.damageWithExcess(6, source, game) > 0) {
|
||||||
permanent.damage(6, source.getSourceId(), source, game);
|
new LanderToken().putOntoBattlefield(1, game, source);
|
||||||
if (lethal < 6) {
|
|
||||||
new CreateTokenEffect(new LanderToken()).apply(game, source);
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,15 +7,18 @@ import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.filter.StaticFilters;
|
import mage.game.Controllable;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.players.Player;
|
|
||||||
import mage.target.TargetPermanent;
|
import mage.target.TargetPermanent;
|
||||||
import mage.target.common.TargetControlledCreaturePermanent;
|
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.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL;
|
import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL;
|
||||||
|
|
||||||
|
|
@ -47,6 +50,7 @@ class RamThroughEffect extends OneShotEffect {
|
||||||
|
|
||||||
RamThroughEffect() {
|
RamThroughEffect() {
|
||||||
super(Outcome.Benefit);
|
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. " +
|
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.";
|
"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
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
if (source.getTargets().size() != 2) {
|
List<Permanent> permanents = this
|
||||||
throw new IllegalStateException("It must have two targets, but found " + source.getTargets().size());
|
.getTargetPointer()
|
||||||
}
|
.getTargets(game, source)
|
||||||
|
.stream()
|
||||||
Permanent myPermanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
.map(game::getPermanent)
|
||||||
Permanent anotherPermanent = game.getPermanent(source.getTargets().get(1).getFirstTarget());
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.toList());
|
||||||
if (myPermanent == null || anotherPermanent == null) {
|
if (permanents.size() < 2) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int power = myPermanent.getPower().getValue();
|
Permanent permanent = permanents.get(0);
|
||||||
|
int power = permanent.getPower().getValue();
|
||||||
if (power < 1) {
|
if (power < 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!myPermanent.getAbilities().containsKey(TrampleAbility.getInstance().getId())) {
|
Permanent creature = permanents.get(1);
|
||||||
return anotherPermanent.damage(power, myPermanent.getId(), source, game, false, true) > 0;
|
if (!permanent.hasAbility(TrampleAbility.getInstance(), game)) {
|
||||||
|
return creature.damage(power, permanent.getId(), source, game) > 0;
|
||||||
}
|
}
|
||||||
int lethal = anotherPermanent.getLethalDamage(myPermanent.getId(), game);
|
int excess = creature.damageWithExcess(power, permanent.getId(), source, game);
|
||||||
lethal = Math.min(lethal, power);
|
if (excess > 0) {
|
||||||
anotherPermanent.damage(lethal, myPermanent.getId(), source, game);
|
Optional.ofNullable(creature)
|
||||||
Player player = game.getPlayer(anotherPermanent.getControllerId());
|
.map(Controllable::getControllerId)
|
||||||
if (player != null && lethal < power) {
|
.map(game::getPlayer)
|
||||||
player.damage(power - lethal, myPermanent.getId(), source, game);
|
.ifPresent(player -> player.damage(excess, permanent.getId(), source, game));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
72
Mage.Sets/src/mage/cards/r/RazorRings.java
Normal file
72
Mage.Sets/src/mage/cards/r/RazorRings.java
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -60,8 +60,7 @@ class TorchTheWitnessEffect extends OneShotEffect {
|
||||||
if (permanent == null) {
|
if (permanent == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int lethal = permanent.getLethalDamage(source.getSourceId(), game);
|
if (permanent.damageWithExcess(2 * CardUtil.getSourceCostsTag(game, source, "X", 0), source, game) > 0) {
|
||||||
if (lethal < permanent.damage(2 * CardUtil.getSourceCostsTag(game, source, "X", 0), source, game)) {
|
|
||||||
InvestigateEffect.doInvestigate(source.getControllerId(), 1, game, source);
|
InvestigateEffect.doInvestigate(source.getControllerId(), 1, game, source);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -67,19 +67,18 @@ class UnleashTheInfernoEffect extends OneShotEffect {
|
||||||
if (permanent == null) {
|
if (permanent == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int lethal = Math.min(permanent.getLethalDamage(source.getSourceId(), game), 7);
|
int excess = permanent.damageWithExcess(7, source, game);
|
||||||
permanent.damage(7, source, game);
|
if (excess < 1) {
|
||||||
int excess = 7 - lethal;
|
return true;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,13 @@ import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.constants.SubType;
|
import mage.constants.SubType;
|
||||||
import mage.constants.SuperType;
|
import mage.constants.SuperType;
|
||||||
|
import mage.game.Controllable;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.common.TargetAnyTarget;
|
import mage.target.common.TargetAnyTarget;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -91,14 +93,11 @@ class VikyaScorchingStalwartEffect extends OneShotEffect {
|
||||||
if (!permanent.isCreature(game)) {
|
if (!permanent.isCreature(game)) {
|
||||||
return permanent.damage(amount, source, game) > 0;
|
return permanent.damage(amount, source, game) > 0;
|
||||||
}
|
}
|
||||||
int lethal = permanent.getLethalDamage(source.getSourceId(), game);
|
if (permanent.damageWithExcess(amount, source, game) > 0) {
|
||||||
permanent.damage(amount, source.getSourceId(), source, game);
|
Optional.ofNullable(source)
|
||||||
if (lethal >= amount) {
|
.map(Controllable::getControllerId)
|
||||||
return true;
|
.map(game::getPlayer)
|
||||||
}
|
.ifPresent(player -> player.drawCards(1, source, game));
|
||||||
Player player = game.getPlayer(source.getControllerId());
|
|
||||||
if (player != null) {
|
|
||||||
player.drawCards(1, source, game);
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,32 +1,33 @@
|
||||||
package mage.cards.w;
|
package mage.cards.w;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.filter.StaticFilters;
|
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.game.permanent.token.ElfWarriorToken;
|
import mage.game.permanent.token.ElfWarriorToken;
|
||||||
import mage.target.TargetPermanent;
|
import mage.target.TargetPermanent;
|
||||||
import mage.target.common.TargetControlledCreaturePermanent;
|
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;
|
import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author bwsinger
|
* @author bwsinger
|
||||||
*/
|
*/
|
||||||
public final class WindswiftSlice extends CardImpl {
|
public final class WindswiftSlice extends CardImpl {
|
||||||
|
|
||||||
public WindswiftSlice(UUID ownerId, CardSetInfo setInfo) {
|
public WindswiftSlice(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{G}");
|
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.
|
// 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());
|
this.getSpellAbility().addEffect(new WindswiftSliceEffect());
|
||||||
|
|
@ -48,6 +49,7 @@ class WindswiftSliceEffect extends OneShotEffect {
|
||||||
|
|
||||||
WindswiftSliceEffect() {
|
WindswiftSliceEffect() {
|
||||||
super(Outcome.Benefit);
|
super(Outcome.Benefit);
|
||||||
|
this.setTargetPointer(new EachTargetPointer());
|
||||||
staticText = "Target creature you control deals damage equal to its power to target " +
|
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 " +
|
"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.";
|
"tokens equal to the amount of excess damage dealt this way.";
|
||||||
|
|
@ -64,27 +66,26 @@ class WindswiftSliceEffect extends OneShotEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
Permanent myPermanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
List<Permanent> permanents = this
|
||||||
Permanent anotherPermanent = game.getPermanent(source.getTargets().get(1).getFirstTarget());
|
.getTargetPointer()
|
||||||
|
.getTargets(game, source)
|
||||||
if (myPermanent == null || anotherPermanent == null) {
|
.stream()
|
||||||
|
.map(game::getPermanent)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if (permanents.size() < 2) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Permanent permanent = permanents.get(0);
|
||||||
int power = myPermanent.getPower().getValue();
|
int power = permanent.getPower().getValue();
|
||||||
if (power < 1) {
|
if (power < 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Permanent creature = permanents.get(1);
|
||||||
int lethal = anotherPermanent.getLethalDamage(myPermanent.getId(), game);
|
int excess = creature.damageWithExcess(power, permanent.getId(), source, game);
|
||||||
lethal = Math.min(lethal, power);
|
if (excess > 0) {
|
||||||
|
new ElfWarriorToken().putOntoBattlefield(excess, game, source);
|
||||||
anotherPermanent.damage(power, myPermanent.getId(), source, game);
|
|
||||||
|
|
||||||
if (lethal < power) {
|
|
||||||
new ElfWarriorToken().putOntoBattlefield(power - lethal, game, source, source.getControllerId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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("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("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("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("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", 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));
|
cards.add(new SetCardInfo("Redirect Lightning", 343, Rarity.RARE, mage.cards.r.RedirectLightning.class, NON_FULL_USE_VARIOUS));
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,11 @@ import mage.abilities.dynamicvalue.DynamicValue;
|
||||||
import mage.abilities.dynamicvalue.common.StaticValue;
|
import mage.abilities.dynamicvalue.common.StaticValue;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
|
import mage.game.Controllable;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.players.Player;
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author TheElk801
|
* @author TheElk801
|
||||||
|
|
@ -47,12 +49,12 @@ public class DamageWithExcessEffect extends OneShotEffect {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int damage = amount.calculate(game, source, this);
|
int damage = amount.calculate(game, source, this);
|
||||||
int lethal = permanent.getLethalDamage(source.getSourceId(), game);
|
int excess = permanent.damageWithExcess(damage, source, game);
|
||||||
lethal = Math.min(lethal, damage);
|
if (excess > 0) {
|
||||||
permanent.damage(lethal, source.getSourceId(), source, game);
|
Optional.ofNullable(permanent)
|
||||||
Player player = game.getPlayer(permanent.getControllerId());
|
.map(Controllable::getControllerId)
|
||||||
if (player != null && lethal < damage) {
|
.map(game::getPlayer)
|
||||||
player.damage(damage - lethal, source.getSourceId(), source, game);
|
.ifPresent(player -> player.damage(excess, source, game));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import mage.constants.Zone;
|
||||||
import mage.game.Controllable;
|
import mage.game.Controllable;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.GameState;
|
import mage.game.GameState;
|
||||||
|
import mage.util.CardUtil;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
@ -177,6 +178,23 @@ public interface Permanent extends Card, Controllable {
|
||||||
|
|
||||||
int getLethalDamage(UUID attackerId, Game game);
|
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 removeAllDamage(Game game);
|
||||||
|
|
||||||
void reset(Game game);
|
void reset(Game game);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue