Merge branch 'master' into feature/implement-harmonize-ability

This commit is contained in:
theelk801 2025-03-27 19:05:22 -04:00
commit 849e1847c6
38 changed files with 1832 additions and 37 deletions

View file

@ -18,20 +18,27 @@ import java.util.Objects;
public class CardsLeaveGraveyardTriggeredAbility extends TriggeredAbilityImpl {
private final FilterCard filter;
private final boolean yourTurn;
public CardsLeaveGraveyardTriggeredAbility(Effect effect) {
this(effect, StaticFilters.FILTER_CARD_CARDS);
}
public CardsLeaveGraveyardTriggeredAbility(Effect effect, FilterCard filter) {
this(effect, filter, false);
}
public CardsLeaveGraveyardTriggeredAbility(Effect effect, FilterCard filter, boolean yourTurn) {
super(Zone.BATTLEFIELD, effect, false);
this.filter = filter;
setTriggerPhrase("Whenever one or more " + filter + " leave your graveyard, ");
this.yourTurn = yourTurn;
setTriggerPhrase("Whenever one or more " + filter + " leave your graveyard" + (yourTurn ? " during your turn" : "") + ", ");
}
private CardsLeaveGraveyardTriggeredAbility(final CardsLeaveGraveyardTriggeredAbility ability) {
super(ability);
this.filter = ability.filter;
this.yourTurn = ability.yourTurn;
}
@Override
@ -41,6 +48,9 @@ public class CardsLeaveGraveyardTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (yourTurn && !isControlledBy(game.getActivePlayerId())) {
return false;
}
ZoneChangeGroupEvent zEvent = (ZoneChangeGroupEvent) event;
return zEvent != null
&& Zone.GRAVEYARD == zEvent.getFromZone()

View file

@ -0,0 +1,26 @@
package mage.abilities.condition.common;
import mage.abilities.Ability;
import mage.abilities.condition.Condition;
import mage.abilities.keyword.BeholdDragonAbility;
import mage.game.Game;
import mage.util.CardUtil;
/**
* Checks if the spell was cast with the alternate behold a Dragon cost
*
* @author TheElk801
*/
public enum BeheldDragonCondition implements Condition {
instance;
@Override
public boolean apply(Game game, Ability source) {
return CardUtil.checkSourceCostsTagExists(game, source, BeholdDragonAbility.BEHOLD_DRAGON_ACTIVATION_VALUE_KEY);
}
@Override
public String toString() {
return "Dragon was beheld";
}
}

View file

@ -0,0 +1,91 @@
package mage.abilities.keyword;
import mage.abilities.Ability;
import mage.abilities.SpellAbility;
import mage.abilities.StaticAbility;
import mage.abilities.costs.*;
import mage.abilities.costs.common.BeholdDragonCost;
import mage.abilities.costs.common.CollectEvidenceCost;
import mage.abilities.hint.common.EvidenceHint;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
/**
* @author TheElk801
*/
public class BeholdDragonAbility extends StaticAbility implements OptionalAdditionalSourceCosts {
private static final String promptString = "Behold a Dragon";
private static final String keywordText = "As an additional cost to cast this spell, you may behold a Dragon";
private static final String reminderText = "Choose a Dragon you control or reveal a Dragon card from your hand.";
private final String rule;
public static final String BEHOLD_DRAGON_ACTIVATION_VALUE_KEY = "beholdDragonActivation";
protected OptionalAdditionalCost additionalCost;
public static OptionalAdditionalCost makeCost() {
OptionalAdditionalCost cost = new OptionalAdditionalCostImpl(keywordText , reminderText, new BeholdDragonCost());
cost.setRepeatable(false);
return cost;
}
public BeholdDragonAbility( ) {
super(Zone.STACK, null);
this.additionalCost = makeCost();
this.rule = additionalCost.getName() + ". " + additionalCost.getReminderText();
this.setRuleAtTheTop(true);
}
private BeholdDragonAbility(final BeholdDragonAbility ability) {
super(ability);
this.rule = ability.rule;
this.additionalCost = ability.additionalCost.copy();
}
@Override
public BeholdDragonAbility copy() {
return new BeholdDragonAbility(this);
}
public void resetCost() {
if (additionalCost != null) {
additionalCost.reset();
}
}
@Override
public void addOptionalAdditionalCosts(Ability ability, Game game) {
if (!(ability instanceof SpellAbility)) {
return;
}
Player player = game.getPlayer(ability.getControllerId());
if (player == null) {
return;
}
this.resetCost();
boolean canPay = additionalCost.canPay(ability, this, ability.getControllerId(), game);
if (!canPay || !player.chooseUse(Outcome.Exile, promptString + '?', ability, game)) {
return;
}
additionalCost.activate();
for (Cost cost : ((Costs<Cost>) additionalCost)) {
ability.getCosts().add(cost.copy());
}
ability.setCostsTag(BEHOLD_DRAGON_ACTIVATION_VALUE_KEY, null);
}
@Override
public String getCastMessageSuffix() {
return additionalCost.getCastSuffixMessage(0);
}
@Override
public String getRule() {
return rule;
}
}

View file

@ -2,12 +2,13 @@ package mage.abilities.keyword;
import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.permanent.token.RedWarriorToken;
import mage.players.Player;
import mage.util.CardUtil;
/**
@ -16,10 +17,11 @@ import mage.util.CardUtil;
public class MobilizeAbility extends AttacksTriggeredAbility {
public MobilizeAbility(int count) {
super(new MobilizeEffect(count), false, "Mobilize " + count + " <i>(Whenever this creature attacks, create "
+ (count == 1 ? "a" : CardUtil.numberToText(count)) + " tapped and attacking 1/1 red Warrior creature "
+ (count == 1 ? "token" : "tokens") + ". Sacrifice " + (count == 1 ? "it" : "them")
+ " at the beginning of the next end step.)");
this(StaticValue.get(count));
}
public MobilizeAbility(DynamicValue count) {
super(new MobilizeEffect(count), false, makeText(count));
}
protected MobilizeAbility(final MobilizeAbility ability) {
@ -30,13 +32,33 @@ public class MobilizeAbility extends AttacksTriggeredAbility {
public MobilizeAbility copy() {
return new MobilizeAbility(this);
}
private static String makeText(DynamicValue amount) {
StringBuilder sb = new StringBuilder();
String message;
String numToText;
boolean plural;
if (amount instanceof StaticValue) {
int count = ((StaticValue) amount).getValue();
message = "" + count;
numToText = CardUtil.numberToText(count, "a");
plural = count > 1;
} else {
message = "X, where X is " + amount.getMessage() + '.';
numToText = "X";
plural = true;
}
return "Mobilize " + message + " <i>(Whenever this creature attacks, create " +
numToText + " tapped and attacking 1/1 red Warrior creature token" + (plural ? "s" : "") +
". Sacrifice " + (plural ? "them" : "it") + " at the beginning of the next end step.)</i>";
}
}
class MobilizeEffect extends OneShotEffect {
private final int count;
private final DynamicValue count;
MobilizeEffect(int count) {
MobilizeEffect(DynamicValue count) {
super(Outcome.Benefit);
this.count = count;
}
@ -53,13 +75,9 @@ class MobilizeEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
CreateTokenEffect effect = new CreateTokenEffect(new RedWarriorToken(), this.count, true, true);
effect.apply(game, source);
effect.sacrificeTokensCreatedAtNextEndStep(game, source);
return true;
}
}
}

View file

@ -0,0 +1,44 @@
package mage.game.permanent.token;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.LifelinkAbility;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.target.common.TargetAnyTarget;
/**
* @author TheElk801
*/
public final class ReliquaryDragonToken extends TokenImpl {
public ReliquaryDragonToken() {
super("Reliquary Dragon", "4/4 Dragon creature token named Reliquary Dragon that's all colors. It has flying, lifelink, and \"When this token enters, it deals 3 damage to any target.\"");
cardType.add(CardType.CREATURE);
color.setWhite(true);
color.setBlue(true);
color.setBlack(true);
color.setRed(true);
color.setGreen(true);
subtype.add(SubType.DRAGON);
power = new MageInt(4);
toughness = new MageInt(4);
addAbility(FlyingAbility.getInstance());
addAbility(LifelinkAbility.getInstance());
Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(3, "it"));
ability.addTarget(new TargetAnyTarget());
addAbility(ability);
}
private ReliquaryDragonToken(final ReliquaryDragonToken token) {
super(token);
}
public ReliquaryDragonToken copy() {
return new ReliquaryDragonToken(this);
}
}