[BRO] Implemented Urza, Lord Protector / Urza, Planeswalker

This commit is contained in:
Evan Kranzler 2022-09-30 22:02:38 -04:00
parent 5fa9a850b1
commit 9706274141
7 changed files with 241 additions and 3 deletions

View file

@ -0,0 +1,76 @@
package mage.cards.u;
import mage.MageInt;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.Condition;
import mage.abilities.condition.common.MeldCondition;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.effects.common.MeldEffect;
import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class UrzaLordProtector extends CardImpl {
private static final FilterCard filter = new FilterCard("artifact, instant, and sorcery spells");
static {
filter.add(Predicates.or(
CardType.ARTIFACT.getPredicate(),
CardType.INSTANT.getPredicate(),
CardType.SORCERY.getPredicate()
));
}
private static final Condition condition = new MeldCondition("The Mightstone and Weakstone");
public UrzaLordProtector(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{U}");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.ARTIFICER);
this.power = new MageInt(2);
this.toughness = new MageInt(4);
// Artifact, instant, and sorcery spells you cast cost {1} less to cast.
this.addAbility(new SimpleStaticAbility(new SpellsCostReductionControllerEffect(filter, 1)));
// {7}: If you both own and control Urza, Lord Protector and an artifact named The Mightstone and Weakstone, exile them, then meld them into Urza, Planeswalker. Activate only as a sorcery.
this.addAbility(new SimpleActivatedAbility(new ConditionalOneShotEffect(
new MeldEffect(
"The Mightstone and Weakstone",
new UrzaPlaneswalker(
ownerId,
new CardSetInfo(
"Urza, Planeswalker", setInfo.getExpansionSetCode(),
"238b", Rarity.MYTHIC
)
)
), condition, "If you both own and control {this} and an artifact named " +
"The Mightstone and Weakstone, exile them, then meld them into Urza, Planeswalker"
), new GenericManaCost(7)));
}
private UrzaLordProtector(final UrzaLordProtector card) {
super(card);
}
@Override
public UrzaLordProtector copy() {
return new UrzaLordProtector(this);
}
}

View file

@ -0,0 +1,117 @@
package mage.cards.u;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.common.*;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect;
import mage.abilities.keyword.IndestructibleAbility;
import mage.cards.CardSetInfo;
import mage.cards.MeldCard;
import mage.constants.*;
import mage.filter.FilterCard;
import mage.filter.FilterPermanent;
import mage.filter.StaticFilters;
import mage.filter.predicate.Predicates;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.SoldierArtifactToken;
import mage.target.common.TargetNonlandPermanent;
import java.util.Optional;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class UrzaPlaneswalker extends MeldCard {
private static final FilterCard filter = new FilterCard("artifact, instant, and sorcery spells");
private static final FilterPermanent filter2 = new FilterPermanent("artifacts and planeswalkers");
static {
filter.add(Predicates.or(
CardType.ARTIFACT.getPredicate(),
CardType.INSTANT.getPredicate(),
CardType.SORCERY.getPredicate()
));
filter2.add(Predicates.or(
CardType.ARTIFACT.getPredicate(),
CardType.PLANESWALKER.getPredicate()
));
}
public UrzaPlaneswalker(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "");
this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.URZA);
this.setStartingLoyalty(7);
this.nightCard = true;
// You may activate the loyalty abilities of Urza, Planeswalker twice each turn rather than only once.
this.addAbility(new SimpleStaticAbility(new UrzaPlaneswalkerEffect()));
// +2: Artifact, instant, and sorcery spells you cast this turn cost {2} less to cast. You gain 2 life.
Ability ability = new LoyaltyAbility(new SpellsCostReductionControllerEffect(filter, 1)
.setDuration(Duration.EndOfTurn)
.setText("artifact, instant, and sorcery spells you cast this turn cost {2} less to cast"), 2);
ability.addEffect(new GainLifeEffect(2));
this.addAbility(ability);
// +1: Draw two cards, then discard a card.
this.addAbility(new LoyaltyAbility(new DrawDiscardTargetEffect(2, 1), 1));
// 0: Create two 1/1 colorless Soldier artifact creature tokens.
this.addAbility(new LoyaltyAbility(new CreateTokenEffect(new SoldierArtifactToken()), 0));
// -3: Exile target nonland permanent.
ability = new LoyaltyAbility(new ExileTargetEffect(), -3);
ability.addTarget(new TargetNonlandPermanent());
this.addAbility(ability);
// -10: Artifacts and planeswalkers you control gain indestructible until end of turn. Destroy all nonland permanents.
ability = new LoyaltyAbility(new GainAbilityControlledEffect(
IndestructibleAbility.getInstance(), Duration.EndOfTurn, filter2
), -10);
ability.addEffect(new DestroyAllEffect(StaticFilters.FILTER_PERMANENTS_NON_LAND));
this.addAbility(ability);
}
private UrzaPlaneswalker(final UrzaPlaneswalker card) {
super(card);
}
@Override
public UrzaPlaneswalker copy() {
return new UrzaPlaneswalker(this);
}
}
class UrzaPlaneswalkerEffect extends ContinuousEffectImpl {
public UrzaPlaneswalkerEffect() {
super(Duration.WhileOnBattlefield, Layer.RulesEffects, SubLayer.NA, Outcome.Benefit);
staticText = "once during each of your turns, you may activate an additional loyalty ability of {this}";
}
public UrzaPlaneswalkerEffect(final UrzaPlaneswalkerEffect effect) {
super(effect);
}
@Override
public UrzaPlaneswalkerEffect copy() {
return new UrzaPlaneswalkerEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Optional.ofNullable(source.getSourcePermanentIfItStillExists(game))
.ifPresent(Permanent::incrementLoyaltyActivationsAvailable);
return true;
}
}

View file

@ -29,7 +29,9 @@ public final class TheBrothersWar extends ExpansionSet {
cards.add(new SetCardInfo("Recruitment Officer", 23, Rarity.UNCOMMON, mage.cards.r.RecruitmentOfficer.class)); cards.add(new SetCardInfo("Recruitment Officer", 23, Rarity.UNCOMMON, mage.cards.r.RecruitmentOfficer.class));
cards.add(new SetCardInfo("Surge Engine", 81, Rarity.MYTHIC, mage.cards.s.SurgeEngine.class)); cards.add(new SetCardInfo("Surge Engine", 81, Rarity.MYTHIC, mage.cards.s.SurgeEngine.class));
cards.add(new SetCardInfo("Swamp", 282, Rarity.LAND, mage.cards.basiclands.Swamp.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Swamp", 282, Rarity.LAND, mage.cards.basiclands.Swamp.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("The Mightstone and Weakstone", 238, Rarity.RARE, mage.cards.t.TheMightstoneAndWeakstone.class)); cards.add(new SetCardInfo("The Mightstone and Weakstone", "238a", Rarity.RARE, mage.cards.t.TheMightstoneAndWeakstone.class));
cards.add(new SetCardInfo("Urza, Lord Protector", 225, Rarity.MYTHIC, mage.cards.u.UrzaLordProtector.class));
cards.add(new SetCardInfo("Urza, Planeswalker", "238b", Rarity.MYTHIC, mage.cards.u.UrzaPlaneswalker.class));
} }
// @Override // @Override

View file

@ -478,7 +478,7 @@ public enum SubType {
TIBALT("Tibalt", SubTypeSet.PlaneswalkerType), TIBALT("Tibalt", SubTypeSet.PlaneswalkerType),
TYVAR("Tyvar", SubTypeSet.PlaneswalkerType), TYVAR("Tyvar", SubTypeSet.PlaneswalkerType),
UGIN("Ugin", SubTypeSet.PlaneswalkerType), UGIN("Ugin", SubTypeSet.PlaneswalkerType),
URZA("Urza", SubTypeSet.PlaneswalkerType, true), // Unstable URZA("Urza", SubTypeSet.PlaneswalkerType),
VENSER("Venser", SubTypeSet.PlaneswalkerType), VENSER("Venser", SubTypeSet.PlaneswalkerType),
VIVIEN("Vivien", SubTypeSet.PlaneswalkerType), VIVIEN("Vivien", SubTypeSet.PlaneswalkerType),
VRASKA("Vraska", SubTypeSet.PlaneswalkerType), VRASKA("Vraska", SubTypeSet.PlaneswalkerType),

View file

@ -214,6 +214,8 @@ public interface Permanent extends Card, Controllable {
void removeAbilities(List<Ability> abilitiesToRemove, UUID sourceId, Game game); void removeAbilities(List<Ability> abilitiesToRemove, UUID sourceId, Game game);
void incrementLoyaltyActivationsAvailable();
void addLoyaltyUsed(); void addLoyaltyUsed();
boolean canLoyaltyBeUsed(Game game); boolean canLoyaltyBeUsed(Game game);

View file

@ -102,6 +102,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
protected List<MarkedDamageInfo> markedDamage; protected List<MarkedDamageInfo> markedDamage;
protected int markedLifelink; protected int markedLifelink;
protected int timesLoyaltyUsed = 0; protected int timesLoyaltyUsed = 0;
protected int loyaltyActivationsAvailable = 1;
protected int transformCount = 0; protected int transformCount = 0;
protected Map<String, String> info; protected Map<String, String> info;
protected int createOrder; protected int createOrder;
@ -169,6 +170,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
this.pairedPermanent = permanent.pairedPermanent; this.pairedPermanent = permanent.pairedPermanent;
this.bandedCards.addAll(permanent.bandedCards); this.bandedCards.addAll(permanent.bandedCards);
this.timesLoyaltyUsed = permanent.timesLoyaltyUsed; this.timesLoyaltyUsed = permanent.timesLoyaltyUsed;
this.loyaltyActivationsAvailable = permanent.loyaltyActivationsAvailable;
this.transformCount = permanent.transformCount; this.transformCount = permanent.transformCount;
this.morphed = permanent.morphed; this.morphed = permanent.morphed;
@ -211,6 +213,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
this.maxBlockedBy = 0; this.maxBlockedBy = 0;
this.copy = false; this.copy = false;
this.goadingPlayers.clear(); this.goadingPlayers.clear();
this.loyaltyActivationsAvailable = 1;
} }
@Override @Override
@ -462,6 +465,11 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
} }
} }
@Override
public void incrementLoyaltyActivationsAvailable() {
this.loyaltyActivationsAvailable++;
}
@Override @Override
public void addLoyaltyUsed() { public void addLoyaltyUsed() {
this.timesLoyaltyUsed++; this.timesLoyaltyUsed++;
@ -471,7 +479,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
public boolean canLoyaltyBeUsed(Game game) { public boolean canLoyaltyBeUsed(Game game) {
Player controller = game.getPlayer(controllerId); Player controller = game.getPlayer(controllerId);
if (controller != null) { if (controller != null) {
return controller.getLoyaltyUsePerTurn() > timesLoyaltyUsed; return Math.max(controller.getLoyaltyUsePerTurn(), loyaltyActivationsAvailable) > timesLoyaltyUsed;
} }
return false; return false;
} }

View file

@ -0,0 +1,33 @@
package mage.game.permanent.token;
import mage.MageInt;
import mage.constants.CardType;
import mage.constants.SubType;
import java.util.Arrays;
/**
* @author TheElk801
*/
public final class SoldierArtifactToken extends TokenImpl {
public SoldierArtifactToken() {
super("Soldier Token", "1/1 colorless Soldier artifact creature token");
cardType.add(CardType.ARTIFACT);
cardType.add(CardType.CREATURE);
subtype.add(SubType.SOLDIER);
power = new MageInt(1);
toughness = new MageInt(1);
availableImageSetCodes = Arrays.asList("BRO");
}
public SoldierArtifactToken(final SoldierArtifactToken token) {
super(token);
}
public SoldierArtifactToken copy() {
return new SoldierArtifactToken(this);
}
}