WIP: Implement Role mechanic (#10816)

* [WOE] Implement Embereth Veteran

* add SBA for role tokens

* [WOE] Implement Cursed Courtier

* [WOE] Implement Conceited Witch

* [WOE] Implement Besotted Knight

* [WOE] Implement Syr Armont, the Redeemer

* [WOE] Implement Living Lectern

* add role test

* [WOE] Implement Lord Skitter's Blessing

* [WOE] Implement Faunsbane Troll

* [WOE] Implement Twisted Fealty

* [WOC] Implement Ellivere of the Wild Court

* [WOE] Implement Monstrous Rage

* [WOE] Implement Spellbook Vendor

* add verify skips

* extra fix
This commit is contained in:
Evan Kranzler 2023-08-17 10:18:21 -04:00 committed by GitHub
parent bf508aca9b
commit b20bdcede7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 1230 additions and 6 deletions

View file

@ -0,0 +1,41 @@
package mage.cards.b;
import mage.MageInt;
import mage.abilities.effects.common.CreateRoleAttachedTargetEffect;
import mage.cards.AdventureCard;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.RoleType;
import mage.constants.SubType;
import mage.target.common.TargetControlledCreaturePermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class BesottedKnight extends AdventureCard {
public BesottedKnight(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, new CardType[]{CardType.SORCERY}, "{3}{W}", "Betroth the Beast", "{W}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.KNIGHT);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// Betroth the Beast
// Create a Royal Role token attached to target creature you control.
this.getSpellCard().getSpellAbility().addEffect(new CreateRoleAttachedTargetEffect(RoleType.ROYAL));
this.getSpellCard().getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
}
private BesottedKnight(final BesottedKnight card) {
super(card);
}
@Override
public BesottedKnight copy() {
return new BesottedKnight(this);
}
}

View file

@ -0,0 +1,45 @@
package mage.cards.c;
import mage.MageInt;
import mage.abilities.effects.common.CreateRoleAttachedTargetEffect;
import mage.abilities.keyword.MenaceAbility;
import mage.cards.AdventureCard;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.RoleType;
import mage.constants.SubType;
import mage.target.common.TargetControlledCreaturePermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class ConceitedWitch extends AdventureCard {
public ConceitedWitch(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, new CardType[]{CardType.SORCERY}, "{2}{B}", "Price of Beauty", "{B}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.WARLOCK);
this.power = new MageInt(2);
this.toughness = new MageInt(3);
// Menace
this.addAbility(new MenaceAbility());
// Price of Beauty
// Create a Wicked Role token attached to target creature you control.
this.getSpellCard().getSpellAbility().addEffect(new CreateRoleAttachedTargetEffect(RoleType.WICKED));
this.getSpellCard().getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
}
private ConceitedWitch(final ConceitedWitch card) {
super(card);
}
@Override
public ConceitedWitch copy() {
return new ConceitedWitch(this);
}
}

View file

@ -0,0 +1,43 @@
package mage.cards.c;
import mage.MageInt;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.CreateRoleAttachedSourceEffect;
import mage.abilities.keyword.LifelinkAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.RoleType;
import mage.constants.SubType;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class CursedCourtier extends CardImpl {
public CursedCourtier(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.NOBLE);
this.power = new MageInt(3);
this.toughness = new MageInt(3);
// Lifelink
this.addAbility(LifelinkAbility.getInstance());
// When Cursed Courtier enters the battlefield, create a Cursed Role token attached to it.
this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateRoleAttachedSourceEffect(RoleType.CURSED)));
}
private CursedCourtier(final CursedCourtier card) {
super(card);
}
@Override
public CursedCourtier copy() {
return new CursedCourtier(this);
}
}

View file

@ -0,0 +1,61 @@
package mage.cards.e;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DealsDamageToAPlayerAllTriggeredAbility;
import mage.abilities.common.EntersBattlefieldOrAttacksSourceTriggeredAbility;
import mage.abilities.effects.common.CreateRoleAttachedTargetEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.FilterPermanent;
import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.permanent.EnchantedPredicate;
import mage.target.TargetPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class EllivereOfTheWildCourt extends CardImpl {
private static final FilterPermanent filter
= new FilterControlledCreaturePermanent("an enchanted creature you control");
static {
filter.add(EnchantedPredicate.instance);
}
public EllivereOfTheWildCourt(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{W}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.KNIGHT);
this.power = new MageInt(4);
this.toughness = new MageInt(4);
// Whenever Ellivere of the Wild Court enters the battlefield or attacks, create a Virtuous Role token attached to another target creature you control.
Ability ability = new EntersBattlefieldOrAttacksSourceTriggeredAbility(new CreateRoleAttachedTargetEffect(RoleType.VIRTUOUS));
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE));
this.addAbility(ability);
// Whenever an enchanted creature you control deals combat damage to a player, draw a card.
this.addAbility(new DealsDamageToAPlayerAllTriggeredAbility(
new DrawCardSourceControllerEffect(1), filter,
false, SetTargetPointer.NONE, true
));
}
private EllivereOfTheWildCourt(final EllivereOfTheWildCourt card) {
super(card);
}
@Override
public EllivereOfTheWildCourt copy() {
return new EllivereOfTheWildCourt(this);
}
}

View file

@ -0,0 +1,49 @@
package mage.cards.e;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.CreateRoleAttachedTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.RoleType;
import mage.constants.SubType;
import mage.filter.StaticFilters;
import mage.target.TargetPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class EmberethVeteran extends CardImpl {
public EmberethVeteran(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.KNIGHT);
this.power = new MageInt(2);
this.toughness = new MageInt(1);
// {1}, Sacrifice Embereth Veteran: Create a Young Hero Role token attached to another target creature.
Ability ability = new SimpleActivatedAbility(
new CreateRoleAttachedTargetEffect(RoleType.YOUNG_HERO), new GenericManaCost(1)
);
ability.addCost(new SacrificeSourceCost());
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE));
this.addAbility(ability);
}
private EmberethVeteran(final EmberethVeteran card) {
super(card);
}
@Override
public EmberethVeteran copy() {
return new EmberethVeteran(this);
}
}

View file

@ -0,0 +1,74 @@
package mage.cards.f;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.ActivateAsSorceryActivatedAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.CreateRoleAttachedSourceEffect;
import mage.abilities.effects.common.ExileTargetIfDiesEffect;
import mage.abilities.effects.common.FightTargetSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.RoleType;
import mage.constants.SubType;
import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.ObjectSourcePlayer;
import mage.filter.predicate.ObjectSourcePlayerPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.TargetPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class FaunsbaneTroll extends CardImpl {
private static final FilterControlledPermanent filter
= new FilterControlledPermanent(SubType.AURA, "an Aura attached to {this}");
static {
filter.add(FaunsbaneTrollPredicate.instance);
}
public FaunsbaneTroll(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{G}");
this.subtype.add(SubType.TROLL);
this.power = new MageInt(4);
this.toughness = new MageInt(4);
// When Faunsbane Troll enters the battlefield, create a Monster Role token attached to it.
this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateRoleAttachedSourceEffect(RoleType.MONSTER)));
// {1}, Sacrifice an Aura attached to Faunsbane Troll: Faunsbane Troll fights target creature you don't control. If that creature would die this turn, exile it instead. Activate only as a sorcery.
Ability ability = new ActivateAsSorceryActivatedAbility(new FightTargetSourceEffect(), new GenericManaCost(1));
ability.addCost(new SacrificeTargetCost(filter));
ability.addEffect(new ExileTargetIfDiesEffect());
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL));
this.addAbility(ability);
}
private FaunsbaneTroll(final FaunsbaneTroll card) {
super(card);
}
@Override
public FaunsbaneTroll copy() {
return new FaunsbaneTroll(this);
}
}
enum FaunsbaneTrollPredicate implements ObjectSourcePlayerPredicate<Permanent> {
instance;
@Override
public boolean apply(ObjectSourcePlayer<Permanent> input, Game game) {
return input.getSource().getSourceId().equals(input.getObject().getAttachedTo());
}
}

View file

@ -0,0 +1,52 @@
package mage.cards.l;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.ActivateAsSorceryActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.CreateRoleAttachedTargetEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.RoleType;
import mage.constants.SubType;
import mage.filter.StaticFilters;
import mage.target.TargetPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class LivingLectern extends CardImpl {
public LivingLectern(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{1}{U}");
this.subtype.add(SubType.CONSTRUCT);
this.power = new MageInt(0);
this.toughness = new MageInt(4);
// {1}, Sacrifice Living Lectern: Draw a card. Create a Sorcerer Role token attached to up to one other target creature you control. Activate only as a sorcery.
Ability ability = new ActivateAsSorceryActivatedAbility(
new DrawCardSourceControllerEffect(1), new GenericManaCost(1)
);
ability.addCost(new SacrificeSourceCost());
ability.addEffect(new CreateRoleAttachedTargetEffect(RoleType.SORCERER));
ability.addTarget(new TargetPermanent(
0, 1, StaticFilters.FILTER_ANOTHER_CREATURE_YOU_CONTROL
));
this.addAbility(ability);
}
private LivingLectern(final LivingLectern card) {
super(card);
}
@Override
public LivingLectern copy() {
return new LivingLectern(this);
}
}

View file

@ -0,0 +1,67 @@
package mage.cards.l;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfDrawTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.CreateRoleAttachedTargetEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.LoseLifeSourceControllerEffect;
import mage.abilities.hint.ConditionHint;
import mage.abilities.hint.Hint;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.RoleType;
import mage.constants.TargetController;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.permanent.EnchantedPredicate;
import mage.target.common.TargetControlledCreaturePermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class LordSkittersBlessing extends CardImpl {
private static final FilterPermanent filter = new FilterControlledCreaturePermanent();
static {
filter.add(EnchantedPredicate.instance);
}
private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter);
private static final Hint hint = new ConditionHint(condition, "You control an enchanted creaeture");
public LordSkittersBlessing(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}");
// When Lord Skitter's Blessing enters the battlefield, create a Wicked Role token attached to target creature you control.
Ability ability = new EntersBattlefieldTriggeredAbility(new CreateRoleAttachedTargetEffect(RoleType.WICKED));
ability.addTarget(new TargetControlledCreaturePermanent());
this.addAbility(ability);
// At the beginning of your draw step, if you control an enchanted creature, you lose 1 life and you draw an additional card.
ability = new ConditionalInterveningIfTriggeredAbility(
new BeginningOfDrawTriggeredAbility(
new LoseLifeSourceControllerEffect(1), TargetController.YOU, false
), condition, "At the beginning of your draw step, if you control " +
"an enchanted creature, you lose 1 life and you draw an additional card."
);
ability.addEffect(new DrawCardSourceControllerEffect(1));
this.addAbility(ability);
}
private LordSkittersBlessing(final LordSkittersBlessing card) {
super(card);
}
@Override
public LordSkittersBlessing copy() {
return new LordSkittersBlessing(this);
}
}

View file

@ -0,0 +1,35 @@
package mage.cards.m;
import mage.abilities.effects.common.CreateRoleAttachedTargetEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.RoleType;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class MonstrousRage extends CardImpl {
public MonstrousRage(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}");
// Target creature gets +2/+0 until end of turn. Create a Monster Role attached to it.
this.getSpellAbility().addEffect(new BoostTargetEffect(2, 0));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
this.getSpellAbility().addEffect(new CreateRoleAttachedTargetEffect(RoleType.MONSTER).setText("create a Monster Role attached to it"));
}
private MonstrousRage(final MonstrousRage card) {
super(card);
}
@Override
public MonstrousRage copy() {
return new MonstrousRage(this);
}
}

View file

@ -0,0 +1,54 @@
package mage.cards.s;
import mage.MageInt;
import mage.abilities.common.BeginningOfCombatTriggeredAbility;
import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.CreateRoleAttachedTargetEffect;
import mage.abilities.effects.common.DoWhenCostPaid;
import mage.abilities.keyword.VigilanceAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.RoleType;
import mage.constants.SubType;
import mage.constants.TargetController;
import mage.target.common.TargetControlledCreaturePermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class SpellbookVendor extends CardImpl {
public SpellbookVendor(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.PEASANT);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// Vigilance
this.addAbility(VigilanceAbility.getInstance());
// At the beginning of combat on your turn, you may pay {1}. When you do, create a Sorcerer Role token attached to target creature you control.
ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(
new CreateRoleAttachedTargetEffect(RoleType.SORCERER), false
);
ability.addTarget(new TargetControlledCreaturePermanent());
this.addAbility(new BeginningOfCombatTriggeredAbility(new DoWhenCostPaid(
ability, new GenericManaCost(1), "Pay {1}?"
), TargetController.YOU, false));
}
private SpellbookVendor(final SpellbookVendor card) {
super(card);
}
@Override
public SpellbookVendor copy() {
return new SpellbookVendor(this);
}
}

View file

@ -0,0 +1,58 @@
package mage.cards.s;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.CreateRoleAttachedTargetEffect;
import mage.abilities.effects.common.continuous.BoostControlledEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.StaticFilters;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.EnchantedPredicate;
import mage.target.TargetPermanent;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class SyrArmontTheRedeemer extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("enchanted creatures");
static {
filter.add(EnchantedPredicate.instance);
}
public SyrArmontTheRedeemer(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{W}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.KNIGHT);
this.power = new MageInt(4);
this.toughness = new MageInt(4);
// When Syr Armont, the Redeemer enters the battlefield, create a Monster Role token attached to another target creature you control.
Ability ability = new EntersBattlefieldTriggeredAbility(new CreateRoleAttachedTargetEffect(RoleType.MONSTER));
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_CREATURE_YOU_CONTROL));
this.addAbility(ability);
// Enchanted creatures you control get +1/+1.
this.addAbility(new SimpleStaticAbility(new BoostControlledEffect(
1, 1, Duration.WhileOnBattlefield, filter
)));
}
private SyrArmontTheRedeemer(final SyrArmontTheRedeemer card) {
super(card);
}
@Override
public SyrArmontTheRedeemer copy() {
return new SyrArmontTheRedeemer(this);
}
}

View file

@ -0,0 +1,48 @@
package mage.cards.t;
import mage.abilities.effects.common.CreateRoleAttachedTargetEffect;
import mage.abilities.effects.common.UntapTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.effects.common.continuous.GainControlTargetEffect;
import mage.abilities.keyword.HasteAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.RoleType;
import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.SecondTargetPointer;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class TwistedFealty extends CardImpl {
public TwistedFealty(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R}");
// Gain control of target creature until end of turn. Untap that creature. It gains haste until end of turn.
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
this.getSpellAbility().addEffect(new GainControlTargetEffect(Duration.EndOfTurn));
this.getSpellAbility().addEffect(new UntapTargetEffect().setText("Untap that creature"));
this.getSpellAbility().addEffect(new GainAbilityTargetEffect(
HasteAbility.getInstance(), Duration.EndOfTurn
).setText("It gains haste until end of turn."));
// Create a Wicked Role token attached to up to one target creature.
this.getSpellAbility().addEffect(new CreateRoleAttachedTargetEffect(RoleType.WICKED)
.setTargetPointer(new SecondTargetPointer()));
this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 1));
}
private TwistedFealty(final TwistedFealty card) {
super(card);
}
@Override
public TwistedFealty copy() {
return new TwistedFealty(this);
}
}

View file

@ -22,12 +22,17 @@ public final class WildsOfEldraine extends ExpansionSet {
cards.add(new SetCardInfo("Ash, Party Crasher", 201, Rarity.UNCOMMON, mage.cards.a.AshPartyCrasher.class));
cards.add(new SetCardInfo("Beanstalk Wurm", 161, Rarity.COMMON, mage.cards.b.BeanstalkWurm.class));
cards.add(new SetCardInfo("Besotted Knight", 4, Rarity.COMMON, mage.cards.b.BesottedKnight.class));
cards.add(new SetCardInfo("Break the Spell", 5, Rarity.COMMON, mage.cards.b.BreakTheSpell.class));
cards.add(new SetCardInfo("Conceited Witch", 84, Rarity.COMMON, mage.cards.c.ConceitedWitch.class));
cards.add(new SetCardInfo("Cruel Somnophage", 222, Rarity.RARE, mage.cards.c.CruelSomnophage.class));
cards.add(new SetCardInfo("Cursed Courtier", 9, Rarity.UNCOMMON, mage.cards.c.CursedCourtier.class));
cards.add(new SetCardInfo("Elvish Archivist", 168, Rarity.RARE, mage.cards.e.ElvishArchivist.class));
cards.add(new SetCardInfo("Embereth Veteran", 127, Rarity.UNCOMMON, mage.cards.e.EmberethVeteran.class));
cards.add(new SetCardInfo("Evolving Wilds", 256, Rarity.COMMON, mage.cards.e.EvolvingWilds.class));
cards.add(new SetCardInfo("Faerie Dreamthief", 89, Rarity.UNCOMMON, mage.cards.f.FaerieDreamthief.class));
cards.add(new SetCardInfo("Farsight Ritual", 49, Rarity.RARE, mage.cards.f.FarsightRitual.class));
cards.add(new SetCardInfo("Faunsbane Troll", 203, Rarity.RARE, mage.cards.f.FaunsbaneTroll.class));
cards.add(new SetCardInfo("Forest", 266, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Frolicking Familiar", 226, Rarity.UNCOMMON, mage.cards.f.FrolickingFamiliar.class));
cards.add(new SetCardInfo("Gallant Pie-Wielder", 15, Rarity.UNCOMMON, mage.cards.g.GallantPieWielder.class));
@ -35,7 +40,10 @@ public final class WildsOfEldraine extends ExpansionSet {
cards.add(new SetCardInfo("Greta, Sweettooth Scourge", 205, Rarity.UNCOMMON, mage.cards.g.GretaSweettoothScourge.class));
cards.add(new SetCardInfo("Island", 263, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Knight of Doves", 19, Rarity.UNCOMMON, mage.cards.k.KnightOfDoves.class));
cards.add(new SetCardInfo("Living Lectern", 59, Rarity.COMMON, mage.cards.l.LivingLectern.class));
cards.add(new SetCardInfo("Lord Skitter's Blessing", 98, Rarity.RARE, mage.cards.l.LordSkittersBlessing.class));
cards.add(new SetCardInfo("Lord Skitter's Butcher", 99, Rarity.UNCOMMON, mage.cards.l.LordSkittersButcher.class));
cards.add(new SetCardInfo("Monstrous Rage", 142, Rarity.UNCOMMON, mage.cards.m.MonstrousRage.class));
cards.add(new SetCardInfo("Moonshaker Cavalry", 21, Rarity.MYTHIC, mage.cards.m.MoonshakerCavalry.class));
cards.add(new SetCardInfo("Mountain", 265, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Neva, Stalked by Nightmares", 209, Rarity.UNCOMMON, mage.cards.n.NevaStalkedByNightmares.class));
@ -43,8 +51,8 @@ public final class WildsOfEldraine extends ExpansionSet {
cards.add(new SetCardInfo("Plains", 262, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Rat Out", 103, Rarity.COMMON, mage.cards.r.RatOut.class));
cards.add(new SetCardInfo("Ratcatcher Trainee", 144, Rarity.COMMON, mage.cards.r.RatcatcherTrainee.class));
cards.add(new SetCardInfo("Restless Cottage", 258, Rarity.RARE, mage.cards.r.RestlessCottage.class));
cards.add(new SetCardInfo("Realm-Scorcher Hellkite", 145, Rarity.MYTHIC, mage.cards.r.RealmScorcherHellkite.class));
cards.add(new SetCardInfo("Restless Cottage", 258, Rarity.RARE, mage.cards.r.RestlessCottage.class));
cards.add(new SetCardInfo("Restless Fortress", 259, Rarity.RARE, mage.cards.r.RestlessFortress.class));
cards.add(new SetCardInfo("Return from the Wilds", 181, Rarity.COMMON, mage.cards.r.ReturnFromTheWilds.class));
cards.add(new SetCardInfo("Rootrider Faun", 182, Rarity.COMMON, mage.cards.r.RootriderFaun.class));
@ -53,8 +61,10 @@ public final class WildsOfEldraine extends ExpansionSet {
cards.add(new SetCardInfo("Sharae of Numbing Depths", 213, Rarity.UNCOMMON, mage.cards.s.SharaeOfNumbingDepths.class));
cards.add(new SetCardInfo("Skybeast Tracker", 185, Rarity.COMMON, mage.cards.s.SkybeastTracker.class));
cards.add(new SetCardInfo("Sleight of Hand", 67, Rarity.COMMON, mage.cards.s.SleightOfHand.class));
cards.add(new SetCardInfo("Spellbook Vendor", 31, Rarity.RARE, mage.cards.s.SpellbookVendor.class));
cards.add(new SetCardInfo("Swamp", 264, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Sweettooth Witch", 111, Rarity.COMMON, mage.cards.s.SweettoothWitch.class));
cards.add(new SetCardInfo("Syr Armont, the Redeemer", 214, Rarity.UNCOMMON, mage.cards.s.SyrArmontTheRedeemer.class));
cards.add(new SetCardInfo("Syr Ginger, the Meal Ender", 252, Rarity.RARE, mage.cards.s.SyrGingerTheMealEnder.class));
cards.add(new SetCardInfo("Talion, the Kindly Lord", 215, Rarity.MYTHIC, mage.cards.t.TalionTheKindlyLord.class));
cards.add(new SetCardInfo("Tanglespan Lookout", 188, Rarity.UNCOMMON, mage.cards.t.TanglespanLookout.class));
@ -66,6 +76,7 @@ public final class WildsOfEldraine extends ExpansionSet {
cards.add(new SetCardInfo("Tough Cookie", 193, Rarity.UNCOMMON, mage.cards.t.ToughCookie.class));
cards.add(new SetCardInfo("Troublemaker Ouphe", 194, Rarity.COMMON, mage.cards.t.TroublemakerOuphe.class));
cards.add(new SetCardInfo("Troyan, Gutsy Explorer", 217, Rarity.UNCOMMON, mage.cards.t.TroyanGutsyExplorer.class));
cards.add(new SetCardInfo("Twisted Fealty", 154, Rarity.UNCOMMON, mage.cards.t.TwistedFealty.class));
cards.add(new SetCardInfo("Warehouse Tabby", 117, Rarity.COMMON, mage.cards.w.WarehouseTabby.class));
}

View file

@ -18,5 +18,7 @@ public final class WildsOfEldraineCommander extends ExpansionSet {
private WildsOfEldraineCommander() {
super("Wilds of Eldraine Commander", "WOC", ExpansionSet.buildDate(2023, 9, 8), SetType.SUPPLEMENTAL);
this.hasBasicLands = false;
cards.add(new SetCardInfo("Ellivere of the Wild Court", 2, Rarity.MYTHIC, mage.cards.e.EllivereOfTheWildCourt.class));
}
}

View file

@ -0,0 +1,51 @@
package org.mage.test.cards.enchantments;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* @author TheElk801
*/
public class RoleTest extends CardTestPlayerBase {
private static final String courtier = "Cursed Courtier";
private static final String veteran = "Embereth Veteran";
@Test
public void testRegular() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
addCard(Zone.HAND, playerA, courtier);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, courtier);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, courtier, 1);
assertPermanentCount(playerA, "Cursed", 1);
assertPowerToughness(playerA, courtier, 1, 1);
}
@Test
public void testReplace() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
addCard(Zone.BATTLEFIELD, playerA, veteran);
addCard(Zone.HAND, playerA, courtier);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, courtier);
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{1}, Sacrifice", courtier);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, courtier, 1);
assertPermanentCount(playerA, veteran, 0);
assertGraveyardCount(playerA, veteran, 1);
assertPermanentCount(playerA, "Cursed", 0);
assertPermanentCount(playerA, "Young Hero", 1);
assertPowerToughness(playerA, courtier, 3, 3);
}
}

View file

@ -124,6 +124,7 @@ public class VerifyCardDataTest {
// cost
skipListCreate(SKIP_LIST_COST);
skipListAddName(SKIP_LIST_COST, "WOE", "Price of Beauty"); // temporary
// supertype
skipListCreate(SKIP_LIST_SUPERTYPE);
@ -134,6 +135,7 @@ public class VerifyCardDataTest {
skipListAddName(SKIP_LIST_TYPE, "UND", "Old Fogey");
skipListAddName(SKIP_LIST_TYPE, "UST", "capital offense"); // uses "instant" instead "Instant" as a joke card
skipListAddName(SKIP_LIST_TYPE, "WOE", "Knight of Doves"); // temporary
skipListAddName(SKIP_LIST_TYPE, "WOE", "Faunsbane Troll"); // temporary
// subtype
skipListCreate(SKIP_LIST_SUBTYPE);
@ -141,6 +143,7 @@ public class VerifyCardDataTest {
skipListAddName(SKIP_LIST_SUBTYPE, "UGL", "Elvish Impersonators"); // subtype is "Elves" pun
skipListAddName(SKIP_LIST_SUBTYPE, "UND", "Elvish Impersonators");
skipListAddName(SKIP_LIST_SUBTYPE, "WOE", "Knight of Doves"); // temporary
skipListAddName(SKIP_LIST_SUBTYPE, "WOE", "Faunsbane Troll"); // temporary
// number
skipListCreate(SKIP_LIST_NUMBER);

View file

@ -0,0 +1,50 @@
package mage.abilities.effects.common;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
import mage.constants.RoleType;
import mage.game.Game;
import mage.game.permanent.Permanent;
/**
* @author TheElk801
*/
public class CreateRoleAttachedSourceEffect extends OneShotEffect {
private final RoleType roleType;
public CreateRoleAttachedSourceEffect(RoleType roleType) {
super(Outcome.Benefit);
this.roleType = roleType;
}
private CreateRoleAttachedSourceEffect(final CreateRoleAttachedSourceEffect effect) {
super(effect);
this.roleType = effect.roleType;
}
@Override
public CreateRoleAttachedSourceEffect copy() {
return new CreateRoleAttachedSourceEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = source.getSourcePermanentIfItStillExists(game);
if (permanent == null) {
return false;
}
roleType.createToken(permanent, game, source);
return true;
}
@Override
public String getText(Mode mode) {
if (staticText != null && !staticText.isEmpty()) {
return staticText;
}
return "create a " + roleType.getName() + " Role token attached to it";
}
}

View file

@ -0,0 +1,51 @@
package mage.abilities.effects.common;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
import mage.constants.RoleType;
import mage.game.Game;
import mage.game.permanent.Permanent;
/**
* @author TheElk801
*/
public class CreateRoleAttachedTargetEffect extends OneShotEffect {
private final RoleType roleType;
public CreateRoleAttachedTargetEffect(RoleType roleType) {
super(Outcome.Benefit);
this.roleType = roleType;
}
private CreateRoleAttachedTargetEffect(final CreateRoleAttachedTargetEffect effect) {
super(effect);
this.roleType = effect.roleType;
}
@Override
public CreateRoleAttachedTargetEffect copy() {
return new CreateRoleAttachedTargetEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (permanent == null) {
return false;
}
roleType.createToken(permanent, game, source);
return true;
}
@Override
public String getText(Mode mode) {
if (staticText != null && !staticText.isEmpty()) {
return staticText;
}
return "create a " + roleType.getName() + " Role token attached to " +
getTargetPointer().describeTargets(mode.getTargets(), "it");
}
}

View file

@ -0,0 +1,53 @@
package mage.constants;
import mage.abilities.Ability;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.*;
import java.util.UUID;
import java.util.function.Supplier;
/**
* @author TheElk801
*/
public enum RoleType {
CURSED("Cursed", CursedRoleToken::new),
MONSTER("Monster", MonsterRoleToken::new),
ROYAL("Royal", RoyalRoleToken::new),
SORCERER("Sorcerer", SorcererRoleToken::new),
VIRTUOUS("Virtuous", VirtuousRoleToken::new),
WICKED("Wicked", WickedRoleToken::new),
YOUNG_HERO("Young Hero", YoungHeroRoleToken::new);
private final String name;
private final Supplier<Token> supplier;
RoleType(String name, Supplier<Token> supplier) {
this.name = name;
this.supplier = supplier;
}
public String getName() {
return name;
}
@Override
public String toString() {
return name;
}
public Token createToken(Permanent permanent, Game game, Ability source) {
Token token = supplier.get();
token.putOntoBattlefield(1, game, source);
for (UUID tokenId : token.getLastAddedTokenIds()) {
Permanent aura = game.getPermanent(tokenId);
if (aura == null || !aura.hasSubtype(SubType.AURA, game)) {
continue;
}
aura.getAbilities().get(0).getTargets().get(0).add(permanent.getId(), game);
aura.getAbilities().get(0).getEffects().get(0).apply(game, aura.getAbilities().get(0));
}
return token;
}
}

View file

@ -40,6 +40,7 @@ public enum SubType {
CARTOUCHE("Cartouche", SubTypeSet.EnchantmentType),
CLASS("Class", SubTypeSet.EnchantmentType),
CURSE("Curse", SubTypeSet.EnchantmentType),
ROLE("Role", SubTypeSet.EnchantmentType),
RUNE("Rune", SubTypeSet.EnchantmentType),
SAGA("Saga", SubTypeSet.EnchantmentType),
SHARD("Shard", SubTypeSet.EnchantmentType),

View file

@ -63,11 +63,7 @@ import mage.target.Target;
import mage.target.TargetCard;
import mage.target.TargetPermanent;
import mage.target.TargetPlayer;
import mage.util.CardUtil;
import mage.util.GameLog;
import mage.util.MessageToClient;
import mage.util.MultiAmountMessage;
import mage.util.RandomUtil;
import mage.util.*;
import mage.util.functions.CopyApplier;
import mage.watchers.Watcher;
import mage.watchers.common.*;
@ -2331,6 +2327,7 @@ public abstract class GameImpl implements Game {
List<Permanent> legendary = new ArrayList<>();
List<Permanent> worldEnchantment = new ArrayList<>();
Map<UUID, Map<UUID, Set<Permanent>>> roleMap = new HashMap<>();
List<FilterCreaturePermanent> usePowerInsteadOfToughnessForDamageLethalityFilters = getState().getActivePowerInsteadOfToughnessForDamageLethalityFilters();
for (Permanent perm : getBattlefield().getAllActivePermanents()) {
if (perm.isCreature(this)) {
@ -2510,6 +2507,11 @@ public abstract class GameImpl implements Game {
}
}
}
if (perm.hasSubtype(SubType.ROLE, this) && state.getZone(perm.getId()) == Zone.BATTLEFIELD) {
roleMap.computeIfAbsent(perm.getControllerId(), x -> new HashMap<>())
.computeIfAbsent(perm.getAttachedTo(), x -> new HashSet<>())
.add(perm);
}
}
// 704.5s If the number of lore counters on a Saga permanent is greater than or equal to its final chapter number
// and it isn't the source of a chapter ability that has triggered but not yet left the stack, that Saga's controller sacrifices it.
@ -2733,6 +2735,29 @@ public abstract class GameImpl implements Game {
}
}
if (!roleMap.isEmpty()) {
List<Set<Permanent>> rolesToHandle = roleMap.values()
.stream()
.map(Map::values)
.flatMap(Collection::stream)
.filter(s -> s.size() > 1)
.collect(Collectors.toList());
if (!rolesToHandle.isEmpty()) {
for (Set<Permanent> roleSet : rolesToHandle) {
int newest = roleSet
.stream()
.mapToInt(Permanent::getCreateOrder)
.max()
.orElse(-1);
roleSet.removeIf(permanent -> permanent.getCreateOrder() == newest);
for (Permanent permanent : roleSet) {
movePermanentToGraveyardWithInfo(permanent);
somethingHappened = true;
}
}
}
}
// Daybound/Nightbound permanents should be transformed according to day/night
// This is not a state-based action but it's unclear where else to put it
if (hasDayNight()) {

View file

@ -0,0 +1,42 @@
package mage.game.permanent.token;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.continuous.SetBasePowerToughnessEnchantedEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
/**
* @author TheElk801
*/
public final class CursedRoleToken extends TokenImpl {
public CursedRoleToken() {
super("Cursed", "Cursed Role token");
cardType.add(CardType.ENCHANTMENT);
subtype.add(SubType.AURA);
subtype.add(SubType.ROLE);
TargetPermanent auraTarget = new TargetCreaturePermanent();
Ability ability = new EnchantAbility(auraTarget);
ability.addTarget(auraTarget);
ability.addEffect(new AttachEffect(Outcome.BoostCreature));
this.addAbility(ability);
// Enchanted creature is 1/1.
this.addAbility(new SimpleStaticAbility(new SetBasePowerToughnessEnchantedEffect(1, 1)));
}
private CursedRoleToken(final CursedRoleToken token) {
super(token);
}
public CursedRoleToken copy() {
return new CursedRoleToken(this);
}
}

View file

@ -0,0 +1,49 @@
package mage.game.permanent.token;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.continuous.BoostEnchantedEffect;
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.constants.AttachmentType;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
/**
* @author TheElk801
*/
public final class MonsterRoleToken extends TokenImpl {
public MonsterRoleToken() {
super("Monster", "Monster Role token");
cardType.add(CardType.ENCHANTMENT);
subtype.add(SubType.AURA);
subtype.add(SubType.ROLE);
TargetPermanent auraTarget = new TargetCreaturePermanent();
Ability ability = new EnchantAbility(auraTarget);
ability.addTarget(auraTarget);
ability.addEffect(new AttachEffect(Outcome.BoostCreature));
this.addAbility(ability);
// Enchanted creature gets +1/+1 and has trample
ability = new SimpleStaticAbility(new BoostEnchantedEffect(1, 1));
ability.addEffect(new GainAbilityAttachedEffect(
TrampleAbility.getInstance(), AttachmentType.AURA
).setText("and has trample"));
this.addAbility(ability);
}
private MonsterRoleToken(final MonsterRoleToken token) {
super(token);
}
public MonsterRoleToken copy() {
return new MonsterRoleToken(this);
}
}

View file

@ -0,0 +1,50 @@
package mage.game.permanent.token;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.continuous.BoostEnchantedEffect;
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.abilities.keyword.WardAbility;
import mage.constants.AttachmentType;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
/**
* @author TheElk801
*/
public final class RoyalRoleToken extends TokenImpl {
public RoyalRoleToken() {
super("Royal", "Royal Role token");
cardType.add(CardType.ENCHANTMENT);
subtype.add(SubType.AURA);
subtype.add(SubType.ROLE);
TargetPermanent auraTarget = new TargetCreaturePermanent();
Ability ability = new EnchantAbility(auraTarget);
ability.addTarget(auraTarget);
ability.addEffect(new AttachEffect(Outcome.BoostCreature));
this.addAbility(ability);
// Enchanted creature gets +1/+1 and has ward {1}
ability = new SimpleStaticAbility(new BoostEnchantedEffect(1, 1));
ability.addEffect(new GainAbilityAttachedEffect(
new WardAbility(new GenericManaCost(1), false), AttachmentType.AURA
).setText("and has ward {1}"));
this.addAbility(ability);
}
private RoyalRoleToken(final RoyalRoleToken token) {
super(token);
}
public RoyalRoleToken copy() {
return new RoyalRoleToken(this);
}
}

View file

@ -0,0 +1,52 @@
package mage.game.permanent.token;
import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.continuous.BoostEnchantedEffect;
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
import mage.abilities.effects.keyword.ScryEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.constants.AttachmentType;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
/**
* @author TheElk801
*/
public final class SorcererRoleToken extends TokenImpl {
public SorcererRoleToken() {
super("Sorcerer", "Sorcerer Role token");
cardType.add(CardType.ENCHANTMENT);
subtype.add(SubType.AURA);
subtype.add(SubType.ROLE);
TargetPermanent auraTarget = new TargetCreaturePermanent();
Ability ability = new EnchantAbility(auraTarget);
ability.addTarget(auraTarget);
ability.addEffect(new AttachEffect(Outcome.BoostCreature));
this.addAbility(ability);
// Enchanted creature gets +1/+1 and has "Whenever this creature attacks, scry 1."
ability = new SimpleStaticAbility(new BoostEnchantedEffect(1, 1));
ability.addEffect(new GainAbilityAttachedEffect(
new AttacksTriggeredAbility(new ScryEffect(1, false))
.setTriggerPhrase("Whenever this creature attacks, "),
AttachmentType.AURA
).setText("and has \"Whenever this creature attacks, scry 1.\""));
this.addAbility(ability);
}
private SorcererRoleToken(final SorcererRoleToken token) {
super(token);
}
public SorcererRoleToken copy() {
return new SorcererRoleToken(this);
}
}

View file

@ -0,0 +1,47 @@
package mage.game.permanent.token;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.continuous.BoostEnchantedEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.filter.StaticFilters;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
/**
* @author TheElk801
*/
public final class VirtuousRoleToken extends TokenImpl {
private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(StaticFilters.FILTER_CONTROLLED_PERMANENT_ENCHANTMENT);
public VirtuousRoleToken() {
super("Virtuous", "Virtuous Role token");
cardType.add(CardType.ENCHANTMENT);
subtype.add(SubType.AURA);
subtype.add(SubType.ROLE);
TargetPermanent auraTarget = new TargetCreaturePermanent();
Ability ability = new EnchantAbility(auraTarget);
ability.addTarget(auraTarget);
ability.addEffect(new AttachEffect(Outcome.BoostCreature));
this.addAbility(ability);
// Enchanted creature gets +1/+1 for each enchantment you control.
this.addAbility(new SimpleStaticAbility(new BoostEnchantedEffect(xValue, xValue)));
}
private VirtuousRoleToken(final VirtuousRoleToken token) {
super(token);
}
public VirtuousRoleToken copy() {
return new VirtuousRoleToken(this);
}
}

View file

@ -0,0 +1,48 @@
package mage.game.permanent.token;
import mage.abilities.Ability;
import mage.abilities.common.PutIntoGraveFromBattlefieldSourceTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.LoseLifeOpponentsEffect;
import mage.abilities.effects.common.continuous.BoostEnchantedEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
/**
* @author TheElk801
*/
public final class WickedRoleToken extends TokenImpl {
public WickedRoleToken() {
super("Wicked", "Wicked Role token");
cardType.add(CardType.ENCHANTMENT);
subtype.add(SubType.AURA);
subtype.add(SubType.ROLE);
TargetPermanent auraTarget = new TargetCreaturePermanent();
Ability ability = new EnchantAbility(auraTarget);
ability.addTarget(auraTarget);
ability.addEffect(new AttachEffect(Outcome.BoostCreature));
this.addAbility(ability);
// Enchanted creature gets +1/+1
this.addAbility(new SimpleStaticAbility(new BoostEnchantedEffect(1, 1)));
// When this Aura is put into a graveyard from the battlefield, each opponent loses 1 life."
this.addAbility(new PutIntoGraveFromBattlefieldSourceTriggeredAbility(new LoseLifeOpponentsEffect(1))
.setTriggerPhrase("When this Aura is put into a graveyard from the battlefield, "));
}
private WickedRoleToken(final WickedRoleToken token) {
super(token);
}
public WickedRoleToken copy() {
return new WickedRoleToken(this);
}
}

View file

@ -0,0 +1,62 @@
package mage.game.permanent.token;
import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.Condition;
import mage.abilities.condition.common.SourceMatchesFilterCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.constants.*;
import mage.counters.CounterType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.ToughnessPredicate;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
/**
* @author TheElk801
*/
public final class YoungHeroRoleToken extends TokenImpl {
private static final FilterPermanent filter = new FilterCreaturePermanent();
static {
filter.add(new ToughnessPredicate(ComparisonType.FEWER_THAN, 4));
}
private static final Condition condition = new SourceMatchesFilterCondition(filter);
public YoungHeroRoleToken() {
super("Young Hero", "Young Hero Role token");
cardType.add(CardType.ENCHANTMENT);
subtype.add(SubType.AURA);
subtype.add(SubType.ROLE);
TargetPermanent auraTarget = new TargetCreaturePermanent();
Ability ability = new EnchantAbility(auraTarget);
ability.addTarget(auraTarget);
ability.addEffect(new AttachEffect(Outcome.BoostCreature));
this.addAbility(ability);
// Enchanted creature has "Whenever this creature attacks, if its toughness is 3 or less, put a +1/+1 counter on it."
this.addAbility(new SimpleStaticAbility(new GainAbilityAttachedEffect(
new ConditionalInterveningIfTriggeredAbility(
new AttacksTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance())),
condition, "Whenever this creature attacks, if its toughness is 3 or less, put a +1/+1 counter on it."
), AttachmentType.AURA
)));
}
private YoungHeroRoleToken(final YoungHeroRoleToken token) {
super(token);
}
public YoungHeroRoleToken copy() {
return new YoungHeroRoleToken(this);
}
}