Merge origin/master

This commit is contained in:
USER 2019-08-28 13:14:37 +08:00
commit 204ab9c55d
13 changed files with 505 additions and 10 deletions

View file

@ -33,11 +33,13 @@ public class Modern extends Constructed {
banned.add("Dig Through Time");
banned.add("Dread Return");
banned.add("Eye of Ugin");
banned.add("Faithless Looting");
banned.add("Gitaxian Probe");
banned.add("Glimpse of Nature");
banned.add("Golgari Grave-Troll");
banned.add("Great Furnace");
banned.add("Green Sun's Zenith");
banned.add("Hogaak, Arisen Necropolis");
banned.add("Hypergenesis");
banned.add("Krark-Clan Ironworks");
banned.add("Mental Misstep");
@ -49,7 +51,6 @@ public class Modern extends Constructed {
banned.add("Second Sunrise");
banned.add("Seething Song");
banned.add("Sensei's Divining Top");
banned.add("Stoneforge Mystic");
banned.add("Skullclamp");
banned.add("Splinter Twin");
banned.add("Summer Bloom");

View file

@ -16,8 +16,6 @@ public class Standard extends Constructed {
super("Constructed - Standard");
setCodes.addAll(makeLegalSets());
banned.add("Rampaging Ferocidon"); // since 2018-01-15
}
private static boolean isFallSet(ExpansionSet set) {

View file

@ -51,11 +51,12 @@ public class Vintage extends Constructed {
restricted.add("Demonic Consultation");
restricted.add("Demonic Tutor");
restricted.add("Dig Through Time");
restricted.add("Fastbond");
restricted.add("Flash");
restricted.add("Gitaxian Probe");
restricted.add("Golgari Grave-Troll");
restricted.add("Gush");
restricted.add("Imperial Seal");
restricted.add("Karn, the Great Creator");
restricted.add("Library of Alexandria");
restricted.add("Lion's Eye Diamond");
restricted.add("Lodestone Golem");
@ -63,6 +64,7 @@ public class Vintage extends Constructed {
restricted.add("Mana Crypt");
restricted.add("Mana Vault");
restricted.add("Memory Jar");
restricted.add("Mental Misstep");
restricted.add("Merchant Scroll");
restricted.add("Mind's Desire");
restricted.add("Monastery Mentory");
@ -71,6 +73,7 @@ public class Vintage extends Constructed {
restricted.add("Mox Pearl");
restricted.add("Mox Ruby");
restricted.add("Mox Sapphire");
restricted.add("Mystic Forge");
restricted.add("Mystical Tutor");
restricted.add("Necropotence");
restricted.add("Ponder");

View file

@ -0,0 +1,129 @@
package mage.cards.e;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTappedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.common.ManaEffect;
import mage.abilities.mana.SimpleManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.choices.ChoiceColor;
import mage.constants.CardType;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class EmpoweredAutogenerator extends CardImpl {
public EmpoweredAutogenerator(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}");
// Empowered Autogenerator enters the battlefield tapped.
this.addAbility(new EntersBattlefieldTappedAbility());
// {T}: Put a charge counter on Empowered Autogenerator. Add X mana of any one color, where X is the number of charge counters on Empowered Autogenerator.
this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, new AstralCornucopiaManaEffect(), new TapSourceCost()));
}
private EmpoweredAutogenerator(final EmpoweredAutogenerator card) {
super(card);
}
@Override
public EmpoweredAutogenerator copy() {
return new EmpoweredAutogenerator(this);
}
}
class AstralCornucopiaManaEffect extends ManaEffect {
private final Mana computedMana;
AstralCornucopiaManaEffect() {
super();
computedMana = new Mana();
this.staticText = "Put a charge counter on {this}. Add X mana of any one color, " +
"where X is the number of charge counters on {this}";
}
private AstralCornucopiaManaEffect(final AstralCornucopiaManaEffect effect) {
super(effect);
this.computedMana = effect.computedMana.copy();
}
@Override
public AstralCornucopiaManaEffect copy() {
return new AstralCornucopiaManaEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
checkToFirePossibleEvents(getMana(game, source), game, source);
controller.getManaPool().addMana(getMana(game, source), game, source);
return true;
}
@Override
public Mana produceMana(boolean netMana, Game game, Ability source) {
Mana mana = new Mana();
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
if (sourcePermanent == null) {
return mana;
}
sourcePermanent.addCounters(CounterType.CHARGE.createInstance(), source, game);
game.applyEffects();
int counters = sourcePermanent.getCounters(game).getCount(CounterType.CHARGE);
if (counters <= 0) {
return mana;
}
if (netMana) {
return new Mana(0, 0, 0, 0, 0, 0, counters, 0);
}
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return mana;
}
ChoiceColor choice = new ChoiceColor();
choice.setMessage("Choose a color to add mana of that color");
if (!controller.choose(outcome, choice, game)) {
return mana;
}
if (choice.getChoice() == null) {
return mana;
}
String color = choice.getChoice();
switch (color) {
case "Red":
mana.setRed(counters);
break;
case "Blue":
mana.setBlue(counters);
break;
case "White":
mana.setWhite(counters);
break;
case "Black":
mana.setBlack(counters);
break;
case "Green":
mana.setGreen(counters);
break;
}
return mana;
}
}

View file

@ -74,7 +74,7 @@ class HateMirageEffect extends OneShotEffect {
.flatMap(Collection::stream)
.forEach(uuid -> {
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(
source.getId(), null, true
source.getControllerId(), null, true
);
effect.setTargetPointer(new FixedTarget(uuid, game));
effect.apply(game, source);

View file

@ -95,8 +95,8 @@ class JeskaiInfiltratorEffect extends OneShotEffect {
Ability newSource = source.copy();
newSource.setWorksFaceDown(true);
while (!exileZone.isEmpty()) {
Card card = exileZone.getRandom(game);
//the Set will mimic the Shuffling
exileZone.getCards(game).forEach(card -> {
ManaCosts manaCosts = null;
if (card.isCreature()) {
manaCosts = card.getSpellAbility().getManaCosts();
@ -106,7 +106,7 @@ class JeskaiInfiltratorEffect extends OneShotEffect {
}
MageObjectReference objectReference = new MageObjectReference(card.getId(), card.getZoneChangeCounter(game) + 1, game);
game.addEffect(new BecomesFaceDownCreatureEffect(manaCosts, objectReference, Duration.Custom, FaceDownType.MANIFESTED), newSource);
}
});
controller.moveCards(exileZone.getCards(game), Zone.BATTLEFIELD, source, game, false, true, false, null);
return true;
}

View file

@ -67,7 +67,7 @@ class LeadershipVacuumEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
Player player = game.getPlayer(source.getFirstTarget());
if (player == null) {
return false;
}

View file

@ -65,7 +65,7 @@ class RangerCaptainOfEosEffect extends ContinuousRuleModifyingEffectImpl {
RangerCaptainOfEosEffect() {
super(Duration.EndOfTurn, Outcome.Benefit);
staticText = "Your opponents can't noncreature cast spells this turn.";
staticText = "Your opponents can't cast noncreature spells this turn.";
}
private RangerCaptainOfEosEffect(final RangerCaptainOfEosEffect effect) {

View file

@ -0,0 +1,157 @@
package mage.cards.t;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.combat.CantBeBlockedByMoreThanOneSourceEffect;
import mage.abilities.effects.common.continuous.GainControlTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.common.FilterPlayerOrPlaneswalker;
import mage.filter.predicate.Predicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetPlayerOrPlaneswalker;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class TahngarthFirstMate extends CardImpl {
public TahngarthFirstMate(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{G}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.MINOTAUR);
this.subtype.add(SubType.WARRIOR);
this.power = new MageInt(5);
this.toughness = new MageInt(5);
// Tahngarth, First Mate can't be blocked by more than one creature.
this.addAbility(new SimpleStaticAbility(new CantBeBlockedByMoreThanOneSourceEffect()));
// Whenever an opponent attacks with one or more creatures, if Tahngarth is tapped, you may have that opponent gain control of Tahngarth until end of combat. If you do, choose a player or planeswalker that opponent is attacking. Tahngarth is attacking that player or planeswalker.
this.addAbility(new TahngarthFirstMateTriggeredAbility());
}
private TahngarthFirstMate(final TahngarthFirstMate card) {
super(card);
}
@Override
public TahngarthFirstMate copy() {
return new TahngarthFirstMate(this);
}
}
class TahngarthFirstMateTriggeredAbility extends TriggeredAbilityImpl {
TahngarthFirstMateTriggeredAbility() {
super(Zone.BATTLEFIELD, new TahngarthFirstMateEffect(), true);
}
private TahngarthFirstMateTriggeredAbility(final TahngarthFirstMateTriggeredAbility ability) {
super(ability);
}
@Override
public TahngarthFirstMateTriggeredAbility copy() {
return new TahngarthFirstMateTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DECLARED_ATTACKERS;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return game.getOpponents(getControllerId()).contains(game.getActivePlayerId())
&& !game.getCombat().getAttackers().isEmpty();
}
@Override
public boolean checkInterveningIfClause(Game game) {
Permanent permanent = game.getPermanent(getSourceId());
return permanent != null && permanent.isTapped();
}
@Override
public String getRule() {
return "Whenever an opponent attacks with one or more creatures, " +
"if {this} is tapped, you may have that opponent gain control of {this} until end of combat. " +
"If you do, choose a player or planeswalker that opponent is attacking. " +
"{this} is attacking that player or planeswalker.";
}
}
class TahngarthFirstMateEffect extends OneShotEffect {
private static final FilterPlayerOrPlaneswalker filter
= new FilterPlayerOrPlaneswalker("player or planeswalker active player is attacking");
static {
filter.getPlayerFilter().add(TahngarthFirstMatePlayerPredicate.instance);
filter.getPermanentFilter().add(TahngarthFirstMatePermanentPredicate.instance);
}
TahngarthFirstMateEffect() {
super(Outcome.Benefit);
}
private TahngarthFirstMateEffect(final TahngarthFirstMateEffect effect) {
super(effect);
}
@Override
public TahngarthFirstMateEffect copy() {
return new TahngarthFirstMateEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Player player = game.getPlayer(game.getActivePlayerId());
Permanent permanent = game.getPermanent(source.getSourceId());
if (controller == null || player == null || permanent == null) {
return false;
}
TargetPlayerOrPlaneswalker target = new TargetPlayerOrPlaneswalker(filter);
target.setNotTarget(true);
if (!controller.choose(outcome, target, source.getSourceId(), game)) {
return false;
}
ContinuousEffect effect = new GainControlTargetEffect(Duration.EndOfCombat, player.getId());
effect.setTargetPointer(new FixedTarget(permanent, game));
game.addEffect(effect, source);
game.applyEffects();
return game.getCombat().addAttackerToCombat(permanent.getId(), target.getFirstTarget(), game);
}
}
enum TahngarthFirstMatePlayerPredicate implements Predicate<Player> {
instance;
@Override
public boolean apply(Player input, Game game) {
return game.getCombat().getDefenders().contains(input.getId());
}
}
enum TahngarthFirstMatePermanentPredicate implements Predicate<Permanent> {
instance;
@Override
public boolean apply(Permanent input, Game game) {
return game.getCombat().getDefenders().contains(input.getId());
}
}

View file

@ -0,0 +1,90 @@
package mage.cards.w;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.UntapEnchantedEffect;
import mage.abilities.effects.common.continuous.GainControlTargetEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.TargetPermanent;
import mage.target.common.TargetLandPermanent;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class Wellspring extends CardImpl {
public Wellspring(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}{W}");
this.subtype.add(SubType.AURA);
// Enchant land
TargetPermanent auraTarget = new TargetLandPermanent();
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
Ability ability = new EnchantAbility(auraTarget.getTargetName());
this.addAbility(ability);
// When Wellspring enters the battlefield, gain control of enchanted land until end of turn.
this.addAbility(new EntersBattlefieldTriggeredAbility(
new WellspringEffect("gain control of enchanted land until end of turn")
));
// At the beginning of your upkeep, untap enchanted land. You gain control of that land until end of turn.
ability = new BeginningOfUpkeepTriggeredAbility(
new UntapEnchantedEffect().setText("untap enchanted land."), TargetController.YOU, false
);
ability.addEffect(new WellspringEffect("You gain control of that land until end of turn"));
this.addAbility(ability);
}
private Wellspring(final Wellspring card) {
super(card);
}
@Override
public Wellspring copy() {
return new Wellspring(this);
}
}
class WellspringEffect extends OneShotEffect {
WellspringEffect(String text) {
super(Outcome.Benefit);
staticText = text;
}
private WellspringEffect(final WellspringEffect effect) {
super(effect);
}
@Override
public WellspringEffect copy() {
return new WellspringEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
if (permanent == null) {
return false;
}
ContinuousEffect effect = new GainControlTargetEffect(Duration.EndOfTurn);
effect.setTargetPointer(new FixedTarget(permanent.getAttachedTo(), game));
game.addEffect(effect, source);
return true;
}
}

View file

@ -0,0 +1,113 @@
package mage.cards.w;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.meta.OrTriggeredAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.TargetPlayer;
import mage.target.common.TargetCardInGraveyard;
import org.apache.log4j.Logger;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class WildfireDevils extends CardImpl {
public WildfireDevils(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}");
this.subtype.add(SubType.DEVIL);
this.power = new MageInt(4);
this.toughness = new MageInt(2);
// When Wildfire Devils enters the battlefield and at the beginning of your upkeep, choose a player at random. That player exiles an instant or sorcery card from their graveyard. Copy that card. You may cast the copy without paying its mana cost.
this.addAbility(new OrTriggeredAbility(
Zone.BATTLEFIELD, new WildfireDevilsEffect(), false,
"When {this} enters the battlefield and at the beginning of your upkeep, ",
new EntersBattlefieldTriggeredAbility(null, false),
new BeginningOfUpkeepTriggeredAbility(null, TargetController.YOU, false)
));
}
private WildfireDevils(final WildfireDevils card) {
super(card);
}
@Override
public WildfireDevils copy() {
return new WildfireDevils(this);
}
}
class WildfireDevilsEffect extends OneShotEffect {
WildfireDevilsEffect() {
super(Outcome.Benefit);
staticText = "choose a player at random. That player exiles an instant or sorcery card from their graveyard. " +
"Copy that card. You may cast the copy without paying its mana cost.";
}
private WildfireDevilsEffect(final WildfireDevilsEffect effect) {
super(effect);
}
@Override
public WildfireDevilsEffect copy() {
return new WildfireDevilsEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
TargetPlayer targetPlayer = new TargetPlayer();
targetPlayer.setRandom(true);
targetPlayer.setNotTarget(true);
if (!controller.choose(outcome, targetPlayer, source.getSourceId(), game)) {
return false;
}
Player player = game.getPlayer(targetPlayer.getFirstTarget());
if (player == null || player.getGraveyard().getCards(game).stream().noneMatch(Card::isInstantOrSorcery)) {
return false;
}
TargetCard targetCard = new TargetCardInGraveyard(StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY);
targetCard.setNotTarget(true);
if (!player.choose(outcome, player.getGraveyard(), targetCard, game)) {
return false;
}
Card card = game.getCard(targetCard.getFirstTarget());
player.moveCards(card, Zone.EXILED, source, game);
if (game.getState().getZone(card.getId()) != Zone.EXILED) {
return false;
}
Card copiedCard = game.copyCard(card, source, controller.getId());
if (copiedCard == null) {
return false;
}
game.getExile().add(source.getSourceId(), "", card);
game.setZone(copiedCard.getId(), Zone.EXILED);
if (!controller.chooseUse(outcome, "Cast the exiled card?", source, game)) {
return true;
}
if (copiedCard.getSpellAbility() == null) {
Logger.getLogger(WildfireDevilsEffect.class).error("Wildfire Devils: spell ability == null " + copiedCard.getName());
return true;
}
return controller.cast(copiedCard.getSpellAbility(), game, true, new MageObjectReference(source.getSourceObject(game), game));
}
}

View file

@ -90,6 +90,7 @@ public final class Commander2019Edition extends ExpansionSet {
cards.add(new SetCardInfo("Elemental Bond", 163, Rarity.UNCOMMON, mage.cards.e.ElementalBond.class));
cards.add(new SetCardInfo("Elsha of the Infinite", 40, Rarity.MYTHIC, mage.cards.e.ElshaOfTheInfinite.class));
cards.add(new SetCardInfo("Emmara Tandris", 191, Rarity.RARE, mage.cards.e.EmmaraTandris.class));
cards.add(new SetCardInfo("Empowered Autogenerator", 54, Rarity.RARE, mage.cards.e.EmpoweredAutogenerator.class));
cards.add(new SetCardInfo("Evolving Wilds", 241, Rarity.COMMON, mage.cards.e.EvolvingWilds.class));
cards.add(new SetCardInfo("Exotic Orchard", 242, Rarity.RARE, mage.cards.e.ExoticOrchard.class));
cards.add(new SetCardInfo("Explore", 164, Rarity.COMMON, mage.cards.e.Explore.class));
@ -265,6 +266,7 @@ public final class Commander2019Edition extends ExpansionSet {
cards.add(new SetCardInfo("Sunken Hollow", 278, Rarity.RARE, mage.cards.s.SunkenHollow.class));
cards.add(new SetCardInfo("Swamp", 294, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Swiftwater Cliffs", 279, Rarity.COMMON, mage.cards.s.SwiftwaterCliffs.class));
cards.add(new SetCardInfo("Tahngarth, First Mate", 50, Rarity.RARE, mage.cards.t.TahngarthFirstMate.class));
cards.add(new SetCardInfo("Talrand, Sky Summoner", 97, Rarity.RARE, mage.cards.t.TalrandSkySummoner.class));
cards.add(new SetCardInfo("Tectonic Hellion", 29, Rarity.RARE, mage.cards.t.TectonicHellion.class));
cards.add(new SetCardInfo("Temple of the False God", 280, Rarity.UNCOMMON, mage.cards.t.TempleOfTheFalseGod.class));
@ -295,6 +297,7 @@ public final class Commander2019Edition extends ExpansionSet {
cards.add(new SetCardInfo("Vraska the Unseen", 207, Rarity.MYTHIC, mage.cards.v.VraskaTheUnseen.class));
cards.add(new SetCardInfo("Warstorm Surge", 155, Rarity.RARE, mage.cards.w.WarstormSurge.class));
cards.add(new SetCardInfo("Wayfaring Temple", 208, Rarity.RARE, mage.cards.w.WayfaringTemple.class));
cards.add(new SetCardInfo("Wildfire Devils", 30, Rarity.RARE, mage.cards.w.WildfireDevils.class));
cards.add(new SetCardInfo("Willbender", 102, Rarity.UNCOMMON, mage.cards.w.Willbender.class));
cards.add(new SetCardInfo("Wind-Scarred Crag", 285, Rarity.COMMON, mage.cards.w.WindScarredCrag.class));
cards.add(new SetCardInfo("Wingmate Roc", 78, Rarity.MYTHIC, mage.cards.w.WingmateRoc.class));

View file

@ -329,6 +329,7 @@ public final class Mirage extends ExpansionSet {
cards.add(new SetCardInfo("Ward of Lights", 47, Rarity.COMMON, mage.cards.w.WardOfLights.class));
cards.add(new SetCardInfo("Warping Wurm", 287, Rarity.RARE, mage.cards.w.WarpingWurm.class));
cards.add(new SetCardInfo("Wave Elemental", 102, Rarity.UNCOMMON, mage.cards.w.WaveElemental.class));
cards.add(new SetCardInfo("Wellspring", 288, Rarity.RARE, mage.cards.w.Wellspring.class));
cards.add(new SetCardInfo("Wild Elephant", 254, Rarity.COMMON, mage.cards.w.WildElephant.class));
cards.add(new SetCardInfo("Wildfire Emissary", 203, Rarity.UNCOMMON, mage.cards.w.WildfireEmissary.class));
cards.add(new SetCardInfo("Windreaper Falcon", 289, Rarity.UNCOMMON, mage.cards.w.WindreaperFalcon.class));