[ALL] reworked Fatal Lore and Misfortune to use mode selection

This commit is contained in:
Evan Kranzler 2022-04-05 20:27:38 -04:00
parent 3fe6a60616
commit 80f9fdfb79
3 changed files with 98 additions and 85 deletions

View file

@ -1,37 +1,46 @@
package mage.cards.f;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.Effect;
import mage.abilities.Mode;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.effects.common.DrawCardTargetEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.ControllerIdPredicate;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
import mage.target.common.TargetOpponent;
import mage.target.targetpointer.FixedTarget;
import mage.target.TargetPermanent;
import mage.target.targetadjustment.TargetAdjuster;
import java.util.Objects;
import java.util.UUID;
/**
*
* @author jeffwadsworth
* @author TheElk801
*/
public final class FatalLore extends CardImpl {
public FatalLore(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{B}{B}");
// An opponent chooses one - You draw three cards; or you destroy up to two target creatures that opponent controls and that player draws up to three cards. Those creatures can't be regenerated.
this.getSpellAbility().addEffect(new FatalLoreEffect());
this.getSpellAbility().addTarget(new TargetOpponent(true));
// An opponent chooses one
this.getSpellAbility().getModes().setModeChooser(TargetController.OPPONENT);
// You draw three cards.
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).setText("you draw three cards"));
// You destroy up to two target creatures that player controls. They can't be regenerated. That player draws up to three cards.
this.getSpellAbility().addMode(new Mode(new DestroyTargetEffect(
"you destroy up to two target creatures that player controls. " +
"They can't be regenerated", true
)).addEffect(new FatalLoreEffect()));
this.getSpellAbility().setTargetAdjuster(FatalLoreAdjuster.instance);
}
private FatalLore(final FatalLore card) {
@ -44,14 +53,37 @@ public final class FatalLore extends CardImpl {
}
}
enum FatalLoreAdjuster implements TargetAdjuster {
instance;
@Override
public void adjustTargets(Ability ability, Game game) {
Mode mode = ability.getModes().getMode();
if (mode.getEffects().stream().noneMatch(DestroyTargetEffect.class::isInstance)) {
return;
}
UUID playerId = mode
.getEffects()
.stream()
.findFirst()
.filter(Objects::nonNull)
.map(effect -> (UUID) effect.getValue("choosingPlayer"))
.orElse(null);
FilterPermanent filter = new FilterCreaturePermanent("creatures controlled by " + game.getPlayer(playerId).getName());
filter.add(new ControllerIdPredicate(playerId));
mode.getTargets().clear();
mode.addTarget(new TargetPermanent(0, 2, filter));
}
}
class FatalLoreEffect extends OneShotEffect {
public FatalLoreEffect() {
super(Outcome.Neutral);
staticText = "An opponent chooses one - You draw three cards; or you destroy up to two target creatures that opponent controls and that player draws up to three cards. Those creatures can't be regenerated";
FatalLoreEffect() {
super(Outcome.Benefit);
staticText = "That player draws up to three cards";
}
public FatalLoreEffect(final FatalLoreEffect effect) {
private FatalLoreEffect(final FatalLoreEffect effect) {
super(effect);
}
@ -62,30 +94,11 @@ class FatalLoreEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Player chosenOpponent = game.getPlayer(targetPointer.getFirst(game, source));
if (controller != null
&& chosenOpponent != null) {
if (chosenOpponent.chooseUse(Outcome.Neutral, "If you choose Yes, the controller draws three cards. If no, the controller gets to destroy up to two target creatures that you control and you get to draw up to 3 cards. Those creatures can't be regenerated.", source, game)) {
controller.drawCards(3, source, game);
} else {
FilterCreaturePermanent filter = new FilterCreaturePermanent("chosen opponent's creature");
filter.add(new ControllerIdPredicate(chosenOpponent.getId()));
TargetCreaturePermanent target = new TargetCreaturePermanent(0, 2, filter, false);
if (target.canChoose(controller.getId(), source, game)
&& controller.choose(Outcome.DestroyPermanent, target, source, game)) {
for (UUID targetId : target.getTargets()) {
Effect destroyCreature = new DestroyTargetEffect(true);
destroyCreature.setTargetPointer(new FixedTarget(targetId, game));
destroyCreature.apply(game, source);
}
Effect opponentDrawsCards = new DrawCardTargetEffect(StaticValue.get(3), false, true);
opponentDrawsCards.setTargetPointer(new FixedTarget(chosenOpponent.getId()));
opponentDrawsCards.apply(game, source);
return true;
}
}
Player player = game.getPlayer((UUID) getValue("choosingPlayer"));
if (player == null) {
return false;
}
return false;
int toDraw = player.getAmount(0, 3, "Choose how many cards to draw", game);
return player.drawCards(toDraw, source, game) > 0;
}
}

View file

@ -1,34 +1,42 @@
package mage.cards.m;
import mage.abilities.Ability;
import mage.abilities.effects.Effect;
import mage.abilities.Mode;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.counter.AddCountersAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.counters.CounterType;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.ControllerIdPredicate;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetOpponent;
import java.util.UUID;
/**
* @author jeffwadsworth
* @author TheElk801
*/
public final class Misfortune extends CardImpl {
public Misfortune(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{B}{R}{G}");
// An opponent chooses one - You put a +1/+1 counter on each creature you control and gain 4 life; or you put a -1/-1 counter on each creature that player controls and Misfortune deals 4 damage to that player.
this.getSpellAbility().addEffect(new MisfortuneEffect());
this.getSpellAbility().addTarget(new TargetOpponent(true));
// An opponent chooses one
this.getSpellAbility().getModes().setModeChooser(TargetController.OPPONENT);
// You put a +1/+1 counter on each creature you control and gain 4 life.
this.getSpellAbility().addEffect(new AddCountersAllEffect(
CounterType.P1P1.createInstance(), StaticFilters.FILTER_CONTROLLED_CREATURE
).setText("you put a +1/+1 counter on each creature you control"));
this.getSpellAbility().addEffect(new GainLifeEffect(4).setText("and gain 4 life"));
// You put a -1/-1 counter on each creature that player controls and Misfortune deals 4 damage to that player.
this.getSpellAbility().addMode(new Mode(new MisfortuneEffect()));
}
private Misfortune(final Misfortune card) {
@ -43,15 +51,13 @@ public final class Misfortune extends CardImpl {
class MisfortuneEffect extends OneShotEffect {
public MisfortuneEffect() {
super(Outcome.Neutral);
staticText = "An opponent chooses one - "
+ "You put a +1/+1 counter on each creature you control and gain "
+ "4 life; or you put a -1/-1 counter on each creature that player "
+ "controls and Misfortune deals 4 damage to that player";
MisfortuneEffect() {
super(Outcome.Benefit);
staticText = "you put a -1/-1 counter on each creature that player controls " +
"and {this} deals 4 damage to that player";
}
public MisfortuneEffect(final MisfortuneEffect effect) {
private MisfortuneEffect(final MisfortuneEffect effect) {
super(effect);
}
@ -62,27 +68,16 @@ class MisfortuneEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Player chosenOpponent = game.getPlayer(targetPointer.getFirst(game, source));
if (controller != null
&& chosenOpponent != null) {
if (chosenOpponent.chooseUse(Outcome.Neutral, "If you choose Yes, the controller puts a +1/+1 counter"
+ "on each creature they control and they gain 4 life. If no, the controller puts a -1/-1 counter"
+ "on each creature you control and {this} deals 4 damage to you.", source, game)) {
Effect putP1P1CounterOnEachControlledCreature = new AddCountersAllEffect(
CounterType.P1P1.createInstance(), new FilterControlledCreaturePermanent());
putP1P1CounterOnEachControlledCreature.apply(game, source);
controller.gainLife(4, game, source);
} else {
FilterCreaturePermanent filterOpponentCreatures = new FilterCreaturePermanent();
filterOpponentCreatures.add(new ControllerIdPredicate(chosenOpponent.getId()));
Effect putM1M1CounterOnEachOpponentCreature = new AddCountersAllEffect(
CounterType.M1M1.createInstance(), filterOpponentCreatures);
putM1M1CounterOnEachOpponentCreature.apply(game, source);
chosenOpponent.damage(4, source.getSourceId(), source, game);
}
return true;
Player player = game.getPlayer((UUID) getValue("choosingPlayer"));
if (player == null) {
return false;
}
return false;
for (Permanent permanent : game.getBattlefield().getActivePermanents(
StaticFilters.FILTER_CONTROLLED_CREATURE, player.getId(), source, game
)) {
permanent.addCounters(CounterType.M1M1.createInstance(), source.getControllerId(), source, game);
}
player.damage(4, source, game);
return true;
}
}

View file

@ -306,19 +306,18 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
// Some spells and abilities specify that a player other than their controller chooses a mode for it.
// In that case, the other player does so when the spell or ability's controller normally would do so.
// If there is more than one other player who could make such a choice, the spell or ability's controller decides which of those players will make the choice.
UUID playerId = null;
UUID playerId;
if (modeChooser == TargetController.OPPONENT) {
TargetOpponent targetOpponent = new TargetOpponent();
if (targetOpponent.choose(Outcome.Benefit, source.getControllerId(), source.getSourceId(), source, game)) {
playerId = targetOpponent.getFirstTarget();
}
targetOpponent.choose(Outcome.Benefit, source.getControllerId(), source.getSourceId(), source, game);
playerId = targetOpponent.getFirstTarget();
} else {
playerId = source.getControllerId();
}
if (playerId == null) {
Player player = game.getPlayer(playerId);
if (player == null) {
return false;
}
Player player = game.getPlayer(playerId);
// player chooses modes manually
this.currentMode = null;
@ -341,7 +340,13 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
if (isEachModeOnlyOnce()) {
setAlreadySelectedModes(source, game);
}
return true;
if (modeChooser == TargetController.OPPONENT) {
selectedModes
.stream()
.map(this::get)
.map(Mode::getEffects)
.forEach(effects -> effects.setValue("choosingPlayer", playerId));
}
} else {
// only one mode available
if (currentMode == null) {
@ -350,8 +355,8 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
this.addSelectedMode(mode.getId());
this.setActiveMode(mode);
}
return true;
}
return true;
}
/**