It is currently 08 Sep 2025, 15:44
   
Text Size

Contrib. Coll.

Post MTG Forge Related Programming Questions Here

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

Contrib. Coll.

Postby Hellfish » 11 Jun 2010, 13:27

Or, Contribution Collection :)
I'll be posting a bunch of cards here, as soon as I've tested them tonight/some of them tomorrow. I thought this was neater,more organized than dumping them all in the middle of another thread.

Coming soon:
Adarkar Wastes
Brushland
Karplusan Forest
Sulfurous Springs
Underground River
Battlefield Forge
Caves of Koilos
Llanowar Wastes
Shivan Reef
Yavimaya Coast
Salt Flats
Pine Barrens
Skyshroud Forest
Caldera Lake
Scabland
Talisman of Dominance
Talisman of Impulse
Talisman of Indulgence
Talisman of Progress
Talisman of Unity
NOTE: The above pain-manasources will be keyworded. There was very old, non-functional code for them in Ability_Mana that I aim to replace.
Muddle the Mixture
Journey to Nowhere
Trusted Advisor
NOTE: Trusted Advisor also needs my HandSize keyword.
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 Beached As » 11 Jun 2010, 16:18

Nice work man! With this we'll be getting close to 3500 cards :).
Beached As
Programmer
 
Posts: 110
Joined: 23 Feb 2010, 07:48
Has thanked: 0 time
Been thanked: 0 time

Re: Contrib. Coll.

Postby Hellfish » 11 Jun 2010, 17:38

Thanks! 3500's gonna be sweet. Just 12000 to go :P But now...
Here comes the pain(lands)!

Add this either just in CardFactory before the links to the specific factories OR at the end of CardFactory and at the end of CardFactory_Lands.
Code: Select all
        while(hasKeyword(card,"paintap") != -1)
        {
           String toParse = card.getIntrinsicKeyword().get(hasKeyword(card,"paintap"));
           card.removeIntrinsicKeyword(toParse);
           String[] splitkeyword = toParse.split(":");

           final int amountHurt = Integer.parseInt(splitkeyword[1]);
           final String manaGenerated = splitkeyword[2];
           final Ability_Mana addMana = new Ability_Mana(card, "tap: add " + manaGenerated + " to your mana pool.CARDNAME deals " + amountHurt + " damage to you.") {
                 private static final long serialVersionUID = -259088242789L;
                 
                 @Override
                 public void resolve()
                 {
                    AllZone.GameAction.getPlayerLife(getController()).subtractLife(amountHurt);
                    super.resolve();
                 }
                 
                 @Override
                 public String mana() {
                 return manaGenerated;
              }
                                                
            };
            card.addSpellAbility(addMana);
        }//paintap
Keyword format: "paintap:AmountOfDamageToGivePlayer:ManaToGivePlayer"
Yes, I know, all pain lands do only 1 damage but flexibility isn't a bad thing, for neither custom or possibly upcoming cards.

cards.txt entries:
Code: Select all
Adarkar Wastes
no cost
Land
no text
tap: add 1
paintap:1:W
paintap:1:U

Brushland
no cost
Land
no text
tap: add 1
paintap:1:W
paintap:1:G

Karplusan Forest
no cost
Land
no text
tap: add 1
paintap:1:R
paintap:1:G

Sulfurous Springs
no cost
Land
no text
tap: add 1
paintap:1:B
paintap:1:R

Underground River
no cost
Land
no text
tap: add 1
paintap:1:U
paintap:1:B

Battlefield Forge
no cost
Land
no text
tap: add 1
paintap:1:W
paintap:1:R

Caves of Koilos
no cost
Land
no text
tap: add 1
paintap:1:W
paintap:1:B

Llanowar Wastes
no cost
Land
no text
tap: add 1
paintap:1:B
paintap:1:G

Shivan Reef
no cost
Land
no text
tap: add 1
paintap:1:U
paintap:1:R

Yavimaya Coast
no cost
Land
no text
tap: add 1
paintap:1:U
paintap:1:G

Salt Flats
no cost
Land
no text
tap: add 1
paintap:1:W
paintap:1:B
Comes into play tapped.

Pine Barrens
no cost
Land
no text
tap: add 1
paintap:1:B
paintap:1:G
Comes into play tapped.

Skyshroud Forest
no cost
Land
no text
tap: add 1
paintap:1:G
paintap:1:U
Comes into play tapped.

Caldera Lake
no cost
Land
no text
tap: add 1
paintap:1:U
paintap:1:R
Comes into play tapped.

Scabland
no cost
Land
no text
tap: add 1
paintap:1:R
paintap:1:W
Comes into play tapped.

Talisman of Dominance
2
Artifact
no text
tap: add 1
paintap:1:U
paintap:1:B

Talisman of Impulse
2
Artifact
no text
tap: add 1
paintap:1:R
paintap:1:G

Talisman of Indulgence
2
Artifact
no text
tap: add 1
paintap:1:B
paintap:1:R

Talisman of Progress
2
Artifact
no text
tap: add 1
paintap:1:W
paintap:1:U

Talisman of Unity
2
Artifact
no text
tap: add 1
paintap:1:G
paintap:1:W
Remove the following from Ability_Mana:
Code: Select all
        //pain lands
        ArrayList<String> pain = new ArrayList<String>();
        pain.add("Battlefield Forge");
        pain.add("Caves of Koilos");
        pain.add("Llanowar Wastes");
        pain.add("Shivan Reef");
        pain.add("Yavimaya Coast");
        pain.add("Adarkar Wastes");
        pain.add("Brushland");
        pain.add("Karplusan Forest");
        pain.add("Underground River");
        pain.add("Sulfurous Springs");
        if(pain.contains(sourceCard.getName()) && !Mana.equals("1")) runcommands.add(new Command() {
            private static final long serialVersionUID = -5904507275105961979L;
           
            public void execute() {
               
                AllZone.GameAction.getPlayerLife(getController()).subtractLife(1);
            }
        });
(I actually sorta-kinda got this code working, but still, a generalized keyword > hardcoded lists)

The one thing about this is that the pain mana can be used directly in payment, like ordinary lands. This means that if the painland can only produce one type of mana needed for the cost (for instance, tapping an Adarkar Wastes during payment for an Akrasan Squire) it will not ask for confirmation and just use the mana and deal the damage directly. It *can* be rewritten into a normal ability, though, so it's not a huge issue but then you won't be able to use that mana like ordinary lands.
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 » 11 Jun 2010, 18:06

Here goes Journey to Nowhere
Code: Select all
        //*************** START *********** START **************************
        else if(cardName.equals("Journey to Nowhere")) {
                       
           final CommandReturn getPerm = new CommandReturn() {
                public Object execute() {
                    //get all creatures
                    CardList tempList = new CardList();
                    tempList.addAll(AllZone.Human_Play.getCards());
                    tempList.addAll(AllZone.Computer_Play.getCards());
                   
                    CardList list = new CardList();
                   
                    for(int i = 0; i < tempList.size(); i++) {
                        if(tempList.get(i).isPermanent() && tempList.get(i).isCreature()
                                && CardFactoryUtil.canTarget(card, tempList.get(i))) list.add(tempList.get(i));
                    }
                   
                    //remove "this card"
                    list.remove(card);
                   
                    return list;
                }
            };//CommandReturn
           
            final SpellAbility abilityComes = new Ability(card, "0") {
                @Override
                public void resolve() {
                    if(AllZone.GameAction.isCardInPlay(getTargetCard())
                            && CardFactoryUtil.canTarget(card, getTargetCard())) {
                        AllZone.GameAction.removeFromGame(getTargetCard());
                    }
                }//resolve()
            };
           
            final Input inputComes = new Input() {
                private static final long serialVersionUID = -3613946694360326887L;
               
                @Override
                public void showMessage() {
                    CardList choice = (CardList) getPerm.execute();
                   
                    stopSetNext(CardFactoryUtil.input_targetSpecific(abilityComes, choice,
                            "Select target creature to remove from the game", true, false));
                    ButtonUtil.disableAll();//to disable the Cancel button
                }
            };
            Command commandComes = new Command() {
                private static final long serialVersionUID = -6250376920501373535L;
               
                public void execute() {
                    CardList perm = (CardList) getPerm.execute();
                    String s = card.getController();
                    if(perm.size() == 0) return;
                    else if(s.equals(Constant.Player.Human)) AllZone.InputControl.setInput(inputComes);
                    else //computer
                    {
                        Card target;
                       
                        //try to target human creature
                        CardList human = CardFactoryUtil.AI_getHumanCreature(card, true);
                        target = CardFactoryUtil.AI_getBestCreature(human);//returns null if list is empty
                       
                        // try to target human permanent
                        if(target == null) {
                            int convertedCost = 0;
                            CardList tempList = new CardList();
                            tempList.addAll(AllZone.Human_Play.getCards());
                           
                            for(int i = 0; i < tempList.size(); i++) {
                                if(tempList.get(i).isPermanent()
                                        && !tempList.get(i).isLand()
                                        && CardFactoryUtil.canTarget(card, tempList.get(i))
                                        && (CardUtil.getConvertedManaCost(tempList.get(i).getManaCost()) > convertedCost)) {
                                    target = tempList.get(i);
                                    convertedCost = CardUtil.getConvertedManaCost(tempList.get(i).getManaCost());
                                }
                            }
                        }
                       
                        //target something cheaper (manacost 0?) instead:
                        if(target == null) {
                            CardList humanPerms = new CardList();
                            humanPerms.addAll(AllZone.Human_Play.getCards());
                            humanPerms = humanPerms.filter(new CardListFilter() {
                                public boolean addCard(Card c) {
                                    return c.isPermanent() && !c.isLand() && CardFactoryUtil.canTarget(card, c);
                                }
                            });
                           
                            if(humanPerms.size() > 0) target = humanPerms.get(0);
                        }
                       
                        if(target == null) {
                            //must target computer creature
                            CardList computer = new CardList(AllZone.Computer_Play.getCards());
                            computer = computer.getType("Creature");
                            computer.remove(card);
                           
                            computer.shuffle();
                            if(computer.size() != 0) target = computer.get(0);
                            else target = card;
                        }
                        abilityComes.setTargetCard(target);
                        AllZone.Stack.add(abilityComes);
                    }//else
                }//execute()
            };//CommandComes
            Command commandLeavesPlay = new Command() {
                private static final long serialVersionUID = 6997038208952910355L;
               
                public void execute() {
                    Object o = abilityComes.getTargetCard();
                    if(o == null || ((Card) o).isToken() || !AllZone.GameAction.isCardRemovedFromGame((Card) o)) return;
                   
                    SpellAbility ability = new Ability(card, "0") {
                        @Override
                        public void resolve() {
                            //copy card to reset card attributes like attack and defense
                            Card c = abilityComes.getTargetCard();
                            if(!c.isToken()) {
                                c = AllZone.CardFactory.dynamicCopyCard(c);
                                c.setController(c.getOwner());
                               
                                PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getOwner());
                                PlayerZone removed = AllZone.getZone(Constant.Zone.Removed_From_Play, c.getOwner());
                                removed.remove(c);
                                if (c.isTapped())
                                   c.untap();
                                play.add(c);
                               
                            }
                        }//resolve()
                    };//SpellAbility
                    ability.setStackDescription("Journey to Nowhere - returning creature to play.");
                    AllZone.Stack.add(ability);
                }//execute()
            };//Command
           
            card.addComesIntoPlayCommand(commandComes);
            card.addLeavesPlayCommand(commandLeavesPlay);
           
            card.setSVar("PlayMain1", "TRUE");
           
            card.clearSpellAbility();
            card.addSpellAbility(new Spell_Permanent(card) {
                private static final long serialVersionUID = -3250095291930182087L;
               
                @Override
                public boolean canPlayAI() {
                    Object o = getPerm.execute();
                    if(o == null) return false;
                   
                    CardList cList = new CardList(AllZone.Human_Play.getCards());
                  cList = cList.filter(new CardListFilter()
                  {
                     public boolean addCard(Card crd)
                     {
                        return CardFactoryUtil.canTarget(card, crd) && crd.isCreature();
                     }
                  });
                   
                    CardList cl = (CardList) getPerm.execute();
                    return (o != null) && cList.size() > 0 && cl.size() > 0 && AllZone.getZone(getSourceCard()).is(Constant.Zone.Hand);
                }
            });
           
        }//*************** END ************ END **************************
It's based on Oblivion Ring 's code, and they can probably be intertwined by a better programmer than I.
cards.txt:
Code: Select all
Journey to Nowhere
1 W
Enchantment
When Journey to Nowhere enters the battlefield, exile target creature. When Journey to Nowhere leaves the battlefield, return the exiled card to the battlefield under its owner's control.
EDIT: There is a difference between 't' and 'T'.
Last edited by Hellfish on 12 Jun 2010, 08:24, edited 1 time in total.
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 » 11 Jun 2010, 18:11

Muddle the Mixture

Add to CardFactory
Code: Select all
//*************** START *********** START **************************
        else if(cardName.equals("Muddle the Mixture")) {
            SpellAbility spell = new Spell(card) {
                private static final long serialVersionUID = -2489268054171391552L;
               
                @Override
                public void resolve() {
                    SpellAbility sa = AllZone.Stack.pop();
           AllZone.GameAction.moveToGraveyard(sa.getSourceCard());
                }
               
                @Override
                public boolean canPlay() {
                    if(AllZone.Stack.size() == 0) return false;
                   
                    //see if spell is on stack and that opponent played it
                    String opponent = AllZone.GameAction.getOpponent(card.getController());
                    SpellAbility sa = AllZone.Stack.peek();
                                       

                    return sa.isSpell()
                && opponent.equals(sa.getSourceCard().getController())
                            && CardFactoryUtil.isCounterable(sa.getSourceCard())
                && (sa.getSourceCard().isInstant() || sa.getSourceCard().isSorcery());
                }
            };
            card.clearSpellAbility();
      spell.setDescription("Counter target instant or sorcery spell.");
      spell.setStackDescription("Muddle The Mixture - Counters target instant or sorcery.");
            card.addSpellAbility(spell);
        }//*************** END ************ END **************************
Based on the block of counterspells. Again, can probably be intertwined but when I tried it just became unreadable.

cards.txt:
Code: Select all
Muddle the Mixture
U U
Instant
no text
Transmute:1 U U
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 Sloth » 12 Jun 2010, 07:51

You forgot these beauties:

Code: Select all
Grand Coliseum
no cost
Land
no text
tap: add 1
paintap:1:W
paintap:1:U
paintap:1:B
paintap:1:R
paintap:1:G
Comes into play tapped.

Elves of Deep Shadow
G
Creature Elf Druid
no text
1/1
paintap:1:B
User avatar
Sloth
Programmer
 
Posts: 3498
Joined: 23 Jun 2009, 19:40
Has thanked: 125 times
Been thanked: 507 times

Re: Contrib. Coll.

Postby Hellfish » 12 Jun 2010, 08:30

Sloth wrote:You forgot these beauties:
Oh yeah, thanks for the reminder. :) Up next: Trusted Advisor, then I'll probably go see what's unclaimed at the request list.
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 Beached As » 13 Jun 2010, 08:05

I just committed your pain lands and artifacts Hellfish. Yours too Sloth. Thanks very much for the effort :)
Beached As
Programmer
 
Posts: 110
Joined: 23 Feb 2010, 07:48
Has thanked: 0 time
Been thanked: 0 time

Re: Contrib. Coll.

Postby Chris H. » 14 Jun 2010, 22:20

Hellfish wrote:Here goes Journey to Nowhere

EDIT: There is a difference between 't' and 'T'.
`
I added Journey To Nowhere to the SVN. I had a few problems but was able to resolve them. Code tested and it works.

And, opps. I will try to remember to lowercase the "to". :mrgreen:
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: Contrib. Coll.

Postby Chris H. » 15 Jun 2010, 13:31

Hellfish wrote:Muddle the Mixture
`
Added Muddle the Mixture. The computer can not use this spell.

You may want to look at the ComputerAI_counterSpells.java and ComputerAI_counterSpells2.java. This code allows the computer to cast counter spells. Unfortunately, code will need to be added to allow this new card to be usable by the AI. :D
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: Contrib. Coll.

Postby Hellfish » 15 Jun 2010, 14:49

Well, I looked into ComputerAI_counterSpell2.java (BTW, is there a good reason for keeping ComputerAI_counterspell.java around? It's not referenced anywhere.) and it turns out it was surprisingly easy to let the AI us MtM :)! paste this code in at the beginning of the addCard method used by the CardListFilter in getPlayableCounterspells(final spellAbility sa):
Code: Select all
if(sa.getSourceCard().getType().contains("Sorcery") || sa.getSourceCard().getType().contains("Instant")) {
               if(c.getName().equals("Muddle the Mixture"))
                  return true;
            }
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 Chris H. » 15 Jun 2010, 15:06

I will try to add your additions, I think that I will find the place for this code. Thank for the submission.
`
Merged into the SVN. Works OK. :D
Last edited by Chris H. on 15 Jun 2010, 15:53, edited 1 time in total.
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: Contrib. Coll.

Postby mtgrares » 15 Jun 2010, 15:50

Hellfish wrote:BTW, is there a good reason for keeping ComputerAI_counterspell.java around? (It's not referenced anywhere.)
Nope, you can delete it. ComputerAI_Rats.java used to be around to and that can be deleted also.
mtgrares
DEVELOPER
 
Posts: 1352
Joined: 08 Sep 2008, 22:10
Has thanked: 3 times
Been thanked: 12 times

Punch Card

Postby mtgrares » 15 Jun 2010, 15:56

Chris H wrote: I took a few intro college courses in the old days. The college did not have personal computers or terminals for it's students. We had to use card punch machines.
Punch cards, that does seem like a long time ago. Batch processing at its best (or worse). In high school I wrote about Charles Babbage and punch cards but I've never used one. The Hackers book (early computing, from the late 1950s to the mid-1980s) by Steven Levy talks about punch cards and I read it in high school.
mtgrares
DEVELOPER
 
Posts: 1352
Joined: 08 Sep 2008, 22:10
Has thanked: 3 times
Been thanked: 12 times

Re: Contrib. Coll.

Postby Hellfish » 16 Jun 2010, 11:56

Lost my big reply to stupid IE... >:(
The gist of it was: "Thanks for the tip, rares! I am working on keyword for counterspell-likes, might not pan out but if so I'll have specific code for the following new cards:
Annul
Artifact Blast
Confound
Dismal Failure
Dispel
Dream Fracture
Envelop
Fervent Denial (sans Flashback,I think)
Flash Counter
Hisoka's Defiance
Illumination
Intervene
Mystic Denial
Negate
Rebuff the Wicked
Thoughtbind
"
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

Next

Return to Developer's Corner

Who is online

Users browsing this forum: No registered users and 43 guests

Main Menu

User Menu

Our Partners


Who is online

In total there are 43 users online :: 0 registered, 0 hidden and 43 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 43 guests

Login Form