diff --git a/forge-ai/src/main/java/forge/ai/AiController.java b/forge-ai/src/main/java/forge/ai/AiController.java index 8f3838ff2b5..384b9944db9 100644 --- a/forge-ai/src/main/java/forge/ai/AiController.java +++ b/forge-ai/src/main/java/forge/ai/AiController.java @@ -18,7 +18,6 @@ package forge.ai; import com.esotericsoftware.minlog.Log; -import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import forge.ai.AiCardMemory.MemorySet; @@ -64,6 +63,7 @@ import io.sentry.Breadcrumb; import io.sentry.Sentry; import java.util.*; +import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.concurrent.CompletableFuture; @@ -2208,8 +2208,6 @@ public class AiController { return activePlayerSAs; } - List result = Lists.newArrayList(); - // filter list by ApiTypes List discard = filterListByApi(activePlayerSAs, ApiType.Discard); List mandatoryDiscard = filterList(discard, SpellAbilityPredicates.isMandatory()); @@ -2225,37 +2223,33 @@ public class AiController { List pump = filterListByApi(activePlayerSAs, ApiType.Pump); List pumpAll = filterListByApi(activePlayerSAs, ApiType.PumpAll); + List result = Lists.newArrayList(activePlayerSAs); + // do mandatory discard early if hand is empty or has DiscardMe card - boolean discardEarly = false; CardCollectionView playerHand = player.getCardsIn(ZoneType.Hand); - if (playerHand.isEmpty() || playerHand.anyMatch(CardPredicates.hasSVar("DiscardMe"))) { - discardEarly = true; + if (!playerHand.isEmpty() && !playerHand.anyMatch(CardPredicates.hasSVar("DiscardMe"))) { result.addAll(mandatoryDiscard); + mandatoryDiscard.clear(); } - // token should be added first so they might get the pump bonus - result.addAll(token); - result.addAll(pump); - result.addAll(pumpAll); - - // do Evolve Trigger before other PutCounter SpellAbilities - // do putCounter before Draw/Discard because it can cause a Draw Trigger - result.addAll(evolve); - result.addAll(putCounter); - result.addAll(putCounterAll); - + // optional Discard, probably combined with Draw + result.addAll(discard); // do Draw before Discard result.addAll(draw); - result.addAll(discard); // optional Discard, probably combined with Draw - if (!discardEarly) { - result.addAll(mandatoryDiscard); - } + result.addAll(putCounterAll); + // do putCounter before Draw/Discard because it can cause a Draw Trigger + result.addAll(putCounter); + // do Evolve Trigger before other PutCounter SpellAbilities + result.addAll(evolve); - result.addAll(activePlayerSAs); + // token should be added first so they might get the pump bonus + result.addAll(pumpAll); + result.addAll(pump); + result.addAll(token); + + result.addAll(mandatoryDiscard); - //need to reverse because of magic stack - Collections.reverse(result); return result; } @@ -2267,6 +2261,10 @@ public class AiController { } // TODO move to more common place + public static List filterList(List input, Function pred, Object value) { + return filterList(input, trb -> pred.apply(trb.ensureAbility()) == value); + } + public static List filterListByApi(List input, ApiType type) { return filterList(input, SpellAbilityPredicates.isApi(type)); } @@ -2303,12 +2301,11 @@ public class AiController { public ReplacementEffect chooseSingleReplacementEffect(List list) { // no need to choose anything if (list.size() <= 1) { - return Iterables.getFirst(list, null); + return list.get(0); } - ReplacementType mode = Iterables.getFirst(list, null).getMode(); + ReplacementType mode = list.get(0).getMode(); - // replace lifegain effects if (mode.equals(ReplacementType.GainLife)) { List noGain = filterListByAiLogic(list, "NoLife"); List loseLife = filterListByAiLogic(list, "LoseLife"); @@ -2317,16 +2314,16 @@ public class AiController { if (!noGain.isEmpty()) { // no lifegain is better than lose life - return Iterables.getFirst(noGain, null); + return noGain.get(0); } else if (!loseLife.isEmpty()) { // lose life before double life to prevent lose double - return Iterables.getFirst(loseLife, null); + return loseLife.get(0); } else if (!lichDraw.isEmpty()) { // lich draw before double life to prevent to draw to much - return Iterables.getFirst(lichDraw, null); + return lichDraw.get(0); } else if (!doubleLife.isEmpty()) { // other than that, do double life - return Iterables.getFirst(doubleLife, null); + return doubleLife.get(0); } } else if (mode.equals(ReplacementType.DamageDone)) { List prevention = filterList(list, CardTraitPredicates.hasParam("Prevent")); @@ -2334,7 +2331,7 @@ public class AiController { // TODO when Protection is done as ReplacementEffect do them // before normal prevention if (!prevention.isEmpty()) { - return Iterables.getFirst(prevention, null); + return prevention.get(0); } } else if (mode.equals(ReplacementType.Destroy)) { List shield = filterList(list, CardTraitPredicates.hasParam("ShieldCounter")); @@ -2344,30 +2341,35 @@ public class AiController { // Indestructible umbra armor is the best if (!umbraArmorIndestructible.isEmpty()) { - return Iterables.getFirst(umbraArmorIndestructible, null); + return umbraArmorIndestructible.get(0); } // then it might be better to remove shield counter if able? if (!shield.isEmpty()) { - return Iterables.getFirst(shield, null); + return shield.get(0); } // TODO get the RunParams for Affected to check if the creature already dealt combat damage for Regeneration effects // is using a Regeneration Effect better than using a Umbra Armor? if (!regeneration.isEmpty()) { - return Iterables.getFirst(regeneration, null); + return regeneration.get(0); } if (!umbraArmor.isEmpty()) { // sort them by cmc umbraArmor.sort(Comparator.comparing(CardTraitBase::getHostCard, Comparator.comparing(Card::getCMC))); - return Iterables.getFirst(umbraArmor, null); + return umbraArmor.get(0); + } + } else if (mode.equals(ReplacementType.Draw)) { + List winGame = filterList(list, SpellAbility::getApi, ApiType.WinsGame); + if (!winGame.isEmpty()) { + return winGame.get(0); } } // TODO always lower counters with Vorinclex first, might turn it from 1 to 0 as final - return Iterables.getFirst(list, null); + return list.get(0); } } diff --git a/forge-ai/src/main/java/forge/ai/CreatureEvaluator.java b/forge-ai/src/main/java/forge/ai/CreatureEvaluator.java index 384b5379ca8..b5dd1016310 100644 --- a/forge-ai/src/main/java/forge/ai/CreatureEvaluator.java +++ b/forge-ai/src/main/java/forge/ai/CreatureEvaluator.java @@ -248,10 +248,10 @@ public class CreatureEvaluator implements Function { value -= subValue(10, "echo-unpaid"); } if (t.isKeyword(Keyword.FADING)) { - value -= subValue(20 / (Math.max(1, c.getCounters(CounterEnumType.FADE))), "fading"); + value -= subValue(20 / (Math.max(1, c.isInPlay() ? c.getCounters(CounterEnumType.FADE) : c.getKeywordMagnitude(Keyword.FADING))), "fading"); } if (t.isKeyword(Keyword.VANISHING)) { - value -= subValue(20 / (Math.max(1, c.getCounters(CounterEnumType.TIME))), "vanishing"); + value -= subValue(20 / (Math.max(1, c.isInPlay() ? c.getCounters(CounterEnumType.TIME) : c.getKeywordMagnitude(Keyword.VANISHING))), "vanishing"); } SpellAbility ab = t.ensureAbility(); diff --git a/forge-core/src/main/java/forge/card/CardRulesPredicates.java b/forge-core/src/main/java/forge/card/CardRulesPredicates.java index 838587234fc..ed439d0419c 100644 --- a/forge-core/src/main/java/forge/card/CardRulesPredicates.java +++ b/forge-core/src/main/java/forge/card/CardRulesPredicates.java @@ -253,7 +253,7 @@ public final class CardRulesPredicates { } public static Predicate canBePartnerCommanderWith(final CardRules commander) { - return (rules) -> rules.canBePartnerCommanders(commander); + return rules -> rules.canBePartnerCommanders(commander); } private static class LeafString extends PredicateString { diff --git a/forge-core/src/main/java/forge/util/collect/FCollection.java b/forge-core/src/main/java/forge/util/collect/FCollection.java index 1c4b0f90125..824184fec03 100644 --- a/forge-core/src/main/java/forge/util/collect/FCollection.java +++ b/forge-core/src/main/java/forge/util/collect/FCollection.java @@ -549,17 +549,17 @@ public class FCollection implements List, /*Set,*/ FCollectionView, @Override public Stream stream() { - return list.stream(); + return list.stream(); } @Override public boolean anyMatch(Predicate test) { - return set.stream().anyMatch(test); + return set.stream().anyMatch(test); } @Override public boolean allMatch(Predicate test) { - return set.stream().allMatch(test); + return set.stream().allMatch(test); } /** diff --git a/forge-game/src/main/java/forge/game/ability/effects/ActivateAbilityEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ActivateAbilityEffect.java index 4ea52020a48..f2d038a1861 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ActivateAbilityEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ActivateAbilityEffect.java @@ -5,7 +5,6 @@ import java.util.List; import org.apache.commons.lang3.StringUtils; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Lists; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; @@ -45,7 +44,7 @@ public class ActivateAbilityEffect extends SpellAbilityEffect { List list = CardLists.getType(p.getCardsIn(ZoneType.Battlefield), sa.getParamOrDefault("Type", "Card")); for (Card c : list) { - List possibleAb = Lists.newArrayList(c.getAllPossibleAbilities(p, true)); + List possibleAb = c.getAllPossibleAbilities(p, true); if (isManaAb) { possibleAb.retainAll((FCollection)c.getManaAbilities()); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java index d9c0a138c11..024577d3ee1 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java @@ -880,13 +880,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect { * a {@link forge.game.spellability.SpellAbility} object. */ private void changeHiddenOriginResolve(final SpellAbility sa) { - List fetchers; - - if (sa.hasParam("DefinedPlayer")) { - fetchers = AbilityUtils.getDefinedPlayers(sa.getHostCard(), sa.getParam("DefinedPlayer"), sa); - } else { - fetchers = Lists.newArrayList(sa.getActivatingPlayer()); - } + List fetchers = AbilityUtils.getDefinedPlayers(sa.getHostCard(), sa.getParam("DefinedPlayer"), sa); Player chooser = null; if (sa.hasParam("Chooser")) { @@ -1059,7 +1053,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect { handleCastWhileSearching(fetchList, decider); } final Map runParams = AbilityKey.mapFromPlayer(decider); - runParams.put(AbilityKey.Target, Lists.newArrayList(player)); + runParams.put(AbilityKey.Target, player); game.getTriggerHandler().runTrigger(TriggerType.SearchedLibrary, runParams, false); } if (searchedLibrary && sa.hasParam("Searched")) { diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChooseCardNameEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChooseCardNameEffect.java index 30ac9ee1888..cd2de5f8362 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ChooseCardNameEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ChooseCardNameEffect.java @@ -22,7 +22,6 @@ public class ChooseCardNameEffect extends SpellAbilityEffect { @Override protected String getStackDescription(SpellAbility sa) { - return Lang.joinHomogenous(getTargetPlayers(sa)) + " names a card."; } @@ -58,21 +57,6 @@ public class ChooseCardNameEffect extends SpellAbilityEffect { continue; } String chosen; - //This section was used for Momir Avatar, which no longer uses it - commented out 7/28/2021 - //if (randomChoice) { - //String numericAmount = "X"; - //final int validAmount = StringUtils.isNumeric(numericAmount) ? Integer.parseInt(numericAmount) : - // AbilityUtils.calculateAmount(host, numericAmount, sa); - // Momir needs PaperCard - //Collection cards = StaticData.instance().getCommonCards().getUniqueCards(); - //Predicate cpp = Predicates.and( - // Predicates.compose(CardRulesPredicates.IS_CREATURE, PaperCard.FN_GET_RULES), - // Predicates.compose(CardRulesPredicates.cmc(ComparableOp.EQUALS, validAmount), PaperCard.FN_GET_RULES)); - //cards = Lists.newArrayList(Iterables.filter(cards, cpp)); - //if (!cards.isEmpty()) { chosen = Aggregates.random(cards).getName(); - //} else { - // chosen = ""; - //} if (chooseFromDefined) { CardCollection choices = AbilityUtils.getDefinedCards(host, sa.getParam("ChooseFromDefinedCards"), sa); choices = CardLists.getValidCards(choices, valid, host.getController(), host, sa); diff --git a/forge-game/src/main/java/forge/game/ability/effects/ControlExchangeEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ControlExchangeEffect.java index 9e6a7e87c88..65fb4634f6f 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ControlExchangeEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ControlExchangeEffect.java @@ -2,12 +2,11 @@ package forge.game.ability.effects; import java.util.List; -import com.google.common.collect.Lists; - import forge.game.Game; import forge.game.ability.AbilityUtils; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; +import forge.game.card.CardCollectionView; import forge.game.player.Player; import forge.game.spellability.SpellAbility; import forge.util.CardTranslation; @@ -23,9 +22,9 @@ public class ControlExchangeEffect extends SpellAbilityEffect { protected String getStackDescription(SpellAbility sa) { Card object1 = null; Card object2 = null; - List tgts = null; + CardCollectionView tgts = null; if (sa.usesTargeting()) { - tgts = Lists.newArrayList(sa.getTargets().getTargetCards()); + tgts = sa.getTargets().getTargetCards(); if (tgts.size() > 0) { object1 = tgts.get(0); } @@ -57,9 +56,9 @@ public class ControlExchangeEffect extends SpellAbilityEffect { Card object1 = null; Card object2 = null; - List tgts = null; + CardCollectionView tgts = null; if (sa.usesTargeting()) { - tgts = Lists.newArrayList(sa.getTargets().getTargetCards()); + tgts = sa.getTargets().getTargetCards(); if (tgts.size() > 0) { object1 = tgts.get(0); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/CopySpellAbilityEffect.java b/forge-game/src/main/java/forge/game/ability/effects/CopySpellAbilityEffect.java index c51968e750e..cc926cdd2a8 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/CopySpellAbilityEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/CopySpellAbilityEffect.java @@ -72,10 +72,7 @@ public class CopySpellAbilityEffect extends SpellAbilityEffect { return; } - List controllers = Lists.newArrayList(sa.getActivatingPlayer()); - if (sa.hasParam("Controller")) { - controllers = AbilityUtils.getDefinedPlayers(card, sa.getParam("Controller"), sa); - } + List controllers = AbilityUtils.getDefinedPlayers(card, sa.getParam("Controller"), sa); boolean isOptional = sa.hasParam("Optional"); diff --git a/forge-game/src/main/java/forge/game/ability/effects/DrawEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DrawEffect.java index 6f51da53447..cede75c96f2 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DrawEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DrawEffect.java @@ -65,7 +65,7 @@ public class DrawEffect extends SpellAbilityEffect { final List tgts = getTargetPlayersWithDuplicates(true, "Defined", sa); - for (final Player p : Sets.newHashSet(tgts)) { + for (final Player p : Sets.newLinkedHashSet(tgts)) { if (!p.isInGame()) { continue; } diff --git a/forge-game/src/main/java/forge/game/ability/effects/FlipOntoBattlefieldEffect.java b/forge-game/src/main/java/forge/game/ability/effects/FlipOntoBattlefieldEffect.java index bd34b2310c0..53bff88b5e0 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/FlipOntoBattlefieldEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/FlipOntoBattlefieldEffect.java @@ -98,7 +98,7 @@ public class FlipOntoBattlefieldEffect extends SpellAbilityEffect { // as well as the current card attachments that are visually located next to the requested card or are assumed to be near it. Player controller = c.getController(); ArrayList attachments = Lists.newArrayList(); - ArrayList cardsOTB = Lists.newArrayList(CardLists.filter( + CardCollection cardsOTB = CardLists.filter( controller.getCardsIn(ZoneType.Battlefield), card -> { if (card.isAttachedToEntity(c)) { attachments.add(card); @@ -114,7 +114,7 @@ public class FlipOntoBattlefieldEffect extends SpellAbilityEffect { } return card.sharesCardTypeWith(c); } - )); + ); // Chance to hit an attachment float hitAttachment = 0.50f; diff --git a/forge-game/src/main/java/forge/game/ability/effects/LifeGainEffect.java b/forge-game/src/main/java/forge/game/ability/effects/LifeGainEffect.java index 2e960e40f6f..330fc305093 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/LifeGainEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/LifeGainEffect.java @@ -26,7 +26,7 @@ public class LifeGainEffect extends SpellAbilityEffect { sb.append(Lang.joinHomogenous(getDefinedPlayersOrTargeted(sa))); if (sb.length() == 0 && spellDesc != null) { - return (spellDesc); + return spellDesc; } else { sb.append(getDefinedPlayersOrTargeted(sa).size() > 1 ? " gain " : " gains "); if (!StringUtils.isNumeric(amountStr) && spellDesc != null && spellDesc.contains("life equal to")) { diff --git a/forge-game/src/main/java/forge/game/ability/effects/RestartGameEffect.java b/forge-game/src/main/java/forge/game/ability/effects/RestartGameEffect.java index 67bfc46627a..f521b0b8aef 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/RestartGameEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/RestartGameEffect.java @@ -29,7 +29,7 @@ public class RestartGameEffect extends SpellAbilityEffect { List restartZones = new ArrayList<>(Arrays.asList(ZoneType.Battlefield, ZoneType.Library, ZoneType.Graveyard, ZoneType.Hand, ZoneType.Exile)); - ZoneType leaveZone = ZoneType.smartValueOf(sa.hasParam("RestrictFromZone") ? sa.getParam("RestrictFromZone") : null); + ZoneType leaveZone = ZoneType.smartValueOf(sa.getParam("RestrictFromZone")); restartZones.remove(leaveZone); String leaveRestriction = sa.getParamOrDefault("RestrictFromValid", "Card"); diff --git a/forge-game/src/main/java/forge/game/spellability/AbilityManaPart.java b/forge-game/src/main/java/forge/game/spellability/AbilityManaPart.java index 742a5dc318d..5e58e9b6a22 100644 --- a/forge-game/src/main/java/forge/game/spellability/AbilityManaPart.java +++ b/forge-game/src/main/java/forge/game/spellability/AbilityManaPart.java @@ -252,7 +252,7 @@ public class AbilityManaPart implements java.io.Serializable { eff.setColor(MagicColor.COLORLESS); eff.setGamePieceType(GamePieceType.EFFECT); - String cantcounterstr = "Event$ Counter | ValidCard$ Card.IsRemembered | Description$ That spell can't be countered."; + String cantcounterstr = "Event$ Counter | ValidSA$ Spell.IsRemembered | Description$ That spell can't be countered."; ReplacementEffect re = ReplacementHandler.parseReplacement(cantcounterstr, eff, true); re.setLayer(ReplacementLayer.CantHappen); eff.addReplacementEffect(re); diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java index d45ef97b333..480c59dcb6f 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java @@ -453,11 +453,9 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit } public void setActivatingPlayer(final Player player) { // trickle down activating player - boolean updated = false; // don't use equals because player might be from simulation if (player == null || player != activatingPlayer) { activatingPlayer = player; - updated = true; } if (subAbility != null) { subAbility.setActivatingPlayer(player); diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerSearchedLibrary.java b/forge-game/src/main/java/forge/game/trigger/TriggerSearchedLibrary.java index 026aa9bce8e..508e6fa2ff9 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerSearchedLibrary.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerSearchedLibrary.java @@ -17,7 +17,6 @@ */ package forge.game.trigger; -import java.util.List; import java.util.Map; import forge.game.ability.AbilityKey; @@ -60,9 +59,8 @@ public class TriggerSearchedLibrary extends Trigger { return false; } if (hasParam("SearchOwnLibrary")) { - @SuppressWarnings("unchecked") - List targets = (List) runParams.get(AbilityKey.Target); - if (!targets.contains(runParams.get(AbilityKey.Player))) { + Player target = (Player) runParams.get(AbilityKey.Target); + if (!target.equals(runParams.get(AbilityKey.Player))) { return false; } } diff --git a/forge-gui/res/cardsfolder/e/ellivere_of_the_wild_court.txt b/forge-gui/res/cardsfolder/e/ellivere_of_the_wild_court.txt index 999a55d9b92..bc57089577f 100644 --- a/forge-gui/res/cardsfolder/e/ellivere_of_the_wild_court.txt +++ b/forge-gui/res/cardsfolder/e/ellivere_of_the_wild_court.txt @@ -4,7 +4,7 @@ Types:Legendary Creature Human Knight PT:4/4 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ Whenever CARDNAME enters or attacks, create a Virtuous Role token attached to another target creature you control. (If you control another Role on it, put that one into the graveyard. Enchanted creature gets +1/+1 for each enchantment you control.) T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigToken | Secondary$ True | TriggerDescription$ Whenever CARDNAME enters or attacks, create a Virtuous Role token attached to another target creature you control. (If you control another Role on it, put that one into the graveyard. Enchanted creature gets +1/+1 for each enchantment you control.) -SVar:TrigToken:DB$ Token | TokenScript$ role_virtuous | AttachedTo$ Targeted | ValidTgts$ Creature.YouCtrl+Other +SVar:TrigToken:DB$ Token | TokenScript$ role_virtuous | AttachedTo$ Targeted | ValidTgts$ Creature.YouCtrl+Other | TokenOwner$ You T:Mode$ DamageDone | ValidSource$ Creature.YouCtrl+enchanted | ValidTarget$ Player | CombatDamage$ True | TriggerZones$ Battlefield | Execute$ TrigDraw | TriggerDescription$ Whenever an enchanted creature you control deals combat damage to a player, draw a card. SVar:TrigDraw:DB$ Draw SVar:HasAttackEffect:TRUE diff --git a/forge-gui/res/cardsfolder/g/grenzo_dungeon_warden.txt b/forge-gui/res/cardsfolder/g/grenzo_dungeon_warden.txt index 2acfd98896e..e92bf3a2352 100644 --- a/forge-gui/res/cardsfolder/g/grenzo_dungeon_warden.txt +++ b/forge-gui/res/cardsfolder/g/grenzo_dungeon_warden.txt @@ -4,7 +4,7 @@ Types:Legendary Creature Goblin Rogue PT:2/2 K:etbCounter:P1P1:X SVar:X:Count$xPaid -A:AB$ ChangeZone | Cost$ 2 | Defined$ BottomOfLibrary | Origin$ Library | Destination$ Graveyard | RememberChanged$ True | SubAbility$ DBChangeZone | StackDescription$ SpellDescription | SpellDescription$ Put the bottom card of your library into your graveyard. If it's a creature card with power less than or equal to CARDNAME's power, put it onto the battlefield. +A:AB$ ChangeZone | Cost$ 2 | Defined$ BottomOfLibrary | Origin$ Library | Destination$ Graveyard | RememberChanged$ True | SubAbility$ DBChangeZone | StackDescription$ SpellDescription | SpellDescription$ Put the bottom card of your library into your graveyard. If it's a creature card with power less than or equal to NICKNAME's power, put it onto the battlefield. SVar:DBChangeZone:DB$ ChangeZone | Defined$ Remembered | Origin$ All | Destination$ Battlefield | Hidden$ True | ConditionDefined$ Remembered | ConditionPresent$ Card.Creature+powerLEY | ConditionCompare$ GE1 | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:Y:Count$CardPower diff --git a/forge-gui/res/cardsfolder/v/veiled_apparition.txt b/forge-gui/res/cardsfolder/v/veiled_apparition.txt index 8fbfb628a6a..ea023c9c5af 100644 --- a/forge-gui/res/cardsfolder/v/veiled_apparition.txt +++ b/forge-gui/res/cardsfolder/v/veiled_apparition.txt @@ -2,5 +2,7 @@ Name:Veiled Apparition ManaCost:1 U Types:Enchantment T:Mode$ SpellCast | ValidCard$ Card | ValidActivatingPlayer$ Opponent | TriggerZones$ Battlefield | IsPresent$ Card.Self+Enchantment | Execute$ TrigAnimate | TriggerDescription$ When an opponent casts a spell, if CARDNAME is an enchantment, CARDNAME becomes a 3/3 Illusion creature with flying and "At the beginning of your upkeep, sacrifice CARDNAME unless you pay {1}{U}." -SVar:TrigAnimate:DB$ Animate | Defined$ Self | Power$ 3 | Toughness$ 3 | Keywords$ Flying & UpkeepCost:1 U | Types$ Creature,Illusion | RemoveCardTypes$ True | RemoveCreatureTypes$ True | Duration$ Permanent +SVar:TrigAnimate:DB$ Animate | Defined$ Self | Power$ 3 | Toughness$ 3 | Keywords$ Flying | Triggers$ UpkeepCostTrigger | Types$ Creature,Illusion | RemoveCardTypes$ True | RemoveCreatureTypes$ True | Duration$ Permanent +SVar:UpkeepCostTrigger:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigUpkeep | TriggerDescription$ At the beginning of your upkeep, sacrifice CARDNAME unless you pay {1}{U}. +SVar:TrigUpkeep:DB$ Sacrifice | UnlessPayer$ You | UnlessCost$ 1 U Oracle:When an opponent casts a spell, if Veiled Apparition is an enchantment, Veiled Apparition becomes a 3/3 Illusion creature with flying and "At the beginning of your upkeep, sacrifice Veiled Apparition unless you pay {1}{U}."