From 970627414161f439a727c869820c95ca5c51703d Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Fri, 30 Sep 2022 22:02:38 -0400 Subject: [PATCH] [BRO] Implemented Urza, Lord Protector / Urza, Planeswalker --- .../src/mage/cards/u/UrzaLordProtector.java | 76 ++++++++++++ .../src/mage/cards/u/UrzaPlaneswalker.java | 117 ++++++++++++++++++ Mage.Sets/src/mage/sets/TheBrothersWar.java | 4 +- .../src/main/java/mage/constants/SubType.java | 2 +- .../java/mage/game/permanent/Permanent.java | 2 + .../mage/game/permanent/PermanentImpl.java | 10 +- .../permanent/token/SoldierArtifactToken.java | 33 +++++ 7 files changed, 241 insertions(+), 3 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/u/UrzaLordProtector.java create mode 100644 Mage.Sets/src/mage/cards/u/UrzaPlaneswalker.java create mode 100644 Mage/src/main/java/mage/game/permanent/token/SoldierArtifactToken.java diff --git a/Mage.Sets/src/mage/cards/u/UrzaLordProtector.java b/Mage.Sets/src/mage/cards/u/UrzaLordProtector.java new file mode 100644 index 00000000000..03665b1cc66 --- /dev/null +++ b/Mage.Sets/src/mage/cards/u/UrzaLordProtector.java @@ -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); + } +} diff --git a/Mage.Sets/src/mage/cards/u/UrzaPlaneswalker.java b/Mage.Sets/src/mage/cards/u/UrzaPlaneswalker.java new file mode 100644 index 00000000000..e4298a11071 --- /dev/null +++ b/Mage.Sets/src/mage/cards/u/UrzaPlaneswalker.java @@ -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; + } +} diff --git a/Mage.Sets/src/mage/sets/TheBrothersWar.java b/Mage.Sets/src/mage/sets/TheBrothersWar.java index 31db5a2727e..c56d326b1ab 100644 --- a/Mage.Sets/src/mage/sets/TheBrothersWar.java +++ b/Mage.Sets/src/mage/sets/TheBrothersWar.java @@ -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("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("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 diff --git a/Mage/src/main/java/mage/constants/SubType.java b/Mage/src/main/java/mage/constants/SubType.java index 067c6ee4a61..379eb292bce 100644 --- a/Mage/src/main/java/mage/constants/SubType.java +++ b/Mage/src/main/java/mage/constants/SubType.java @@ -478,7 +478,7 @@ public enum SubType { TIBALT("Tibalt", SubTypeSet.PlaneswalkerType), TYVAR("Tyvar", SubTypeSet.PlaneswalkerType), UGIN("Ugin", SubTypeSet.PlaneswalkerType), - URZA("Urza", SubTypeSet.PlaneswalkerType, true), // Unstable + URZA("Urza", SubTypeSet.PlaneswalkerType), VENSER("Venser", SubTypeSet.PlaneswalkerType), VIVIEN("Vivien", SubTypeSet.PlaneswalkerType), VRASKA("Vraska", SubTypeSet.PlaneswalkerType), diff --git a/Mage/src/main/java/mage/game/permanent/Permanent.java b/Mage/src/main/java/mage/game/permanent/Permanent.java index fd173a185df..14bb7bb0075 100644 --- a/Mage/src/main/java/mage/game/permanent/Permanent.java +++ b/Mage/src/main/java/mage/game/permanent/Permanent.java @@ -214,6 +214,8 @@ public interface Permanent extends Card, Controllable { void removeAbilities(List abilitiesToRemove, UUID sourceId, Game game); + void incrementLoyaltyActivationsAvailable(); + void addLoyaltyUsed(); boolean canLoyaltyBeUsed(Game game); diff --git a/Mage/src/main/java/mage/game/permanent/PermanentImpl.java b/Mage/src/main/java/mage/game/permanent/PermanentImpl.java index ac95e3b0f38..2f505bf0aa9 100644 --- a/Mage/src/main/java/mage/game/permanent/PermanentImpl.java +++ b/Mage/src/main/java/mage/game/permanent/PermanentImpl.java @@ -102,6 +102,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { protected List markedDamage; protected int markedLifelink; protected int timesLoyaltyUsed = 0; + protected int loyaltyActivationsAvailable = 1; protected int transformCount = 0; protected Map info; protected int createOrder; @@ -169,6 +170,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { this.pairedPermanent = permanent.pairedPermanent; this.bandedCards.addAll(permanent.bandedCards); this.timesLoyaltyUsed = permanent.timesLoyaltyUsed; + this.loyaltyActivationsAvailable = permanent.loyaltyActivationsAvailable; this.transformCount = permanent.transformCount; this.morphed = permanent.morphed; @@ -211,6 +213,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { this.maxBlockedBy = 0; this.copy = false; this.goadingPlayers.clear(); + this.loyaltyActivationsAvailable = 1; } @Override @@ -462,6 +465,11 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { } } + @Override + public void incrementLoyaltyActivationsAvailable() { + this.loyaltyActivationsAvailable++; + } + @Override public void addLoyaltyUsed() { this.timesLoyaltyUsed++; @@ -471,7 +479,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { public boolean canLoyaltyBeUsed(Game game) { Player controller = game.getPlayer(controllerId); if (controller != null) { - return controller.getLoyaltyUsePerTurn() > timesLoyaltyUsed; + return Math.max(controller.getLoyaltyUsePerTurn(), loyaltyActivationsAvailable) > timesLoyaltyUsed; } return false; } diff --git a/Mage/src/main/java/mage/game/permanent/token/SoldierArtifactToken.java b/Mage/src/main/java/mage/game/permanent/token/SoldierArtifactToken.java new file mode 100644 index 00000000000..c4fcd5c7811 --- /dev/null +++ b/Mage/src/main/java/mage/game/permanent/token/SoldierArtifactToken.java @@ -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); + } + +}