mirror of
https://github.com/correl/mage.git
synced 2024-12-25 03:00:15 +00:00
Implemented Invasion cards
This commit is contained in:
parent
4e640dc8ab
commit
44b2e7f84e
8 changed files with 860 additions and 0 deletions
199
Mage.Sets/src/mage/cards/b/BendOrBreak.java
Normal file
199
Mage.Sets/src/mage/cards/b/BendOrBreak.java
Normal 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;
|
||||
}
|
||||
}
|
129
Mage.Sets/src/mage/cards/d/DeathOrGlory.java
Normal file
129
Mage.Sets/src/mage/cards/d/DeathOrGlory.java
Normal 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 opponent’s 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 opponent’s 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;
|
||||
}
|
||||
}
|
109
Mage.Sets/src/mage/cards/f/FightOrFlight.java
Normal file
109
Mage.Sets/src/mage/cards/f/FightOrFlight.java
Normal 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 opponent’s 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;
|
||||
}
|
||||
}
|
98
Mage.Sets/src/mage/cards/p/PulseOfLlanowar.java
Normal file
98
Mage.Sets/src/mage/cards/p/PulseOfLlanowar.java
Normal 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;
|
||||
}
|
||||
}
|
90
Mage.Sets/src/mage/cards/s/SamiteMinistration.java
Normal file
90
Mage.Sets/src/mage/cards/s/SamiteMinistration.java
Normal 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;
|
||||
}
|
||||
}
|
133
Mage.Sets/src/mage/cards/s/StandOrFall.java
Normal file
133
Mage.Sets/src/mage/cards/s/StandOrFall.java
Normal 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 player’s 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 player’s 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 doesn’t choose an opponent to become the defending player.
|
||||
// Instead, all the attacking player’s 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 it’s 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;
|
||||
}
|
||||
}
|
95
Mage.Sets/src/mage/cards/v/VigorousCharge.java
Normal file
95
Mage.Sets/src/mage/cards/v/VigorousCharge.java
Normal 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.";
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
|
|
Loading…
Reference in a new issue