rework and fix Stand or Fall

This commit is contained in:
xenohedron 2024-05-16 16:22:48 -04:00
parent 5e9b01bfbe
commit 6fd6417d0b
2 changed files with 48 additions and 79 deletions

View file

@ -3,8 +3,7 @@ package mage.cards.s;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfCombatTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.RestrictionEffect;
import mage.abilities.effects.common.combat.CantBlockTargetEffect;
import mage.abilities.effects.common.combat.CantBlockAllEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
@ -13,28 +12,28 @@ import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.filter.StaticFilters;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.permanent.ControllerIdPredicate;
import mage.filter.predicate.permanent.PermanentReferenceInCollectionPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
import mage.target.common.TargetOpponent;
import mage.target.targetpointer.FixedTarget;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
/**
* @author LevelX2 & L_J
* @author xenohedron
*/
public final class StandOrFall extends CardImpl {
public StandOrFall(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}");
// At the beginning of combat on your turn, separate all creatures defending player controls into two piles. Only creatures in the pile of that players choice can block this turn.
// At the beginning of combat on your turn, for each defending player, separate all creatures that player controls into two piles and that player chooses one. Only creatures in the chosen piles can block this turn.
this.addAbility(new BeginningOfCombatTriggeredAbility(new StandOrFallEffect(), TargetController.YOU, false));
}
@ -52,7 +51,8 @@ class StandOrFallEffect extends OneShotEffect {
StandOrFallEffect() {
super(Outcome.Detriment);
this.staticText = "separate all creatures that player controls into two piles and that player chooses one. Only creatures in the chosen piles can block this turn";
this.staticText = "for each defending player, separate all creatures that player controls into two piles and that player chooses one." +
" Only creatures in the chosen piles can block this turn";
}
private StandOrFallEffect(final StandOrFallEffect effect) {
@ -66,34 +66,21 @@ class StandOrFallEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
// 802.2. As the combat phase starts, the attacking player doesnt choose an opponent to become the defending player.
// Instead, all the attacking players opponents are defending players during the combat phase.
//
// 802.2a Any rule, object, or effect that refers to a defending player refers to one specific defending player, not to all of the defending players.
// If an ability of an attacking creature refers to a defending player, or a spell or ability refers to both an attacking creature and a defending player,
// then unless otherwise specified, the defending player its referring to is the player that creature was attacking at the time it became an attacking
// creature that combat, or the controller of the planeswalker that creature was attacking at the time it became an attacking creature that combat. If a spell or ability
// could apply to multiple attacking creatures, the appropriate defending player is individually determined for each of those attacking creatures.
// If there are multiple defending players that could be chosen, the controller of the spell or ability chooses one.
//
// https://www.mtgsalvation.com/forums/magic-fundamentals/magic-rulings/756140-stand-or-fall-mechanics
Player player = game.getPlayer(source.getControllerId());
Set<UUID> opponents = game.getOpponents(source.getControllerId());
if (!opponents.isEmpty()) {
Player targetPlayer = game.getPlayer(opponents.iterator().next());
if (opponents.size() > 1) {
TargetOpponent targetOpponent = new TargetOpponent(true);
if (player != null && player.chooseTarget(Outcome.Neutral, targetOpponent, source, game)) {
targetPlayer = game.getPlayer(targetOpponent.getFirstTarget());
game.informPlayers(player.getLogName() + " chose " + targetPlayer.getLogName() + " as the defending player");
if (player == null) {
return false;
}
List<Permanent> canBlock = new ArrayList<>();
for (UUID oppId : game.getOpponents(source.getControllerId())) {
Player opponent = game.getPlayer(oppId);
if (opponent == null) {
continue;
}
if (player != null && targetPlayer != null) {
int count = game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT_CREATURES, targetPlayer.getId(), game);
TargetCreaturePermanent creatures = new TargetCreaturePermanent(0, count, new FilterCreaturePermanent("creatures to put in the first pile"), true);
List<Permanent> pile1 = new ArrayList<>();
FilterCreaturePermanent opponentFilter = new FilterCreaturePermanent();
opponentFilter.add(new ControllerIdPredicate(oppId));
TargetCreaturePermanent creatures = new TargetCreaturePermanent(0, Integer.MAX_VALUE, opponentFilter, true);
creatures.setRequired(false);
List<Permanent> pile1 = new ArrayList<>();
if (player.choose(Outcome.Neutral, creatures, source, game)) {
List<UUID> targets = creatures.getTargets();
for (UUID targetId : targets) {
@ -104,27 +91,21 @@ class StandOrFallEffect extends OneShotEffect {
}
}
List<Permanent> pile2 = new ArrayList<>();
for (Permanent p : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, targetPlayer.getId(), game)) {
for (Permanent p : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, opponent.getId(), game)) {
if (!pile1.contains(p)) {
pile2.add(p);
}
}
boolean choice = targetPlayer.choosePile(outcome, "Choose which pile can block this turn.", pile1, pile2, game);
List<Permanent> chosenPile = choice ? pile2 : pile1;
List<Permanent> otherPile = choice ? pile1 : pile2;
for (Permanent permanent : chosenPile) {
if (permanent != null) {
RestrictionEffect effect = new CantBlockTargetEffect(Duration.EndOfTurn);
effect.setText("");
effect.setTargetPointer(new FixedTarget(permanent, game));
game.addEffect(effect, source);
boolean choice = opponent.choosePile(outcome, "Choose which pile can block this turn.", pile1, pile2, game);
canBlock.addAll(choice ? pile1 : pile2);
}
}
game.informPlayers("Creatures that can block this turn: " + otherPile.stream().map(Permanent::getLogName).collect(Collectors.joining(", ")));
FilterCreaturePermanent filterRestriction = new FilterCreaturePermanent();
filterRestriction.add(Predicates.not(new PermanentReferenceInCollectionPredicate(canBlock, game)));
game.addEffect(new CantBlockAllEffect(filterRestriction, Duration.EndOfTurn), source);
game.informPlayers("Creatures that can block this turn: " + canBlock
.stream()
.map(Permanent::getLogName)
.collect(Collectors.joining(", ")));
return true;
}
}
return false;
}
}

View file

@ -1,7 +1,6 @@
package mage.abilities.effects.common.combat;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.RestrictionEffect;
import mage.constants.Duration;
import mage.filter.common.FilterCreaturePermanent;
@ -18,6 +17,7 @@ public class CantBlockAllEffect extends RestrictionEffect {
public CantBlockAllEffect(FilterCreaturePermanent filter, Duration duration) {
super(duration);
this.filter = filter;
this.staticText = filter.getMessage() + " can't block" + (duration == Duration.EndOfTurn ? " this turn" : "");
}
protected CantBlockAllEffect(final CantBlockAllEffect effect) {
@ -40,16 +40,4 @@ public class CantBlockAllEffect extends RestrictionEffect {
return new CantBlockAllEffect(this);
}
@Override
public String getText(Mode mode) {
if (staticText != null && !staticText.isEmpty()) {
return staticText;
}
StringBuilder sb = new StringBuilder();
sb.append(filter.getMessage()).append(" can't block");
if (this.duration == Duration.EndOfTurn) {
sb.append(" this turn");
}
return sb.toString();
}
}