@Override public void resolve(final SpellAbility sa) { final Card host = sa.getHostCard(); final Map<String, String> svars = host.getSVars(); // AF specific sa int power = -1; if (sa.hasParam("Power")) { power = AbilityUtils.calculateAmount(host, sa.getParam("Power"), sa); } int toughness = -1; if (sa.hasParam("Toughness")) { toughness = AbilityUtils.calculateAmount(host, sa.getParam("Toughness"), sa); } final Game game = sa.getActivatingPlayer().getGame(); // Every Animate event needs a unique time stamp final long timestamp = game.getNextTimestamp(); final boolean permanent = sa.hasParam("Permanent"); final CardType types = new CardType(); if (sa.hasParam("Types")) { types.addAll(Arrays.asList(sa.getParam("Types").split(","))); } final CardType removeTypes = new CardType(); if (sa.hasParam("RemoveTypes")) { removeTypes.addAll(Arrays.asList(sa.getParam("RemoveTypes").split(","))); } // allow ChosenType - overrides anything else specified if (types.hasSubtype("ChosenType")) { types.clear(); types.add(host.getChosenType()); } final List<String> keywords = new ArrayList<String>(); if (sa.hasParam("Keywords")) { keywords.addAll(Arrays.asList(sa.getParam("Keywords").split(" & "))); } final List<String> removeKeywords = new ArrayList<String>(); if (sa.hasParam("RemoveKeywords")) { removeKeywords.addAll(Arrays.asList(sa.getParam("RemoveKeywords").split(" & "))); } final List<String> hiddenKeywords = new ArrayList<String>(); if (sa.hasParam("HiddenKeywords")) { hiddenKeywords.addAll(Arrays.asList(sa.getParam("HiddenKeywords").split(" & "))); } // allow SVar substitution for keywords for (int i = 0; i < keywords.size(); i++) { final String k = keywords.get(i); if (svars.containsKey(k)) { keywords.add(svars.get(k)); keywords.remove(k); } } // colors to be added or changed to String tmpDesc = ""; if (sa.hasParam("Colors")) { final String colors = sa.getParam("Colors"); if (colors.equals("ChosenColor")) { tmpDesc = CardUtil.getShortColorsString(host.getChosenColors()); } else { tmpDesc = CardUtil.getShortColorsString(new ArrayList<String>(Arrays.asList(colors.split(",")))); } } final String finalDesc = tmpDesc; // abilities to add to the animated being final List<String> abilities = new ArrayList<String>(); if (sa.hasParam("Abilities")) { abilities.addAll(Arrays.asList(sa.getParam("Abilities").split(","))); } // replacement effects to add to the animated being final List<String> replacements = new ArrayList<String>(); if (sa.hasParam("Replacements")) { replacements.addAll(Arrays.asList(sa.getParam("Replacements").split(","))); } // triggers to add to the animated being final List<String> triggers = new ArrayList<String>(); if (sa.hasParam("Triggers")) { triggers.addAll(Arrays.asList(sa.getParam("Triggers").split(","))); } // sVars to add to the animated being final List<String> sVars = new ArrayList<String>(); if (sa.hasParam("sVars")) { sVars.addAll(Arrays.asList(sa.getParam("sVars").split(","))); } String valid = ""; if (sa.hasParam("ValidCards")) { valid = sa.getParam("ValidCards"); } CardCollectionView list; List<Player> tgtPlayers = getTargetPlayers(sa); if (!sa.usesTargeting() && !sa.hasParam("Defined")) { list = game.getCardsIn(ZoneType.Battlefield); } else { list = tgtPlayers.get(0).getCardsIn(ZoneType.Battlefield); } list = CardLists.getValidCards(list, valid.split(","), host.getController(), host); for (final Card c : list) { doAnimate( c, sa, power, toughness, types, removeTypes, finalDesc, keywords, removeKeywords, hiddenKeywords, timestamp); // give abilities final List<SpellAbility> addedAbilities = new ArrayList<SpellAbility>(); if (abilities.size() > 0) { for (final String s : abilities) { final String actualAbility = host.getSVar(s); final SpellAbility grantedAbility = AbilityFactory.getAbility(actualAbility, c); addedAbilities.add(grantedAbility); c.addSpellAbility(grantedAbility); } } // remove abilities final List<SpellAbility> removedAbilities = new ArrayList<SpellAbility>(); if (sa.hasParam("OverwriteAbilities") || sa.hasParam("RemoveAllAbilities")) { for (final SpellAbility ab : c.getSpellAbilities()) { if (ab.isAbility()) { c.removeSpellAbility(ab); removedAbilities.add(ab); } } } // give replacement effects final List<ReplacementEffect> addedReplacements = new ArrayList<ReplacementEffect>(); if (replacements.size() > 0) { for (final String s : replacements) { final String actualReplacement = host.getSVar(s); final ReplacementEffect parsedReplacement = ReplacementHandler.parseReplacement(actualReplacement, c, false); addedReplacements.add(c.addReplacementEffect(parsedReplacement)); } } // Grant triggers final List<Trigger> addedTriggers = new ArrayList<Trigger>(); if (triggers.size() > 0) { for (final String s : triggers) { final String actualTrigger = host.getSVar(s); final Trigger parsedTrigger = TriggerHandler.parseTrigger(actualTrigger, c, false); addedTriggers.add(c.addTrigger(parsedTrigger)); } } // suppress triggers from the animated card final List<Trigger> removedTriggers = new ArrayList<Trigger>(); if (sa.hasParam("OverwriteTriggers") || sa.hasParam("RemoveAllAbilities")) { final FCollectionView<Trigger> triggersToRemove = c.getTriggers(); for (final Trigger trigger : triggersToRemove) { trigger.setSuppressed(true); removedTriggers.add(trigger); } } // suppress static abilities from the animated card final List<StaticAbility> removedStatics = new ArrayList<StaticAbility>(); if (sa.hasParam("OverwriteStatics") || sa.hasParam("RemoveAllAbilities")) { final FCollectionView<StaticAbility> staticsToRemove = c.getStaticAbilities(); for (final StaticAbility stAb : staticsToRemove) { stAb.setTemporarilySuppressed(true); removedStatics.add(stAb); } } // suppress static abilities from the animated card final List<ReplacementEffect> removedReplacements = new ArrayList<ReplacementEffect>(); if (sa.hasParam("OverwriteReplacements") || sa.hasParam("RemoveAllAbilities")) { final FCollectionView<ReplacementEffect> replacementsToRemove = c.getReplacementEffects(); for (final ReplacementEffect re : replacementsToRemove) { re.setTemporarilySuppressed(true); removedReplacements.add(re); } } // give sVars if (sVars.size() > 0) { for (final String s : sVars) { final String actualsVar = host.getSVar(s); c.setSVar(s, actualsVar); } } game.fireEvent(new GameEventCardStatsChanged(c)); final GameCommand unanimate = new GameCommand() { private static final long serialVersionUID = -5861759814760561373L; @Override public void run() { doUnanimate( c, sa, finalDesc, hiddenKeywords, addedAbilities, addedTriggers, addedReplacements, false, removedAbilities, timestamp); // give back suppressed triggers for (final Trigger t : removedTriggers) { t.setSuppressed(false); } // give back suppressed static abilities for (final StaticAbility s : removedStatics) { s.setTemporarilySuppressed(false); } // give back suppressed replacement effects for (final ReplacementEffect re : removedReplacements) { re.setTemporarilySuppressed(false); } game.fireEvent(new GameEventCardStatsChanged(c)); } }; if (!permanent) { if (sa.hasParam("UntilEndOfCombat")) { game.getEndOfCombat().addUntil(unanimate); } else { game.getEndOfTurn().addUntil(unanimate); } } } } // animateAllResolve
@Override public void resolve(SpellAbility sa) { final Card host = sa.getHostCard(); final Player player = sa.getActivatingPlayer(); final Game game = player.getGame(); // make list of creatures that controller has on Battlefield CardCollectionView choices = game.getCardsIn(ZoneType.Battlefield); choices = CardLists.getValidCards(choices, "Creature.YouCtrl", host.getController(), host); // if no creatures on battlefield, cannot encoded if (choices.isEmpty()) { return; } // Handle choice of whether or not to encoded final StringBuilder sb = new StringBuilder(); sb.append("Do you want to exile " + host + " and encode it onto a creature you control?"); if (!player.getController().confirmAction(sa, null, sb.toString())) { return; } // move host card to exile Card movedCard = game.getAction().moveTo(ZoneType.Exile, host); // choose a creature Card choice = player .getController() .chooseSingleEntityForEffect( choices, sa, "Choose a creature you control to encode ", true); if (choice == null) { return; } StringBuilder codeLog = new StringBuilder(); codeLog.append("Encoding ").append(host.toString()).append(" to ").append(choice.toString()); game.getGameLog().add(GameLogEntryType.STACK_RESOLVE, codeLog.toString()); // store hostcard in encoded array choice.addEncodedCard(movedCard); // 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; }
/* (non-Javadoc) * @see forge.card.ability.SpellAbilityEffect#resolve(forge.card.spellability.SpellAbility) */ @Override public void resolve(final SpellAbility sa) { final Card hostCard = sa.getHostCard(); final Game game = hostCard.getGame(); final List<String> keywords = new ArrayList<String>(); final List<String> types = new ArrayList<String>(); final List<String> svars = new ArrayList<String>(); final List<String> triggers = new ArrayList<String>(); if (sa.hasParam("Optional")) { if (!sa.getActivatingPlayer() .getController() .confirmAction(sa, null, "Copy this permanent?")) { return; } } if (sa.hasParam("Keywords")) { keywords.addAll(Arrays.asList(sa.getParam("Keywords").split(" & "))); } if (sa.hasParam("AddTypes")) { types.addAll(Arrays.asList(sa.getParam("AddTypes").split(" & "))); } if (sa.hasParam("AddSVars")) { svars.addAll(Arrays.asList(sa.getParam("AddSVars").split(" & "))); } if (sa.hasParam("Triggers")) { triggers.addAll(Arrays.asList(sa.getParam("Triggers").split(" & "))); } final int numCopies = sa.hasParam("NumCopies") ? AbilityUtils.calculateAmount(hostCard, sa.getParam("NumCopies"), sa) : 1; Player controller = null; if (sa.hasParam("Controller")) { final FCollectionView<Player> defined = AbilityUtils.getDefinedPlayers(hostCard, sa.getParam("Controller"), sa); if (!defined.isEmpty()) { controller = defined.getFirst(); } } if (controller == null) { controller = sa.getActivatingPlayer(); } List<Card> tgtCards = getTargetCards(sa); final TargetRestrictions tgt = sa.getTargetRestrictions(); if (sa.hasParam("ValidSupportedCopy")) { List<PaperCard> cards = Lists.newArrayList(StaticData.instance().getCommonCards().getUniqueCards()); String valid = sa.getParam("ValidSupportedCopy"); if (valid.contains("X")) { valid = valid.replace("X", Integer.toString(AbilityUtils.calculateAmount(hostCard, "X", sa))); } if (StringUtils.containsIgnoreCase(valid, "creature")) { Predicate<PaperCard> cpp = Predicates.compose(CardRulesPredicates.Presets.IS_CREATURE, PaperCard.FN_GET_RULES); cards = Lists.newArrayList(Iterables.filter(cards, cpp)); } if (StringUtils.containsIgnoreCase(valid, "equipment")) { Predicate<PaperCard> cpp = Predicates.compose(CardRulesPredicates.Presets.IS_EQUIPMENT, PaperCard.FN_GET_RULES); cards = Lists.newArrayList(Iterables.filter(cards, cpp)); } if (sa.hasParam("RandomCopied")) { List<PaperCard> copysource = new ArrayList<PaperCard>(cards); List<Card> choice = new ArrayList<Card>(); final String num = sa.hasParam("RandomNum") ? sa.getParam("RandomNum") : "1"; int ncopied = AbilityUtils.calculateAmount(hostCard, num, sa); while (ncopied > 0) { final PaperCard cp = Aggregates.random(copysource); Card possibleCard = Card.fromPaperCard( cp, sa.getActivatingPlayer()); // Need to temporarily set the Owner so the Game is set if (possibleCard.isValid(valid, hostCard.getController(), hostCard)) { choice.add(possibleCard); copysource.remove(cp); ncopied -= 1; } } tgtCards = choice; } else if (sa.hasParam("DefinedName")) { String name = sa.getParam("DefinedName"); if (name.equals("NamedCard")) { if (!hostCard.getNamedCard().isEmpty()) { name = hostCard.getNamedCard(); } } Predicate<PaperCard> cpp = Predicates.compose( CardRulesPredicates.name(StringOp.EQUALS, name), PaperCard.FN_GET_RULES); cards = Lists.newArrayList(Iterables.filter(cards, cpp)); tgtCards.clear(); if (!cards.isEmpty()) { tgtCards.add(Card.fromPaperCard(cards.get(0), controller)); } } } hostCard.clearClones(); for (final Card c : tgtCards) { if ((tgt == null) || c.canBeTargetedBy(sa)) { int multiplier = numCopies * hostCard.getController().getTokenDoublersMagnitude(); final List<Card> crds = new ArrayList<Card>(multiplier); for (int i = 0; i < multiplier; i++) { final Card copy = CardFactory.copyCopiableCharacteristics(c, sa.getActivatingPlayer()); copy.setToken(true); copy.setCopiedPermanent(c); CardFactory.copyCopiableAbilities(c, copy); // add keywords from sa for (final String kw : keywords) { copy.addIntrinsicKeyword(kw); } for (final String type : types) { copy.addType(type); } for (final String svar : svars) { String actualsVar = hostCard.getSVar(svar); String name = svar; if (actualsVar.startsWith("SVar:")) { actualsVar = actualsVar.split("SVar:")[1]; name = actualsVar.split(":")[0]; actualsVar = actualsVar.split(":")[1]; } copy.setSVar(name, actualsVar); } for (final String s : triggers) { final String actualTrigger = hostCard.getSVar(s); final Trigger parsedTrigger = TriggerHandler.parseTrigger(actualTrigger, copy, true); copy.addTrigger(parsedTrigger); } // Temporarily register triggers of an object created with CopyPermanent // game.getTriggerHandler().registerActiveTrigger(copy, false); final Card copyInPlay = game.getAction().moveToPlay(copy); // when copying something stolen: copyInPlay.setController(controller, 0); copyInPlay.setSetCode(c.getSetCode()); copyInPlay.setCloneOrigin(hostCard); sa.getHostCard().addClone(copyInPlay); crds.add(copyInPlay); if (sa.hasParam("RememberCopied")) { hostCard.addRemembered(copyInPlay); } if (sa.hasParam("Tapped")) { copyInPlay.setTapped(true); } if (sa.hasParam("CopyAttacking") && game.getPhaseHandler().inCombat()) { final String attacked = sa.getParam("CopyAttacking"); GameEntity defender; if ("True".equals(attacked)) { FCollectionView<GameEntity> defs = game.getCombat().getDefenders(); defender = c.getController() .getController() .chooseSingleEntityForEffect( defs, sa, "Choose which defender to attack with " + c, false); } else { defender = AbilityUtils.getDefinedPlayers(hostCard, sa.getParam("CopyAttacking"), sa).get(0); } game.getCombat().addAttacker(copyInPlay, defender); game.fireEvent(new GameEventCombatChanged()); } if (sa.hasParam("AttachedTo")) { CardCollectionView list = AbilityUtils.getDefinedCards(hostCard, sa.getParam("AttachedTo"), sa); if (list.isEmpty()) { list = copyInPlay.getController().getGame().getCardsIn(ZoneType.Battlefield); list = CardLists.getValidCards( list, sa.getParam("AttachedTo"), copyInPlay.getController(), copyInPlay); } if (!list.isEmpty()) { Card attachedTo = sa.getActivatingPlayer() .getController() .chooseSingleEntityForEffect( list, sa, copyInPlay + " - Select a card to attach to."); if (copyInPlay.isAura()) { if (attachedTo.canBeEnchantedBy(copyInPlay)) { copyInPlay.enchantEntity(attachedTo); } else { // can't enchant continue; } } else if (copyInPlay.isEquipment()) { // Equipment if (attachedTo.canBeEquippedBy(copyInPlay)) { copyInPlay.equipCard(attachedTo); } else { continue; } } else { // Fortification copyInPlay.fortifyCard(attachedTo); } } else { continue; } } } if (sa.hasParam("AtEOT")) { final String location = sa.getParam("AtEOT"); registerDelayedTrigger(sa, location, crds); } } // end canBeTargetedBy } // end foreach Card } // end resolve