mirror of
https://github.com/correl/mage.git
synced 2024-12-24 11:50:45 +00:00
Merge origin/master
This commit is contained in:
commit
f30c0a7054
12 changed files with 274 additions and 232 deletions
|
@ -28,6 +28,7 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.CreatureEntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect;
|
||||
|
@ -39,18 +40,23 @@ import mage.constants.Duration;
|
|||
import mage.constants.SubType;
|
||||
import mage.game.permanent.token.TokenImpl;
|
||||
import mage.game.permanent.token.Token;
|
||||
import mage.game.permanent.token.custom.CreatureToken;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Loki
|
||||
*/
|
||||
public class AngelsTomb extends CardImpl {
|
||||
|
||||
public AngelsTomb(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
|
||||
|
||||
// Whenever a creature enters the battlefield under your control, you may have Angel's Tomb become a 3/3 white Angel artifact creature with flying until end of turn.
|
||||
this.addAbility(new CreatureEntersBattlefieldTriggeredAbility(new BecomesCreatureSourceEffect(new AngelTombToken(), "", Duration.EndOfTurn), true));
|
||||
this.addAbility(new CreatureEntersBattlefieldTriggeredAbility(new BecomesCreatureSourceEffect(
|
||||
new CreatureToken(3, 3, "3/3 white Angel artifact creature with flying")
|
||||
.withColor("W")
|
||||
.withSubType(SubType.ANGEL)
|
||||
.withAbility(FlyingAbility.getInstance()),
|
||||
"", Duration.EndOfTurn), true));
|
||||
}
|
||||
|
||||
public AngelsTomb(final AngelsTomb card) {
|
||||
|
@ -61,26 +67,4 @@ public class AngelsTomb extends CardImpl {
|
|||
public AngelsTomb copy() {
|
||||
return new AngelsTomb(this);
|
||||
}
|
||||
}
|
||||
|
||||
class AngelTombToken extends TokenImpl {
|
||||
|
||||
public AngelTombToken() {
|
||||
super("", "3/3 white Angel artifact creature with flying");
|
||||
cardType.add(CardType.ARTIFACT);
|
||||
cardType.add(CardType.CREATURE);
|
||||
color.setWhite(true);
|
||||
|
||||
subtype.add(SubType.ANGEL);
|
||||
power = new MageInt(3);
|
||||
toughness = new MageInt(3);
|
||||
addAbility(FlyingAbility.getInstance());
|
||||
}
|
||||
public AngelTombToken(final AngelTombToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
public AngelTombToken copy() {
|
||||
return new AngelTombToken(this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,6 +28,7 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
|
@ -43,23 +44,28 @@ import mage.constants.SubType;
|
|||
import mage.constants.Zone;
|
||||
import mage.game.permanent.token.TokenImpl;
|
||||
import mage.game.permanent.token.Token;
|
||||
import mage.game.permanent.token.custom.CreatureToken;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fireshoes
|
||||
*/
|
||||
public class AtarkaMonument extends CardImpl {
|
||||
|
||||
public AtarkaMonument(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
|
||||
|
||||
// {T}: Add {R} or {G}.
|
||||
this.addAbility(new RedManaAbility());
|
||||
this.addAbility(new GreenManaAbility());
|
||||
|
||||
|
||||
// {4}{R}{G}: Atarka Monument becomes a 4/4 red and green Dragon artifact creature with flying until end of turn.
|
||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect
|
||||
(new AtarkaMonumentToken(), "", Duration.EndOfTurn), new ManaCostsImpl("{4}{R}{G}")));
|
||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(
|
||||
new CreatureToken(4, 4, "4/4 red and green Dragon artifact creature with flying")
|
||||
.withColor("RG")
|
||||
.withSubType(SubType.DRAGON)
|
||||
.withType(CardType.ARTIFACT)
|
||||
.withAbility(FlyingAbility.getInstance()),
|
||||
"", Duration.EndOfTurn), new ManaCostsImpl("{4}{R}{G}")));
|
||||
}
|
||||
|
||||
public AtarkaMonument(final AtarkaMonument card) {
|
||||
|
@ -70,25 +76,4 @@ public class AtarkaMonument extends CardImpl {
|
|||
public AtarkaMonument copy() {
|
||||
return new AtarkaMonument(this);
|
||||
}
|
||||
|
||||
private static class AtarkaMonumentToken extends TokenImpl {
|
||||
AtarkaMonumentToken() {
|
||||
super("", "4/4 red and green Dragon artifact creature with flying");
|
||||
this.cardType.add(CardType.ARTIFACT);
|
||||
this.cardType.add(CardType.CREATURE);
|
||||
this.color.setRed(true);
|
||||
this.color.setGreen(true);
|
||||
this.subtype.add(SubType.DRAGON);
|
||||
this.power = new MageInt(4);
|
||||
this.toughness = new MageInt(4);
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
}
|
||||
public AtarkaMonumentToken(final AtarkaMonumentToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
public AtarkaMonumentToken copy() {
|
||||
return new AtarkaMonumentToken(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
|
@ -43,6 +44,7 @@ import mage.constants.SubType;
|
|||
import mage.constants.Zone;
|
||||
import mage.game.permanent.token.TokenImpl;
|
||||
import mage.game.permanent.token.Token;
|
||||
import mage.game.permanent.token.custom.CreatureToken;
|
||||
|
||||
/**
|
||||
* @author LevelX2
|
||||
|
@ -50,14 +52,20 @@ import mage.game.permanent.token.Token;
|
|||
public class AzoriusKeyrune extends CardImpl {
|
||||
|
||||
public AzoriusKeyrune(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
|
||||
|
||||
// {T}: Add {W} or {U}.
|
||||
this.addAbility(new WhiteManaAbility());
|
||||
this.addAbility(new BlueManaAbility());
|
||||
|
||||
// {W}{U}: Azorius Keyrune becomes a 2/2 white and blue Bird artifact creature with flying until end of turn.
|
||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(new AzoriusKeyruneToken(), "", Duration.EndOfTurn), new ManaCostsImpl("{W}{U}")));
|
||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(
|
||||
new CreatureToken(2, 2, "2/2 white and blue Bird artifact creature with flying")
|
||||
.withColor("WU")
|
||||
.withSubType(SubType.BIRD)
|
||||
.withType(CardType.ARTIFACT)
|
||||
.withAbility(FlyingAbility.getInstance()),
|
||||
"", Duration.EndOfTurn), new ManaCostsImpl("{W}{U}")));
|
||||
}
|
||||
|
||||
public AzoriusKeyrune(final AzoriusKeyrune card) {
|
||||
|
@ -68,25 +76,4 @@ public class AzoriusKeyrune extends CardImpl {
|
|||
public AzoriusKeyrune copy() {
|
||||
return new AzoriusKeyrune(this);
|
||||
}
|
||||
|
||||
private static class AzoriusKeyruneToken extends TokenImpl {
|
||||
AzoriusKeyruneToken() {
|
||||
super("", "2/2 white and blue Bird artifact creature with flying");
|
||||
cardType.add(CardType.ARTIFACT);
|
||||
cardType.add(CardType.CREATURE);
|
||||
color.setWhite(true);
|
||||
color.setBlue(true);
|
||||
this.subtype.add(SubType.BIRD);
|
||||
power = new MageInt(2);
|
||||
toughness = new MageInt(2);
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
}
|
||||
public AzoriusKeyruneToken(final AzoriusKeyruneToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
public AzoriusKeyruneToken copy() {
|
||||
return new AzoriusKeyruneToken(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
|
@ -48,6 +49,7 @@ import mage.filter.FilterPermanent;
|
|||
import mage.filter.predicate.mageobject.SubtypePredicate;
|
||||
import mage.game.permanent.token.TokenImpl;
|
||||
import mage.game.permanent.token.Token;
|
||||
import mage.game.permanent.token.custom.CreatureToken;
|
||||
import mage.target.TargetPermanent;
|
||||
|
||||
/**
|
||||
|
@ -62,14 +64,19 @@ public class BlinkmothNexus extends CardImpl {
|
|||
}
|
||||
|
||||
public BlinkmothNexus(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.LAND},null);
|
||||
|
||||
super(ownerId, setInfo, new CardType[]{CardType.LAND}, null);
|
||||
|
||||
// {T}: Add {C}to your mana pool.
|
||||
this.addAbility(new ColorlessManaAbility());
|
||||
|
||||
|
||||
// {1}: Blinkmoth Nexus becomes a 1/1 Blinkmoth artifact creature with flying until end of turn. It's still a land.
|
||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(new BlinkmothNexusToken(), "land", Duration.EndOfTurn), new GenericManaCost(1)));
|
||||
|
||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(
|
||||
new CreatureToken(1, 1, "1/1 Blinkmoth artifact creature with flying")
|
||||
.withSubType(SubType.BLINKMOTH)
|
||||
.withType(CardType.ARTIFACT)
|
||||
.withAbility(FlyingAbility.getInstance()),
|
||||
"land", Duration.EndOfTurn), new GenericManaCost(1)));
|
||||
|
||||
// {1}, {T}: Target Blinkmoth creature gets +1/+1 until end of turn.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(1, 1, Duration.EndOfTurn), new GenericManaCost(1));
|
||||
ability.addCost(new TapSourceCost());
|
||||
|
@ -88,22 +95,3 @@ public class BlinkmothNexus extends CardImpl {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
class BlinkmothNexusToken extends TokenImpl {
|
||||
public BlinkmothNexusToken() {
|
||||
super("Blinkmoth", "1/1 Blinkmoth artifact creature with flying");
|
||||
cardType.add(CardType.ARTIFACT);
|
||||
cardType.add(CardType.CREATURE);
|
||||
this.subtype.add(SubType.BLINKMOTH);
|
||||
power = new MageInt(1);
|
||||
toughness = new MageInt(1);
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
}
|
||||
public BlinkmothNexusToken(final BlinkmothNexusToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
public BlinkmothNexusToken copy() {
|
||||
return new BlinkmothNexusToken(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
|
@ -43,22 +44,28 @@ import mage.constants.SubType;
|
|||
import mage.constants.Zone;
|
||||
import mage.game.permanent.token.TokenImpl;
|
||||
import mage.game.permanent.token.Token;
|
||||
import mage.game.permanent.token.custom.CreatureToken;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class BorosKeyrune extends CardImpl {
|
||||
|
||||
public BorosKeyrune(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
|
||||
|
||||
// {T}: Add {R} or {W}.
|
||||
this.addAbility(new RedManaAbility());
|
||||
this.addAbility(new WhiteManaAbility());
|
||||
|
||||
// {R}{W}: Boros Keyrune becomes a 1/1 red and white Soldier artifact creature with double strike until end of turn.
|
||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(new BorosKeyruneToken(), "", Duration.EndOfTurn), new ManaCostsImpl("{R}{W}")));
|
||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(
|
||||
new CreatureToken(1, 1, "1/1 red and white Soldier artifact creature with double strike")
|
||||
.withColor("RW")
|
||||
.withSubType(SubType.SOLDIER)
|
||||
.withType(CardType.ARTIFACT)
|
||||
.withAbility(DoubleStrikeAbility.getInstance()),
|
||||
"", Duration.EndOfTurn), new ManaCostsImpl("{R}{W}")));
|
||||
}
|
||||
|
||||
public BorosKeyrune(final BorosKeyrune card) {
|
||||
|
@ -69,25 +76,4 @@ public class BorosKeyrune extends CardImpl {
|
|||
public BorosKeyrune copy() {
|
||||
return new BorosKeyrune(this);
|
||||
}
|
||||
|
||||
private static class BorosKeyruneToken extends TokenImpl {
|
||||
BorosKeyruneToken() {
|
||||
super("Soldier", "1/1 red and white Soldier artifact creature with double strike");
|
||||
cardType.add(CardType.ARTIFACT);
|
||||
cardType.add(CardType.CREATURE);
|
||||
color.setRed(true);
|
||||
color.setWhite(true);
|
||||
subtype.add(SubType.SOLDIER);
|
||||
power = new MageInt(1);
|
||||
toughness = new MageInt(1);
|
||||
this.addAbility(DoubleStrikeAbility.getInstance());
|
||||
}
|
||||
public BorosKeyruneToken(final BorosKeyruneToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
public BorosKeyruneToken copy() {
|
||||
return new BorosKeyruneToken(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
package mage.cards.c;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.EntersBattlefieldTappedAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
|
@ -45,20 +46,31 @@ import mage.constants.Duration;
|
|||
import mage.constants.Zone;
|
||||
import mage.game.permanent.token.TokenImpl;
|
||||
import mage.game.permanent.token.Token;
|
||||
import mage.game.permanent.token.custom.CreatureToken;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class CelestialColonnade extends CardImpl {
|
||||
|
||||
public CelestialColonnade(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.LAND},null);
|
||||
super(ownerId, setInfo, new CardType[]{CardType.LAND}, null);
|
||||
|
||||
// Celestial Colonnade enters the battlefield tapped.
|
||||
this.addAbility(new EntersBattlefieldTappedAbility());
|
||||
|
||||
// {T}: Add {W} or {U]
|
||||
this.addAbility(new BlueManaAbility());
|
||||
this.addAbility(new WhiteManaAbility());
|
||||
|
||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(new CelestialColonnadeToken(), "land", Duration.EndOfTurn), new ManaCostsImpl("{3}{W}{U}")));
|
||||
// {3}{W}{U}: Until end of turn, Celestial Colonnade becomes a 4/4 white and blue Elemental creature with flying and vigilance. It’s still a land.
|
||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(
|
||||
new CreatureToken(4, 4, "4/4 white and blue Elemental creature with flying and vigilance")
|
||||
.withColor("WU")
|
||||
.withSubType(SubType.ELEMENTAL)
|
||||
.withAbility(FlyingAbility.getInstance())
|
||||
.withAbility(VigilanceAbility.getInstance()),
|
||||
"land", Duration.EndOfTurn), new ManaCostsImpl("{3}{W}{U}")));
|
||||
}
|
||||
|
||||
public CelestialColonnade(final CelestialColonnade card) {
|
||||
|
@ -70,27 +82,4 @@ public class CelestialColonnade extends CardImpl {
|
|||
return new CelestialColonnade(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class CelestialColonnadeToken extends TokenImpl {
|
||||
|
||||
public CelestialColonnadeToken() {
|
||||
super("", "4/4 white and blue Elemental creature with flying and vigilance");
|
||||
cardType.add(CardType.CREATURE);
|
||||
subtype.add(SubType.ELEMENTAL);
|
||||
color.setBlue(true);
|
||||
color.setWhite(true);
|
||||
power = new MageInt(4);
|
||||
toughness = new MageInt(4);
|
||||
addAbility(FlyingAbility.getInstance());
|
||||
addAbility(VigilanceAbility.getInstance());
|
||||
}
|
||||
public CelestialColonnadeToken(final CelestialColonnadeToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
public CelestialColonnadeToken copy() {
|
||||
return new CelestialColonnadeToken(this);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -28,6 +28,7 @@
|
|||
package mage.cards.c;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.common.SpellCastOpponentTriggeredAbility;
|
||||
|
@ -48,11 +49,10 @@ import mage.filter.predicate.Predicates;
|
|||
import mage.filter.predicate.mageobject.CardTypePredicate;
|
||||
import mage.game.permanent.token.TokenImpl;
|
||||
import mage.game.permanent.token.Token;
|
||||
|
||||
import mage.game.permanent.token.custom.CreatureToken;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Pete Rossi
|
||||
*/
|
||||
public class ChimericEgg extends CardImpl {
|
||||
|
@ -65,13 +65,17 @@ public class ChimericEgg extends CardImpl {
|
|||
|
||||
public ChimericEgg(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
|
||||
|
||||
|
||||
// Whenever an opponent casts a nonartifact spell, put a charge counter on Chimeric Egg.
|
||||
this.addAbility(new SpellCastOpponentTriggeredAbility(new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), nonArtifactFilter, false));
|
||||
|
||||
// Remove three charge counters from Chimeric Egg: Chimeric Egg becomes a 6/6 Construct artifact creature with trample until end of turn.
|
||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect
|
||||
(new ChimericEggToken(), "", Duration.EndOfTurn), new RemoveCountersSourceCost(new Counter(CounterType.CHARGE.getName(), 3))));
|
||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(
|
||||
new CreatureToken(6, 6, "6/6 Construct artifact creature with trample")
|
||||
.withSubType(SubType.CONSTRUCT)
|
||||
.withType(CardType.ARTIFACT)
|
||||
.withAbility(TrampleAbility.getInstance()),
|
||||
"", Duration.EndOfTurn), new RemoveCountersSourceCost(new Counter(CounterType.CHARGE.getName(), 3))));
|
||||
}
|
||||
|
||||
public ChimericEgg(final ChimericEgg card) {
|
||||
|
@ -82,23 +86,4 @@ public class ChimericEgg extends CardImpl {
|
|||
public ChimericEgg copy() {
|
||||
return new ChimericEgg(this);
|
||||
}
|
||||
|
||||
private static class ChimericEggToken extends TokenImpl {
|
||||
ChimericEggToken() {
|
||||
super("", "6/6 Construct artifact creature with trample");
|
||||
cardType.add(CardType.ARTIFACT);
|
||||
cardType.add(CardType.CREATURE);
|
||||
this.subtype.add(SubType.CONSTRUCT);
|
||||
power = new MageInt(6);
|
||||
toughness = new MageInt(6);
|
||||
this.addAbility(TrampleAbility.getInstance());
|
||||
}
|
||||
public ChimericEggToken(final ChimericEggToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
public ChimericEggToken copy() {
|
||||
return new ChimericEggToken(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
package mage.cards.c;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
|
@ -43,19 +44,23 @@ import mage.constants.Zone;
|
|||
import mage.filter.common.FilterControlledLandPermanent;
|
||||
import mage.game.permanent.token.TokenImpl;
|
||||
import mage.game.permanent.token.Token;
|
||||
import mage.game.permanent.token.custom.CreatureToken;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class ChimericIdol extends CardImpl {
|
||||
|
||||
public ChimericIdol(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
|
||||
|
||||
// {0}: Tap all lands you control. Chimeric Idol becomes a 3/3 Turtle artifact creature until end of turn.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapAllEffect(new FilterControlledLandPermanent("lands you control")), new ManaCostsImpl("{0}"));
|
||||
ability.addEffect(new BecomesCreatureSourceEffect(new ChimericIdolToken(), "", Duration.EndOfTurn));
|
||||
ability.addEffect(new BecomesCreatureSourceEffect(
|
||||
new CreatureToken(3, 3, "3/3 Turtle artifact creature")
|
||||
.withSubType(SubType.TURTLE)
|
||||
.withType(CardType.ARTIFACT),
|
||||
"", Duration.EndOfTurn));
|
||||
this.addAbility(ability);
|
||||
|
||||
}
|
||||
|
@ -68,23 +73,4 @@ public class ChimericIdol extends CardImpl {
|
|||
public ChimericIdol copy() {
|
||||
return new ChimericIdol(this);
|
||||
}
|
||||
}
|
||||
|
||||
class ChimericIdolToken extends TokenImpl {
|
||||
|
||||
public ChimericIdolToken() {
|
||||
super("Turtle", "3/3 Turtle artifact creature token");
|
||||
cardType.add(CardType.ARTIFACT);
|
||||
cardType.add(CardType.CREATURE);
|
||||
subtype.add(SubType.TURTLE);
|
||||
power = new MageInt(3);
|
||||
toughness = new MageInt(3);
|
||||
}
|
||||
public ChimericIdolToken(final ChimericIdolToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
public ChimericIdolToken copy() {
|
||||
return new ChimericIdolToken(this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,6 +28,7 @@
|
|||
package mage.cards.c;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.EntersBattlefieldAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
|
@ -46,6 +47,7 @@ import mage.constants.Zone;
|
|||
import mage.counters.CounterType;
|
||||
import mage.game.permanent.token.TokenImpl;
|
||||
import mage.game.permanent.token.Token;
|
||||
import mage.game.permanent.token.custom.CreatureToken;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
@ -53,14 +55,19 @@ import mage.game.permanent.token.Token;
|
|||
public class ChimericMass extends CardImpl {
|
||||
|
||||
public ChimericMass(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{X}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{X}");
|
||||
|
||||
// Chimeric Mass enters the battlefield with X charge counters on it.
|
||||
this.addAbility(new EntersBattlefieldAbility(new EntersBattlefieldWithXCountersEffect(CounterType.CHARGE.createInstance())));
|
||||
|
||||
// {1}: Until end of turn, Chimeric Mass becomes a Construct artifact creature with "This creature's power and toughness are each equal to the number of charge counters on it."
|
||||
// set to character defining to prevent setting P/T again to 0 becuase already set by CDA of the token
|
||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(new ChimericMassToken(), "", Duration.EndOfTurn, false, true), new GenericManaCost(1)));
|
||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(
|
||||
new CreatureToken(0, 0, "Construct artifact creature with \"This creature's power and toughness are each equal to the number of charge counters on it.\"")
|
||||
.withType(CardType.ARTIFACT)
|
||||
.withSubType(SubType.CONSTRUCT)
|
||||
.withAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SetPowerToughnessSourceEffect(new CountersSourceCount(CounterType.CHARGE), Duration.WhileOnBattlefield))),
|
||||
"", Duration.EndOfTurn, false, true), new GenericManaCost(1)));
|
||||
}
|
||||
|
||||
public ChimericMass(final ChimericMass card) {
|
||||
|
@ -72,23 +79,4 @@ public class ChimericMass extends CardImpl {
|
|||
return new ChimericMass(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ChimericMassToken extends TokenImpl {
|
||||
|
||||
public ChimericMassToken() {
|
||||
super("", "Construct artifact creature with \"This creature's power and toughness are each equal to the number of charge counters on it.\"");
|
||||
cardType.add(CardType.CREATURE);
|
||||
subtype.add(SubType.CONSTRUCT);
|
||||
power = new MageInt(0);
|
||||
toughness = new MageInt(0);
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SetPowerToughnessSourceEffect(new CountersSourceCount(CounterType.CHARGE), Duration.WhileOnBattlefield)));
|
||||
}
|
||||
public ChimericMassToken(final ChimericMassToken token) {
|
||||
super(token);
|
||||
}
|
||||
|
||||
public ChimericMassToken copy() {
|
||||
return new ChimericMassToken(this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -41,6 +41,17 @@
|
|||
<type>jar</type>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.reflections</groupId>
|
||||
<artifactId>reflections</artifactId>
|
||||
<version>0.9.11</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mage</groupId>
|
||||
<artifactId>mage-client</artifactId>
|
||||
<version>1.4.29</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -1,15 +1,25 @@
|
|||
package mage.verify;
|
||||
|
||||
import javassist.bytecode.SignatureAttribute;
|
||||
import mage.ObjectColor;
|
||||
import mage.cards.*;
|
||||
import mage.cards.basiclands.BasicLand;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.SuperType;
|
||||
import mage.game.permanent.token.Token;
|
||||
import mage.game.permanent.token.TokenImpl;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.mage.plugins.card.images.CardDownloadData;
|
||||
import org.mage.plugins.card.images.DownloadPictures;
|
||||
import org.reflections.Reflections;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
|
@ -19,6 +29,10 @@ import java.util.regex.Matcher;
|
|||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class VerifyCardDataTest {
|
||||
|
||||
// right now this is very noisy, and not useful enough to make any assertions on
|
||||
|
@ -241,6 +255,139 @@ public class VerifyCardDataTest {
|
|||
}
|
||||
}
|
||||
|
||||
private Object createNewObject(Class<?> clazz) {
|
||||
try {
|
||||
Constructor<?> cons = clazz.getConstructor();
|
||||
return cons.newInstance();
|
||||
} catch (InvocationTargetException ex) {
|
||||
Throwable e = ex.getTargetException();
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void printMessages(Collection<String> list) {
|
||||
for (String mes : list) {
|
||||
System.out.println(mes);
|
||||
}
|
||||
}
|
||||
|
||||
private String extractShortClass(Class<? extends TokenImpl> tokenClass) {
|
||||
String origin = tokenClass.getName();
|
||||
if (origin.contains("$")) {
|
||||
// inner classes, example: mage.cards.f.FigureOfDestiny$FigureOfDestinyToken3
|
||||
return origin.replaceAll(".+\\$(.+)", "$1");
|
||||
} else {
|
||||
// public classes, example: mage.game.permanent.token.FigureOfDestinyToken
|
||||
return origin.replaceAll(".+\\.(.+)", "$1");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore // TODO: enable test after massive token fixes
|
||||
public void checkMissingTokenData() {
|
||||
|
||||
Collection<String> errorsList = new ArrayList<>();
|
||||
Collection<String> warningsList = new ArrayList<>();
|
||||
|
||||
// all tokens must be stores in card-pictures-tok.txt (if not then viewer and image downloader are missing token images)
|
||||
// https://github.com/ronmamo/reflections
|
||||
Reflections reflections = new Reflections("mage.");
|
||||
Set<Class<? extends TokenImpl>> tokenClassesList = reflections.getSubTypesOf(TokenImpl.class);
|
||||
|
||||
// xmage tokens
|
||||
Set<Class<? extends TokenImpl>> privateTokens = new HashSet<>();
|
||||
Set<Class<? extends TokenImpl>> publicTokens = new HashSet<>();
|
||||
for (Class<? extends TokenImpl> tokenClass : tokenClassesList) {
|
||||
if (Modifier.isPublic(tokenClass.getModifiers())) {
|
||||
publicTokens.add(tokenClass);
|
||||
} else {
|
||||
privateTokens.add(tokenClass);
|
||||
}
|
||||
}
|
||||
|
||||
// tok file's data
|
||||
ArrayList<CardDownloadData> tokFileTokens = DownloadPictures.getTokenCardUrls();
|
||||
LinkedHashMap<String, String> tokDataClassesIndex = new LinkedHashMap<>();
|
||||
LinkedHashMap<String, String> tokDataNamesIndex = new LinkedHashMap<>();
|
||||
for (CardDownloadData tokData : tokFileTokens) {
|
||||
|
||||
String searchName;
|
||||
String setsList;
|
||||
|
||||
// by class
|
||||
searchName = tokData.getTokenClassName();
|
||||
setsList = tokDataClassesIndex.getOrDefault(searchName, "");
|
||||
if (!setsList.isEmpty()) {
|
||||
setsList += ",";
|
||||
}
|
||||
setsList += tokData.getSet();
|
||||
tokDataClassesIndex.put(searchName, setsList);
|
||||
|
||||
// by name
|
||||
searchName = tokData.getName();
|
||||
setsList = tokDataNamesIndex.getOrDefault(searchName, "");
|
||||
if (!setsList.isEmpty()) {
|
||||
setsList += ",";
|
||||
}
|
||||
setsList += tokData.getSet();
|
||||
tokDataNamesIndex.put(searchName, setsList);
|
||||
}
|
||||
|
||||
// 1. check token name convention
|
||||
for (Class<? extends TokenImpl> tokenClass : tokenClassesList) {
|
||||
if (!tokenClass.getName().endsWith("Token")) {
|
||||
String className = extractShortClass(tokenClass);
|
||||
warningsList.add("warning, token class must ends with Token: " + className + " from " + tokenClass.getName());
|
||||
}
|
||||
}
|
||||
|
||||
// 2. check store file for public
|
||||
for (Class<? extends TokenImpl> tokenClass : publicTokens) {
|
||||
String fullClass = tokenClass.getName();
|
||||
if (!fullClass.startsWith("mage.game.permanent.token.")) {
|
||||
String className = extractShortClass(tokenClass);
|
||||
errorsList.add("error, public token must stores in mage.game.permanent.token package: " + className + " from " + tokenClass.getName());
|
||||
}
|
||||
}
|
||||
|
||||
// 3. check private tokens (they aren't need at all)
|
||||
for (Class<? extends TokenImpl> tokenClass : privateTokens) {
|
||||
String className = extractShortClass(tokenClass);
|
||||
errorsList.add("error, no needs in private tokens, replace it with CreatureToken: " + className + " from " + tokenClass.getName());
|
||||
}
|
||||
|
||||
// 4. all public tokens must have tok-data (private tokens uses for innner abilities -- no need images for it)
|
||||
for (Class<? extends TokenImpl> tokenClass : publicTokens) {
|
||||
String className = extractShortClass(tokenClass);
|
||||
Token token = (Token) createNewObject(tokenClass);
|
||||
//Assert.assertNotNull("Can't create token by default constructor", token);
|
||||
if (token == null) {
|
||||
Assert.fail("Can't create token by default constructor: " + className);
|
||||
}
|
||||
|
||||
if (tokDataNamesIndex.getOrDefault(token.getName(), "").isEmpty()) {
|
||||
errorsList.add("error, can't find data in card-pictures-tok.txt for token: " + tokenClass.getName() + " -> " + token.getName());
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: all sets must have full tokens data in tok file (token in every set)
|
||||
// 1. Download scryfall tokens list: https://api.scryfall.com/cards/search?q=t:token
|
||||
// 2. Proccess each token with all prints: read "prints_search_uri" field from token data and go to link like
|
||||
// https://api.scryfall.com/cards/search?order=set&q=%21%E2%80%9CAngel%E2%80%9D&unique=prints
|
||||
// 3. Collect all strings in "set@name"
|
||||
// 4. Proccess tokens data and find missing strings from "set@name" list
|
||||
|
||||
printMessages(warningsList);
|
||||
printMessages(errorsList);
|
||||
if(errorsList.size() > 0){
|
||||
Assert.fail("Founded token errors: " + errorsList.size());
|
||||
}
|
||||
}
|
||||
|
||||
private static final Pattern SHORT_JAVA_STRING = Pattern.compile("(?<=\")[A-Z][a-z]+(?=\")");
|
||||
|
||||
private Set<String> findSourceTokens(Class c) throws IOException {
|
||||
|
|
|
@ -42,24 +42,24 @@ import mage.game.permanent.token.Token;
|
|||
public class BecomesCreatureSourceEffect extends ContinuousEffectImpl implements SourceEffect {
|
||||
|
||||
protected Token token;
|
||||
protected String type;
|
||||
protected String theyAreStillType;
|
||||
protected boolean losePreviousTypes;
|
||||
protected DynamicValue power = null;
|
||||
protected DynamicValue toughness = null;
|
||||
|
||||
public BecomesCreatureSourceEffect(Token token, String type, Duration duration) {
|
||||
this(token, type, duration, false, false);
|
||||
public BecomesCreatureSourceEffect(Token token, String theyAreStillType, Duration duration) {
|
||||
this(token, theyAreStillType, duration, false, false);
|
||||
}
|
||||
|
||||
public BecomesCreatureSourceEffect(Token token, String type, Duration duration, boolean losePreviousTypes, boolean characterDefining) {
|
||||
this(token, type, duration, losePreviousTypes, characterDefining, null, null);
|
||||
public BecomesCreatureSourceEffect(Token token, String theyAreStillType, Duration duration, boolean losePreviousTypes, boolean characterDefining) {
|
||||
this(token, theyAreStillType, duration, losePreviousTypes, characterDefining, null, null);
|
||||
}
|
||||
|
||||
public BecomesCreatureSourceEffect(Token token, String type, Duration duration, boolean losePreviousTypes, boolean characterDefining, DynamicValue power, DynamicValue toughness) {
|
||||
public BecomesCreatureSourceEffect(Token token, String theyAreStillType, Duration duration, boolean losePreviousTypes, boolean characterDefining, DynamicValue power, DynamicValue toughness) {
|
||||
super(duration, Outcome.BecomeCreature);
|
||||
this.characterDefining = characterDefining;
|
||||
this.token = token;
|
||||
this.type = type;
|
||||
this.theyAreStillType = theyAreStillType;
|
||||
this.losePreviousTypes = losePreviousTypes;
|
||||
this.power = power;
|
||||
this.toughness = toughness;
|
||||
|
@ -69,7 +69,7 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl implements
|
|||
public BecomesCreatureSourceEffect(final BecomesCreatureSourceEffect effect) {
|
||||
super(effect);
|
||||
this.token = effect.token.copy();
|
||||
this.type = effect.type;
|
||||
this.theyAreStillType = effect.theyAreStillType;
|
||||
this.losePreviousTypes = effect.losePreviousTypes;
|
||||
if (effect.power != null) {
|
||||
this.power = effect.power.copy();
|
||||
|
@ -110,7 +110,7 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl implements
|
|||
for (CardType cardType : token.getCardType()) {
|
||||
permanent.addCardType(cardType);
|
||||
}
|
||||
if (type != null && type.isEmpty() || type == null && permanent.isLand()) {
|
||||
if (theyAreStillType != null && theyAreStillType.isEmpty() || theyAreStillType == null && permanent.isLand()) {
|
||||
permanent.getSubtype(game).retainAll(SubType.getLandTypes(false));
|
||||
}
|
||||
if (!token.getSubtype(game).isEmpty()) {
|
||||
|
@ -119,6 +119,7 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl implements
|
|||
permanent.setIsAllCreatureTypes(token.isAllCreatureTypes());
|
||||
}
|
||||
break;
|
||||
|
||||
case ColorChangingEffects_5:
|
||||
if (sublayer == SubLayer.NA) {
|
||||
if (token.getColor(game).hasColor()) {
|
||||
|
@ -126,19 +127,20 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl implements
|
|||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AbilityAddingRemovingEffects_6:
|
||||
if (sublayer == SubLayer.NA) {
|
||||
for (Ability ability : token.getAbilities()) {
|
||||
permanent.addAbility(ability, source.getSourceId(), game);
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case PTChangingEffects_7:
|
||||
if ((sublayer == SubLayer.CharacteristicDefining_7a && isCharacterDefining())
|
||||
|| (sublayer == SubLayer.SetPT_7b && !isCharacterDefining())) {
|
||||
if (power != null) {
|
||||
permanent.getPower().setValue(power.calculate(game, source, this));
|
||||
permanent.getPower().setValue(power.calculate(game, source, this)); // check all other becomes to use calculate?
|
||||
} else if (token.getPower() != null) {
|
||||
permanent.getPower().setValue(token.getPower().getValue());
|
||||
}
|
||||
|
@ -148,11 +150,15 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl implements
|
|||
permanent.getToughness().setValue(token.getToughness().getValue());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} else if (duration == Duration.Custom) {
|
||||
this.discard();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -162,8 +168,8 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl implements
|
|||
}
|
||||
|
||||
private void setText() {
|
||||
if (type != null && !type.isEmpty()) {
|
||||
staticText = duration.toString() + " {this} becomes a " + token.getDescription() + " that's still a " + this.type;
|
||||
if (theyAreStillType != null && !theyAreStillType.isEmpty()) {
|
||||
staticText = duration.toString() + " {this} becomes a " + token.getDescription() + " that's still a " + this.theyAreStillType;
|
||||
} else {
|
||||
staticText = duration.toString() + " {this} becomes a " + token.getDescription();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue