It is currently 08 Sep 2025, 05:02
   
Text Size

New keyword: spBounceTgt

Post MTG Forge Related Programming Questions Here

Moderators: timmermac, Blacksmith, KrazyTheFox, Agetian, friarsol, CCGHQ Admins

Re: New keyword: spBounceTgt

Postby Rob Cashwalker » 28 Aug 2010, 21:28

Multi-target versions vary a bit - some are precisely N targets, and others are "up to" N targets... so I will look into making that as a separate keyword, since the AI would have to take that into consideration.

Meanwhile, I've revised the code for this keyword to handle drawbacks and the target selection prompt string takes the different destinations into account.

Code: Select all

        // Generic bounce target card
        if(hasKeyword(card, "spBounceTgt") != -1) {
            int n = hasKeyword(card, "spBounceTgt");
           
            String parse = card.getKeyword().get(n).toString();
            card.removeIntrinsicKeyword(parse);
           
            String k[] = parse.split(":");
            String Targets = k[1]; // Artifact, Creature, Enchantment, Land, Permanent, White, Blue, Black, Red, Green, Colorless, MultiColor
            // non-Artifact, non-Creature, non-Enchantment, non-Land, non-Permanent,
            //non-White, non-Blue, non-Black, non-Red, non-Green, non-Colorless, non-MultiColor
            final String Tgts[] = Targets.split(",");
                       
            final String Destination = k[2];
           
            final String Drawback[] = {"none"};
            if (k.length > 3)
            {
               if (k[3].contains("Drawback$"))
                  Drawback[0] = k[3];
            }
           
            final String Selec[] = {"Select a target "};
            String tgtType = "";
            if (Destination.equals("Hand"))
            {
                tgtType = card.getSpellText().substring("Return target ".length());
                int i = tgtType.indexOf(" to its owner's hand.");
                tgtType = tgtType.substring(0, i);
                Selec[0] += tgtType + " to return.";
            }
            else if (Destination.equals("Exile"))
            {
               tgtType = card.getSpellText().substring("Exile target ".length());
               int i = tgtType.indexOf(".");
               tgtType = tgtType.substring(0, i);
               Selec[0] += tgtType + " to exile.";
            }
            else if (Destination.equals("TopofLibrary"))
            {
               tgtType = card.getSpellText().substring("Put target ".length());
               int i = tgtType.indexOf(" on top of its owner's library.");
               tgtType = tgtType.substring(0, i);
               Selec[0] += tgtType + " to put on top of the library.";
            }
            else
            {
               Selec[0] = card.getSpellText();
            }
           
            card.clearSpellAbility();
           
            final SpellAbility spBnceTgt = new Spell(card) {
                private static final long serialVersionUID = 152897134770L;
               
                @Override
                public boolean canPlayAI() {
                   if (AllZone.Phase.getTurn() <= 3) return false;
                   
                    CardList results = new CardList();
                    CardList choices = getTargets();                   
                   
                    if(choices.size() > 0) {
                        for(int i = 0; i < Tgts.length; i++) {
                            if(Tgts[i].startsWith("Artifact")) {
                                if(CardFactoryUtil.AI_getBestArtifact(choices) != null) results.add(CardFactoryUtil.AI_getBestArtifact(choices));
                            } else if(Tgts[i].startsWith("Creature")) {
                                if(CardFactoryUtil.AI_getBestCreature(choices) != null) results.add(CardFactoryUtil.AI_getBestCreature(choices));
                            } else if(Tgts[i].startsWith("Enchantment")) {
                                if(CardFactoryUtil.AI_getBestEnchantment(choices, card, true) != null) results.add(CardFactoryUtil.AI_getBestEnchantment(
                                        choices, card, true));
                            } else if(Tgts[i].startsWith("Land")) {
                                if(CardFactoryUtil.AI_getBestLand(choices) != null) results.add(CardFactoryUtil.AI_getBestLand(choices));
                            } else if(Tgts[i].startsWith("Permanent")) {
                                if(CardFactoryUtil.AI_getMostExpensivePermanent(choices, card, true) != null) results.add(CardFactoryUtil.AI_getMostExpensivePermanent(
                                        choices, card, true));
                            }
                        }
                    }

                    if(results.size() > 0) {
                        results.shuffle();
                        setTargetCard(results.get(0));
                        return true;
                    }
                    return false;
                }
               
                CardList getTargets() {
                    CardList tmpList = new CardList();
                    tmpList.addAll(AllZone.Human_Play.getCards());
                    tmpList = tmpList.filter(new CardListFilter() {
                        public boolean addCard(Card c) {
                            return (CardFactoryUtil.canTarget(card, c));
                        }
                    });
                   
                    return tmpList.getValidCards(Tgts);
                }
               
               @Override
                public void resolve()
                {
                   Card tgtC = getTargetCard();
                   
                  if(AllZone.GameAction.isCardInPlay(tgtC)
                            && CardFactoryUtil.canTarget(card, tgtC))
                    {
                       if(getTargetCard().isToken())
                          AllZone.getZone(tgtC).remove(tgtC);
                       else
                       { 
                          if(Destination.equals("TopofLibrary"))
                             AllZone.GameAction.moveToTopOfLibrary(tgtC);
                          else if(Destination.equals("ShuffleIntoLibrary"))
                          {
                             AllZone.GameAction.moveToTopOfLibrary(tgtC);
                             AllZone.GameAction.shuffle(tgtC.getOwner());
                          }
                          else if(Destination.equals("Exile"))
                             AllZone.GameAction.removeFromGame(tgtC);
                          else if(Destination.equals("Hand"))
                          {
                              PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, tgtC.getOwner());
                                 AllZone.GameAction.moveTo(hand, tgtC);
                          }
                       }
                       
                       if (!Drawback[0].equals("none"))
                          CardFactoryUtil.doDrawBack(Drawback[0], 0, card.getController(), AllZone.GameAction.getOpponent(card.getController()), tgtC.getController(), card, tgtC);
                    }
                }
            }; //SpBnceTgt

            Input InGetTarget = CardFactoryUtil.input_targetValid(spBnceTgt, Tgts, Selec[0]);
           
            card.setSVar("PlayMain1", "TRUE");
           
            spBnceTgt.setBeforePayMana(InGetTarget);
            spBnceTgt.setDescription(card.getSpellText());
            card.setText("");
            card.addSpellAbility(spBnceTgt);
           
            String bbCost = card.getSVar("Buyback");
            if (!bbCost.equals(""))
            {
               SpellAbility bbBnceTgt = spBnceTgt.copy();
               bbBnceTgt.setManaCost(CardUtil.addManaCosts(card.getManaCost(), bbCost));
               bbBnceTgt.setDescription("Buyback " + bbCost + "(You may pay an additional " + bbCost + " as you cast this spell. If you do, put this card into your hand as it resolves.)");
               bbBnceTgt.setIsBuyBackAbility(true);
               
               bbBnceTgt.setBeforePayMana(CardFactoryUtil.input_targetValid(bbBnceTgt, Tgts, Selec[0]));
               
               card.addSpellAbility(bbBnceTgt);
            }

        }//spBounceTgt
Cards that should work now:
Code: Select all
Call to Heel
1 U
Instant
Return target creature to its owner's hand. Its controller draws a card.
spBounceTgt:Creature:Hand:Drawback$TgtCtrlrDraw/1

Clutch of the Undercity
1 U U B
Instant
Return target permanent to its owner's hand. Its controller loses 3 life.
spBounceTgt:Permanent:Hand:Drawback$TgtCtrlrLoseLife/3
Transmute: 1 U B

Recoil
1 U B
Instant
Return target permanent to its owner's hand. Then that player discard a card.
spBounceTgt:Permanent:Hand:Drawback$TgtOwnerDiscard/1

Snap
1 U
Instant
Return target creature to its owner's hand. Untap up to two lands.
spBounceTgt:Creature:Hand:Drawback$YouUntapUpTo/2/Land

Last Breath
1 W
Instant
Exile target creature with power 2 or less. Its controller gains 4 life.
spBounceTgt:Creature.powerLTE2:Exile:Drawback$TgtCtrlrGainLife/4

Swords to Plowshares
W
Instant
Exile target creature. Its controller gains life equal to its power.
spBounceTgt:Creature:Exile:Drawback$TgtCtrlrGainLife/dX
SVar:dX:Count$TgtCardPower
The Force will be with you, Always.
User avatar
Rob Cashwalker
Programmer
 
Posts: 2167
Joined: 09 Sep 2008, 15:09
Location: New York
Has thanked: 5 times
Been thanked: 40 times

Previous

Return to Developer's Corner

Who is online

Users browsing this forum: No registered users and 41 guests

Main Menu

User Menu

Our Partners


Who is online

In total there are 41 users online :: 0 registered, 0 hidden and 41 guests (based on users active over the past 10 minutes)
Most users ever online was 7303 on 15 Jul 2025, 20:46

Users browsing this forum: No registered users and 41 guests

Login Form