diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index 997f9fb1517..ff206fbaa72 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -299,6 +299,19 @@ public class GameAction { if (!zoneTo.is(ZoneType.Exile) && !zoneTo.is(ZoneType.Stack)) { c.setExiledWith(null); } + + // cleanup Encoding + if (c.hasEncodedCard()) { + for (final Card e : c.getEncodedCards()) { + e.setEncodingCard(null); + } + } + if (zoneFrom.is(ZoneType.Exile)) { + Card e = c.getEncodingCard(); + if (e != null) { + e.removeEncodedCard(c); + } + } } // "enter the battlefield as a copy" - apply code here diff --git a/forge-game/src/main/java/forge/game/ability/effects/EncodeEffect.java b/forge-game/src/main/java/forge/game/ability/effects/EncodeEffect.java index bb795c0ae9b..fcee4a9c273 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/EncodeEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/EncodeEffect.java @@ -5,11 +5,8 @@ import forge.game.GameLogEntryType; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; import forge.game.card.CardCollectionView; -import forge.game.card.CardLists; import forge.game.player.Player; import forge.game.spellability.SpellAbility; -import forge.game.trigger.Trigger; -import forge.game.trigger.TriggerHandler; import forge.game.zone.ZoneType; public class EncodeEffect extends SpellAbilityEffect { @@ -38,8 +35,7 @@ public class EncodeEffect extends SpellAbilityEffect { } // make list of creatures that controller has on Battlefield - CardCollectionView choices = game.getCardsIn(ZoneType.Battlefield); - choices = CardLists.getValidCards(choices, "Creature.YouCtrl", host.getController(), host); + CardCollectionView choices = host.getController().getCreaturesInPlay(); // if no creatures on battlefield, cannot encoded if (choices.isEmpty()) { @@ -70,19 +66,8 @@ public class EncodeEffect extends SpellAbilityEffect { // store hostcard in encoded array choice.addEncodedCard(movedCard); + movedCard.setEncodingCard(choice); - // add trigger - final int numEncoded = choice.getEncodedCards().size(); - final StringBuilder cipherTrigger = new StringBuilder(); - cipherTrigger.append("Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | Execute$ PlayEncoded").append(numEncoded); - cipherTrigger.append(" | CombatDamage$ True | OptionalDecider$ You | TriggerDescription$ "); - cipherTrigger.append("Whenever CARDNAME deals combat damage to a player, its controller may cast a copy of "); - cipherTrigger.append(movedCard).append(" without paying its mana cost."); - final String abName = "PlayEncoded" + numEncoded; - final String abString = "AB$ Play | Cost$ 0 | Encoded$ " + numEncoded + " | WithoutManaCost$ True | CopyCard$ True"; - final Trigger parsedTrigger = TriggerHandler.parseTrigger(cipherTrigger.toString(), choice, false); - choice.addTrigger(parsedTrigger); - choice.setSVar(abName, abString); return; } diff --git a/forge-game/src/main/java/forge/game/ability/effects/PlayEffect.java b/forge-game/src/main/java/forge/game/ability/effects/PlayEffect.java index 6fd2f1e8c7d..834965b76da 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/PlayEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/PlayEffect.java @@ -74,11 +74,6 @@ public class PlayEffect extends SpellAbilityEffect { } tgtCards = (CardCollection)AbilityUtils.filterListByType(game.getCardsIn(zone), sa.getParam("Valid"), sa); } - else if (sa.hasParam("Encoded")) { - final CardCollectionView encodedCards = source.getEncodedCards(); - final int encodedIndex = Integer.parseInt(sa.getParam("Encoded")) - 1; - tgtCards = new CardCollection(encodedCards.get(encodedIndex)); - } else if (sa.hasParam("AnySupportedCard")) { List cards = Lists.newArrayList(StaticData.instance().getCommonCards().getUniqueCards()); final String valid = sa.getParam("AnySupportedCard"); diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index ef37859c8f9..e1ee22ef9f6 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -107,7 +107,7 @@ public class Card extends GameEntity implements Comparable { private CardCollection mustBlockCards, clones, gainControlTargets, chosenCards, blockedThisTurn, blockedByThisTurn; // if this card is attached or linked to something, what card is it currently attached to - private Card equipping, fortifying, cloneOrigin, haunting, effectSource, pairedWith, meldedWith; + private Card equipping, encoding, fortifying, cloneOrigin, haunting, effectSource, pairedWith, meldedWith; // if this card is an Aura, what Entity is it enchanting? private GameEntity enchanting = null; @@ -763,6 +763,14 @@ public class Card extends GameEntity implements Comparable { encodedCards = view.clearCards(encodedCards, TrackableProperty.EncodedCards); } + public final Card getEncodingCard() { + return encoding; + } + + public final void setEncodingCard(final Card e) { + encoding = e; + } + public final String getFlipResult(final Player flipper) { if (flipResult == null) { return null; @@ -4099,6 +4107,10 @@ public class Card extends GameEntity implements Comparable { if (!getExiledWith().equals(host)) { return false; } + } else if (property.equals("EncodedWithSource")) { + if (!getEncodedCards().contains(source)) { + return false; + } } else if (property.equals("EffectSource")) { if (!source.isEmblem() && !source.getType().hasSubtype("Effect")) { return false; diff --git a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java index 3ad43a06fe9..37c7ee379cb 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -1950,6 +1950,8 @@ public class CardFactoryUtil { for (String keyword : card.getKeywords()) { if (keyword.startsWith("Absorb")) { addStaticAbility(keyword, card, null); + } else if (keyword.equals("Cipher")) { + addStaticAbility(keyword, card, null); } else if (keyword.startsWith("Multikicker")) { final String[] n = keyword.split(":"); final SpellAbility sa = card.getFirstSpellAbility(); @@ -4079,6 +4081,31 @@ public class CardFactoryUtil { sb.append(n).append("| Secondary$ True | Description$ Absorb ").append(n); sb.append(" (").append(Keyword.getInstance(keyword).getReminderText()).append(")"); effect = sb.toString(); + } else if (keyword.equals("Changeling")) { + effect = "Mode$ Continuous | EffectZone$ All | Affected$ Card.Self" + + " | CharacteristicDefining$ True | AddType$ AllCreatureTypes | Secondary$ True" + + " | Description$ Changeling (" + Keyword.getInstance(keyword).getReminderText() + ")"; + } else if (keyword.equals("Cipher")) { + StringBuilder sb = new StringBuilder(); + sb.append("Mode$ Continuous | EffectZone$ Exile | Affected$ Card.EncodedWithSource"); + sb.append(" | AddTrigger$ CipherTrigger"); + sb.append(" | Description$ Cipher (" + Keyword.getInstance(keyword).getReminderText() + ")"); + + effect = sb.toString(); + + sb = new StringBuilder(); + + sb.append("Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | Execute$ PlayEncoded"); + sb.append(" | CombatDamage$ True | OptionalDecider$ You | TriggerDescription$ "); + sb.append("Whenever CARDNAME deals combat damage to a player, its controller may cast a copy of "); + sb.append(card.getName()).append(" without paying its mana cost."); + + String trig = sb.toString(); + + String ab = "DB$ Play | Defined$ OriginalHost | WithoutManaCost$ True | CopyCard$ True"; + + card.setSVar("CipherTrigger", trig); + card.setSVar("PlayEncoded", ab); } else if (keyword.startsWith("Escalate")) { final String[] k = keyword.split(":"); final String manacost = k[1]; @@ -4092,10 +4119,6 @@ public class CardFactoryUtil { effect = "Mode$ RaiseCost | ValidCard$ Card.Self | Type$ Spell | Amount$ Escalate | Cost$ "+ manacost +" | EffectZone$ All" + " | Description$ " + sb.toString() + " (" + Keyword.getInstance(keyword).getReminderText() + ")"; - } else if (keyword.equals("Changeling")) { - effect = "Mode$ Continuous | EffectZone$ All | Affected$ Card.Self" + - " | CharacteristicDefining$ True | AddType$ AllCreatureTypes | Secondary$ True" + - " | Description$ Changeling (" + Keyword.getInstance(keyword).getReminderText() + ")"; } else if (keyword.startsWith("Strive")) { final String[] k = keyword.split(":"); final String manacost = k[1]; diff --git a/forge-game/src/main/java/forge/game/keyword/Keyword.java b/forge-game/src/main/java/forge/game/keyword/Keyword.java index 742bb4f64c5..c3644838936 100644 --- a/forge-game/src/main/java/forge/game/keyword/Keyword.java +++ b/forge-game/src/main/java/forge/game/keyword/Keyword.java @@ -25,6 +25,7 @@ public enum Keyword { CASCADE(SimpleKeyword.class, false, "When you cast this spell, exile cards from the top of your library until you exile a nonland card whose converted mana cost is less than this spell's converted mana cost. You may cast that card without paying its mana cost. Then put all cards exiled this way that weren't cast on the bottom of your library in a random order."), CHAMPION(KeywordWithType.class, false, "When this enters the battlefield, sacrifice it unless you exile another %s you control. When this leaves the battlefield, that card returns to the battlefield."), CHANGELING(SimpleKeyword.class, true, "This card is every creature type."), + CIPHER(SimpleKeyword.class, true, "Then you may exile this spell card encoded on a creature you control. Whenever that creature deals combat damage to a player, its controller may cast a copy of the encoded card without paying its mana cost."), CONSPIRE(SimpleKeyword.class, false, "As an additional cost to cast this spell, you may tap two untapped creatures you control that each share a color with it. If you do, copy it."), CONVOKE(SimpleKeyword.class, true, "Each creature you tap while playing this spell reduces its cost by {1} or by one mana of that creature's color."), CREW(KeywordWithAmount.class, true, "Tap any number of creatures you control with total power %1$d or more: This Vehicle becomes an artifact creature until end of turn."),