It is currently 30 Oct 2025, 22:07
   
Text Size

etbDestroyTgt keyword

Post MTG Forge Related Programming Questions Here

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

etbDestroyTgt keyword

Postby Rob Cashwalker » 04 Sep 2010, 15:15

Cards that destroy target ____ when they enter the battlefield. It supports a "May" clause, "NoRegen", "Evoke" and drawbacks.

Follows the basic syntax of the spDestroyTgt keyword:
etbDestroyTgt{May}:{ValidCards}:{NoRegen and/or Drawback}

Use SVar:Evoke:{cost} to enable Evoke.

CardFactory:
Code: Select all
        // Generic enters the battlefield destroy target
        if (hasKeyword(card, "etbDestroyTgt") != -1)
        {
           int n = hasKeyword(card, "etbDestroyTgt");
           
           String parse = card.getKeyword().get(n).toString();
           card.removeIntrinsicKeyword(parse);
           
           String k[] = parse.split(":");
           
           final boolean May[] = {false};
           if (k[0].contains("May"))
              May[0] = true;
           
           String Targets = k[1];
           final String Tgts[] = Targets.split(",");
           
            String tmpDesc = card.getSpellText();
            int i = tmpDesc.indexOf("destroy target ");
            tmpDesc = tmpDesc.substring(i + 15);
            i = tmpDesc.indexOf(".");
            tmpDesc = tmpDesc.substring(0, i);
            final String Selec = "Select target " + tmpDesc + " to destroy.";
           
           final boolean NoRegen[] = {false};
           final String Drawback[] = {"none"};
           if (k.length > 2)
           {
              if (k[2].equals("NoRegen"))
            {
               NoRegen[0] = true;
               if (k.length > 3)
                  Drawback[0] = k[3];
            }
              else
                 Drawback[0] = k[2];
           }
           
           if (!Drawback[0].equals("none"))
           {
              String kk[] = Drawback[0].split("\\$");
                Drawback[0] = kk[1];
           }
           
           final boolean Evoke[] = {false};
           if (card.getSVar("Evoke").length() > 0)
              Evoke[0] = true;
           
           card.setSVar("PlayMain1", "TRUE");
           card.clearSpellAbility();
           
           // over-rides the default Spell_Permanent
           // enables the AI to play the card when appropriate
           SpellAbility spETBDestroyTgt = new Spell_Permanent(card)
           {
                private static final long serialVersionUID = -1148528222969323318L;
               
                @Override
                public boolean canPlayAI()
                {
                    Random r = new Random();
                                      
                    CardList hCards = new CardList(AllZone.getZone(Constant.Zone.Play, Constant.Player.Human).getCards());
                    hCards = hCards.getValidCards(Tgts);
                    if (hCards.size() > 0)
                       return true;
                   
                    CardList cCards = new CardList(AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer).getCards());
                    cCards = cCards.getValidCards(Tgts);
                    if (cCards.size() == 0)
                       return true;
                    else
                    {
                       if (r.nextInt(100) > 67)
                          return true;
                    }
                   
                   return false;
                }
           };
           card.addSpellAbility(spETBDestroyTgt);
           
            // performs the destruction
           final SpellAbility saDestroyTgt = new Ability(card, "0")
            {
                @Override
                public void resolve()
                {
                    Card c = getTargetCard();
                    if (c == null)
                       return;
                   
                    if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c))
                    {
                        if(c.isToken())
                           AllZone.getZone(c).remove(c);
                        else
                           AllZone.GameAction.destroy(c);
                       
                        if (!Drawback[0].equals("none"))
                           CardFactoryUtil.doDrawBack(Drawback[0], 0, card.getController(), AllZone.GameAction.getOpponent(card.getController()), c.getController(), card, c);
                    }
                }
            };
            saDestroyTgt.setStackDescription(card.getName() + " - destroy target " + Selec + ".");
           
            // when the card enters the battlefield, enable the human to target
            // or the AI decides on a target
            Command etbDestroyTgt = new Command()
            {
                private static final long serialVersionUID = 9072052875006010497L;
               
                public void execute()
                {
                    CardList hCards = new CardList(AllZone.Human_Play.getCards());
                    CardList cCards = new CardList(AllZone.Computer_Play.getCards());
                   
                    hCards = hCards.getValidCards(Tgts);
                    cCards = cCards.getValidCards(Tgts);
                   
                    if(hCards.size() > 0 || cCards.size() > 0)
                    {
                        if (card.getController().equals(Constant.Player.Human))
                        {
                            Input inDT = CardFactoryUtil.input_targetValid(saDestroyTgt, Tgts, Selec);

                            AllZone.InputControl.setInput(inDT);
                           
                            if (May[0] == true)
                               ButtonUtil.enableOnlyCancel();
                            else
                               ButtonUtil.disableAll();
                        }
                        else
                        {
                           Card c = new Card();
                           CardList dChoices = new CardList();
                           if(hCards.size() > 0)
                            {
                                for (int i=0; i<Tgts.length; i++)
                                {
                                   if (Tgts[i].startsWith("Creature"))
                                   {
                                      c = CardFactoryUtil.AI_getBestCreature(hCards);
                                      if (c != null)
                                         dChoices.add(c);
                                   }
                                   
                                   CardListUtil.sortByTextLen(hCards);
                                   dChoices.add(hCards.get(0));
                                   
                                   CardListUtil.sortCMC(hCards);
                                   dChoices.add(hCards.get(0));
                                }
                               
                                c = dChoices.get(CardUtil.getRandomIndex(dChoices));
                                saDestroyTgt.setTargetCard(c);
                                AllZone.Stack.add(saDestroyTgt);
                            }
                           else if (cCards.size() > 0 && May[0] == false)
                           {
                             for (int i=0; i<Tgts.length; i++)
                             {
                                if (Tgts[i].startsWith("Creature"))
                                {
                                   c = CardFactoryUtil.AI_getWorstCreature(cCards);
                                   if (c != null)
                                      dChoices.add(c);
                                }
                                
                                CardListUtil.sortByTextLen(cCards);
                                dChoices.add(cCards.get(cCards.size() - 1));
                                
                                CardListUtil.sortCMC(cCards);
                                dChoices.add(cCards.get(cCards.size() - 1));
                             }
                             
                             c = dChoices.get(CardUtil.getRandomIndex(dChoices));
                                saDestroyTgt.setTargetCard(c);
                                AllZone.Stack.add(saDestroyTgt);
                           }
                        }
                    }
                }
            };
            card.addComesIntoPlayCommand(etbDestroyTgt);
           
            // handle SVar:Evoke:{cost}
            if (Evoke[0] == true)
            {
               String EvCost = card.getSVar("Evoke");
               
               SpellAbility evDestroyTgt = new Spell_Evoke(card, EvCost)
               {
                    private static final long serialVersionUID = 5261598836419831953L;
                   
                    @Override
                    public boolean canPlayAI() {
                        return false;
                    }                  
               };
               card.addSpellAbility(evDestroyTgt);
            }
        } // etbDestoryTgt
Cards:
Code: Select all

Acidic Slime
3 G G
Creature Ooze
When Acidic Slime enters the battlefield, destroy target artifact, enchantment, or land.
2/2
Deathtouch
etbDestroyTgt:Artifact,Enchantment,Land

Angel of Despair
3 W W B B
Creature Angel
When Angel of Despair enters the battlefield, destroy target permanent.
5/5
Flying
etbDestroyTgt:Permanent

Avalanche Riders
3 R
Creature Human Nomad
When Avalanche Riders enters the battlefield, destroy target land.
2/2
Haste
Echo:3 R
etbDestroyTgt:Land

Aven Cloudchaser
3 W
Creature Bird Soldier
When Aven Cloudchaser enters the battlefield, destroy target enchantment.
2/2
Flying
etbDestroyTgt:Enchantment

Bala Ged Scorpion
3 B
Creature Scorpion
When Bala Ged Scorpion enters the battlefield, you may destroy target creature with power 1 or less.
2/3
etbDestroyTgtMay:Creature.powerLE1

Bone Shredder
2 B
Creature Minion
When Bone Shredder enters the battlefield, destroy target nonartifact, nonblack creature.
1/1
Flying
Echo:2B
etbDestroyTgt:Creature.nonArtifact.nonBlack

Cloudchaser Eagle
3 W
Creature Bird
When Cloudchaser Eagle enters the battlefield, destroy target enchantment.
2/2
Flying
etbDestroyTgt:Enchantment

Dakmor Lancer
4 B B
Creature Human Knight
When Dakmor Lancer enters the battlefield, destroy target nonblack creature.
3/3
etbDestroyTgt:Creature.nonBlack

Dark Hatchling
4 B B
Creature Horror
When Dark Hatchling enters the battlefield, destroy target nonblack creature. It can't be regenerated.
3/3
Flying
etbDestroyTgt:Creature.nonBlack:NoRegen

Faultgrinder
6 R
Creature Elemental
When Faultgrinder enters the battlefield, destroy target land.
4/4
Trample
etbDestroyTgt:Land
SVar:Evoke:4 R

Goblin Settler
3 R
Creature Goblin
When Goblin Settler enters the battlefield, destroy target land.
1/1
etbDestroyTgt:Land

Halo Hunter
2 B B B
Creature Demon
When Halo Hunter enters the battlefield, destroy target Angel.
6/3
Intimidate
etbDestroyTgt:Angel

Hammerheim Deadeye
3 R
Creature Giant Warrior
When Hammerheim Deadeye enters the battlefield, destroy target creature with flying.
3/3
Echo:5 R
etbDestroyTgt:Creature.withFlying

Indrik Stomphowler
4 G
Creature Beast
When Indrik Stomphowler enters the battlefield, destroy target artifact or enchantment.
4/4
etbDestroyTgt:Artfact,Enchantment

Ingot Chewer
4 R
Creature Elemental
When Ingot Chewer enters the battlefield, destroy target artifact.
3/3
etbDestroyTgt:Artifact
SVar:Evoke:R

Keldon Vandals
2 R
Creature Human Rogue
When Keldon Vandals enters the battlefield, destroy target artifact.
4/1
Echo:2 R
etbDestroyTgt:Artifact

Manic Vandal
2 R
Creature Human Warrior
When Manic Vandal enters the battlefield, destroy target artifact.
2/2
etbDestroyTgt:Artifact

Monk Realist
1 W
Creature Human Monk Cleric
When Monk Realist enters the battlefield, destroy target enchantment.
1/1
etbDestroyTgt:Enchantment

Nekrataal
2 B B
Creature Human Assassin
When Nekrataal enters the battlefield, destroy target nonartifact, nonblack creature. That creature can't be regenerated.
2/1
First Strike
etbDestroyTgt:Creature.nonArtifact.nonBlack:NoRegen

Ogre Arsonist
4 R
Creature Ogre
When Ogre Arsonist enters the battlefield, destroy target land.
3/3
etbDestroyTgt:Land

Ogre Gatecrasher
3 R
Creature Ogre Rogue
When Ogre Gatecrasher enters the battlefield, destroy target creature with defender.
3/3
etbDestroyTgt:Creature.withDefender

Ravaging Horde
3 R R
Creature Human Soldier
When Ravaging Horde enters the battlefield, destroy target land.
3/3
etbDestroyTgt:Land

Ravenous Baboons
3 R
Creature Ape
When Ravenous Baboons enters the battlefield, destroy target nonbasic land.
2/2
etbDestroyTgt:Land.nonBasic

Rustspore Ram
4
Artifact Creature Sheep
When Rustspore Ram enters the battlefield, destroy target Equipment.
1/3
etbDestroyTgt:Equipment

Serpent Assassin
3 B B
Creature Snake Assassin
When Serpent Assassin enters the battlefield, you may destroy target nonblack creature.
2/2
etbDestroyTgtMay:Creature.nonBlack

Shriekmaw
4 B
Creature Elemental
When Shriekmaw enters the battlefield, destroy target nonartifact, nonblack creature.
3/2
Fear
etbDestroyTgt:Creature.nonArtifact.nonBlack
SVar:Evoke:1 B

Tivadar of Thorn
1 W W
Legendary Creature Human Knight
When Tivadar of Thorn enters the battlefield, destroy target Goblin.
2/2
First Strike
Protection from red
etbDestroyTgt:Goblin

Uktabi Orangutan
2 G
Creature Ape
When Uktabi Orangutan enters the battlefield, destroy target artifact.
2/2
etbDestroyTgt:Artifact

Viridian Shaman
2 G
Creature Elf Shaman
When Viridian Shaman enters the battlefield, destroy target artifact.
2/2
etbDestroyTgt:Artifact

Vithian Renegades
1 R G
Creature Human Shaman
When Vithian Renegades enters the battlefield, destroy target artifact.
3/2
etbDestroyTgt:Artifact

War Priest of Thune
1 W
Creature Human Cleric
When War Priest of Thune enters the battlefield, you may destroy target enchantment.
2/2
etbDestroyTgtMay:Enchantment

Wispmare
2 W
Creature Elemental
When Wispmare enters the battlefield, destroy target enchantment.
1/3
etbDestroyTgt:Enchantment
SVar:Evoke:W
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

Re: etbDestroyTgt keyword

Postby Sloth » 04 Sep 2010, 21:59

Nice keyword, Rob!

Most of the cards were possible with the whenever keyword, but the targeting for the AI caused an error when using destroy.

I agree with adding simple keywords to replace some of the wheneverkeyword's functionalities. It will make the AI more easily improveable.

I'm not up to date with isValidCard, but shouldn't
etbDestroyTgt:Creature.nonArtifact.nonBlack
be
etbDestroyTgt:Creature.nonArtifact+nonBlack
?

used in:

Code: Select all
Bone Shredder
2 B
Creature Minion
When Bone Shredder enters the battlefield, destroy target nonartifact, nonblack creature.
1/1
Flying
Echo:2B
etbDestroyTgt:Creature.nonArtifact.nonBlack
and Nekrataal
User avatar
Sloth
Programmer
 
Posts: 3498
Joined: 23 Jun 2009, 19:40
Has thanked: 125 times
Been thanked: 507 times

Re: etbDestroyTgt keyword

Postby Chris H. » 04 Sep 2010, 22:48

Hope you had a good vacation, Sloth.

Here is the cards.txt entry for Terror:

Terror
1 B
Instant
Destroy target nonartifact, nonblack creature. It can't be regenerated.
spDestroyTgt:Creature.nonArtifact+nonBlack:NoRegen
User avatar
Chris H.
Forge Moderator
 
Posts: 6320
Joined: 04 Nov 2008, 12:11
Location: Mac OS X Yosemite
Has thanked: 644 times
Been thanked: 643 times

Re: etbDestroyTgt keyword

Postby Rob Cashwalker » 04 Sep 2010, 23:23

It certainly is....

Figures.. I recently put together the reference topic, and didn't even notice that.
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

Re: etbDestroyTgt keyword

Postby jeffwadsworth » 14 Jan 2011, 04:09

Would a "etbDestroyAll" keyword be a waste of time with all the changes taking place? I would like to add Desolation Angel and Desolation Giant.
jeffwadsworth
Super Tester Elite
 
Posts: 1172
Joined: 20 Oct 2010, 04:47
Location: USA
Has thanked: 287 times
Been thanked: 70 times

Re: etbDestroyTgt keyword

Postby friarsol » 14 Jan 2011, 04:35

jeffwadsworth wrote:Would a "etbDestroyAll" keyword be a waste of time with all the changes taking place? I would like to add Desolation Angel and Desolation Giant.
Yep. Once triggers are in place we should be able to do that.
friarsol
Global Moderator
 
Posts: 7593
Joined: 15 May 2010, 04:20
Has thanked: 243 times
Been thanked: 965 times


Return to Developer's Corner

Who is online

Users browsing this forum: No registered users and 38 guests

Main Menu

User Menu

Our Partners


Who is online

In total there are 38 users online :: 0 registered, 0 hidden and 38 guests (based on users active over the past 10 minutes)
Most users ever online was 9298 on 10 Oct 2025, 12:54

Users browsing this forum: No registered users and 38 guests

Login Form