refactor: properly support "in addition to its other types"

in BecomesCreatureSourceEffect, rather than always relying on the original card type to infer
This commit is contained in:
xenohedron 2024-09-15 18:03:26 -04:00
parent 2f0559fda3
commit 7eee2c7ef2
4 changed files with 28 additions and 25 deletions

View file

@ -46,7 +46,7 @@ public final class HauntedScreen extends CardImpl {
); );
ability.addEffect(new BecomesCreatureSourceEffect(new CreatureToken( ability.addEffect(new BecomesCreatureSourceEffect(new CreatureToken(
0, 0, "0/0 Spirit creature", SubType.SPIRIT 0, 0, "0/0 Spirit creature", SubType.SPIRIT
), CardType.ARTIFACT, Duration.Custom)); ), CardType.ARTIFACT, Duration.Custom).withKeepCreatureSubtypes(true));
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -46,8 +46,8 @@ public final class RestlessSpire extends CardImpl {
new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.WhileOnBattlefield), new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.WhileOnBattlefield),
MyTurnCondition.instance, "As long as it's your turn, this creature has first strike." MyTurnCondition.instance, "As long as it's your turn, this creature has first strike."
)).addHint(MyTurnHint.instance)), )).addHint(MyTurnHint.instance)),
CardType.LAND, Duration.EndOfTurn, true CardType.LAND, Duration.EndOfTurn
), new ManaCostsImpl<>("{U}{R}"))); ).withDurationRuleAtStart(true), new ManaCostsImpl<>("{U}{R}")));
// Whenever Restless Spire attacks, scry 1. // Whenever Restless Spire attacks, scry 1.
this.addAbility(new AttacksTriggeredAbility(new ScryEffect(1, false), false)); this.addAbility(new AttacksTriggeredAbility(new ScryEffect(1, false), false));

View file

@ -48,8 +48,8 @@ public final class RestlessVinestalk extends CardImpl {
new CreatureToken(5, 5, "5/5 green and blue Plant creature with trample") new CreatureToken(5, 5, "5/5 green and blue Plant creature with trample")
.withColor("GU").withSubType(SubType.PLANT) .withColor("GU").withSubType(SubType.PLANT)
.withAbility(TrampleAbility.getInstance()), .withAbility(TrampleAbility.getInstance()),
CardType.LAND, Duration.EndOfTurn, true CardType.LAND, Duration.EndOfTurn
), new ManaCostsImpl<>("{3}{G}{U}"))); ).withDurationRuleAtStart(true), new ManaCostsImpl<>("{3}{G}{U}")));
// Whenever Restless Vinestalk attacks, up to one other target creature has base power and toughness 3/3 until end of turn. // Whenever Restless Vinestalk attacks, up to one other target creature has base power and toughness 3/3 until end of turn.
Ability ability = new AttacksTriggeredAbility(new SetBasePowerToughnessTargetEffect(3, 3, Duration.EndOfTurn), false); Ability ability = new AttacksTriggeredAbility(new SetBasePowerToughnessTargetEffect(3, 3, Duration.EndOfTurn), false);

View file

@ -35,13 +35,14 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl {
* existing creature types. * existing creature types.
*/ */
protected Token token; private final Token token;
protected CardType retainType; // if null, loses previous types private final CardType retainType; // if null, loses previous types
protected boolean loseAbilities = false; private boolean loseAbilities = false;
protected boolean loseEquipmentType = false; private boolean loseEquipmentType = false;
protected DynamicValue power = null; private boolean keepCreatureSubtypes;
protected DynamicValue toughness = null; private DynamicValue power = null;
protected boolean durationRuleAtStart; // put duration rule at the start of the rules text rather than the end private DynamicValue toughness = null;
private boolean durationRuleAtStart; // put duration rule at the start of the rules text rather than the end
/** /**
* @param token Token as blueprint for creature to become * @param token Token as blueprint for creature to become
@ -49,20 +50,11 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl {
* @param duration Duration for the effect * @param duration Duration for the effect
*/ */
public BecomesCreatureSourceEffect(Token token, CardType retainType, Duration duration) { public BecomesCreatureSourceEffect(Token token, CardType retainType, Duration duration) {
this(token, retainType, duration, (retainType == CardType.PLANESWALKER || retainType == CardType.CREATURE));
}
/**
* @param token Token as blueprint for creature to become
* @param retainType If null, permanent loses its previous types, otherwise retains types with appropriate text
* @param duration Duration for the effect
* @param durationRuleAtStart for text rule generation
*/
public BecomesCreatureSourceEffect(Token token, CardType retainType, Duration duration, boolean durationRuleAtStart) {
super(duration, Outcome.BecomeCreature); super(duration, Outcome.BecomeCreature);
this.token = token; this.token = token;
this.retainType = retainType; this.retainType = retainType;
this.durationRuleAtStart = durationRuleAtStart; this.keepCreatureSubtypes = (retainType == CardType.ENCHANTMENT); // default usage, override if needed
this.durationRuleAtStart = (retainType == CardType.PLANESWALKER || retainType == CardType.CREATURE);
setText(); setText();
this.addDependencyType(DependencyType.BecomeCreature); this.addDependencyType(DependencyType.BecomeCreature);
} }
@ -73,6 +65,7 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl {
this.retainType = effect.retainType; this.retainType = effect.retainType;
this.loseAbilities = effect.loseAbilities; this.loseAbilities = effect.loseAbilities;
this.loseEquipmentType = effect.loseEquipmentType; this.loseEquipmentType = effect.loseEquipmentType;
this.keepCreatureSubtypes = effect.keepCreatureSubtypes;
if (effect.power != null) { if (effect.power != null) {
this.power = effect.power.copy(); this.power = effect.power.copy();
} }
@ -124,7 +117,7 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl {
if (loseEquipmentType) { if (loseEquipmentType) {
permanent.removeSubType(game, SubType.EQUIPMENT); permanent.removeSubType(game, SubType.EQUIPMENT);
} }
if (retainType == CardType.CREATURE || retainType == CardType.ARTIFACT) { if (!keepCreatureSubtypes) {
permanent.removeAllCreatureTypes(game); permanent.removeAllCreatureTypes(game);
} }
permanent.copySubTypesFrom(game, token); permanent.copySubTypesFrom(game, token);
@ -191,6 +184,16 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl {
return this; return this;
} }
/**
* Source becomes a creature "in addition to its other types".
* Not needed when retainType is ENCHANTMENT, which sets this true by default.
*/
public BecomesCreatureSourceEffect withKeepCreatureSubtypes(boolean keepCreatureSubtypes) {
this.keepCreatureSubtypes = keepCreatureSubtypes;
setText();
return this;
}
public BecomesCreatureSourceEffect withDurationRuleAtStart(boolean durationRuleAtStart) { public BecomesCreatureSourceEffect withDurationRuleAtStart(boolean durationRuleAtStart) {
this.durationRuleAtStart = durationRuleAtStart; this.durationRuleAtStart = durationRuleAtStart;
setText(); setText();
@ -205,7 +208,7 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl {
} }
sb.append("{this} becomes a "); sb.append("{this} becomes a ");
sb.append(token.getDescription()); sb.append(token.getDescription());
if (retainType == CardType.ENCHANTMENT) { if (keepCreatureSubtypes) {
sb.append(" in addition to its other types"); sb.append(" in addition to its other types");
} }
if (!duration.toString().isEmpty() && !durationRuleAtStart) { if (!duration.toString().isEmpty() && !durationRuleAtStart) {