mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 03:38:01 +00:00
Cipher is now a Keyword with a StaticAbility
This commit is contained in:
@@ -299,6 +299,19 @@ public class GameAction {
|
|||||||
if (!zoneTo.is(ZoneType.Exile) && !zoneTo.is(ZoneType.Stack)) {
|
if (!zoneTo.is(ZoneType.Exile) && !zoneTo.is(ZoneType.Stack)) {
|
||||||
c.setExiledWith(null);
|
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
|
// "enter the battlefield as a copy" - apply code here
|
||||||
|
|||||||
@@ -5,11 +5,8 @@ import forge.game.GameLogEntryType;
|
|||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardCollectionView;
|
import forge.game.card.CardCollectionView;
|
||||||
import forge.game.card.CardLists;
|
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.trigger.Trigger;
|
|
||||||
import forge.game.trigger.TriggerHandler;
|
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
|
|
||||||
public class EncodeEffect extends SpellAbilityEffect {
|
public class EncodeEffect extends SpellAbilityEffect {
|
||||||
@@ -38,8 +35,7 @@ public class EncodeEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// make list of creatures that controller has on Battlefield
|
// make list of creatures that controller has on Battlefield
|
||||||
CardCollectionView choices = game.getCardsIn(ZoneType.Battlefield);
|
CardCollectionView choices = host.getController().getCreaturesInPlay();
|
||||||
choices = CardLists.getValidCards(choices, "Creature.YouCtrl", host.getController(), host);
|
|
||||||
|
|
||||||
// if no creatures on battlefield, cannot encoded
|
// if no creatures on battlefield, cannot encoded
|
||||||
if (choices.isEmpty()) {
|
if (choices.isEmpty()) {
|
||||||
@@ -70,19 +66,8 @@ public class EncodeEffect extends SpellAbilityEffect {
|
|||||||
|
|
||||||
// store hostcard in encoded array
|
// store hostcard in encoded array
|
||||||
choice.addEncodedCard(movedCard);
|
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;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,11 +74,6 @@ public class PlayEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
tgtCards = (CardCollection)AbilityUtils.filterListByType(game.getCardsIn(zone), sa.getParam("Valid"), sa);
|
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")) {
|
else if (sa.hasParam("AnySupportedCard")) {
|
||||||
List<PaperCard> cards = Lists.newArrayList(StaticData.instance().getCommonCards().getUniqueCards());
|
List<PaperCard> cards = Lists.newArrayList(StaticData.instance().getCommonCards().getUniqueCards());
|
||||||
final String valid = sa.getParam("AnySupportedCard");
|
final String valid = sa.getParam("AnySupportedCard");
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
private CardCollection mustBlockCards, clones, gainControlTargets, chosenCards, blockedThisTurn, blockedByThisTurn;
|
private CardCollection mustBlockCards, clones, gainControlTargets, chosenCards, blockedThisTurn, blockedByThisTurn;
|
||||||
|
|
||||||
// if this card is attached or linked to something, what card is it currently attached to
|
// 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?
|
// if this card is an Aura, what Entity is it enchanting?
|
||||||
private GameEntity enchanting = null;
|
private GameEntity enchanting = null;
|
||||||
@@ -763,6 +763,14 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
encodedCards = view.clearCards(encodedCards, TrackableProperty.EncodedCards);
|
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) {
|
public final String getFlipResult(final Player flipper) {
|
||||||
if (flipResult == null) {
|
if (flipResult == null) {
|
||||||
return null;
|
return null;
|
||||||
@@ -4099,6 +4107,10 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
if (!getExiledWith().equals(host)) {
|
if (!getExiledWith().equals(host)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
} else if (property.equals("EncodedWithSource")) {
|
||||||
|
if (!getEncodedCards().contains(source)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else if (property.equals("EffectSource")) {
|
} else if (property.equals("EffectSource")) {
|
||||||
if (!source.isEmblem() && !source.getType().hasSubtype("Effect")) {
|
if (!source.isEmblem() && !source.getType().hasSubtype("Effect")) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -1950,6 +1950,8 @@ public class CardFactoryUtil {
|
|||||||
for (String keyword : card.getKeywords()) {
|
for (String keyword : card.getKeywords()) {
|
||||||
if (keyword.startsWith("Absorb")) {
|
if (keyword.startsWith("Absorb")) {
|
||||||
addStaticAbility(keyword, card, null);
|
addStaticAbility(keyword, card, null);
|
||||||
|
} else if (keyword.equals("Cipher")) {
|
||||||
|
addStaticAbility(keyword, card, null);
|
||||||
} else if (keyword.startsWith("Multikicker")) {
|
} else if (keyword.startsWith("Multikicker")) {
|
||||||
final String[] n = keyword.split(":");
|
final String[] n = keyword.split(":");
|
||||||
final SpellAbility sa = card.getFirstSpellAbility();
|
final SpellAbility sa = card.getFirstSpellAbility();
|
||||||
@@ -4079,6 +4081,31 @@ public class CardFactoryUtil {
|
|||||||
sb.append(n).append("| Secondary$ True | Description$ Absorb ").append(n);
|
sb.append(n).append("| Secondary$ True | Description$ Absorb ").append(n);
|
||||||
sb.append(" (").append(Keyword.getInstance(keyword).getReminderText()).append(")");
|
sb.append(" (").append(Keyword.getInstance(keyword).getReminderText()).append(")");
|
||||||
effect = sb.toString();
|
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")) {
|
} else if (keyword.startsWith("Escalate")) {
|
||||||
final String[] k = keyword.split(":");
|
final String[] k = keyword.split(":");
|
||||||
final String manacost = k[1];
|
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" +
|
effect = "Mode$ RaiseCost | ValidCard$ Card.Self | Type$ Spell | Amount$ Escalate | Cost$ "+ manacost +" | EffectZone$ All" +
|
||||||
" | Description$ " + sb.toString() + " (" + Keyword.getInstance(keyword).getReminderText() + ")";
|
" | 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")) {
|
} else if (keyword.startsWith("Strive")) {
|
||||||
final String[] k = keyword.split(":");
|
final String[] k = keyword.split(":");
|
||||||
final String manacost = k[1];
|
final String manacost = k[1];
|
||||||
|
|||||||
@@ -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."),
|
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."),
|
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."),
|
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."),
|
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."),
|
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."),
|
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."),
|
||||||
|
|||||||
Reference in New Issue
Block a user