forked from External/mage
Implement Prototype ability (#11249)
Prototype is a SpellAbilityType, for which alternate costs are permitted. It has a continuous effect that applies on the battlefield as well as a method to modify the spell on the stack. Permanents have an isPrototyped flag that copy effects can check explicitly (same brittle method as transformed permanents use; reworking copy effects to streamline them is a separate scope). Many test cases have been added to confirm functionality (thanks to Zerris for additional test suggestions). --------- Co-authored-by: Susucre <34709007+Susucre@users.noreply.github.com> Co-authored-by: Evan Kranzler <theelk801@gmail.com> Co-authored-by: xenohedron <xenohedron@users.noreply.github.com>
This commit is contained in:
parent
ac20483b73
commit
5e095afdb0
23 changed files with 946 additions and 17 deletions
|
|
@ -442,6 +442,9 @@ public abstract class AbilityImpl implements Ability {
|
|||
// mandatory additional costs the spell has, such as that of Tormenting Voice. (2018-12-07)
|
||||
canUseAdditionalCost = true;
|
||||
break;
|
||||
case PROTOTYPE:
|
||||
// Notably, casting a spell as a prototype does not count as paying an alternative cost.
|
||||
// https://magic.wizards.com/en/news/feature/comprehensive-rules-changes
|
||||
case NORMAL:
|
||||
canUseAlternativeCost = true;
|
||||
canUseAdditionalCost = true;
|
||||
|
|
|
|||
|
|
@ -322,7 +322,7 @@ public class SpellAbility extends ActivatedAbilityImpl {
|
|||
}
|
||||
if (spellCharacteristics != null) {
|
||||
if (getSpellAbilityCastMode() != SpellAbilityCastMode.NORMAL) {
|
||||
spellCharacteristics = getSpellAbilityCastMode().getTypeModifiedCardObjectCopy(spellCharacteristics, game);
|
||||
spellCharacteristics = getSpellAbilityCastMode().getTypeModifiedCardObjectCopy(spellCharacteristics, this);
|
||||
}
|
||||
}
|
||||
return spellCharacteristics;
|
||||
|
|
|
|||
|
|
@ -146,6 +146,7 @@ public class CopyEffect extends ContinuousEffectImpl {
|
|||
//permanent.setSecondCardFace(targetPermanent.getSecondCardFace());
|
||||
permanent.setFlipCard(targetPermanent.isFlipCard());
|
||||
permanent.setFlipCardName(targetPermanent.getFlipCardName());
|
||||
permanent.setPrototyped(targetPermanent.isPrototyped());
|
||||
}
|
||||
|
||||
CardUtil.copySetAndCardNumber(permanent, copyFromObject);
|
||||
|
|
|
|||
|
|
@ -1,21 +1,48 @@
|
|||
package mage.abilities.keyword;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.*;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
* @author TheElk801, Susucr, notgreat
|
||||
*/
|
||||
public class PrototypeAbility extends SpellAbility {
|
||||
|
||||
private final int power;
|
||||
private final int toughness;
|
||||
private final String manaString;
|
||||
private final String rule;
|
||||
|
||||
public PrototypeAbility(Card card, String manaString, int power, int toughness) {
|
||||
super(new ManaCostsImpl<>(manaString), card.getName());
|
||||
// TODO: implement this
|
||||
this.setSpellAbilityCastMode(SpellAbilityCastMode.PROTOTYPE);
|
||||
this.setTiming(TimingRule.SORCERY);
|
||||
this.addSubAbility(new SimpleStaticAbility(
|
||||
Zone.BATTLEFIELD, new PrototypeEffect(power, toughness, manaString)
|
||||
).setRuleVisible(false));
|
||||
this.rule = "Prototype " + manaString + " — " + power + "/" + toughness +
|
||||
" <i>(You may cast this spell with different mana cost, color, and size. It keeps its abilities and types.)</i>";
|
||||
setRuleAtTheTop(true);
|
||||
this.power = power;
|
||||
this.toughness = toughness;
|
||||
this.manaString = manaString;
|
||||
}
|
||||
|
||||
private PrototypeAbility(final PrototypeAbility ability) {
|
||||
super(ability);
|
||||
this.rule = ability.rule;
|
||||
this.power = ability.power;
|
||||
this.toughness = ability.toughness;
|
||||
this.manaString = ability.manaString;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -25,6 +52,68 @@ public class PrototypeAbility extends SpellAbility {
|
|||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Prototype";
|
||||
return rule;
|
||||
}
|
||||
|
||||
//based on TransformAbility
|
||||
public Card prototypeCardSpell(Card original) {
|
||||
Card newCard = original.copy();
|
||||
newCard.setManaCost(new ManaCostsImpl<>(manaString));
|
||||
newCard.getPower().setModifiedBaseValue(power);
|
||||
newCard.getToughness().setModifiedBaseValue(toughness);
|
||||
newCard.getColor().setColor(new ObjectColor(manaString));
|
||||
return newCard;
|
||||
}
|
||||
|
||||
public void prototypePermanent(MageObject targetObject, Game game) {
|
||||
if (targetObject instanceof Permanent) {
|
||||
((Permanent)targetObject).setPrototyped(true);
|
||||
}
|
||||
targetObject.getColor(game).setColor(new ObjectColor(manaString));
|
||||
targetObject.setManaCost(new ManaCostsImpl<>(manaString));
|
||||
targetObject.getPower().setModifiedBaseValue(power);
|
||||
targetObject.getToughness().setModifiedBaseValue(toughness);
|
||||
}
|
||||
}
|
||||
|
||||
class PrototypeEffect extends ContinuousEffectImpl {
|
||||
|
||||
private final int power;
|
||||
private final int toughness;
|
||||
private final String manaString;
|
||||
private final ObjectColor color;
|
||||
|
||||
PrototypeEffect(int power, int toughness, String manaString) {
|
||||
super(Duration.EndOfGame, Layer.CopyEffects_1, SubLayer.CopyEffects_1a, Outcome.Benefit);
|
||||
this.power = power;
|
||||
this.toughness = toughness;
|
||||
this.manaString = manaString;
|
||||
this.color = new ObjectColor(manaString);
|
||||
}
|
||||
|
||||
private PrototypeEffect(final PrototypeEffect effect) {
|
||||
super(effect);
|
||||
this.power = effect.power;
|
||||
this.toughness = effect.toughness;
|
||||
this.manaString = effect.manaString;
|
||||
this.color = effect.color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrototypeEffect copy() {
|
||||
return new PrototypeEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (permanent == null || !permanent.isPrototyped()) {
|
||||
return false;
|
||||
}
|
||||
permanent.setManaCost(new ManaCostsImpl<>(manaString));
|
||||
permanent.getColor(game).setColor(color);
|
||||
permanent.getPower().setModifiedBaseValue(power);
|
||||
permanent.getToughness().setModifiedBaseValue(toughness);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue