[FIN] Implement Summon: Brynhildr (#13699)

* [FIN] Implement Summon: Brynhildr

* cleanup of common classes and constructors

---------

Co-authored-by: xenohedron <12538125+xenohedron@users.noreply.github.com>
This commit is contained in:
Evan Kranzler 2025-09-12 18:28:09 -04:00 committed by GitHub
parent 6d0dc2f0df
commit 652ca6c9e1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 288 additions and 167 deletions

View file

@ -1,7 +1,6 @@
package mage.abilities.common.delayed;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.constants.Duration;
import mage.constants.Outcome;
@ -18,9 +17,7 @@ import mage.util.CardUtil;
/**
* @author TheElk801
*/
public class AddCounterNextSpellDelayedTriggeredAbility extends DelayedTriggeredAbility {
private final FilterSpell filter;
public class AddCounterNextSpellDelayedTriggeredAbility extends CastNextSpellDelayedTriggeredAbility {
public AddCounterNextSpellDelayedTriggeredAbility() {
this(StaticFilters.FILTER_SPELL_A_CREATURE);
@ -31,38 +28,17 @@ public class AddCounterNextSpellDelayedTriggeredAbility extends DelayedTriggered
}
public AddCounterNextSpellDelayedTriggeredAbility(int amount, FilterSpell filter) {
super(new AddCounterNextSpellEffect(amount), Duration.EndOfTurn, true, false);
this.filter = filter;
this.setTriggerPhrase("When you next cast " + filter.getMessage() + " this turn, ");
super(new AddCounterNextSpellEffect(amount), filter, false);
}
private AddCounterNextSpellDelayedTriggeredAbility(final AddCounterNextSpellDelayedTriggeredAbility ability) {
super(ability);
this.filter = ability.filter;
}
@Override
public AddCounterNextSpellDelayedTriggeredAbility copy() {
return new AddCounterNextSpellDelayedTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.SPELL_CAST;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (!isControlledBy(event.getPlayerId())) {
return false;
}
Spell spell = game.getSpell(event.getTargetId());
if (spell == null || !filter.match(spell, getControllerId(), this, game)) {
return false;
}
this.getEffects().setValue("spellCast", spell);
return true;
}
}
class AddCounterNextSpellEffect extends ReplacementEffectImpl {
@ -72,7 +48,8 @@ class AddCounterNextSpellEffect extends ReplacementEffectImpl {
AddCounterNextSpellEffect(int amount) {
super(Duration.EndOfStep, Outcome.BoostCreature);
this.amount = amount;
staticText = "that creature enters with " + CardUtil.numberToText(amount, "an") + " additional +1/+1 counter" + (amount > 1 ? "s" : "") + " on it";
staticText = "that creature enters with " + CardUtil.numberToText(amount, "an") +
" additional +1/+1 counter" + (amount > 1 ? "s" : "") + " on it";
}
private AddCounterNextSpellEffect(AddCounterNextSpellEffect effect) {

View file

@ -0,0 +1,59 @@
package mage.abilities.common.delayed;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.constants.Duration;
import mage.filter.FilterSpell;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.stack.Spell;
import mage.target.targetpointer.FixedTarget;
/**
* @author TheElk801
*/
public class CastNextSpellDelayedTriggeredAbility extends DelayedTriggeredAbility {
private final FilterSpell filter;
private final boolean setTargetPointer;
public CastNextSpellDelayedTriggeredAbility(Effect effect, FilterSpell filter, boolean setTargetPointer) {
super(effect, Duration.EndOfTurn, true, false);
this.filter = filter;
this.setTriggerPhrase("When you next cast " + filter.getMessage() + " this turn, ");
this.setTargetPointer = setTargetPointer;
}
protected CastNextSpellDelayedTriggeredAbility(final CastNextSpellDelayedTriggeredAbility ability) {
super(ability);
this.filter = ability.filter;
this.setTargetPointer = ability.setTargetPointer;
}
@Override
public CastNextSpellDelayedTriggeredAbility copy() {
return new CastNextSpellDelayedTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.SPELL_CAST;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (!isControlledBy(event.getPlayerId())) {
return false;
}
Spell spell = game.getSpell(event.getTargetId());
if (spell == null || !filter.match(spell, getControllerId(), this, game)) {
return false;
}
this.getEffects().setValue("spellCast", spell);
if (setTargetPointer) {
this.getEffects().setTargetPointer(new FixedTarget(event.getTargetId()));
}
return true;
}
}

View file

@ -1,75 +1,32 @@
package mage.abilities.common.delayed;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CopyTargetStackObjectEffect;
import mage.constants.Duration;
import mage.filter.FilterSpell;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.stack.Spell;
import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil;
/**
* @author TheElk801
*/
public class CopyNextSpellDelayedTriggeredAbility extends DelayedTriggeredAbility {
private final FilterSpell filter;
private final String rule;
public class CopyNextSpellDelayedTriggeredAbility extends CastNextSpellDelayedTriggeredAbility {
public CopyNextSpellDelayedTriggeredAbility() {
this(StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY);
}
public CopyNextSpellDelayedTriggeredAbility(FilterSpell filter) {
this(filter, new CopyTargetStackObjectEffect(true), null);
this(filter, 1);
}
public CopyNextSpellDelayedTriggeredAbility(FilterSpell filter, Effect effect, String rule) {
super(effect, Duration.EndOfTurn);
this.filter = filter;
this.rule = rule;
public CopyNextSpellDelayedTriggeredAbility(FilterSpell filter, int amount) {
super(new CopyTargetStackObjectEffect(false, true, true, amount, null), filter, true);
}
protected CopyNextSpellDelayedTriggeredAbility(final CopyNextSpellDelayedTriggeredAbility ability) {
super(ability);
this.filter = ability.filter;
this.rule = ability.rule;
}
@Override
public CopyNextSpellDelayedTriggeredAbility copy() {
return new CopyNextSpellDelayedTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.SPELL_CAST;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (!isControlledBy(event.getPlayerId())) {
return false;
}
Spell spell = game.getStack().getSpell(event.getTargetId());
if (spell == null || !filter.match(spell, getControllerId(), this, game)) {
return false;
}
this.getEffects().setValue("spellCast", spell);
this.getEffects().setTargetPointer(new FixedTarget(event.getTargetId()));
return true;
}
@Override
public String getRule() {
if (rule != null && !rule.isEmpty()) {
return rule;
}
return "When you next cast " + CardUtil.addArticle(filter.getMessage()) + " this turn, "
+ "copy that spell. You may choose new targets for the copy.";
}
}

View file

@ -7,6 +7,7 @@ import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.stack.StackObject;
import mage.util.CardUtil;
import mage.util.functions.StackObjectCopyApplier;
/**
@ -96,8 +97,10 @@ public class CopyTargetStackObjectEffect extends OneShotEffect {
if (staticText != null && !staticText.isEmpty()) {
return staticText;
}
return "copy " +
getTargetPointer().describeTargets(mode.getTargets(), objectName) +
(chooseTargets ? ". You may choose new targets for the copy" : "");
String amountText = (amount == 1) ? "" : ((amount == 2) ? " twice" : " " + CardUtil.numberToText(amount) + " times");
String chooseText = chooseTargets ? ". You may choose new targets for the cop" + ((amount == 1) ? "y" : "ies") : "";
return "copy "
+ getTargetPointer().describeTargets(mode.getTargets(), objectName)
+ amountText + chooseText;
}
}