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"),
MergedCards("MergedCards"),
Mode("Mode"),
Modifier("Modifier"),
MonstrosityAmount("MonstrosityAmount"),
NaturalResult("NaturalResult"),
NewCard("NewCard"),

View File

@@ -2220,7 +2220,7 @@ public class AbilityUtils {
// Count$IfCastInOwnMainPhase.<numMain>.<numNotMain> // 7/10
if (sq[0].contains("IfCastInOwnMainPhase")) {
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);
}
@@ -2480,7 +2480,6 @@ public class AbilityUtils {
// But these aren't really things you count so they'll show up in properties most likely
}
//Count$TypesSharedWith [defined]
if (sq[0].startsWith("TypesSharedWith")) {
Set<CardType.CoreType> thisTypes = Sets.newHashSet(c.getType().getCoreTypes());

View File

@@ -1016,8 +1016,9 @@ public abstract class SpellAbilityEffect {
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
final Player activator = sa.getActivatingPlayer();
final PlayerCollection options;
if (loser.isOpponentOf(activator)) {
options = activator.getOpponents();

View File

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

View File

@@ -1,9 +1,12 @@
package forge.game.ability.effects;
import forge.card.ColorSet;
import forge.card.MagicColor;
import forge.deck.DeckRecognizer;
import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
import forge.game.card.CardUtil;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.util.Aggregates;
@@ -41,6 +44,13 @@ public class ChooseColorEffect extends SpellAbilityEffect {
String[] restrictedChoices = sa.getParam("Choices").split(",");
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")) {
for (String s : sa.getParam("Exclude").split(",")) {
colorChoices.remove(s);
@@ -49,24 +59,22 @@ public class ChooseColorEffect extends SpellAbilityEffect {
for (Player p : getTargetPlayers(sa)) {
if (!p.isInGame()) {
p = getNewChooser(sa, sa.getActivatingPlayer(), p);
p = getNewChooser(sa, p);
}
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;
String prompt = null;
if (cntMax == 1) {
prompt = Localizer.getInstance().getMessage("lblChooseAColor");
} else {
if (cntMax > cntMin) {
if (cntMax >= MagicColor.NUMBER_OR_COLORS) {
prompt = Localizer.getInstance().getMessage("lblAtLastChooseNumColors", Lang.getNumeral(cntMin));
} else {
prompt = Localizer.getInstance().getMessage("lblChooseSpecifiedRangeColors", Lang.getNumeral(cntMin), Lang.getNumeral(cntMax));
}
} else if (cntMax > cntMin) {
if (cntMax >= MagicColor.NUMBER_OR_COLORS) {
prompt = Localizer.getInstance().getMessage("lblAtLastChooseNumColors", Lang.getNumeral(cntMin));
} 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;
if (sa.hasParam("Random")) {

View File

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

View File

@@ -22,7 +22,7 @@ public class EndTurnEffect extends SpellAbilityEffect {
final List<Player> enders = getDefinedPlayersOrTargeted(sa, "Defined");
Player ender = enders.isEmpty() ? sa.getActivatingPlayer() : enders.get(0);
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)) {

View File

@@ -60,18 +60,21 @@ public class ManaEffect extends SpellAbilityEffect {
if (abMana.isComboMana()) {
int amount = sa.hasParam("Amount") ? AbilityUtils.calculateAmount(card, sa.getParam("Amount"), sa) : 1;
if(amount <= 0)
if (amount <= 0)
continue;
String express = abMana.getExpressChoice();
String[] colorsProduced = abMana.getComboColors(sa).split(" ");
final StringBuilder choiceString = new StringBuilder();
final StringBuilder choiceSymbols = new StringBuilder();
String combo = abMana.getComboColors(sa);
if (combo.isBlank()) {
return;
}
String[] colorsProduced = combo.split(" ");
ColorSet colorOptions = ColorSet.fromNames(colorsProduced);
String express = abMana.getExpressChoice();
String[] colorsNeeded = express.isEmpty() ? null : express.split(" ");
boolean differentChoice = abMana.getOrigProduced().contains("Different");
ColorSet fullOptions = colorOptions;
final StringBuilder choiceString = new StringBuilder();
final StringBuilder choiceSymbols = new StringBuilder();
// Use specifyManaCombo if possible
if (colorsNeeded == null && amount > 1 && !sa.hasParam("TwoEach")) {
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) {
final Map<AbilityKey, Object> runParams = AbilityKey.mapFromPlayer(player);
runParams.put(AbilityKey.Sides, sides);
runParams.put(AbilityKey.Modifier, modifier);
runParams.put(AbilityKey.Result, roll.getModifiedValue());
runParams.put(AbilityKey.NaturalResult, roll.getNaturalValue());
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("Afterlife") || keyword.startsWith("Hideaway") || keyword.startsWith("Toxic")
|| keyword.startsWith("Afflict") || keyword.startsWith ("Poisonous") || keyword.startsWith("Rampage")
|| keyword.startsWith("Renown") || keyword.startsWith("Annihilator") || keyword.startsWith("Devour")
|| keyword.startsWith("Mobilize")) {
|| keyword.startsWith("Renown") || keyword.startsWith("Annihilator") || keyword.startsWith("Devour")) {
final String[] k = keyword.split(":");
sbLong.append(k[0]).append(" ").append(k[1]).append(" (").append(inst.getReminderText()).append(")");
} else if (keyword.startsWith("Crew")) {
@@ -2667,14 +2666,13 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
final String[] k = keyword.split(":");
String desc = k.length > 2 ? k[2] : CardType.getPluralType(k[1]);
sbLong.append(k[0]).append(" ").append(desc).append(" (").append(inst.getReminderText()).append(")");
} else if (keyword.equals("Convoke") || keyword.equals("Dethrone")|| keyword.equals("Fear")
|| keyword.equals("Melee") || keyword.equals("Improvise")|| keyword.equals("Shroud")
|| keyword.equals("Banding") || keyword.equals("Intimidate")|| keyword.equals("Evolve")
|| keyword.equals("Exalted") || keyword.equals("Extort")|| keyword.equals("Flanking")
|| keyword.equals("Horsemanship") || keyword.equals("Infect")|| keyword.equals("Persist")
|| keyword.equals("Phasing") || keyword.equals("Shadow")|| keyword.equals("Skulk")
|| keyword.equals("Undying") || keyword.equals("Wither")
|| keyword.equals("Bargain")
} else if (keyword.equals("Convoke") || keyword.equals("Dethrone") || keyword.equals("Fear")
|| keyword.equals("Melee") || keyword.equals("Improvise") || keyword.equals("Shroud")
|| keyword.equals("Banding") || keyword.equals("Intimidate") || keyword.equals("Evolve")
|| keyword.equals("Exalted") || keyword.equals("Extort") || keyword.equals("Flanking")
|| keyword.equals("Horsemanship") || keyword.equals("Infect") || keyword.equals("Persist")
|| keyword.equals("Phasing") || keyword.equals("Shadow") || keyword.equals("Skulk")
|| keyword.equals("Undying") || keyword.equals("Wither") || keyword.equals("Bargain")
|| keyword.equals("Mentor") || keyword.equals("Training")) {
if (sb.length() != 0) {
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("Specialize") || keyword.equals("Ravenous")
|| 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
} else if (keyword.equals("Read ahead")) {
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);
}
@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) {
Map<String, Object> toRemove = Maps.newHashMap();
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) {
final List<Map<String, Object>> perp = oldCard.getPerpetual();
perpetual = perp;
for (Map<String, Object> p : perp) {
if (p.get("Category").equals("Abilities")) {
perpetual = oldCard.getPerpetual();
for (Map<String, Object> p : perpetual) {
final String category = (String) p.get("Category");
if (category.equals("Abilities")) {
long timestamp = (long) p.get("Timestamp");
CardTraitChanges ctc = oldCard.getChangedCardTraits().get(timestamp, (long) 0).copy(this, false);
addChangedCardTraits(ctc, timestamp, (long) 0);
} else if (p.get("Category").equals("Incorporate")) {
} else if (category.equals("Incorporate")) {
long ts = (long) p.get("Timestamp");
final ManaCost cCMC = oldCard.changedCardManaCost.get(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) {
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 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() + ")";
final String effect = "DB$ Token | TokenAmount$ " + n + " | TokenScript$ r_1_1_warrior"

View File

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

View File

@@ -17,6 +17,8 @@
*/
package forge.game.spellability;
import com.google.common.base.Function;
import com.google.common.collect.Iterators;
import com.google.common.collect.Lists;
import forge.card.ColorSet;
import forge.card.GamePieceType;
@@ -48,6 +50,7 @@ import forge.game.zone.ZoneType;
import forge.util.TextUtil;
import org.apache.commons.lang3.StringUtils;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -513,7 +516,7 @@ public class AbilityManaPart implements java.io.Serializable {
}
String produced = this.getOrigProduced();
if (produced.contains("Chosen")) {
produced = produced.replace("Chosen", this.getChosenColor(sa));
produced = produced.replace("Chosen", getChosenColor(sa, sa.getHostCard().getChosenColors()));
}
return produced;
}
@@ -649,11 +652,18 @@ public class AbilityManaPart implements java.io.Serializable {
}
// replace Chosen for Combo colors
if (origProduced.contains("Chosen")) {
origProduced = origProduced.replace("Chosen", getChosenColor(sa));
origProduced = origProduced.replace("Chosen", getChosenColor(sa, sa.getHostCard().getChosenColors()));
}
// replace Chosen for Spire colors
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")) {
// 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);
}
public String getChosenColorID(SpellAbility sa) {
public String getChosenColor(SpellAbility sa, Iterable<String> colors) {
if (sa == null) {
return "";
}
Card card = sa.getHostCard();
if (card != null && card.hasMarkedColor()) {
if (card != null) {
StringBuilder values = new StringBuilder();
for (byte c : card.getMarkedColors()) {
for (String c : colors) {
values.append(MagicColor.toShortString(c)).append(" ");
}
return values.toString();
@@ -713,17 +723,6 @@ public class AbilityManaPart implements java.io.Serializable {
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() {
return sourceCard;
}

View File

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

View File

@@ -450,7 +450,7 @@ public class WrappedAbility extends Ability {
if (decider != null) {
if (!decider.isInGame()) {
decider = SpellAbilityEffect.getNewChooser(sa, getActivatingPlayer(), decider);
decider = SpellAbilityEffect.getNewChooser(sa, decider);
}
if (!decider.getController().confirmTrigger(this)) {
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.
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.
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
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
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.
SVar:X:Count$Valid Creature.NotEnchantedBy+YouCtrl
SVar:X:Count$Valid Creature.!EnchantedBy+YouCtrl
SVar:BuffedBy:Creature
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
SVar:AttachAILogic:Pump
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.

View File

@@ -4,6 +4,6 @@ Types:Enchantment Aura
K:Enchant:Creature
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.
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.
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
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: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.)

View File

@@ -4,6 +4,6 @@ Types:Enchantment Aura
K:Enchant:Creature
SVar:AttachAILogic:Pump
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
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
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
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: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

View File

@@ -4,7 +4,7 @@ Types:Enchantment Aura
K:Flash
K:Enchant:Creature.YouCtrl:creature you control
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:X:TriggeredCard$CardPower
DeckHas:Ability$Token & Type$Spirit

View File

@@ -2,10 +2,9 @@ Name:Rumbling Ruin
ManaCost:5 R
Types:Creature Elemental
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.
SVar:TrigStore:DB$ StoreSVar | SVar$ X | Type$ CountSVar | Expression$ Y | SubAbility$ TrigEffect
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$ 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:Number$0
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: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: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:X:Count$ChosenNumber
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.

View File

@@ -3,6 +3,6 @@ ManaCost:U
Types:Enchantment Aura
K:Enchant:Creature
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
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: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.
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
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
K:Enchant:Creature.YouCtrl:creature you control
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
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.

View File

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