It is currently 07 Sep 2025, 17:14
   
Text Size

Contrib. Coll.

Post MTG Forge Related Programming Questions Here

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

Re: Contrib. Coll.

Postby DennisBergkamp » 18 Aug 2010, 18:28

Hm, Sutured Ghoul should be easy (look at the multi selection list for say, Mycoloth's devour ability).
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Re: Contrib. Coll.

Postby Hellfish » 21 Aug 2010, 08:38

Yeah, coding it up wasn't that hard, though testing was (MHS is pretty damn useful for these kind of things). But it did reveal a bit of a flaw and not in Sutured Ghoul's code either. It now correctly dies to zero toughness if you for some reason not choose any creatures to exile or have none in the graveyard. HOWEVER, if the ability is countered (Voidslime, Bind etc..) then Sutured Ghoul will stay on the battlefield as a 1/1 because I had to set that in cards.txt to make sure he didn't die to zero toughness before getting his *actual* P/T. I'm really not sure how to solve that.

EDIT: Also, Patriarch's Bidding sorta works already, but I'll have to code up a way for the cards to bypass the stack on their way from the grave to the battlefield.
So now you're
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
User avatar
Hellfish
Programmer
 
Posts: 1297
Joined: 07 Jun 2009, 10:41
Location: South of the Pumphouse
Has thanked: 110 times
Been thanked: 169 times

Re: Contrib. Coll.

Postby friarsol » 21 Aug 2010, 17:39

Hellfish wrote: It now correctly dies to zero toughness if you for some reason not choose any creatures to exile or have none in the graveyard. HOWEVER, if the ability is countered (Voidslime, Bind etc..) then Sutured Ghoul will stay on the battlefield as a 1/1 because I had to set that in cards.txt to make sure he didn't die to zero toughness before getting his *actual* P/T.
Ok, I'm on vacation for real but just wanted to comment while I still had an internet connection.

We need to make an ability_static class for these types of abilities that are, well, static. They would not be able to be countered by spells, and would never go on the stack. A lot of the abilities we have now that are listed under triggered would also need to be turned into ability_static. Anything that says "when or whenever" would stay as triggered, and anything that says "as" or "enters the battlefield with" would be static.

It didn't seem to be too tough to implement, but it does require going through each of the triggered abilities and deciding which one it really is. It would also probably require some tweaking to see if abilities resolve immediately, or go on the stack. The code for the class would be pretty similar to triggered abilities just a different class name for interaction purposes.
friarsol
Global Moderator
 
Posts: 7593
Joined: 15 May 2010, 04:20
Has thanked: 243 times
Been thanked: 965 times

Re: Contrib. Coll.

Postby Hellfish » 21 Aug 2010, 17:55

Hey now, you're supposed to be relaxing by a pool or something! ;)
I'll look deeper into it tomorrow, probably.
So now you're
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
User avatar
Hellfish
Programmer
 
Posts: 1297
Joined: 07 Jun 2009, 10:41
Location: South of the Pumphouse
Has thanked: 110 times
Been thanked: 169 times

Re: Contrib. Coll.

Postby Hellfish » 28 Aug 2010, 17:02

Well, it was kind of a 'duh'-moment but I figured it out.I have a comesIntoPlayCommand where I only let the caster select cards to exile, now that same command sets the base P/T as well, instead of an Ability like before. It doesn't go on the stack, but the casting itself does so.. Anybody see a problem with it? I don't, atm.
So now you're
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
User avatar
Hellfish
Programmer
 
Posts: 1297
Joined: 07 Jun 2009, 10:41
Location: South of the Pumphouse
Has thanked: 110 times
Been thanked: 169 times

Re: Contrib. Coll.

Postby DennisBergkamp » 28 Aug 2010, 17:27

Nope, sounds good to me :)
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Re: Contrib. Coll.

Postby Hellfish » 29 Aug 2010, 19:49

Question for the veterans:
So I've got some Splinter Twin code (Based on Kiki-Jiki, Mirror Breaker so I'm fairly certain it's correct) but I can't seem to test it even. First of all, If I place the code in CardFactory_Auras it doesn't work because Forge somehow misses the "Enchant Creature" keyword it has in cards.txt then. That works if I place the code in CardFactory instead. However, the comesIntoPlayCommand I add to the card to specify which card should get the cloning ability added doesn't get run, ever.

My brain is shot for tonight. I might go spelunking in the bowels of Forge tomorrow or Tuesday but if anyone can spot anything obviously wrong here, feel free to point, laugh and point it out. ;)

Code: Select all
//*************** START *********** START **************************
        else if(cardName.equals("Splinter Twin")) {
            final CardFactory cfact = AllZone.CardFactory;
            final Card[] tgt = new Card[1];
           
            final SpellAbility clone = new Ability_Tap(null) {
                private static final long serialVersionUID = -843706942500499644L;
               
                @Override
                public boolean canPlayAI() {
                    return true;
                }
               
                @Override
                public void resolve() {
                       
                        int multiplier = 1;
                         int doublingSeasons = CardFactoryUtil.getCards("Doubling Season", card.getController()).size();
                         if(doublingSeasons > 0) multiplier = (int) Math.pow(2, doublingSeasons);
                         Card[] crds = new Card[multiplier];
                         
                         for (int i=0;i<multiplier;i++)
                         {
                            
                                                   
                           Card copy;
                           if(!getTargetCard().isToken()) {
                               //CardFactory cf = new CardFactory("cards.txt");
                              
   
                               //copy creature and put it into play
                               //copy = getCard(getTargetCard(), getTargetCard().getName(), card.getController());
                               copy = cfact.getCard(tgt[0].getName(), tgt[0].getOwner());
                              
                               //when copying something stolen:
                               copy.setController(tgt[0].getController());
                              
                               copy.setToken(true);
                               copy.setCopiedToken(true);
                              
                               if(getTargetCard().isFaceDown()) {
                                   copy.setIsFaceDown(true);
                                   copy.setManaCost("");
                                   copy.setBaseAttack(2);
                                   copy.setBaseDefense(2);
                                   copy.setIntrinsicKeyword(new ArrayList<String>()); //remove all keywords
                                   copy.setType(new ArrayList<String>()); //remove all types
                                   copy.addType("Creature");
                                   copy.clearSpellAbility(); //disallow "morph_up"
                               }
                               copy.addIntrinsicKeyword("Haste");
                           } else //isToken()
                           {
                               Card c = tgt[0];
                              
                               copy = new Card();
                              
                               copy.setName(c.getName());
                               copy.setImageName(c.getImageName());
                              
                               copy.setOwner(c.getController());
                               copy.setController(c.getController());
                              
                               copy.setManaCost(c.getManaCost());
                               copy.setToken(true);
                              
                               copy.setType(c.getType());
                              
                               copy.setBaseAttack(c.getBaseAttack());
                               copy.setBaseDefense(c.getBaseDefense());
                               copy.addIntrinsicKeyword("Haste");
                           }
                          
                          
                          
                           PlayerZone play = AllZone.getZone(Constant.Zone.Play, tgt[0].getController());
                           play.add(copy);
                           crds[i] = copy;
                       }
                       

                        //have to do this since getTargetCard() might change
                        //if Splinter Twin'd card somehow gets untapped again
                        final Card[] target = new Card[multiplier];
                        for (int i=0;i<multiplier;i++) {
                           final int index = i;
                           target[i] = crds[i];
                           Command atEOT = new Command() {
                               private static final long serialVersionUID = 7803915905490565557L;
                              
                               public void execute() {
                                   //technically your opponent could steal the token
                                   //and the token shouldn't be sacrificed
                                   if(AllZone.GameAction.isCardInPlay(target[index])) AllZone.GameAction.sacrifice(target[index]); //maybe do a setSacrificeAtEOT, but probably not.
                               }
                           };//Command
                           AllZone.EndOfTurn.addAt(atEOT);
                        }
                }//resolve()
            };//SpellAbility

            clone.setStackDescription("Splinter Twin - copy card.");
            clone.setDescription("tap: Put a token into play that's a copy of this creature.");
           
            Command CITPCom = new Command() {
            private static final long serialVersionUID = -8086688988881539249L;

            public void execute() {
               tgt[0] = card.getEnchanting().get(0);
               clone.setSourceCard(tgt[0]);
               tgt[0].addSpellAbility(clone);
               System.out.println("SPLINTAH TWIN IN DA HIZZZOUSE!");
              }
            };
           
            Command LPCom = new Command() {
            private static final long serialVersionUID = -7740916784578902104L;

            public void execute() {
               tgt[0].removeSpellAbility(clone);
               }
            };
           
            card.addComesIntoPlayCommand(CITPCom);
            card.addLeavesPlayCommand(LPCom);
           
        }//*************** END ************ END **************************
So now you're
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
User avatar
Hellfish
Programmer
 
Posts: 1297
Joined: 07 Jun 2009, 10:41
Location: South of the Pumphouse
Has thanked: 110 times
Been thanked: 169 times

Re: Contrib. Coll.

Postby DennisBergkamp » 29 Aug 2010, 20:44

Hm, make sure it's "Enchant creature" and not "Enchant Creature". It should definitely be detected, what does your cards.txt entry look like now?
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Re: Contrib. Coll.

Postby Hellfish » 01 Sep 2010, 18:31

Code: Select all
Splinter Twin
2 R R
Enchantment Aura
no text
Enchant Creature
SVar:Rarity:Rare
Lowercase c in Creature doesn't work in either Cardfactory or CardFactory_Auras. Uppercase C only works in CardFactory. I havn't gotten as much time as I wanted to code so I havn't found anything out.. :/
So now you're
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
User avatar
Hellfish
Programmer
 
Posts: 1297
Joined: 07 Jun 2009, 10:41
Location: South of the Pumphouse
Has thanked: 110 times
Been thanked: 169 times

Re: Contrib. Coll.

Postby DennisBergkamp » 01 Sep 2010, 19:55

I remember now, I don't think we're currently actually using "Enchant creature" as a keyword that generates the Enchant functionality... (If I'm not mistaken, using "enPump" will though).

So the quick and dirty way to fix this is to grab the some of the code from the other Auras, I'd look at Squirrel Nest (just grab the code at the beginning, SpellAbility spell... until right before SpellAbility produceSquirrels). Then stuff the whole block in CardFactory_Auras.
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Previous

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 7303 on 15 Jul 2025, 20:46

Users browsing this forum: No registered users and 38 guests

Login Form