Merge pull request #5386 from Zzooouhh/Zzooouhh-inv

Implemented remaining Invasion cards (Pulse of Llanowar bug)
This commit is contained in:
L_J 2018-10-15 20:55:52 +02:00 committed by GitHub
commit b11c0ea5f8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 860 additions and 0 deletions

View file

@ -0,0 +1,199 @@
package mage.cards.b;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
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.FilterPlayer;
import mage.filter.common.FilterControlledLandPermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.other.PlayerIdPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.players.PlayerList;
import mage.target.Target;
import mage.target.TargetPermanent;
import mage.target.TargetPlayer;
import mage.target.common.TargetControlledPermanent;
/**
*
* @author LevelX2 & L_J
*/
public final class BendOrBreak extends CardImpl {
public BendOrBreak(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{R}");
// Each player separates all nontoken lands they control into two piles. For each player, one of their piles is chosen by one of their opponents of their choice. Destroy all lands in the chosen piles. Tap all lands in the other piles.
this.getSpellAbility().addEffect(new BendOrBreakEffect());
}
public BendOrBreak(final BendOrBreak card) {
super(card);
}
@Override
public BendOrBreak copy() {
return new BendOrBreak(this);
}
}
class BendOrBreakEffect extends OneShotEffect {
public BendOrBreakEffect() {
super(Outcome.DestroyPermanent);
this.staticText = "Each player separates all nontoken lands they control into two piles. For each player, one of their piles is chosen by one of their opponents of their choice. Destroy all lands in the chosen piles. Tap all lands in the other piles";
}
public BendOrBreakEffect(final BendOrBreakEffect effect) {
super(effect);
}
@Override
public BendOrBreakEffect copy() {
return new BendOrBreakEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
// Map of players and their piles
Map<UUID, List<List<Permanent>>> playerPermanents = new LinkedHashMap<>();
PlayerList playerList = game.getState().getPlayerList().copy();
while (!playerList.get().equals(source.getControllerId()) && controller.canRespond()) {
playerList.getNext();
}
Player currentPlayer = game.getPlayer(playerList.get());
Player nextPlayer;
UUID firstNextPlayer = null;
while (!getNextPlayerInDirection(true, playerList, game).equals(firstNextPlayer) && controller.canRespond()) {
nextPlayer = game.getPlayer(playerList.get());
if (nextPlayer == null) {
return false;
}
if (firstNextPlayer == null) {
firstNextPlayer = nextPlayer.getId();
}
if (!nextPlayer.canRespond()) {
continue;
}
// Each player separates all nontoken lands they control into two piles
if (currentPlayer != null && game.getState().getPlayersInRange(controller.getId(), game).contains(currentPlayer.getId())) {
List<Permanent> firstPile = new ArrayList<>();
List<Permanent> secondPile = new ArrayList<>();
FilterControlledLandPermanent filter = new FilterControlledLandPermanent("lands you control to assign to the first pile (lands not chosen will be assigned to the second pile)");
TargetPermanent target = new TargetControlledPermanent(0, Integer.MAX_VALUE, filter, true);
if (target.canChoose(source.getSourceId(), currentPlayer.getId(), game)) {
if (currentPlayer.chooseTarget(Outcome.Neutral, target, source, game)) {
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, currentPlayer.getId(), game)) {
if (target.getTargets().contains(permanent.getId())) {
firstPile.add(permanent);
} else {
secondPile.add(permanent);
}
}
}
StringBuilder sb = new StringBuilder("First pile of ").append(currentPlayer.getLogName()).append(": ");
sb.append(firstPile.stream().map(Permanent::getLogName).collect(Collectors.joining(", ")));
game.informPlayers(sb.toString());
sb = new StringBuilder("Second pile of ").append(currentPlayer.getLogName()).append(": ");
sb.append(secondPile.stream().map(Permanent::getLogName).collect(Collectors.joining(", ")));
game.informPlayers(sb.toString());
}
List<List<Permanent>> playerPiles = new ArrayList<>();
playerPiles.add(firstPile);
playerPiles.add(secondPile);
playerPermanents.put(currentPlayer.getId(), playerPiles);
}
currentPlayer = nextPlayer;
}
// For each player, one of their piles is chosen by one of their opponents of their choice
for (Map.Entry<UUID, List<List<Permanent>>> playerPiles : playerPermanents.entrySet()) {
Player player = game.getPlayer(playerPiles.getKey());
if (player != null) {
FilterPlayer filter = new FilterPlayer("opponent");
List<PlayerIdPredicate> opponentPredicates = new ArrayList<>();
for (UUID opponentId : game.getOpponents(player.getId())) {
opponentPredicates.add(new PlayerIdPredicate(opponentId));
}
filter.add(Predicates.or(opponentPredicates));
Target target = new TargetPlayer(1, 1, true, filter);
target.setTargetController(player.getId());
target.setAbilityController(source.getControllerId());
if (player.chooseTarget(outcome, target, source, game)) {
Player chosenOpponent = game.getPlayer(target.getFirstTarget());
if (chosenOpponent != null) {
List<Permanent> firstPile = playerPiles.getValue().get(0);
List<Permanent> secondPile = playerPiles.getValue().get(1);
game.informPlayers(player.getLogName() + " chose " + chosenOpponent.getLogName() + " to choose his pile");
if (chosenOpponent.choosePile(outcome, "Piles of " + player.getName(), firstPile, secondPile, game)) {
List<List<Permanent>> lists = playerPiles.getValue();
lists.clear();
lists.add(firstPile);
lists.add(secondPile);
game.informPlayers(player.getLogName() + " will have their first pile destroyed");
} else {
List<List<Permanent>> lists = playerPiles.getValue();
lists.clear();
lists.add(secondPile);
lists.add(firstPile);
game.informPlayers(player.getLogName() + " will have their second pile destroyed");
}
}
}
}
}
// Destroy all lands in the chosen piles. Tap all lands in the other piles
for (Map.Entry<UUID, List<List<Permanent>>> playerPiles : playerPermanents.entrySet()) {
Player player = game.getPlayer(playerPiles.getKey());
if (player != null) {
List<Permanent> pileToSac = playerPiles.getValue().get(0);
List<Permanent> pileToTap = playerPiles.getValue().get(1);
for (Permanent permanent : pileToSac) {
if (permanent != null) {
permanent.destroy(source.getSourceId(), game, false);
}
}
for (Permanent permanent : pileToTap) {
if (permanent != null) {
permanent.tap(game);
}
}
}
}
return true;
}
return false;
}
private UUID getNextPlayerInDirection(boolean left, PlayerList playerList, Game game) {
UUID nextPlayerId;
if (left) {
nextPlayerId = playerList.getNext();
} else {
nextPlayerId = playerList.getPrevious();
}
return nextPlayerId;
}
}

View file

@ -0,0 +1,129 @@
package mage.cards.d;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.common.FilterCreatureCard;
import mage.game.Game;
import mage.players.Player;
import mage.target.Target;
import mage.target.TargetCard;
import mage.target.common.TargetOpponent;
/**
*
* @author L_J
*/
public final class DeathOrGlory extends CardImpl {
public DeathOrGlory(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{W}");
// Separate all creature cards in your graveyard into two piles. Exile the pile of an opponents choice and return the other to the battlefield.
this.getSpellAbility().addEffect(new DeathOrGloryEffect());
}
public DeathOrGlory(final DeathOrGlory card) {
super(card);
}
@Override
public DeathOrGlory copy() {
return new DeathOrGlory(this);
}
}
class DeathOrGloryEffect extends OneShotEffect {
DeathOrGloryEffect() {
super(Outcome.Benefit);
this.staticText = "Separate all creature cards in your graveyard into two piles. Exile the pile of an opponents choice and return the other to the battlefield";
}
DeathOrGloryEffect(final DeathOrGloryEffect effect) {
super(effect);
}
@Override
public DeathOrGloryEffect copy() {
return new DeathOrGloryEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Cards cards = new CardsImpl();
cards.addAll(controller.getGraveyard().getCards(new FilterCreatureCard(), game));
if (!cards.isEmpty()) {
TargetCard targetCards = new TargetCard(0, cards.size(), Zone.EXILED, new FilterCard("cards to put in the first pile"));
List<Card> pile1 = new ArrayList<>();
if (controller.choose(Outcome.Neutral, cards, targetCards, game)) {
List<UUID> targets = targetCards.getTargets();
for (UUID targetId : targets) {
Card card = cards.get(targetId, game);
if (card != null) {
pile1.add(card);
cards.remove(card);
}
}
}
List<Card> pile2 = new ArrayList<>();
pile2.addAll(cards.getCards(game));
StringBuilder sb = new StringBuilder("First pile of ").append(controller.getLogName()).append(": ");
sb.append(pile1.stream().map(Card::getLogName).collect(Collectors.joining(", ")));
game.informPlayers(sb.toString());
sb = new StringBuilder("Second pile of ").append(controller.getLogName()).append(": ");
sb.append(pile2.stream().map(Card::getLogName).collect(Collectors.joining(", ")));
game.informPlayers(sb.toString());
Set<UUID> opponents = game.getOpponents(source.getControllerId());
if (!opponents.isEmpty()) {
Player opponent = game.getPlayer(opponents.iterator().next());
if (opponents.size() > 1) {
Target targetOpponent = new TargetOpponent(true);
if (controller.chooseTarget(Outcome.Neutral, targetOpponent, source, game)) {
opponent = game.getPlayer(targetOpponent.getFirstTarget());
game.informPlayers(controller.getLogName() + " chose " + opponent.getLogName() + " to choose his pile");
}
}
if (opponent != null) {
boolean choice = opponent.choosePile(outcome, "Choose a pile to put onto the battlefield.", pile1, pile2, game);
Zone pile1Zone = Zone.EXILED;
Zone pile2Zone = Zone.BATTLEFIELD;
if (choice) {
pile1Zone = Zone.BATTLEFIELD;
pile2Zone = Zone.EXILED;
}
Set<Card> pile1Set = new HashSet<>();
Set<Card> pile2Set = new HashSet<>();
pile1Set.addAll(pile1);
pile2Set.addAll(pile2);
controller.moveCards(pile1Set, pile1Zone, source, game, false, false, false, null);
controller.moveCards(pile2Set, pile2Zone, source, game, false, false, false, null);
}
}
}
return true;
}
return false;
}
}

View file

@ -0,0 +1,109 @@
package mage.cards.f;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
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.CantAttackTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.filter.StaticFilters;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author LevelX2 & L_J
*/
public final class FightOrFlight extends CardImpl {
public FightOrFlight(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{W}");
// At the beginning of combat on each opponents turn, separate all creatures that player controls into two piles. Only creatures in the pile of their choice can attack this turn.
this.addAbility(new BeginningOfCombatTriggeredAbility(new FightOrFlightEffect(), TargetController.OPPONENT, false));
}
public FightOrFlight(final FightOrFlight card) {
super(card);
}
@Override
public FightOrFlight copy() {
return new FightOrFlight(this);
}
}
class FightOrFlightEffect extends OneShotEffect {
public FightOrFlightEffect() {
super(Outcome.Detriment);
this.staticText = "separate all creatures that player controls into two piles. Only creatures in the pile of their choice can attack this turn";
}
public FightOrFlightEffect(final FightOrFlightEffect effect) {
super(effect);
}
@Override
public FightOrFlightEffect copy() {
return new FightOrFlightEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
Player targetPlayer = game.getPlayer(game.getCombat().getAttackingPlayerId());
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<>();
creatures.setRequired(false);
if (player.choose(Outcome.Neutral, creatures, source.getSourceId(), game)) {
List<UUID> targets = creatures.getTargets();
for (UUID targetId : targets) {
Permanent p = game.getPermanent(targetId);
if (p != null) {
pile1.add(p);
}
}
}
List<Permanent> pile2 = new ArrayList<>();
for (Permanent p : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, targetPlayer.getId(), game)) {
if (!pile1.contains(p)) {
pile2.add(p);
}
}
boolean choice = targetPlayer.choosePile(outcome, "Choose which pile can attack 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 CantAttackTargetEffect(Duration.EndOfTurn);
effect.setText("");
effect.setTargetPointer(new FixedTarget(permanent.getId()));
game.addEffect(effect, source);
}
}
StringBuilder sb = new StringBuilder("Creatures that can attack this turn: ");
sb.append(otherPile.stream().map(Permanent::getLogName).collect(Collectors.joining(", ")));
game.informPlayers(sb.toString());
return true;
}
return false;
}
}

View file

@ -0,0 +1,98 @@
package mage.cards.p;
import java.util.UUID;
import mage.MageObject;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.mana.AddManaOfAnyColorEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SuperType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.mageobject.SupertypePredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.events.ManaEvent;
import mage.game.permanent.Permanent;
/**
*
* @author L_J
*/
public final class PulseOfLlanowar extends CardImpl {
public PulseOfLlanowar(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}");
// If a basic land you control is tapped for mana, it produces mana of a color of your choice instead of any other type.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PulseOfLlanowarReplacementEffect()));
}
public PulseOfLlanowar(final PulseOfLlanowar card) {
super(card);
}
@Override
public PulseOfLlanowar copy() {
return new PulseOfLlanowar(this);
}
}
class PulseOfLlanowarReplacementEffect extends ReplacementEffectImpl {
private static final FilterControlledPermanent filter = new FilterControlledPermanent();
static {
filter.add(new SupertypePredicate(SuperType.BASIC));
}
PulseOfLlanowarReplacementEffect() {
super(Duration.WhileOnBattlefield, Outcome.Neutral);
staticText = "If a basic land you control is tapped for mana, it produces mana of a color of your choice instead of any other type";
}
PulseOfLlanowarReplacementEffect(final PulseOfLlanowarReplacementEffect effect) {
super(effect);
}
@Override
public PulseOfLlanowarReplacementEffect copy() {
return new PulseOfLlanowarReplacementEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
ManaEvent manaEvent = (ManaEvent) event;
Mana mana = manaEvent.getMana();
new AddManaOfAnyColorEffect(mana.count()).apply(game,source);
mana.setToMana(new Mana(0,0,0,0,0,0,0,0));
return true;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == EventType.TAPPED_FOR_MANA;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
MageObject mageObject = game.getObject(event.getSourceId());
if (mageObject != null && mageObject.isLand()) {
Permanent land = game.getPermanent(event.getSourceId());
return land != null && filter.match(land, game);
}
return false;
}
}

View file

@ -0,0 +1,90 @@
package mage.cards.s;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.PreventionEffectData;
import mage.abilities.effects.PreventionEffectImpl;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.players.Player;
import mage.target.TargetSource;
/**
*
* @author L_J
*/
public final class SamiteMinistration extends CardImpl {
public SamiteMinistration(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}");
// Prevent all damage that would be dealt to you this turn by a source of your choice. Whenever damage from a black or red source is prevented this way this turn, you gain that much life.
this.getSpellAbility().addEffect(new SamiteMinistrationEffect());
}
public SamiteMinistration(final SamiteMinistration card) {
super(card);
}
@Override
public SamiteMinistration copy() {
return new SamiteMinistration(this);
}
}
class SamiteMinistrationEffect extends PreventionEffectImpl {
private final TargetSource targetSource;
public SamiteMinistrationEffect() {
super(Duration.EndOfTurn, Integer.MAX_VALUE, false);
this.staticText = "Prevent all damage that would be dealt to you this turn by a source of your choice. Whenever damage from a black or red source is prevented this way this turn, you gain that much life";
this.targetSource = new TargetSource();
}
public SamiteMinistrationEffect(final SamiteMinistrationEffect effect) {
super(effect);
this.targetSource = effect.targetSource.copy();
}
@Override
public SamiteMinistrationEffect copy() {
return new SamiteMinistrationEffect(this);
}
@Override
public void init(Ability source, Game game) {
this.targetSource.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), game);
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
PreventionEffectData preventionData = preventDamageAction(event, source, game);
MageObject sourceObject = game.getObject(event.getSourceId());
if (sourceObject.getColor(game).isBlack() || sourceObject.getColor(game).isRed()) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
player.gainLife(preventionData.getPreventedDamage(), game, source);
}
}
return false;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (super.applies(event, source, game)) {
if (event.getTargetId().equals(source.getControllerId()) && event.getSourceId().equals(targetSource.getFirstTarget())) {
return true;
}
}
return false;
}
}

View file

@ -0,0 +1,133 @@
package mage.cards.s;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
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.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.filter.StaticFilters;
import mage.filter.common.FilterCreaturePermanent;
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;
/**
*
* @author LevelX2 & L_J
*/
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.
this.addAbility(new BeginningOfCombatTriggeredAbility(new StandOrFallEffect(), TargetController.YOU, false));
}
public StandOrFall(final StandOrFall card) {
super(card);
}
@Override
public StandOrFall copy() {
return new StandOrFall(this);
}
}
class StandOrFallEffect extends OneShotEffect {
public StandOrFallEffect() {
super(Outcome.Detriment);
this.staticText = "separate all creatures defending player controls into two piles. Only creatures in the pile of that players choice can block this turn";
}
public StandOrFallEffect(final StandOrFallEffect effect) {
super(effect);
}
@Override
public StandOrFallEffect copy() {
return new StandOrFallEffect(this);
}
@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.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 && 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<>();
creatures.setRequired(false);
if (player.choose(Outcome.Neutral, creatures, source.getSourceId(), game)) {
List<UUID> targets = creatures.getTargets();
for (UUID targetId : targets) {
Permanent p = game.getPermanent(targetId);
if (p != null) {
pile1.add(p);
}
}
}
List<Permanent> pile2 = new ArrayList<>();
for (Permanent p : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, targetPlayer.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.getId()));
game.addEffect(effect, source);
}
}
StringBuilder sb = new StringBuilder("Creatures that can block this turn: ");
sb.append(otherPile.stream().map(Permanent::getLogName).collect(Collectors.joining(", ")));
game.informPlayers(sb.toString());
return true;
}
}
return false;
}
}

View file

@ -0,0 +1,95 @@
package mage.cards.v;
import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.condition.LockedInCondition;
import mage.abilities.condition.common.KickedCondition;
import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.keyword.KickerAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.DamagedEvent;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author LevelX2 & L_J
*/
public final class VigorousCharge extends CardImpl {
private static final String staticText = "Whenever that creature deals combat damage this turn, if this spell was kicked, you gain life equal to that damage";
public VigorousCharge(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{G}");
// Kicker {W} (You may pay an additional {W} as you cast this spell.)
this.addAbility(new KickerAbility("{W}"));
// Target creature gains trample until end of turn.
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
this.getSpellAbility().addEffect(new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn));
// Whenever that creature deals combat damage this turn, if this spell was kicked, you gain life equal to that damage.
this.getSpellAbility().addEffect(new ConditionalContinuousEffect(new GainAbilityTargetEffect(new VigorousChargeTriggeredAbility(), Duration.EndOfTurn),
new LockedInCondition(KickedCondition.instance), staticText));
}
public VigorousCharge(final VigorousCharge card) {
super(card);
}
@Override
public VigorousCharge copy() {
return new VigorousCharge(this);
}
}
class VigorousChargeTriggeredAbility extends TriggeredAbilityImpl {
public VigorousChargeTriggeredAbility() {
super(Zone.BATTLEFIELD, null);
}
public VigorousChargeTriggeredAbility(final VigorousChargeTriggeredAbility ability) {
super(ability);
}
@Override
public VigorousChargeTriggeredAbility copy() {
return new VigorousChargeTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == EventType.DAMAGED_CREATURE
|| event.getType() == EventType.DAMAGED_PLAYER
|| event.getType() == EventType.DAMAGED_PLANESWALKER;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
DamagedEvent damageEvent = (DamagedEvent) event;
if (damageEvent.isCombatDamage()) {
if (event.getSourceId().equals(this.sourceId)) {
this.getEffects().clear();
this.getEffects().add(new GainLifeEffect(damageEvent.getAmount()));
return true;
}
}
return false;
}
@Override
public String getRule() {
return "Whenever {this} deals combat damage, you gain that much life.";
}
}

View file

@ -55,6 +55,7 @@ public final class Invasion extends ExpansionSet {
cards.add(new SetCardInfo("Benalish Heralds", 6, Rarity.UNCOMMON, mage.cards.b.BenalishHeralds.class));
cards.add(new SetCardInfo("Benalish Lancer", 7, Rarity.COMMON, mage.cards.b.BenalishLancer.class));
cards.add(new SetCardInfo("Benalish Trapper", 8, Rarity.COMMON, mage.cards.b.BenalishTrapper.class));
cards.add(new SetCardInfo("Bend or Break", 137, Rarity.RARE, mage.cards.b.BendOrBreak.class));
cards.add(new SetCardInfo("Bind", 182, Rarity.RARE, mage.cards.b.Bind.class));
cards.add(new SetCardInfo("Blazing Specter", 236, Rarity.RARE, mage.cards.b.BlazingSpecter.class));
cards.add(new SetCardInfo("Blinding Light", 9, Rarity.UNCOMMON, mage.cards.b.BlindingLight.class));
@ -88,6 +89,7 @@ public final class Invasion extends ExpansionSet {
cards.add(new SetCardInfo("Darigaaz's Attendant", 301, Rarity.UNCOMMON, mage.cards.d.DarigaazsAttendant.class));
cards.add(new SetCardInfo("Darigaaz, the Igniter", 243, Rarity.RARE, mage.cards.d.DarigaazTheIgniter.class));
cards.add(new SetCardInfo("Defiling Tears", 99, Rarity.UNCOMMON, mage.cards.d.DefilingTears.class));
cards.add(new SetCardInfo("Death or Glory", 13, Rarity.RARE, mage.cards.d.DeathOrGlory.class));
cards.add(new SetCardInfo("Desperate Research", 100, Rarity.RARE, mage.cards.d.DesperateResearch.class));
cards.add(new SetCardInfo("Devouring Strossus", 101, Rarity.RARE, mage.cards.d.DevouringStrossus.class));
cards.add(new SetCardInfo("Dismantling Blow", 14, Rarity.COMMON, mage.cards.d.DismantlingBlow.class));
@ -113,6 +115,7 @@ public final class Invasion extends ExpansionSet {
cards.add(new SetCardInfo("Fact or Fiction", 57, Rarity.UNCOMMON, mage.cards.f.FactOrFiction.class));
cards.add(new SetCardInfo("Faerie Squadron", 58, Rarity.COMMON, mage.cards.f.FaerieSquadron.class));
cards.add(new SetCardInfo("Fertile Ground", 188, Rarity.COMMON, mage.cards.f.FertileGround.class));
cards.add(new SetCardInfo("Fight or Flight", 16, Rarity.RARE, mage.cards.f.FightOrFlight.class));
cards.add(new SetCardInfo("Firebrand Ranger", 143, Rarity.UNCOMMON, mage.cards.f.FirebrandRanger.class));
cards.add(new SetCardInfo("Firescreamer", 106, Rarity.COMMON, mage.cards.f.Firescreamer.class));
cards.add(new SetCardInfo("Fires of Yavimaya", 246, Rarity.UNCOMMON, mage.cards.f.FiresOfYavimaya.class));
@ -217,6 +220,7 @@ public final class Invasion extends ExpansionSet {
cards.add(new SetCardInfo("Prohibit", 67, Rarity.COMMON, mage.cards.p.Prohibit.class));
cards.add(new SetCardInfo("Protective Sphere", 26, Rarity.COMMON, mage.cards.p.ProtectiveSphere.class));
cards.add(new SetCardInfo("Psychic Battle", 68, Rarity.RARE, mage.cards.p.PsychicBattle.class));
cards.add(new SetCardInfo("Pulse of Llanowar", 202, Rarity.UNCOMMON, mage.cards.p.PulseOfLlanowar.class));
cards.add(new SetCardInfo("Pure Reflection", 27, Rarity.RARE, mage.cards.p.PureReflection.class));
cards.add(new SetCardInfo("Pyre Zombie", 261, Rarity.RARE, mage.cards.p.PyreZombie.class));
cards.add(new SetCardInfo("Quirion Elves", 203, Rarity.COMMON, mage.cards.q.QuirionElves.class));
@ -250,6 +254,7 @@ public final class Invasion extends ExpansionSet {
cards.add(new SetCardInfo("Sabertooth Nishoba", 268, Rarity.RARE, mage.cards.s.SabertoothNishoba.class));
cards.add(new SetCardInfo("Salt Marsh", 326, Rarity.UNCOMMON, mage.cards.s.SaltMarsh.class));
cards.add(new SetCardInfo("Samite Archer", 269, Rarity.UNCOMMON, mage.cards.s.SamiteArcher.class));
cards.add(new SetCardInfo("Samite Ministration", 36, Rarity.UNCOMMON, mage.cards.s.SamiteMinistration.class));
cards.add(new SetCardInfo("Sapphire Leech", 71, Rarity.RARE, mage.cards.s.SapphireLeech.class));
cards.add(new SetCardInfo("Saproling Infestation", 208, Rarity.RARE, mage.cards.s.SaprolingInfestation.class));
cards.add(new SetCardInfo("Saproling Symbiosis", 209, Rarity.RARE, mage.cards.s.SaprolingSymbiosis.class));
@ -286,6 +291,7 @@ public final class Invasion extends ExpansionSet {
cards.add(new SetCardInfo("Spreading Plague", 125, Rarity.RARE, mage.cards.s.SpreadingPlague.class));
cards.add(new SetCardInfo("Stalking Assassin", 277, Rarity.RARE, mage.cards.s.StalkingAssassin.class));
cards.add(new SetCardInfo("Stand // Deliver", 292, Rarity.UNCOMMON, mage.cards.s.StandDeliver.class));
cards.add(new SetCardInfo("Stand or Fall", 171, Rarity.RARE, mage.cards.s.StandOrFall.class));
cards.add(new SetCardInfo("Sterling Grove", 278, Rarity.UNCOMMON, mage.cards.s.SterlingGrove.class));
cards.add(new SetCardInfo("Stormscape Apprentice", 75, Rarity.COMMON, mage.cards.s.StormscapeApprentice.class));
cards.add(new SetCardInfo("Stormscape Master", 76, Rarity.RARE, mage.cards.s.StormscapeMaster.class));
@ -346,6 +352,7 @@ public final class Invasion extends ExpansionSet {
cards.add(new SetCardInfo("Verduran Emissary", 221, Rarity.UNCOMMON, mage.cards.v.VerduranEmissary.class));
cards.add(new SetCardInfo("Viashino Grappler", 179, Rarity.COMMON, mage.cards.v.ViashinoGrappler.class));
cards.add(new SetCardInfo("Vicious Kavu", 284, Rarity.UNCOMMON, mage.cards.v.ViciousKavu.class));
cards.add(new SetCardInfo("Vigorous Charge", 222, Rarity.COMMON, mage.cards.v.VigorousCharge.class));
cards.add(new SetCardInfo("Vile Consumption", 285, Rarity.RARE, mage.cards.v.VileConsumption.class));
cards.add(new SetCardInfo("Vodalian Hypnotist", 84, Rarity.UNCOMMON, mage.cards.v.VodalianHypnotist.class));
cards.add(new SetCardInfo("Vodalian Merchant", 85, Rarity.COMMON, mage.cards.v.VodalianMerchant.class));