Merge branch 'shardAlternateCost' into 'master'

AlternateCost for Mirrodin Shards

See merge request core-developers/forge!5985
This commit is contained in:
Michael Kamensky
2021-12-28 04:14:24 +00:00
12 changed files with 83 additions and 58 deletions

View File

@@ -92,6 +92,9 @@ public abstract class CardTraitBase extends GameObject implements IHasCardView,
public String putParam(String key, String value) {
return mapParams.put(key, value);
}
public void removeParam(String key) {
mapParams.remove(key);
}
/**
* <p>
* Getter for the field <code>mapParams</code>.

View File

@@ -482,40 +482,62 @@ public final class GameActionUtil {
public static List<SpellAbility> getAdditionalCostSpell(final SpellAbility sa) {
final List<SpellAbility> abilities = Lists.newArrayList(sa);
if (!sa.isSpell()) {
return abilities;
}
final Card source = sa.getHostCard();
for (KeywordInterface inst : source.getKeywords()) {
final String keyword = inst.getOriginal();
if (keyword.startsWith("AlternateAdditionalCost")) {
final List<SpellAbility> newAbilities = Lists.newArrayList();
String[] costs = TextUtil.split(keyword, ':');
if (sa.isSpell()) {
final Card source = sa.getHostCard();
for (KeywordInterface inst : source.getKeywords()) {
final String keyword = inst.getOriginal();
if (keyword.startsWith("AlternateAdditionalCost")) {
final List<SpellAbility> newAbilities = Lists.newArrayList();
String[] costs = TextUtil.split(keyword, ':');
final SpellAbility newSA = sa.copy();
newSA.setBasicSpell(false);
final SpellAbility newSA = sa.copy();
newSA.setBasicSpell(false);
final Cost cost1 = new Cost(costs[1], false);
newSA.setDescription(sa.getDescription() + " (Additional cost " + cost1.toSimpleString() + ")");
newSA.setPayCosts(cost1.add(sa.getPayCosts()));
if (newSA.canPlay()) {
newAbilities.add(newSA);
final Cost cost1 = new Cost(costs[1], false);
newSA.setDescription(sa.getDescription() + " (Additional cost " + cost1.toSimpleString() + ")");
newSA.setPayCosts(cost1.add(sa.getPayCosts()));
if (newSA.canPlay()) {
newAbilities.add(newSA);
}
//second option
final SpellAbility newSA2 = sa.copy();
newSA2.setBasicSpell(false);
final Cost cost2 = new Cost(costs[2], false);
newSA2.setDescription(sa.getDescription() + " (Additional cost " + cost2.toSimpleString() + ")");
newSA2.setPayCosts(cost2.add(sa.getPayCosts()));
if (newSA2.canPlay()) {
newAbilities.add(newSA2);
}
abilities.clear();
abilities.addAll(newAbilities);
}
//second option
final SpellAbility newSA2 = sa.copy();
newSA2.setBasicSpell(false);
final Cost cost2 = new Cost(costs[2], false);
newSA2.setDescription(sa.getDescription() + " (Additional cost " + cost2.toSimpleString() + ")");
newSA2.setPayCosts(cost2.add(sa.getPayCosts()));
if (newSA2.canPlay()) {
newAbilities.add(newSA2);
}
abilities.clear();
abilities.addAll(newAbilities);
}
} else if (sa.isActivatedAbility() && sa.hasParam("AlternateCost")) {
// need to be handled there because it needs to rebuilt the description for the original ability
final List<SpellAbility> newAbilities = Lists.newArrayList();
SpellAbility newSA = sa.copy();
newSA.removeParam("AlternateCost");
newSA.rebuiltDescription();
if (newSA.canPlay()) {
newAbilities.add(newSA);
}
// set the cost to this directly to bypass non mana cost
Cost alternateCost = new Cost(sa.getParam("AlternateCost"), sa.isAbility());
SpellAbility newSA2 = sa.copyWithDefinedCost(alternateCost);
newSA2.removeParam("AlternateCost");
newSA2.rebuiltDescription();
if (newSA2.canPlay()) {
newAbilities.add(newSA2);
}
abilities.clear();
abilities.addAll(newAbilities);
}
return abilities;
}

View File

@@ -301,15 +301,7 @@ public final class AbilityFactory {
: spellAbility.getHostCard().getName();
spellAbility.setDescription(desc);
} else if (mapParams.containsKey("SpellDescription")) {
final StringBuilder sb = new StringBuilder();
if (type != AbilityRecordType.SubAbility) {
// SubAbilities don't have Costs or Cost descriptors
sb.append(spellAbility.getCostDescription());
}
sb.append(mapParams.get("SpellDescription"));
spellAbility.setDescription(sb.toString());
spellAbility.rebuiltDescription();
} else if (api == ApiType.Charm) {
spellAbility.setDescription(CharmEffect.makeFormatedDescription(spellAbility));
} else {

View File

@@ -1962,7 +1962,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
if (mCost.isOnlyManaCost()) {
sbLong.append(" ");
}
sbLong.append(mCost.toString()).delete(sbLong.length() - 2, sbLong.length());
sbLong.append(mCost.toString());
if (!mCost.isOnlyManaCost()) {
sbLong.append(".");
}

View File

@@ -776,7 +776,6 @@ public class Cost implements Serializable {
cost.append("0");
}
cost.append(": ");
return cost.toString();
}

View File

@@ -841,11 +841,32 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
sb.append(getParam("CostDesc")).append(" ");
} else {
sb.append(payCosts.toString());
// for cards like Crystal Shard with {3}, {T} or {U}, {T}:
if (hasParam("AlternateCost")) {
Cost alternateCost = new Cost(getParam("AlternateCost"), payCosts.isAbility());
sb.append(" or ").append(alternateCost.toString());
}
if (payCosts.isAbility()) {
sb.append(": ");
}
}
return sb.toString();
}
}
public void rebuiltDescription() {
final StringBuilder sb = new StringBuilder();
// SubAbilities don't have Costs or Cost descriptors
sb.append(getCostDescription());
sb.append(getParam("SpellDescription"));
setDescription(sb.toString());
}
/** {@inheritDoc} */
@Override
public final String toString() {

View File

@@ -1,8 +1,7 @@
Name:Crystal Shard
ManaCost:3
Types:Artifact
A:AB$ ChangeZone | Cost$ 3 T | ValidTgts$ Creature | TgtPrompt$ Select target creature | Origin$ Battlefield | Destination$ Hand | UnlessCost$ 1 | UnlessPayer$ TargetedController | SpellDescription$ Return target creature to its owner's hand unless its controller pays {1}.
A:AB$ ChangeZone | Cost$ U T | ValidTgts$ Creature | TgtPrompt$ Select target creature | Origin$ Battlefield | Destination$ Hand | UnlessCost$ 1 | UnlessPayer$ TargetedController | SpellDescription$ Return target creature to its owner's hand unless its controller pays {1}.
A:AB$ ChangeZone | Cost$ 3 T | AlternateCost$ U T | ValidTgts$ Creature | TgtPrompt$ Select target creature | Origin$ Battlefield | Destination$ Hand | UnlessCost$ 1 | UnlessPayer$ TargetedController | SpellDescription$ Return target creature to its owner's hand unless its controller pays {1}.
AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/crystal_shard.jpg
Oracle:{3}, {T} or {U}, {T}: Return target creature to its owner's hand unless its controller pays {1}.

View File

@@ -1,7 +1,5 @@
Name:Granite Shard
ManaCost:3
Types:Artifact
A:AB$ DealDamage | Cost$ 3 T | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 1 | SpellDescription$ CARDNAME deals 1 damage to any target.
A:AB$ DealDamage | Cost$ R T | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 1 | SpellDescription$ CARDNAME deals 1 damage to any target.
SVar:Picture:http://www.wizards.com/global/images/magic/general/granite_shard.jpg
A:AB$ DealDamage | Cost$ 3 T | AlternateCost$ R T | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 1 | SpellDescription$ CARDNAME deals 1 damage to any target.
Oracle:{3}, {T} or {R}, {T}: Granite Shard deals 1 damage to any target.

View File

@@ -1,8 +1,6 @@
Name:Heartwood Shard
ManaCost:3
Types:Artifact
A:AB$ Pump | Cost$ 3 T | ValidTgts$ Creature | TgtPrompt$ Select target creature | KW$ Trample | SpellDescription$ Target creature gains trample until end of turn.
A:AB$ Pump | Cost$ G T | ValidTgts$ Creature | TgtPrompt$ Select target creature | KW$ Trample | SpellDescription$ Target creature gains trample until end of turn.
A:AB$ Pump | Cost$ 3 T | AlternateCost$ G T | ValidTgts$ Creature | TgtPrompt$ Select target creature | KW$ Trample | SpellDescription$ Target creature gains trample until end of turn.
AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/heartwood_shard.jpg
Oracle:{3}, {T} or {G}, {T}: Target creature gains trample until end of turn.

View File

@@ -1,7 +1,5 @@
Name:Pearl Shard
ManaCost:3
Types:Artifact
A:AB$ PreventDamage | Cost$ 3 T | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | Amount$ 2 | SpellDescription$ Prevent the next 2 damage that would be dealt to any target this turn.
A:AB$ PreventDamage | Cost$ W T | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | Amount$ 2 | SpellDescription$ Prevent the next 2 damage that would be dealt to any target this turn.
SVar:Picture:http://www.wizards.com/global/images/magic/general/pearl_shard.jpg
A:AB$ PreventDamage | Cost$ 3 T | AlternateCost$ W T | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | Amount$ 2 | SpellDescription$ Prevent the next 2 damage that would be dealt to any target this turn.
Oracle:{3}, {T} or {W}, {T}: Prevent the next 2 damage that would be dealt to any target this turn.

View File

@@ -1,8 +1,6 @@
Name:Skeleton Shard
ManaCost:3
Types:Artifact
A:AB$ ChangeZone | Cost$ 3 T | ValidTgts$ Creature.Artifact+YouCtrl | TgtPrompt$ Choose target artifact creature card in your graveyard | Origin$ Graveyard | Destination$ Hand | SpellDescription$ Return target artifact creature card from your graveyard to your hand.
A:AB$ ChangeZone | Cost$ B T | ValidTgts$ Creature.Artifact+YouCtrl | TgtPrompt$ Choose target artifact creature card in your graveyard | Origin$ Graveyard | Destination$ Hand | SpellDescription$ Return target artifact creature card from your graveyard to your hand.
A:AB$ ChangeZone | Cost$ 3 T | AlternateCost$ B T | ValidTgts$ Creature.Artifact+YouCtrl | TgtPrompt$ Choose target artifact creature card in your graveyard | Origin$ Graveyard | Destination$ Hand | SpellDescription$ Return target artifact creature card from your graveyard to your hand.
AI:RemoveDeck:Random
SVar:Picture:http://www.wizards.com/global/images/magic/general/skeleton_shard.jpg
Oracle:{3}, {T} or {B}, {T}: Return target artifact creature card from your graveyard to your hand.

View File

@@ -139,9 +139,6 @@ public class HumanPlay {
* @return an ArrayList<SpellAbility>.
*/
static SpellAbility chooseOptionalAdditionalCosts(Player p, final SpellAbility original) {
if (!original.isSpell()) {
return original;
}
PlayerController c = p.getController();