Some support for Desert Cenote (#7505)

---------

Co-authored-by: tool4EvEr <tool4EvEr@>
This commit is contained in:
tool4ever
2025-05-11 20:19:37 +02:00
committed by GitHub
parent ca59ac925c
commit 059881a7b5
28 changed files with 101 additions and 132 deletions

View File

@@ -93,7 +93,6 @@ public enum AbilityKey {
Mana("Mana"), Mana("Mana"),
MergedCards("MergedCards"), MergedCards("MergedCards"),
Mode("Mode"), Mode("Mode"),
Modifier("Modifier"),
MonstrosityAmount("MonstrosityAmount"), MonstrosityAmount("MonstrosityAmount"),
NaturalResult("NaturalResult"), NaturalResult("NaturalResult"),
NewCard("NewCard"), NewCard("NewCard"),

View File

@@ -2220,7 +2220,7 @@ public class AbilityUtils {
// Count$IfCastInOwnMainPhase.<numMain>.<numNotMain> // 7/10 // Count$IfCastInOwnMainPhase.<numMain>.<numNotMain> // 7/10
if (sq[0].contains("IfCastInOwnMainPhase")) { if (sq[0].contains("IfCastInOwnMainPhase")) {
final PhaseHandler cPhase = game.getPhaseHandler(); final PhaseHandler cPhase = game.getPhaseHandler();
final boolean isMyMain = cPhase.getPhase().isMain() && cPhase.isPlayerTurn(player) && c.getCastFrom() != null; final boolean isMyMain = cPhase.getPhase().isMain() && cPhase.isPlayerTurn(player) && c.wasCast();
return doXMath(Integer.parseInt(sq[isMyMain ? 1 : 2]), expr, c, ctb); return doXMath(Integer.parseInt(sq[isMyMain ? 1 : 2]), expr, c, ctb);
} }
@@ -2480,7 +2480,6 @@ public class AbilityUtils {
// But these aren't really things you count so they'll show up in properties most likely // But these aren't really things you count so they'll show up in properties most likely
} }
//Count$TypesSharedWith [defined] //Count$TypesSharedWith [defined]
if (sq[0].startsWith("TypesSharedWith")) { if (sq[0].startsWith("TypesSharedWith")) {
Set<CardType.CoreType> thisTypes = Sets.newHashSet(c.getType().getCoreTypes()); Set<CardType.CoreType> thisTypes = Sets.newHashSet(c.getType().getCoreTypes());

View File

@@ -1016,8 +1016,9 @@ public abstract class SpellAbilityEffect {
return true; return true;
} }
public static Player getNewChooser(final SpellAbility sa, final Player activator, final Player loser) { public static Player getNewChooser(final SpellAbility sa, final Player loser) {
// CR 800.4g // CR 800.4g
final Player activator = sa.getActivatingPlayer();
final PlayerCollection options; final PlayerCollection options;
if (loser.isOpponentOf(activator)) { if (loser.isOpponentOf(activator)) {
options = activator.getOpponents(); options = activator.getOpponents();

View File

@@ -103,7 +103,7 @@ public class ChooseCardEffect extends SpellAbilityEffect {
CardCollectionView pChoices = choices; CardCollectionView pChoices = choices;
CardCollection chosen = new CardCollection(); CardCollection chosen = new CardCollection();
if (!p.isInGame()) { if (!p.isInGame()) {
p = getNewChooser(sa, activator, p); p = getNewChooser(sa, p);
} }
if (sa.hasParam("ControlledByPlayer")) { if (sa.hasParam("ControlledByPlayer")) {
final String param = sa.getParam("ControlledByPlayer"); final String param = sa.getParam("ControlledByPlayer");

View File

@@ -1,9 +1,12 @@
package forge.game.ability.effects; package forge.game.ability.effects;
import forge.card.ColorSet;
import forge.card.MagicColor; import forge.card.MagicColor;
import forge.deck.DeckRecognizer; import forge.deck.DeckRecognizer;
import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect; import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardUtil;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import forge.util.Aggregates; import forge.util.Aggregates;
@@ -41,6 +44,13 @@ public class ChooseColorEffect extends SpellAbilityEffect {
String[] restrictedChoices = sa.getParam("Choices").split(","); String[] restrictedChoices = sa.getParam("Choices").split(",");
colorChoices = Arrays.asList(restrictedChoices); colorChoices = Arrays.asList(restrictedChoices);
} }
if (sa.hasParam("ColorsFrom")) {
ColorSet cs = CardUtil.getColorsFromCards(AbilityUtils.getDefinedCards(card, sa.getParam("ColorsFrom"), sa));
if (cs.isColorless()) {
return;
}
colorChoices = cs.stream().map(Object::toString).collect(Collectors.toCollection(ArrayList::new));
}
if (sa.hasParam("Exclude")) { if (sa.hasParam("Exclude")) {
for (String s : sa.getParam("Exclude").split(",")) { for (String s : sa.getParam("Exclude").split(",")) {
colorChoices.remove(s); colorChoices.remove(s);
@@ -49,24 +59,22 @@ public class ChooseColorEffect extends SpellAbilityEffect {
for (Player p : getTargetPlayers(sa)) { for (Player p : getTargetPlayers(sa)) {
if (!p.isInGame()) { if (!p.isInGame()) {
p = getNewChooser(sa, sa.getActivatingPlayer(), p); p = getNewChooser(sa, p);
} }
List<String> chosenColors = new ArrayList<>(); List<String> chosenColors = new ArrayList<>();
int cntMin = sa.hasParam("TwoColors") ? 2 : 1; int cntMin = sa.hasParam("UpTo") ? 0 : sa.hasParam("TwoColors") ? 2 : 1;
int cntMax = sa.hasParam("TwoColors") ? 2 : sa.hasParam("OrColors") ? colorChoices.size() : 1; int cntMax = sa.hasParam("TwoColors") ? 2 : sa.hasParam("OrColors") ? colorChoices.size() : 1;
String prompt = null; String prompt = null;
if (cntMax == 1) { if (cntMax == 1) {
prompt = Localizer.getInstance().getMessage("lblChooseAColor"); prompt = Localizer.getInstance().getMessage("lblChooseAColor");
} else { } else if (cntMax > cntMin) {
if (cntMax > cntMin) { if (cntMax >= MagicColor.NUMBER_OR_COLORS) {
if (cntMax >= MagicColor.NUMBER_OR_COLORS) { prompt = Localizer.getInstance().getMessage("lblAtLastChooseNumColors", Lang.getNumeral(cntMin));
prompt = Localizer.getInstance().getMessage("lblAtLastChooseNumColors", Lang.getNumeral(cntMin));
} else {
prompt = Localizer.getInstance().getMessage("lblChooseSpecifiedRangeColors", Lang.getNumeral(cntMin), Lang.getNumeral(cntMax));
}
} else { } else {
prompt = Localizer.getInstance().getMessage("lblChooseNColors", Lang.getNumeral(cntMax)); prompt = Localizer.getInstance().getMessage("lblChooseSpecifiedRangeColors", Lang.getNumeral(cntMin), Lang.getNumeral(cntMax));
} }
} else {
prompt = Localizer.getInstance().getMessage("lblChooseNColors", Lang.getNumeral(cntMax));
} }
Player noNotify = p; Player noNotify = p;
if (sa.hasParam("Random")) { if (sa.hasParam("Random")) {

View File

@@ -62,7 +62,7 @@ public class ChooseGenericEffect extends SpellAbilityEffect {
for (Player p : getDefinedPlayersOrTargeted(sa)) { for (Player p : getDefinedPlayersOrTargeted(sa)) {
if (!p.isInGame()) { if (!p.isInGame()) {
p = getNewChooser(sa, sa.getActivatingPlayer(), p); p = getNewChooser(sa, p);
} }
// determine if any of the choices are not valid // determine if any of the choices are not valid
@@ -116,7 +116,6 @@ public class ChooseGenericEffect extends SpellAbilityEffect {
} else if (secretly) { } else if (secretly) {
if (record.length() > 0) record.append("\r\n"); if (record.length() > 0) record.append("\r\n");
record.append(Localizer.getInstance().getMessage("lblPlayerChooseValue", p, chosenValue)); record.append(Localizer.getInstance().getMessage("lblPlayerChooseValue", p, chosenValue));
} }
if (sa.hasParam("SetChosenMode")) { if (sa.hasParam("SetChosenMode")) {
sa.getHostCard().setChosenMode(chosenValue); sa.getHostCard().setChosenMode(chosenValue);

View File

@@ -22,7 +22,7 @@ public class EndTurnEffect extends SpellAbilityEffect {
final List<Player> enders = getDefinedPlayersOrTargeted(sa, "Defined"); final List<Player> enders = getDefinedPlayersOrTargeted(sa, "Defined");
Player ender = enders.isEmpty() ? sa.getActivatingPlayer() : enders.get(0); Player ender = enders.isEmpty() ? sa.getActivatingPlayer() : enders.get(0);
if (!ender.isInGame()) { if (!ender.isInGame()) {
ender = getNewChooser(sa, sa.getActivatingPlayer(), ender); ender = getNewChooser(sa, ender);
} }
if (sa.hasParam("Optional") && !ender.getController().confirmAction(sa, null, Localizer.getInstance().getMessage("lblDoYouWantEndTurn"), null)) { if (sa.hasParam("Optional") && !ender.getController().confirmAction(sa, null, Localizer.getInstance().getMessage("lblDoYouWantEndTurn"), null)) {

View File

@@ -60,18 +60,21 @@ public class ManaEffect extends SpellAbilityEffect {
if (abMana.isComboMana()) { if (abMana.isComboMana()) {
int amount = sa.hasParam("Amount") ? AbilityUtils.calculateAmount(card, sa.getParam("Amount"), sa) : 1; int amount = sa.hasParam("Amount") ? AbilityUtils.calculateAmount(card, sa.getParam("Amount"), sa) : 1;
if(amount <= 0) if (amount <= 0)
continue; continue;
String express = abMana.getExpressChoice(); String combo = abMana.getComboColors(sa);
String[] colorsProduced = abMana.getComboColors(sa).split(" "); if (combo.isBlank()) {
return;
final StringBuilder choiceString = new StringBuilder(); }
final StringBuilder choiceSymbols = new StringBuilder(); String[] colorsProduced = combo.split(" ");
ColorSet colorOptions = ColorSet.fromNames(colorsProduced); ColorSet colorOptions = ColorSet.fromNames(colorsProduced);
String express = abMana.getExpressChoice();
String[] colorsNeeded = express.isEmpty() ? null : express.split(" "); String[] colorsNeeded = express.isEmpty() ? null : express.split(" ");
boolean differentChoice = abMana.getOrigProduced().contains("Different"); boolean differentChoice = abMana.getOrigProduced().contains("Different");
ColorSet fullOptions = colorOptions; ColorSet fullOptions = colorOptions;
final StringBuilder choiceString = new StringBuilder();
final StringBuilder choiceSymbols = new StringBuilder();
// Use specifyManaCombo if possible // Use specifyManaCombo if possible
if (colorsNeeded == null && amount > 1 && !sa.hasParam("TwoEach")) { if (colorsNeeded == null && amount > 1 && !sa.hasParam("TwoEach")) {
Map<Byte, Integer> choices = chooser.getController().specifyManaCombo(sa, colorOptions, amount, differentChoice); Map<Byte, Integer> choices = chooser.getController().specifyManaCombo(sa, colorOptions, amount, differentChoice);

View File

@@ -319,7 +319,6 @@ public class RollDiceEffect extends SpellAbilityEffect {
for (DieRollResult roll : resultsList) { for (DieRollResult roll : resultsList) {
final Map<AbilityKey, Object> runParams = AbilityKey.mapFromPlayer(player); final Map<AbilityKey, Object> runParams = AbilityKey.mapFromPlayer(player);
runParams.put(AbilityKey.Sides, sides); runParams.put(AbilityKey.Sides, sides);
runParams.put(AbilityKey.Modifier, modifier);
runParams.put(AbilityKey.Result, roll.getModifiedValue()); runParams.put(AbilityKey.Result, roll.getModifiedValue());
runParams.put(AbilityKey.NaturalResult, roll.getNaturalValue()); runParams.put(AbilityKey.NaturalResult, roll.getNaturalValue());
runParams.put(AbilityKey.RolledToVisitAttractions, toVisitAttractions); runParams.put(AbilityKey.RolledToVisitAttractions, toVisitAttractions);

View File

@@ -2625,8 +2625,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
|| keyword.startsWith("Graft") || keyword.startsWith("Fading") || keyword.startsWith("Vanishing:") || keyword.startsWith("Graft") || keyword.startsWith("Fading") || keyword.startsWith("Vanishing:")
|| keyword.startsWith("Afterlife") || keyword.startsWith("Hideaway") || keyword.startsWith("Toxic") || keyword.startsWith("Afterlife") || keyword.startsWith("Hideaway") || keyword.startsWith("Toxic")
|| keyword.startsWith("Afflict") || keyword.startsWith ("Poisonous") || keyword.startsWith("Rampage") || keyword.startsWith("Afflict") || keyword.startsWith ("Poisonous") || keyword.startsWith("Rampage")
|| keyword.startsWith("Renown") || keyword.startsWith("Annihilator") || keyword.startsWith("Devour") || keyword.startsWith("Renown") || keyword.startsWith("Annihilator") || keyword.startsWith("Devour")) {
|| keyword.startsWith("Mobilize")) {
final String[] k = keyword.split(":"); final String[] k = keyword.split(":");
sbLong.append(k[0]).append(" ").append(k[1]).append(" (").append(inst.getReminderText()).append(")"); sbLong.append(k[0]).append(" ").append(k[1]).append(" (").append(inst.getReminderText()).append(")");
} else if (keyword.startsWith("Crew")) { } else if (keyword.startsWith("Crew")) {
@@ -2667,14 +2666,13 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
final String[] k = keyword.split(":"); final String[] k = keyword.split(":");
String desc = k.length > 2 ? k[2] : CardType.getPluralType(k[1]); String desc = k.length > 2 ? k[2] : CardType.getPluralType(k[1]);
sbLong.append(k[0]).append(" ").append(desc).append(" (").append(inst.getReminderText()).append(")"); sbLong.append(k[0]).append(" ").append(desc).append(" (").append(inst.getReminderText()).append(")");
} else if (keyword.equals("Convoke") || keyword.equals("Dethrone")|| keyword.equals("Fear") } else if (keyword.equals("Convoke") || keyword.equals("Dethrone") || keyword.equals("Fear")
|| keyword.equals("Melee") || keyword.equals("Improvise")|| keyword.equals("Shroud") || keyword.equals("Melee") || keyword.equals("Improvise") || keyword.equals("Shroud")
|| keyword.equals("Banding") || keyword.equals("Intimidate")|| keyword.equals("Evolve") || keyword.equals("Banding") || keyword.equals("Intimidate") || keyword.equals("Evolve")
|| keyword.equals("Exalted") || keyword.equals("Extort")|| keyword.equals("Flanking") || keyword.equals("Exalted") || keyword.equals("Extort") || keyword.equals("Flanking")
|| keyword.equals("Horsemanship") || keyword.equals("Infect")|| keyword.equals("Persist") || keyword.equals("Horsemanship") || keyword.equals("Infect") || keyword.equals("Persist")
|| keyword.equals("Phasing") || keyword.equals("Shadow")|| keyword.equals("Skulk") || keyword.equals("Phasing") || keyword.equals("Shadow") || keyword.equals("Skulk")
|| keyword.equals("Undying") || keyword.equals("Wither") || keyword.equals("Undying") || keyword.equals("Wither") || keyword.equals("Bargain")
|| keyword.equals("Bargain")
|| keyword.equals("Mentor") || keyword.equals("Training")) { || keyword.equals("Mentor") || keyword.equals("Training")) {
if (sb.length() != 0) { if (sb.length() != 0) {
sb.append("\r\n"); sb.append("\r\n");
@@ -2738,7 +2736,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
|| keyword.startsWith("Class") || keyword.startsWith("Blitz") || keyword.startsWith("Class") || keyword.startsWith("Blitz")
|| keyword.startsWith("Specialize") || keyword.equals("Ravenous") || keyword.startsWith("Specialize") || keyword.equals("Ravenous")
|| keyword.equals("For Mirrodin") || keyword.startsWith("Craft") || keyword.equals("For Mirrodin") || keyword.startsWith("Craft")
|| keyword.startsWith("Landwalk") || keyword.startsWith("Visit")) { || keyword.startsWith("Landwalk") || keyword.startsWith("Visit") || keyword.startsWith("Mobilize")) {
// keyword parsing takes care of adding a proper description // keyword parsing takes care of adding a proper description
} else if (keyword.equals("Read ahead")) { } else if (keyword.equals("Read ahead")) {
sb.append(Localizer.getInstance().getMessage("lblReadAhead")).append(" (").append(Localizer.getInstance().getMessage("lblReadAheadDesc")); sb.append(Localizer.getInstance().getMessage("lblReadAhead")).append(" (").append(Localizer.getInstance().getMessage("lblReadAheadDesc"));
@@ -4817,29 +4815,6 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
perpetual.add(p); perpetual.add(p);
} }
@SuppressWarnings("unchecked")
public final void executePerpetual(Map<String, Object> p) {
final String category = (String) p.get("Category");
if (category.equals("NewPT")) {
addNewPT((Integer) p.get("Power"), (Integer) p.get("Toughness"), (long)
p.get("Timestamp"), (long) 0);
} else if (category.equals("PTBoost")) {
addPTBoost((Integer) p.get("Power"), (Integer) p.get("Toughness"), (long)
p.get("Timestamp"), (long) 0);
} else if (category.equals("Keywords")) {
boolean removeAll = p.containsKey("RemoveAll") && (boolean) p.get("RemoveAll") == true;
addChangedCardKeywords((List<String>) p.get("AddKeywords"), (List<String>) p.get("RemoveKeywords"),
removeAll, (long) p.get("Timestamp"), null);
} else if (category.equals("Types")) {
addChangedCardTypes((CardType) p.get("AddTypes"), (CardType) p.get("RemoveTypes"),
false, (Set<RemoveType>) p.get("RemoveXTypes"),
(long) p.get("Timestamp"), (long) 0, true, false);
} else if (category.equals("Colors")) {
addColor((ColorSet) p.get("Colors"), !(boolean) p.get("Overwrite"), (long) p.get("Timestamp"),
(long) 0, false);
}
}
public final void removePerpetual(final long timestamp) { public final void removePerpetual(final long timestamp) {
Map<String, Object> toRemove = Maps.newHashMap(); Map<String, Object> toRemove = Maps.newHashMap();
for (Map<String, Object> p : perpetual) { for (Map<String, Object> p : perpetual) {
@@ -4852,14 +4827,14 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
} }
public final void setPerpetual(final Card oldCard) { public final void setPerpetual(final Card oldCard) {
final List<Map<String, Object>> perp = oldCard.getPerpetual(); perpetual = oldCard.getPerpetual();
perpetual = perp; for (Map<String, Object> p : perpetual) {
for (Map<String, Object> p : perp) { final String category = (String) p.get("Category");
if (p.get("Category").equals("Abilities")) { if (category.equals("Abilities")) {
long timestamp = (long) p.get("Timestamp"); long timestamp = (long) p.get("Timestamp");
CardTraitChanges ctc = oldCard.getChangedCardTraits().get(timestamp, (long) 0).copy(this, false); CardTraitChanges ctc = oldCard.getChangedCardTraits().get(timestamp, (long) 0).copy(this, false);
addChangedCardTraits(ctc, timestamp, (long) 0); addChangedCardTraits(ctc, timestamp, (long) 0);
} else if (p.get("Category").equals("Incorporate")) { } else if (category.equals("Incorporate")) {
long ts = (long) p.get("Timestamp"); long ts = (long) p.get("Timestamp");
final ManaCost cCMC = oldCard.changedCardManaCost.get(ts, (long) 0); final ManaCost cCMC = oldCard.changedCardManaCost.get(ts, (long) 0);
addChangedManaCost(cCMC, ts, (long) 0); addChangedManaCost(cCMC, ts, (long) 0);
@@ -4868,7 +4843,24 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
if (getFirstSpellAbility() != null) { if (getFirstSpellAbility() != null) {
getFirstSpellAbility().getPayCosts().add(new Cost((String) p.get("Incorporate"), false)); getFirstSpellAbility().getPayCosts().add(new Cost((String) p.get("Incorporate"), false));
} }
} else executePerpetual(p); } else if (category.equals("NewPT")) {
addNewPT((Integer) p.get("Power"), (Integer) p.get("Toughness"), (long)
p.get("Timestamp"), (long) 0);
} else if (category.equals("PTBoost")) {
addPTBoost((Integer) p.get("Power"), (Integer) p.get("Toughness"), (long)
p.get("Timestamp"), (long) 0);
} else if (category.equals("Keywords")) {
boolean removeAll = p.containsKey("RemoveAll") && (boolean) p.get("RemoveAll") == true;
addChangedCardKeywords((List<String>) p.get("AddKeywords"), (List<String>) p.get("RemoveKeywords"),
removeAll, (long) p.get("Timestamp"), null);
} else if (category.equals("Types")) {
addChangedCardTypes((CardType) p.get("AddTypes"), (CardType) p.get("RemoveTypes"),
false, (Set<RemoveType>) p.get("RemoveXTypes"),
(long) p.get("Timestamp"), (long) 0, true, false);
} else if (category.equals("Colors")) {
addColor((ColorSet) p.get("Colors"), !(boolean) p.get("Overwrite"), (long) p.get("Timestamp"),
(long) 0, false);
}
} }
} }

View File

@@ -1529,7 +1529,7 @@ public class CardFactoryUtil {
final String[] k = keyword.split(":"); final String[] k = keyword.split(":");
final String n = k[1]; final String n = k[1];
final String trigStr = "Mode$ Attacks | ValidCard$ Card.Self | Secondary$ True" final String trigStr = "Mode$ Attacks | ValidCard$ Card.Self"
+ " | TriggerDescription$ Mobilize " + n + " (" + inst.getReminderText() + ")"; + " | TriggerDescription$ Mobilize " + n + " (" + inst.getReminderText() + ")";
final String effect = "DB$ Token | TokenAmount$ " + n + " | TokenScript$ r_1_1_warrior" final String effect = "DB$ Token | TokenAmount$ " + n + " | TokenScript$ r_1_1_warrior"

View File

@@ -504,18 +504,6 @@ public class CardProperty {
return false; return false;
} }
} }
} else if (property.startsWith("NotEnchantedBy")) {
if (property.substring(14).equals("Targeted")) {
for (final Card c : AbilityUtils.getDefinedCards(source, "Targeted", spellAbility)) {
if (card.isEnchantedBy(c)) {
return false;
}
}
} else {
if (card.isEnchantedBy(source)) {
return false;
}
}
} else if (property.startsWith("Enchanted")) { } else if (property.startsWith("Enchanted")) {
if (!source.equals(card.getEntityAttachedTo())) { if (!source.equals(card.getEntityAttachedTo())) {
return false; return false;
@@ -540,15 +528,6 @@ public class CardProperty {
return false; return false;
} }
} }
} else if (property.substring(16).equals("AllRemembered")) {
for (final Object rem : source.getRemembered()) {
if (rem instanceof Card) {
final Card c = (Card) rem;
if (!card.canBeAttached(c, null)) {
return false;
}
}
}
} else { } else {
if (!card.canBeAttached(source, null)) { if (!card.canBeAttached(source, null)) {
return false; return false;
@@ -556,12 +535,7 @@ public class CardProperty {
} }
} else if (property.startsWith("EquippedBy") || property.startsWith("AttachedBy")) { } else if (property.startsWith("EquippedBy") || property.startsWith("AttachedBy")) {
String prop = property.substring(10); String prop = property.substring(10);
if (prop.equals("Enchanted")) { if (!StringUtils.isBlank(prop)) {
if (source.getEnchantingCard() == null ||
!card.hasCardAttachment(source.getEnchantingCard())) {
return false;
}
} else if (!StringUtils.isBlank(prop)) {
boolean found = false; boolean found = false;
for (final Card c : AbilityUtils.getDefinedCards(source, prop, spellAbility)) { for (final Card c : AbilityUtils.getDefinedCards(source, prop, spellAbility)) {
if (card.hasCardAttachment(c)) { if (card.hasCardAttachment(c)) {

View File

@@ -17,6 +17,8 @@
*/ */
package forge.game.spellability; package forge.game.spellability;
import com.google.common.base.Function;
import com.google.common.collect.Iterators;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import forge.card.ColorSet; import forge.card.ColorSet;
import forge.card.GamePieceType; import forge.card.GamePieceType;
@@ -48,6 +50,7 @@ import forge.game.zone.ZoneType;
import forge.util.TextUtil; import forge.util.TextUtil;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -513,7 +516,7 @@ public class AbilityManaPart implements java.io.Serializable {
} }
String produced = this.getOrigProduced(); String produced = this.getOrigProduced();
if (produced.contains("Chosen")) { if (produced.contains("Chosen")) {
produced = produced.replace("Chosen", this.getChosenColor(sa)); produced = produced.replace("Chosen", getChosenColor(sa, sa.getHostCard().getChosenColors()));
} }
return produced; return produced;
} }
@@ -649,11 +652,18 @@ public class AbilityManaPart implements java.io.Serializable {
} }
// replace Chosen for Combo colors // replace Chosen for Combo colors
if (origProduced.contains("Chosen")) { if (origProduced.contains("Chosen")) {
origProduced = origProduced.replace("Chosen", getChosenColor(sa)); origProduced = origProduced.replace("Chosen", getChosenColor(sa, sa.getHostCard().getChosenColors()));
} }
// replace Chosen for Spire colors // replace Chosen for Spire colors
if (origProduced.contains("ColorID")) { if (origProduced.contains("ColorID")) {
origProduced = origProduced.replace("ColorID", getChosenColorID(sa)); Iterator<String> colors = Iterators.transform(sa.getHostCard().getMarkedColors().iterator(),
new Function<>() {
@Override
public String apply(Byte b) {
return MagicColor.toLongString(b);
}
});
origProduced = origProduced.replace("ColorID", getChosenColor(sa, () -> colors));
} }
if (origProduced.contains("NotedColors")) { if (origProduced.contains("NotedColors")) {
// Should only be used for Paliano, the High City // Should only be used for Paliano, the High City
@@ -698,14 +708,14 @@ public class AbilityManaPart implements java.io.Serializable {
return sb.length() == 0 ? "" : sb.substring(0, sb.length() - 1); return sb.length() == 0 ? "" : sb.substring(0, sb.length() - 1);
} }
public String getChosenColorID(SpellAbility sa) { public String getChosenColor(SpellAbility sa, Iterable<String> colors) {
if (sa == null) { if (sa == null) {
return ""; return "";
} }
Card card = sa.getHostCard(); Card card = sa.getHostCard();
if (card != null && card.hasMarkedColor()) { if (card != null) {
StringBuilder values = new StringBuilder(); StringBuilder values = new StringBuilder();
for (byte c : card.getMarkedColors()) { for (String c : colors) {
values.append(MagicColor.toShortString(c)).append(" "); values.append(MagicColor.toShortString(c)).append(" ");
} }
return values.toString(); return values.toString();
@@ -713,17 +723,6 @@ public class AbilityManaPart implements java.io.Serializable {
return ""; return "";
} }
public String getChosenColor(SpellAbility sa) {
if (sa == null) {
return "";
}
Card card = sa.getHostCard();
if (card != null && card.hasChosenColor()) {
return MagicColor.toShortString(card.getChosenColor());
}
return "";
}
public Card getSourceCard() { public Card getSourceCard() {
return sourceCard; return sourceCard;
} }

View File

@@ -175,7 +175,6 @@ public class StaticAbilityCantAttackBlock {
return true; return true;
} }
public static boolean canBlockTapped(final Card card) { public static boolean canBlockTapped(final Card card) {
final Game game = card.getGame(); final Game game = card.getGame();
for (final Card ca : game.getCardsIn(ZoneType.STATIC_ABILITIES_SOURCE_ZONES)) { for (final Card ca : game.getCardsIn(ZoneType.STATIC_ABILITIES_SOURCE_ZONES)) {
@@ -192,7 +191,6 @@ public class StaticAbilityCantAttackBlock {
return false; return false;
} }
private static boolean applyBlockTapped(final StaticAbility stAb, final Card card) { private static boolean applyBlockTapped(final StaticAbility stAb, final Card card) {
if (!stAb.matchesValidParam("ValidCard", card)) { if (!stAb.matchesValidParam("ValidCard", card)) {
return false; return false;

View File

@@ -450,7 +450,7 @@ public class WrappedAbility extends Ability {
if (decider != null) { if (decider != null) {
if (!decider.isInGame()) { if (!decider.isInGame()) {
decider = SpellAbilityEffect.getNewChooser(sa, getActivatingPlayer(), decider); decider = SpellAbilityEffect.getNewChooser(sa, decider);
} }
if (!decider.getController().confirmTrigger(this)) { if (!decider.getController().confirmTrigger(this)) {
return; return;

View File

@@ -6,6 +6,6 @@ K:Indestructible
S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | CheckSVar$ X | SVarCompare$ LT7 | Description$ As long as your devotion to white and black is less than seven, NICKNAME isn't a creature. S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | CheckSVar$ X | SVarCompare$ LT7 | Description$ As long as your devotion to white and black is less than seven, NICKNAME isn't a creature.
SVar:X:Count$DevotionDual.White.Black SVar:X:Count$DevotionDual.White.Black
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature.YouOwn+Other | TriggerZones$ Battlefield | Execute$ TrigReturn | TriggerDescription$ Whenever another creature you own dies, return it to your hand unless target opponent pays 3 life. T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature.YouOwn+Other | TriggerZones$ Battlefield | Execute$ TrigReturn | TriggerDescription$ Whenever another creature you own dies, return it to your hand unless target opponent pays 3 life.
SVar:TrigReturn:DB$ ChangeZone | Defined$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Hand | UnlessCost$ PayLife<3> | UnlessPayer$ Targeted | ValidTgts$ Opponent | IsCurse$ True | Hidden$ True SVar:TrigReturn:DB$ ChangeZone | ThisDefinedAndTgts$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Hand | UnlessCost$ PayLife<3> | UnlessPayer$ Targeted | ValidTgts$ Opponent | IsCurse$ True
SVar:BuffedBy:Permanent.White,Permanent.Black SVar:BuffedBy:Permanent.White,Permanent.Black
Oracle:Indestructible\nAs long as your devotion to white and black is less than seven, Athreos isn't a creature.\nWhenever another creature you own dies, return it to your hand unless target opponent pays 3 life. Oracle:Indestructible\nAs long as your devotion to white and black is less than seven, Athreos isn't a creature.\nWhenever another creature you own dies, return it to your hand unless target opponent pays 3 life.

View File

@@ -4,6 +4,6 @@ Types:Enchantment Aura
K:Enchant:Creature K:Enchant:Creature
SVar:AttachAILogic:Pump SVar:AttachAILogic:Pump
S:Mode$ Continuous | Affected$ Creature.EnchantedBy | AddPower$ X | AddToughness$ X | Description$ Enchanted creature gets +1/+1 for each other creature you control. S:Mode$ Continuous | Affected$ Creature.EnchantedBy | AddPower$ X | AddToughness$ X | Description$ Enchanted creature gets +1/+1 for each other creature you control.
SVar:X:Count$Valid Creature.NotEnchantedBy+YouCtrl SVar:X:Count$Valid Creature.!EnchantedBy+YouCtrl
SVar:BuffedBy:Creature SVar:BuffedBy:Creature
Oracle:Enchant creature\nEnchanted creature gets +1/+1 for each other creature you control. Oracle:Enchant creature\nEnchanted creature gets +1/+1 for each other creature you control.

View File

@@ -5,5 +5,5 @@ K:Convoke
K:Enchant:Creature K:Enchant:Creature
SVar:AttachAILogic:Pump SVar:AttachAILogic:Pump
S:Mode$ Continuous | Affected$ Card.AttachedBy | AddToughness$ X | Description$ Enchanted creature gets +0/+2 for each other creature you control. S:Mode$ Continuous | Affected$ Card.AttachedBy | AddToughness$ X | Description$ Enchanted creature gets +0/+2 for each other creature you control.
SVar:X:Count$Valid Creature.NotEnchantedBy+YouCtrl/Twice SVar:X:Count$Valid Creature.!EnchantedBy+YouCtrl/Twice
Oracle:Convoke (Your creatures can help cast this spell. Each creature you tap while casting this spell pays for {1} or one mana of that creature's color.)\nEnchant creature\nEnchanted creature gets +0/+2 for each other creature you control. Oracle:Convoke (Your creatures can help cast this spell. Each creature you tap while casting this spell pays for {1} or one mana of that creature's color.)\nEnchant creature\nEnchanted creature gets +0/+2 for each other creature you control.

View File

@@ -4,6 +4,6 @@ Types:Enchantment Aura
K:Enchant:Creature K:Enchant:Creature
SVar:AttachAILogic:Pump SVar:AttachAILogic:Pump
T:Mode$ ChangesZone | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigPump | TriggerZones$ Battlefield | TriggerDescription$ When CARDNAME enters, target creature you control other than enchanted creature gets +2/+2 and gains vigilance until end of turn. T:Mode$ ChangesZone | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigPump | TriggerZones$ Battlefield | TriggerDescription$ When CARDNAME enters, target creature you control other than enchanted creature gets +2/+2 and gains vigilance until end of turn.
SVar:TrigPump:DB$ Pump | ValidTgts$ Creature.YouCtrl+NotEnchantedBy | KW$ Vigilance | TgtPrompt$ Select target creature you control other than enchanted creature | NumAtt$ +2 | NumDef$ +2 SVar:TrigPump:DB$ Pump | ValidTgts$ Creature.YouCtrl+!EnchantedBy | KW$ Vigilance | TgtPrompt$ Select target creature you control other than enchanted creature | NumAtt$ +2 | NumDef$ +2
S:Mode$ Continuous | Affected$ Creature.EnchantedBy | AddPower$ 2 | AddToughness$ 2 | AddKeyword$ Vigilance | Description$ Enchanted creature gets +2/+2 and has vigilance. S:Mode$ Continuous | Affected$ Creature.EnchantedBy | AddPower$ 2 | AddToughness$ 2 | AddKeyword$ Vigilance | Description$ Enchanted creature gets +2/+2 and has vigilance.
Oracle:Enchant creature\nWhen Due Diligence enters, target creature you control other than enchanted creature gets +2/+2 and gains vigilance until end of turn.\nEnchanted creature gets +2/+2 and has vigilance. Oracle:Enchant creature\nWhen Due Diligence enters, target creature you control other than enchanted creature gets +2/+2 and gains vigilance until end of turn.\nEnchanted creature gets +2/+2 and has vigilance.

View File

@@ -5,5 +5,5 @@ K:Enchant:Creature
SVar:AttachAILogic:Pump SVar:AttachAILogic:Pump
S:Mode$ Continuous | Affected$ Creature.EnchantedBy | AddKeyword$ Vigilance | AddAbility$ ABBolster | AddPower$ X | AddToughness$ X | Description$ Enchanted creature gets +1/+1 for each +1/+1 counter on other creatures you control. Enchanted creature has vigilance and "{W}, {T}: Bolster 1." S:Mode$ Continuous | Affected$ Creature.EnchantedBy | AddKeyword$ Vigilance | AddAbility$ ABBolster | AddPower$ X | AddToughness$ X | Description$ Enchanted creature gets +1/+1 for each +1/+1 counter on other creatures you control. Enchanted creature has vigilance and "{W}, {T}: Bolster 1."
SVar:ABBolster:AB$ PutCounter | Cost$ W T | Bolster$ True | CounterNum$ 1 | CounterType$ P1P1 | SpellDescription$ Bolster 1. SVar:ABBolster:AB$ PutCounter | Cost$ W T | Bolster$ True | CounterNum$ 1 | CounterType$ P1P1 | SpellDescription$ Bolster 1.
SVar:X:Count$Valid Creature.YouCtrl+NotEnchantedBy$CardCounters.P1P1 SVar:X:Count$Valid Creature.YouCtrl+!EnchantedBy$CardCounters.P1P1
Oracle:Enchant creature\nEnchanted creature gets +1/+1 for each +1/+1 counter on other creatures you control.\nEnchanted creature has vigilance and "{W}, {T}: Bolster 1." (To bolster 1, choose a creature with the least toughness among creatures you control and put a +1/+1 counter on it.) Oracle:Enchant creature\nEnchanted creature gets +1/+1 for each +1/+1 counter on other creatures you control.\nEnchanted creature has vigilance and "{W}, {T}: Bolster 1." (To bolster 1, choose a creature with the least toughness among creatures you control and put a +1/+1 counter on it.)

View File

@@ -4,6 +4,6 @@ Types:Enchantment Aura
K:Enchant:Creature K:Enchant:Creature
SVar:AttachAILogic:Pump SVar:AttachAILogic:Pump
S:Mode$ Continuous | Affected$ Creature.EnchantedBy | AddPower$ 1 | AddToughness$ 2 | Description$ Enchanted creature gets +1/+2. S:Mode$ Continuous | Affected$ Creature.EnchantedBy | AddPower$ 1 | AddToughness$ 2 | Description$ Enchanted creature gets +1/+2.
A:AB$ Attach | Cost$ 2 U | ValidTgts$ Creature.NotEnchantedBy | TgtPrompt$ Select target creature other than enchanted creature | AILogic$ Pump | SpellDescription$ Attach CARDNAME to target creature other than enchanted creature. A:AB$ Attach | Cost$ 2 U | ValidTgts$ Creature.!EnchantedBy | TgtPrompt$ Select target creature other than enchanted creature | AILogic$ Pump | SpellDescription$ Attach CARDNAME to target creature other than enchanted creature.
AI:RemoveDeck:All AI:RemoveDeck:All
Oracle:Enchant creature\nEnchanted creature gets +1/+2.\n{2}{U}: Attach Kjeldoran Pride to target creature other than enchanted creature. Oracle:Enchant creature\nEnchanted creature gets +1/+2.\n{2}{U}: Attach Kjeldoran Pride to target creature other than enchanted creature.

View File

@@ -2,7 +2,7 @@ Name:Lost Legacy
ManaCost:1 B B ManaCost:1 B B
Types:Sorcery Types:Sorcery
A:SP$ NameCard | Defined$ You | ValidCards$ Card.nonLand+nonArtifact | ValidDescription$ nonartifact, nonland | SubAbility$ ExileHand | SpellDescription$ Choose a nonartifact, nonland card name. Search target player's graveyard, hand, and library for any number of cards with that name and exile them. That player shuffles, then draws a card for each card exiled from their hand this way. | StackDescription$ SpellDescription A:SP$ NameCard | Defined$ You | ValidCards$ Card.nonLand+nonArtifact | ValidDescription$ nonartifact, nonland | SubAbility$ ExileHand | SpellDescription$ Choose a nonartifact, nonland card name. Search target player's graveyard, hand, and library for any number of cards with that name and exile them. That player shuffles, then draws a card for each card exiled from their hand this way. | StackDescription$ SpellDescription
SVar:ExileHand:DB$ ChangeZone | ValidTgts$ Player | TgtPrompt$ Select target player | RememberTargets$ True | Origin$ Hand | Destination$ Exile | DefinedPlayer$ TargetedPlayer | ChangeType$ Card.NamedCard | ChangeNum$ NumInHand | Chooser$ You | SubAbility$ ExileLib | RememberChanged$ True | StackDescription$ None SVar:ExileHand:DB$ ChangeZone | ValidTgts$ Player | TgtPrompt$ Select target player | Origin$ Hand | Destination$ Exile | DefinedPlayer$ TargetedPlayer | ChangeType$ Card.NamedCard | ChangeNum$ NumInHand | Chooser$ You | SubAbility$ ExileLib | RememberChanged$ True | StackDescription$ None
SVar:ExileLib:DB$ ChangeZone | Origin$ Library | Destination$ Exile | DefinedPlayer$ TargetedPlayer | ChangeType$ Card.NamedCard | ChangeNum$ NumInLib | Chooser$ You | Shuffle$ True | SubAbility$ ExileYard | StackDescription$ None SVar:ExileLib:DB$ ChangeZone | Origin$ Library | Destination$ Exile | DefinedPlayer$ TargetedPlayer | ChangeType$ Card.NamedCard | ChangeNum$ NumInLib | Chooser$ You | Shuffle$ True | SubAbility$ ExileYard | StackDescription$ None
SVar:ExileYard:DB$ ChangeZone | Origin$ Graveyard | Destination$ Exile | DefinedPlayer$ TargetedPlayer | ChangeType$ Card.NamedCard | ChangeNum$ NumInYard | Chooser$ You | Hidden$ True | SubAbility$ Draw | StackDescription$ None SVar:ExileYard:DB$ ChangeZone | Origin$ Graveyard | Destination$ Exile | DefinedPlayer$ TargetedPlayer | ChangeType$ Card.NamedCard | ChangeNum$ NumInYard | Chooser$ You | Hidden$ True | SubAbility$ Draw | StackDescription$ None
SVar:Draw:DB$ Draw | Defined$ TargetedPlayer | NumCards$ X | SubAbility$ DBCleanup | StackDescription$ None SVar:Draw:DB$ Draw | Defined$ TargetedPlayer | NumCards$ X | SubAbility$ DBCleanup | StackDescription$ None

View File

@@ -4,7 +4,7 @@ Types:Enchantment Aura
K:Flash K:Flash
K:Enchant:Creature.YouCtrl:creature you control K:Enchant:Creature.YouCtrl:creature you control
SVar:AttachAILogic:Pump SVar:AttachAILogic:Pump
T:Mode$ ChangesZone | ValidCard$ Creature.EnchantedBy,Creature.YouCtrl+modified+NotEnchantedBy | Origin$ Battlefield | Destination$ Graveyard | Execute$ TrigToken | TriggerDescription$ Whenever enchanted creature or another modified creature you control dies, create X 1/1 colorless Spirit creature tokens, where X is that creature's power. (Equipment, Auras you control, and counters are modifications.) T:Mode$ ChangesZone | ValidCard$ Creature.EnchantedBy,Creature.YouCtrl+modified+!EnchantedBy | Origin$ Battlefield | Destination$ Graveyard | Execute$ TrigToken | TriggerDescription$ Whenever enchanted creature or another modified creature you control dies, create X 1/1 colorless Spirit creature tokens, where X is that creature's power. (Equipment, Auras you control, and counters are modifications.)
SVar:TrigToken:DB$ Token | TokenScript$ c_1_1_spirit | TokenAmount$ X SVar:TrigToken:DB$ Token | TokenScript$ c_1_1_spirit | TokenAmount$ X
SVar:X:TriggeredCard$CardPower SVar:X:TriggeredCard$CardPower
DeckHas:Ability$Token & Type$Spirit DeckHas:Ability$Token & Type$Spirit

View File

@@ -2,10 +2,9 @@ Name:Rumbling Ruin
ManaCost:5 R ManaCost:5 R
Types:Creature Elemental Types:Creature Elemental
PT:6/6 PT:6/6
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigStore | TriggerDescription$ When CARDNAME enters, count the number of +1/+1 counters on creatures you control. Creatures your opponents control with power less than or equal to that number can't block this turn. T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigEffect | TriggerDescription$ When CARDNAME enters, count the number of +1/+1 counters on creatures you control. Creatures your opponents control with power less than or equal to that number can't block this turn.
SVar:TrigStore:DB$ StoreSVar | SVar$ X | Type$ CountSVar | Expression$ Y | SubAbility$ TrigEffect SVar:TrigEffect:DB$ Effect | StaticAbilities$ KWPump | SetChosenNumber$ Y | SpellDescription$ Creatures your opponents control with power less than or equal to that number can't block this turn.
SVar:TrigEffect:DB$ Effect | StaticAbilities$ KWPump | SpellDescription$ Creatures your opponents control with power less than or equal to that number can't block this turn. SVar:KWPump:Mode$ CantBlock | ValidCard$ Creature.OppCtrl+powerLEX | Description$ Creatures your opponents control with power less than or equal to that number can't block this turn.
SVar:KWPump:Mode$ Continuous | AffectedZone$ Battlefield | Affected$ Creature.OppCtrl+powerLEX | AddHiddenKeyword$ CARDNAME can't block. | Description$ Creatures your opponents control with power less than or equal to that number can't block this turn. SVar:X:Count$ChosenNumber
SVar:X:Number$0
SVar:Y:Count$Valid Creature.YouCtrl$CardCounters.P1P1 SVar:Y:Count$Valid Creature.YouCtrl$CardCounters.P1P1
Oracle:When Rumbling Ruin enters, count the number of +1/+1 counters on creatures you control. Creatures your opponents control with power less than or equal to that number can't block this turn. Oracle:When Rumbling Ruin enters, count the number of +1/+1 counters on creatures you control. Creatures your opponents control with power less than or equal to that number can't block this turn.

View File

@@ -3,6 +3,6 @@ ManaCost:U
Types:Enchantment Aura Types:Enchantment Aura
K:Enchant:Creature K:Enchant:Creature
SVar:AttachAILogic:Curiosity SVar:AttachAILogic:Curiosity
T:Mode$ DamageDone | ValidSource$ Creature.AttachedBy | ValidTarget$ Player | Execute$ TrigReturn | TriggerDescription$ Whenever enchanted creature deals damage to a player, return target creature that player controls to its owner's hand. T:Mode$ DamageDone | ValidSource$ Creature.AttachedBy | ValidTarget$ Player | Execute$ TrigReturn | TriggerZones$ Battlefield | TriggerDescription$ Whenever enchanted creature deals damage to a player, return target creature that player controls to its owner's hand.
SVar:TrigReturn:DB$ ChangeZone | ValidTgts$ Creature | TargetsWithDefinedController$ TriggeredTarget | TgtPrompt$ Select target creature your opponent controls | IsCurse$ True | Origin$ Battlefield | Destination$ Hand SVar:TrigReturn:DB$ ChangeZone | ValidTgts$ Creature | TargetsWithDefinedController$ TriggeredTarget | TgtPrompt$ Select target creature your opponent controls | IsCurse$ True | Origin$ Battlefield | Destination$ Hand
Oracle:Enchant creature\nWhenever enchanted creature deals damage to a player, return target creature that player controls to its owner's hand. Oracle:Enchant creature\nWhenever enchanted creature deals damage to a player, return target creature that player controls to its owner's hand.

View File

@@ -5,6 +5,6 @@ K:Enchant:Creature
SVar:AttachAITgts:Card.powerGE3 SVar:AttachAITgts:Card.powerGE3
SVar:AttachAILogic:Curse SVar:AttachAILogic:Curse
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ Player.EnchantedController | TriggerZones$ Battlefield | Execute$ TrigDamage | TriggerDescription$ At the beginning of the upkeep of enchanted creature's controller, CARDNAME deals damage equal to that creature's power to that player unless they sacrifice another creature. T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ Player.EnchantedController | TriggerZones$ Battlefield | Execute$ TrigDamage | TriggerDescription$ At the beginning of the upkeep of enchanted creature's controller, CARDNAME deals damage equal to that creature's power to that player unless they sacrifice another creature.
SVar:TrigDamage:DB$ DealDamage | Defined$ TriggeredPlayer | NumDmg$ X | UnlessCost$ Sac<1/Creature.NotEnchantedBy> | UnlessPayer$ EnchantedController SVar:TrigDamage:DB$ DealDamage | Defined$ TriggeredPlayer | NumDmg$ X | UnlessCost$ Sac<1/Creature.!EnchantedBy> | UnlessPayer$ EnchantedController
SVar:X:Enchanted$CardPower SVar:X:Enchanted$CardPower
Oracle:Enchant creature\nAt the beginning of the upkeep of enchanted creature's controller, Unnatural Hunger deals damage equal to that creature's power to that player unless they sacrifice another creature. Oracle:Enchant creature\nAt the beginning of the upkeep of enchanted creature's controller, Unnatural Hunger deals damage equal to that creature's power to that player unless they sacrifice another creature.

View File

@@ -3,7 +3,7 @@ ManaCost:R
Types:Enchantment Aura Types:Enchantment Aura
K:Enchant:Creature.YouCtrl:creature you control K:Enchant:Creature.YouCtrl:creature you control
SVar:AttachAILogic:Pump SVar:AttachAILogic:Pump
A:AB$ Pump | Cost$ tapXType<1/Creature.EnchantedBy/Enchanted Creature> | ValidTgts$ Creature.NotEnchantedBy | TgtPrompt$ Select target creature other than the creature tapped | NumAtt$ +2 | NumDef$ +1 | CostDesc$ Tap enchanted creature: | SpellDescription$ Target creature other than the creature tapped this way gets +2/+1 until end of turn. Activate only if enchanted creature is untapped. A:AB$ Pump | Cost$ tapXType<1/Creature.EnchantedBy/Enchanted Creature> | ValidTgts$ Creature.!EnchantedBy | TgtPrompt$ Select target creature other than the creature tapped | NumAtt$ +2 | NumDef$ +1 | CostDesc$ Tap enchanted creature: | SpellDescription$ Target creature other than the creature tapped this way gets +2/+1 until end of turn. Activate only if enchanted creature is untapped.
AI:RemoveDeck:All AI:RemoveDeck:All
SVar:NonStackingAttachEffect:True SVar:NonStackingAttachEffect:True
Oracle:Enchant creature you control\nTap enchanted creature: Target creature other than the creature tapped this way gets +2/+1 until end of turn. Activate only if enchanted creature is untapped. Oracle:Enchant creature you control\nTap enchanted creature: Target creature other than the creature tapped this way gets +2/+1 until end of turn. Activate only if enchanted creature is untapped.

View File

@@ -449,8 +449,7 @@ public final class CardScriptParser {
"AttachedBy", "Attached", "NameNotEnchantingEnchantedPlayer", "AttachedBy", "Attached", "NameNotEnchantingEnchantedPlayer",
"Enchanted", "CanEnchantRemembered", "Enchanted", "CanEnchantRemembered",
"CanEnchantSource", "CanBeEnchantedBy", "CanBeEnchantedByTargeted", "CanEnchantSource", "CanBeEnchantedBy", "CanBeEnchantedByTargeted",
"CanBeEnchantedByAllRemembered", "EquippedBy", "EquippedBy", "EquippedByTargeted", "EquippedByEnchanted", "FortifiedBy",
"EquippedByTargeted", "EquippedByEnchanted", "FortifiedBy",
"CanBeEquippedBy", "Equipped", "Fortified", "HauntedBy", "CanBeEquippedBy", "Equipped", "Fortified", "HauntedBy",
"notTributed", "madness", "Paired", "PairedWith", "notTributed", "madness", "Paired", "PairedWith",
"Above", "DirectlyAbove", "TopGraveyardCreature", "Above", "DirectlyAbove", "TopGraveyardCreature",
@@ -488,7 +487,7 @@ public final class CardScriptParser {
private static final Set<String> VALID_EXCLUSIVE_STARTSWITH = ImmutableSortedSet private static final Set<String> VALID_EXCLUSIVE_STARTSWITH = ImmutableSortedSet
.of("named", "notnamed", "OwnedBy", "ControlledBy", .of("named", "notnamed", "OwnedBy", "ControlledBy",
"ControllerControls", "AttachedTo", "EnchantedBy", "ControllerControls", "AttachedTo", "EnchantedBy",
"NotEnchantedBy", "TopGraveyard", "SharesColorWith", "TopGraveyard", "SharesColorWith",
"MostProminentColor", "notSharesColorWith", "MostProminentColor", "notSharesColorWith",
"sharesCreatureTypeWith", "sharesCardTypeWith", "sharesLandTypeWith", "sharesCreatureTypeWith", "sharesCardTypeWith", "sharesLandTypeWith",
"sharesNameWith", "doesNotShareNameWith", "sharesNameWith", "doesNotShareNameWith",