[SPM] implement Terrific Team-Up and create a shared effect (#13954)

* create common TargetsDamageTargetsEffect

* [SPM] implement Superior Terrific Team-Up

* fix band together second target predicate

* remove unnecessary checks in TargetsDamageTargetsEffect
This commit is contained in:
Jmlundeen 2025-09-07 16:50:34 -05:00 committed by GitHub
parent d2a7991f8e
commit 432de6f9fe
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 271 additions and 354 deletions

View file

@ -1,17 +1,13 @@
package mage.cards.b; package mage.cards.b;
import mage.abilities.Ability; import mage.abilities.effects.common.TargetsDamageTargetsEffect;
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.filter.FilterPermanent; import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterCreaturePermanent; import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.other.AnotherTargetPredicate; import mage.filter.predicate.other.AnotherTargetPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.Target; import mage.target.Target;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
@ -27,19 +23,19 @@ public final class BandTogether extends CardImpl {
static { static {
filter.add(new AnotherTargetPredicate(1)); filter.add(new AnotherTargetPredicate(1));
filter2.add(new AnotherTargetPredicate(2)); filter2.add(new AnotherTargetPredicate(3));
} }
public BandTogether(UUID ownerId, CardSetInfo setInfo) { public BandTogether(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{G}"); super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{G}");
// Up to two target creatures you control each deal damage equal to their power to another target creature. // Up to two target creatures you control each deal damage equal to their power to another target creature.
this.getSpellAbility().addEffect(new BandTogetherEffect()); this.getSpellAbility().addEffect(new TargetsDamageTargetsEffect(true));
Target target = new TargetPermanent(0, 2, filter, false); Target target = new TargetPermanent(0, 2, filter, false);
target.setTargetTag(1); target.setTargetTag(1);
this.getSpellAbility().addTarget(target); this.getSpellAbility().addTarget(target);
target = new TargetPermanent(1, 1, filter2, false); target = new TargetPermanent(1, 1, filter2, false);
target.setTargetTag(2); target.setTargetTag(3);
this.getSpellAbility().addTarget(target); this.getSpellAbility().addTarget(target);
} }
@ -52,48 +48,3 @@ public final class BandTogether extends CardImpl {
return new BandTogether(this); return new BandTogether(this);
} }
} }
class BandTogetherEffect extends OneShotEffect {
BandTogetherEffect() {
super(Outcome.Benefit);
this.staticText = "Up to two target creatures you control each deal damage equal to their power to another target creature.";
}
private BandTogetherEffect(final BandTogetherEffect effect) {
super(effect);
}
@Override
public BandTogetherEffect copy() {
return new BandTogetherEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
if (source.getTargets().size() < 2) {
return false;
}
Target damageTarget = source.getTargets().get(0);
Target destTarget = source.getTargets().get(1);
if (damageTarget.getTargets().isEmpty() || destTarget.getTargets().isEmpty()) {
return false;
}
Permanent permanentDamage1 = damageTarget.getTargets().isEmpty() ? null : game.getPermanent(damageTarget.getTargets().get(0));
Permanent permanentDamage2 = damageTarget.getTargets().size() < 2 ? null : game.getPermanent(damageTarget.getTargets().get(1));
Permanent permanentDest = game.getPermanent(destTarget.getTargets().get(0));
if (permanentDest == null) {
return false;
}
if (permanentDamage1 != null) {
permanentDest.damage(permanentDamage1.getPower().getValue(), permanentDamage1.getId(), source, game, false, true);
}
if (permanentDamage2 != null) {
permanentDest.damage(permanentDamage2.getPower().getValue(), permanentDamage2.getId(), source, game, false, true);
}
return true;
}
}

View file

@ -1,15 +1,11 @@
package mage.cards.c; package mage.cards.c;
import mage.abilities.Ability; import mage.abilities.effects.common.TargetsDamageTargetsEffect;
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.filter.FilterPermanent; import mage.filter.FilterPermanent;
import mage.filter.common.FilterTeamCreaturePermanent; import mage.filter.common.FilterTeamCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
@ -26,9 +22,9 @@ public final class ComboAttack extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{G}"); super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{G}");
// Two target creatures your team controls each deal damage equal to their power to target creature. // Two target creatures your team controls each deal damage equal to their power to target creature.
this.getSpellAbility().addEffect(new ComboAttackEffect()); this.getSpellAbility().addEffect(new TargetsDamageTargetsEffect(true));
this.getSpellAbility().addTarget(new TargetPermanent(2, filter)); this.getSpellAbility().addTarget(new TargetPermanent(2, filter).setTargetTag(1));
this.getSpellAbility().addTarget(new TargetCreaturePermanent()); this.getSpellAbility().addTarget(new TargetCreaturePermanent().setTargetTag(3));
} }
private ComboAttack(final ComboAttack card) { private ComboAttack(final ComboAttack card) {
@ -40,41 +36,3 @@ public final class ComboAttack extends CardImpl {
return new ComboAttack(this); return new ComboAttack(this);
} }
} }
class ComboAttackEffect extends OneShotEffect {
ComboAttackEffect() {
super(Outcome.Benefit);
this.staticText = "Two target creatures your team controls each deal damage equal to their power to target creature";
}
private ComboAttackEffect(final ComboAttackEffect effect) {
super(effect);
}
@Override
public ComboAttackEffect copy() {
return new ComboAttackEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
if (source.getTargets().size() < 2) {
return false;
}
Permanent permanent3 = game.getPermanent(source.getTargets().get(1).getFirstTarget());
if (permanent3 == null) {
return false;
}
// You cant cast Combo Attack without targeting two creatures your team controls.
// If one of those creatures is an illegal target as Combo Attack resolves,
// the other will still deal damage equal to its power. (2018-06-08)
for (UUID id : source.getTargets().get(0).getTargets()) {
Permanent permanent = game.getPermanent(id);
if (permanent != null) {
permanent3.damage(permanent.getPower().getValue(), permanent.getId(), source, game);
}
}
return true;
}
}

View file

@ -1,21 +1,15 @@
package mage.cards.c; package mage.cards.c;
import mage.abilities.Ability; import mage.abilities.effects.common.TapTargetEffect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.TargetsDamageTargetsEffect;
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.filter.StaticFilters; import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
import mage.target.common.TargetOpponentsCreaturePermanent; import mage.target.common.TargetOpponentsCreaturePermanent;
import java.util.List;
import java.util.Objects;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors;
/** /**
* @author TheElk801 * @author TheElk801
@ -26,11 +20,12 @@ public final class CoordinatedClobbering extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{G}"); super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{G}");
// Tap one or two target untapped creatures you control. They each deal damage equal to their power to target creature an opponent controls. // Tap one or two target untapped creatures you control. They each deal damage equal to their power to target creature an opponent controls.
this.getSpellAbility().addEffect(new CoordinatedClobberingEffect()); this.getSpellAbility().addEffect(new TapTargetEffect());
this.getSpellAbility().addEffect(new TargetsDamageTargetsEffect(false));
this.getSpellAbility().addTarget(new TargetPermanent( this.getSpellAbility().addTarget(new TargetPermanent(
1, 2, StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURES 1, 2, StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURES
)); ).setTargetTag(1));
this.getSpellAbility().addTarget(new TargetOpponentsCreaturePermanent()); this.getSpellAbility().addTarget(new TargetOpponentsCreaturePermanent().setTargetTag(3));
} }
private CoordinatedClobbering(final CoordinatedClobbering card) { private CoordinatedClobbering(final CoordinatedClobbering card) {
@ -42,48 +37,4 @@ public final class CoordinatedClobbering extends CardImpl {
return new CoordinatedClobbering(this); return new CoordinatedClobbering(this);
} }
} }
class CoordinatedClobberingEffect extends OneShotEffect {
CoordinatedClobberingEffect() {
super(Outcome.Benefit);
staticText = "tap one or two target untapped creatures you control. " +
"They each deal damage equal to their power to target creature an opponent controls";
}
private CoordinatedClobberingEffect(final CoordinatedClobberingEffect effect) {
super(effect);
}
@Override
public CoordinatedClobberingEffect copy() {
return new CoordinatedClobberingEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
List<Permanent> permanents = this
.getTargetPointer()
.getTargets(game, source)
.stream()
.map(game::getPermanent)
.filter(Objects::nonNull)
.collect(Collectors.toList());
if (permanents.isEmpty()) {
return false;
}
for (Permanent permanent : permanents) {
permanent.tap(source, game);
}
Permanent targetPermanent = game.getPermanent(source.getTargets().get(1).getFirstTarget());
if (targetPermanent == null) {
return true;
}
game.processAction();
for (Permanent permanent : permanents) {
targetPermanent.damage(permanent.getPower().getValue(), permanent.getId(), source, game);
}
return true;
}
}
// flame on! // flame on!

View file

@ -1,24 +1,17 @@
package mage.cards.f; package mage.cards.f;
import mage.abilities.Ability; import mage.abilities.effects.common.TargetsDamageTargetsEffect;
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.SuperType; import mage.constants.SuperType;
import mage.filter.FilterPermanent; import mage.filter.FilterPermanent;
import mage.filter.StaticFilters; import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.other.AnotherTargetPredicate; import mage.filter.predicate.other.AnotherTargetPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetControlledCreaturePermanent;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.UUID; import java.util.UUID;
/** /**
@ -37,7 +30,7 @@ public final class FriendlyRivalry extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}{G}"); super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}{G}");
// Target creature you control and up to one other target legendary creature you control each deal damage equal to their power to target creature you don't control. // Target creature you control and up to one other target legendary creature you control each deal damage equal to their power to target creature you don't control.
this.getSpellAbility().addEffect(new FriendlyRivalryEffect()); this.getSpellAbility().addEffect(new TargetsDamageTargetsEffect(true));
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent().setTargetTag(1).withChooseHint("to deal damage")); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent().setTargetTag(1).withChooseHint("to deal damage"));
this.getSpellAbility().addTarget(new TargetPermanent(0, 1, filter2).setTargetTag(2).withChooseHint("to deal damage")); this.getSpellAbility().addTarget(new TargetPermanent(0, 1, filter2).setTargetTag(2).withChooseHint("to deal damage"));
this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL).setTargetTag(3).withChooseHint("to take damage")); this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL).setTargetTag(3).withChooseHint("to take damage"));
@ -52,52 +45,3 @@ public final class FriendlyRivalry extends CardImpl {
return new FriendlyRivalry(this); return new FriendlyRivalry(this);
} }
} }
class FriendlyRivalryEffect extends OneShotEffect {
FriendlyRivalryEffect() {
super(Outcome.Benefit);
staticText = "Target creature you control and up to one other target legendary " +
"creature you control each deal damage equal to their power to target creature you don't control.";
}
private FriendlyRivalryEffect(final FriendlyRivalryEffect effect) {
super(effect);
}
@Override
public FriendlyRivalryEffect copy() {
return new FriendlyRivalryEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
int size = source.getTargets().size();
if (size < 3) {
throw new IllegalArgumentException("Wrong code usage. Lost targets list, must has 3, but found: " + source.getTargets());
}
List<Permanent> toDealDamage = new ArrayList<>();
source.getTargets().getTargetsByTag(1).stream()
.map(game::getPermanent)
.filter(Objects::nonNull)
.forEach(toDealDamage::add);
source.getTargets().getTargetsByTag(2).stream()
.map(game::getPermanent)
.filter(Objects::nonNull)
.forEach(toDealDamage::add);
Permanent toTakeDamage = source.getTargets().getTargetsByTag(3).stream()
.map(game::getPermanent)
.filter(Objects::nonNull)
.findFirst().orElse(null);
if (toDealDamage.isEmpty() || toTakeDamage == null) {
return false;
}
toDealDamage.forEach(permanent -> {
toTakeDamage.damage(permanent.getPower().getValue(), permanent.getId(), source, game, false, true);
});
return true;
}
}

View file

@ -1,36 +1,38 @@
package mage.cards.g; package mage.cards.g;
import mage.abilities.Ability; import mage.abilities.effects.common.TargetsDamageTargetsEffect;
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.filter.FilterPermanent; import mage.filter.FilterPermanent;
import mage.filter.StaticFilters; import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.other.AnotherTargetPredicate;
import mage.filter.predicate.permanent.EnchantedPredicate; import mage.filter.predicate.permanent.EnchantedPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
import java.util.List;
import java.util.Objects;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors;
/** /**
* @author TheElk801 * @author TheElk801
*/ */
public final class GracefulTakedown extends CardImpl { public final class GracefulTakedown extends CardImpl {
private static final FilterPermanent filter = new FilterControlledCreaturePermanent("enchanted creatures you control");
private static final FilterControlledCreaturePermanent otherCreatureFilter = new FilterControlledCreaturePermanent("other target creature you control");
static {
filter.add(EnchantedPredicate.instance);
otherCreatureFilter.add(new AnotherTargetPredicate(2));
}
public GracefulTakedown(UUID ownerId, CardSetInfo setInfo) { public GracefulTakedown(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{G}"); super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{G}");
// Any number of target enchanted creatures you control and up to one other target creature you control each deal damage equal to their power to target creature you don't control. // Any number of target enchanted creatures you control and up to one other target creature you control each deal damage equal to their power to target creature you don't control.
this.getSpellAbility().addEffect(new GracefulTakedownEffect()); this.getSpellAbility().addEffect(new TargetsDamageTargetsEffect(true));
this.getSpellAbility().addTarget(new GracefulTakedownTarget()); this.getSpellAbility().addTarget(new TargetPermanent(0, Integer.MAX_VALUE, filter).setTargetTag(1).withChooseHint("enchanted"));
this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); this.getSpellAbility().addTarget(new TargetPermanent(0, 1, otherCreatureFilter).setTargetTag(2));
this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL).setTargetTag(3));
} }
private GracefulTakedown(final GracefulTakedown card) { private GracefulTakedown(final GracefulTakedown card) {
@ -42,78 +44,3 @@ public final class GracefulTakedown extends CardImpl {
return new GracefulTakedown(this); return new GracefulTakedown(this);
} }
} }
class GracefulTakedownTarget extends TargetPermanent {
private static final FilterPermanent filter = new FilterControlledCreaturePermanent("enchanted creatures you control and up to one other creature you control");
GracefulTakedownTarget() {
super(0, Integer.MAX_VALUE, filter);
}
private GracefulTakedownTarget(final GracefulTakedownTarget target) {
super(target);
}
@Override
public GracefulTakedownTarget copy() {
return new GracefulTakedownTarget(this);
}
@Override
public boolean canTarget(UUID playerId, UUID id, Ability source, Game game) {
if (!super.canTarget(playerId, id, source, game)) {
return false;
}
Permanent permanent = game.getPermanent(id);
return permanent != null
&& (EnchantedPredicate.instance.apply(permanent, game)
|| this
.getTargets()
.stream()
.map(game::getPermanent)
.filter(Objects::nonNull)
.allMatch(p -> p.getId().equals(id) || EnchantedPredicate.instance.apply(p, game)));
}
}
class GracefulTakedownEffect extends OneShotEffect {
GracefulTakedownEffect() {
super(Outcome.Benefit);
staticText = "any number of target enchanted creatures you control and up to one other target creature " +
"you control each deal damage equal to their power to target creature you don't control";
}
private GracefulTakedownEffect(final GracefulTakedownEffect effect) {
super(effect);
}
@Override
public GracefulTakedownEffect copy() {
return new GracefulTakedownEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
List<Permanent> permanents = source
.getTargets()
.get(0)
.getTargets()
.stream()
.map(game::getPermanent)
.filter(Objects::nonNull)
.collect(Collectors.toList());
if (permanents.isEmpty()) {
return false;
}
Permanent creature = game.getPermanent(source.getTargets().get(1).getFirstTarget());
if (creature == null) {
return false;
}
for (Permanent permanent : permanents) {
creature.damage(permanent.getPower().getValue(), permanent.getId(), source, game);
}
return true;
}
}

View file

@ -1,18 +1,13 @@
package mage.cards.t; package mage.cards.t;
import mage.abilities.Ability; import mage.abilities.effects.common.TargetsDamageTargetsEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect;
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.filter.FilterPermanent; import mage.filter.FilterPermanent;
import mage.filter.predicate.Predicates; import mage.filter.predicate.Predicates;
import mage.filter.predicate.other.AnotherTargetPredicate; import mage.filter.predicate.other.AnotherTargetPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.Target;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetControlledCreaturePermanent;
@ -23,7 +18,7 @@ import java.util.UUID;
*/ */
public final class TandemTakedown extends CardImpl { public final class TandemTakedown extends CardImpl {
private static final FilterPermanent filter = new FilterPermanent("creature, planeswalker, or battle"); private static final FilterPermanent filter = new FilterPermanent("another target creature, planeswalker, or battle");
static { static {
filter.add(Predicates.or( filter.add(Predicates.or(
@ -40,9 +35,9 @@ public final class TandemTakedown extends CardImpl {
// Up to two target creatures you control each get +1/+0 until end of turn. They each deal damage equal to their power to another target creature, planeswalker, or battle. // Up to two target creatures you control each get +1/+0 until end of turn. They each deal damage equal to their power to another target creature, planeswalker, or battle.
this.getSpellAbility().addEffect(new BoostTargetEffect(1, 0) this.getSpellAbility().addEffect(new BoostTargetEffect(1, 0)
.setText("up to two target creatures you control each get +1/+0 until end of turn")); .setText("up to two target creatures you control each get +1/+0 until end of turn"));
this.getSpellAbility().addEffect(new TandemTakedownEffect()); this.getSpellAbility().addEffect(new TargetsDamageTargetsEffect(false));
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(0, 2).setTargetTag(1)); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(0, 2).setTargetTag(1));
this.getSpellAbility().addTarget(new TargetPermanent(filter).setTargetTag(2)); this.getSpellAbility().addTarget(new TargetPermanent(filter).setTargetTag(3));
} }
private TandemTakedown(final TandemTakedown card) { private TandemTakedown(final TandemTakedown card) {
@ -54,48 +49,3 @@ public final class TandemTakedown extends CardImpl {
return new TandemTakedown(this); return new TandemTakedown(this);
} }
} }
class TandemTakedownEffect extends OneShotEffect {
TandemTakedownEffect() {
super(Outcome.Benefit);
staticText = "They each deal damage equal to their power to another target creature, planeswalker, or battle";
}
private TandemTakedownEffect(final TandemTakedownEffect effect) {
super(effect);
}
@Override
public TandemTakedownEffect copy() {
return new TandemTakedownEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
if (source.getTargets().size() < 2) {
return false;
}
Target damageTarget = source.getTargets().get(0);
Target destTarget = source.getTargets().get(1);
if (damageTarget.getTargets().isEmpty() || destTarget.getTargets().isEmpty()) {
return false;
}
Permanent permanentDamage1 = damageTarget.getTargets().isEmpty() ? null : game.getPermanent(damageTarget.getTargets().get(0));
Permanent permanentDamage2 = damageTarget.getTargets().size() < 2 ? null : game.getPermanent(damageTarget.getTargets().get(1));
Permanent permanentDest = game.getPermanent(destTarget.getTargets().get(0));
if (permanentDest == null) {
return false;
}
if (permanentDamage1 != null) {
permanentDest.damage(permanentDamage1.getPower().getValue(), permanentDamage1.getId(), source, game, false, true);
}
if (permanentDamage2 != null) {
permanentDest.damage(permanentDamage2.getPower().getValue(), permanentDamage2.getId(), source, game, false, true);
}
return true;
}
}

View file

@ -0,0 +1,66 @@
package mage.cards.t;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.Condition;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
import mage.abilities.effects.common.TargetsDamageTargetsEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect;
import mage.abilities.hint.ConditionHint;
import mage.abilities.hint.Hint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.ComparisonType;
import mage.constants.Zone;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.mageobject.ManaValuePredicate;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetOpponentsCreaturePermanent;
import java.util.UUID;
/**
*
* @author Jmlundeen
*/
public final class TerrificTeamUp extends CardImpl {
private static final FilterControlledPermanent filter = new FilterControlledPermanent("you control a permanent with mana value 4 or greater");
static {
filter.add(new ManaValuePredicate(ComparisonType.OR_GREATER, 4));
}
private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter);
private static final Hint hint = new ConditionHint(condition, "You control a permanent with mana value 4 or greater");
public TerrificTeamUp(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{G}");
// This spell costs {2} less to cast if you control a permanent with mana value 4 or greater.
Ability ability = new SimpleStaticAbility(Zone.ALL, new SpellCostReductionSourceEffect(2, condition));
ability.setRuleAtTheTop(true);
ability.addHint(hint);
this.addAbility(ability);
// One or two target creatures you control each get +1/+0 until end of turn. They each deal damage equal to their power to target creature an opponent controls.
this.getSpellAbility().addEffect(new BoostTargetEffect(1, 0));
this.getSpellAbility().addEffect(new TargetsDamageTargetsEffect(false));
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(1, 2).setTargetTag(1).withChooseHint("boost and deal damage"));
this.getSpellAbility().addTarget(new TargetOpponentsCreaturePermanent().setTargetTag(3));
}
private TerrificTeamUp(final TerrificTeamUp card) {
super(card);
}
@Override
public TerrificTeamUp copy() {
return new TerrificTeamUp(this);
}
}

View file

@ -270,6 +270,7 @@ public final class MarvelsSpiderMan extends ExpansionSet {
cards.add(new SetCardInfo("Symbiote Spider-Man", 156, Rarity.RARE, mage.cards.s.SymbioteSpiderMan.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Symbiote Spider-Man", 156, Rarity.RARE, mage.cards.s.SymbioteSpiderMan.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Symbiote Spider-Man", 217, Rarity.RARE, mage.cards.s.SymbioteSpiderMan.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Symbiote Spider-Man", 217, Rarity.RARE, mage.cards.s.SymbioteSpiderMan.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Taxi Driver", 97, Rarity.COMMON, mage.cards.t.TaxiDriver.class)); cards.add(new SetCardInfo("Taxi Driver", 97, Rarity.COMMON, mage.cards.t.TaxiDriver.class));
cards.add(new SetCardInfo("Terrific Team-Up", 120, Rarity.UNCOMMON, mage.cards.t.TerrificTeamUp.class));
cards.add(new SetCardInfo("The Clone Saga", 219, Rarity.RARE, mage.cards.t.TheCloneSaga.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("The Clone Saga", 219, Rarity.RARE, mage.cards.t.TheCloneSaga.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("The Clone Saga", 28, Rarity.RARE, mage.cards.t.TheCloneSaga.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("The Clone Saga", 28, Rarity.RARE, mage.cards.t.TheCloneSaga.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("The Death of Gwen Stacy", 223, Rarity.RARE, mage.cards.t.TheDeathOfGwenStacy.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("The Death of Gwen Stacy", 223, Rarity.RARE, mage.cards.t.TheDeathOfGwenStacy.class, NON_FULL_USE_VARIOUS));

View file

@ -0,0 +1,61 @@
package org.mage.test.cards.single.spm;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.filter.Filter;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author Jmlundeen
*/
public class TerrificTeamUpTest extends CardTestPlayerBase {
/*
Terrific Team-Up
{3}{G}
Instant
This spell costs {2} less to cast if you control a permanent with mana value 4 or greater.
One or two target creatures you control each get +1/+0 until end of turn. They each deal damage equal to their power to target creature an opponent controls.
*/
private static final String terrificTeamUp = "Terrific Team-Up";
/*
Bear Cub
{1}{G}
Creature - Bear
2/2
*/
private static final String bearCub = "Bear Cub";
/*
Sea Monster
{4}{U}{U}
Creature - Serpent
Sea Monster can't attack unless defending player controls an Island.
6/6
*/
private static final String seaMonster = "Sea Monster";
@Test
public void testTerrificTeamUp() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, bearCub, 2);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 4);
addCard(Zone.BATTLEFIELD, playerB, seaMonster);
addCard(Zone.HAND, playerA, terrificTeamUp);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, terrificTeamUp);
addTarget(playerA, bearCub, 2);
addTarget(playerA, seaMonster);
setStopAt(1, PhaseStep.PRECOMBAT_MAIN);
execute();
assertGraveyardCount(playerB, seaMonster, 1);
assertPowerToughness(playerA, bearCub, 3, 2, Filter.ComparisonScope.All);
}
}

View file

@ -4,6 +4,7 @@ import mage.constants.PhaseStep;
import mage.constants.Zone; import mage.constants.Zone;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.mage.test.player.TestPlayer;
import org.mage.test.serverside.base.CardTestPlayerBase; import org.mage.test.serverside.base.CardTestPlayerBase;
/** /**
@ -38,7 +39,8 @@ public class GracefulTakedownTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, takedown); addCard(Zone.HAND, playerA, takedown);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, takedown); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, takedown);
addTarget(playerA, cub); addTarget(playerA, TestPlayer.TARGET_SKIP); // enchanted
addTarget(playerA, cub); // one other
addTarget(playerA, ancient); addTarget(playerA, ancient);
setStopAt(1, PhaseStep.END_COMBAT); setStopAt(1, PhaseStep.END_COMBAT);
@ -62,7 +64,8 @@ public class GracefulTakedownTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, strength, piker, true); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, strength, piker, true);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, takedown); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, takedown);
addTarget(playerA, cub + "^" + piker); addTarget(playerA, piker); // enchanted
addTarget(playerA, cub); // one other
addTarget(playerA, ancient); addTarget(playerA, ancient);
setStopAt(1, PhaseStep.END_COMBAT); setStopAt(1, PhaseStep.END_COMBAT);

View file

@ -0,0 +1,105 @@
package mage.abilities.effects.common;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.Target;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
* Used for [target creatures] deal damage equal to their power to [target creature]
* <br> set targets using tags <i>.setTargetTag(1)</i>
* <br> set the first target tag for creatures dealing damage
* <br> set the second target tag for additional creatures, not required (Friendly Rivalry)
* <br> set the third target tag for creatures receiving damage
*
* @author Jmlundeen
*/
public class TargetsDamageTargetsEffect extends OneShotEffect {
private final boolean describeDamagingTargets;
public TargetsDamageTargetsEffect(boolean describeDamagingTargets) {
super(Outcome.Benefit);
this.describeDamagingTargets = describeDamagingTargets;
}
private TargetsDamageTargetsEffect(final TargetsDamageTargetsEffect effect) {
super(effect);
this.describeDamagingTargets = effect.describeDamagingTargets;
}
@Override
public TargetsDamageTargetsEffect copy() {
return new TargetsDamageTargetsEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
if (source.getTargets().size() < 2) {
return false;
}
Target damageTarget = source.getTargets().getByTag(1);
Target additionalDamageTarget = source.getTargets().getByTag(2);
Target destTarget = source.getTargets().getByTag(3);
List<Permanent> damagingPermanents = new ArrayList<>();
List<Permanent> receivingPermanents = new ArrayList<>();
for (UUID id : damageTarget.getTargets()) {
Permanent permanent = game.getPermanent(id);
if (permanent != null) {
damagingPermanents.add(permanent);
}
}
if (additionalDamageTarget != null) {
for (UUID id : additionalDamageTarget.getTargets()) {
Permanent permanent = game.getPermanent(id);
if (permanent != null) {
damagingPermanents.add(permanent);
}
}
}
for (UUID id : destTarget.getTargets()) {
Permanent permanent = game.getPermanent(id);
if (permanent != null) {
receivingPermanents.add(permanent);
}
}
if (receivingPermanents.isEmpty() || damagingPermanents.isEmpty()) {
return false;
}
for (Permanent receivingPermanent : receivingPermanents) {
for (Permanent damagingPermanent: damagingPermanents) {
receivingPermanent.damage(damagingPermanent.getPower().getValue(), damagingPermanent.getId(), source, game, false, true);
}
}
return true;
}
@Override
public String getText(Mode mode) {
if (staticText != null && !staticText.isEmpty()) {
return staticText;
}
StringBuilder sb = new StringBuilder();
if (describeDamagingTargets) {
sb.append(mode.getTargets().getByTag(1).getDescription());
if (mode.getTargets().getByTag(2) != null) {
sb.append(" and ").append(mode.getTargets().getByTag(2).getDescription());
}
} else {
sb.append("they");
}
sb.append(" each deal damage equal to their power to ");
sb.append(mode.getTargets().getByTag(3).getDescription());
return sb.toString();
}
}