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(
0, 0, "0/0 Spirit creature", SubType.SPIRIT
), CardType.ARTIFACT, Duration.Custom));
), CardType.ARTIFACT, Duration.Custom).withKeepCreatureSubtypes(true));
this.addAbility(ability);
}

View file

@ -46,8 +46,8 @@ public final class RestlessSpire extends CardImpl {
new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.WhileOnBattlefield),
MyTurnCondition.instance, "As long as it's your turn, this creature has first strike."
)).addHint(MyTurnHint.instance)),
CardType.LAND, Duration.EndOfTurn, true
), new ManaCostsImpl<>("{U}{R}")));
CardType.LAND, Duration.EndOfTurn
).withDurationRuleAtStart(true), new ManaCostsImpl<>("{U}{R}")));
// Whenever Restless Spire attacks, scry 1.
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")
.withColor("GU").withSubType(SubType.PLANT)
.withAbility(TrampleAbility.getInstance()),
CardType.LAND, Duration.EndOfTurn, true
), new ManaCostsImpl<>("{3}{G}{U}")));
CardType.LAND, Duration.EndOfTurn
).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.
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.
*/
protected Token token;
protected CardType retainType; // if null, loses previous types
protected boolean loseAbilities = false;
protected boolean loseEquipmentType = false;
protected DynamicValue power = null;
protected DynamicValue toughness = null;
protected boolean durationRuleAtStart; // put duration rule at the start of the rules text rather than the end
private final Token token;
private final CardType retainType; // if null, loses previous types
private boolean loseAbilities = false;
private boolean loseEquipmentType = false;
private boolean keepCreatureSubtypes;
private DynamicValue power = null;
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
@ -49,20 +50,11 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl {
* @param duration Duration for the effect
*/
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);
this.token = token;
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();
this.addDependencyType(DependencyType.BecomeCreature);
}
@ -73,6 +65,7 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl {
this.retainType = effect.retainType;
this.loseAbilities = effect.loseAbilities;
this.loseEquipmentType = effect.loseEquipmentType;
this.keepCreatureSubtypes = effect.keepCreatureSubtypes;
if (effect.power != null) {
this.power = effect.power.copy();
}
@ -124,7 +117,7 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl {
if (loseEquipmentType) {
permanent.removeSubType(game, SubType.EQUIPMENT);
}
if (retainType == CardType.CREATURE || retainType == CardType.ARTIFACT) {
if (!keepCreatureSubtypes) {
permanent.removeAllCreatureTypes(game);
}
permanent.copySubTypesFrom(game, token);
@ -191,6 +184,16 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl {
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) {
this.durationRuleAtStart = durationRuleAtStart;
setText();
@ -205,7 +208,7 @@ public class BecomesCreatureSourceEffect extends ContinuousEffectImpl {
}
sb.append("{this} becomes a ");
sb.append(token.getDescription());
if (retainType == CardType.ENCHANTMENT) {
if (keepCreatureSubtypes) {
sb.append(" in addition to its other types");
}
if (!duration.toString().isEmpty() && !durationRuleAtStart) {