It is currently 09 Sep 2025, 11:41
   
Text Size

Code from slapshot5

Post MTG Forge Related Programming Questions Here

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

Code from slapshot5

Postby slapshot5 » 07 Apr 2010, 02:36

Rather than burying code in the Card Requests thread or the Bugs thread, I'll start my own thread and post back here when I have code to contribute. I'll start in the following posts...

-slapshot5
slapshot5
Programmer
 
Posts: 1391
Joined: 03 Jan 2010, 17:47
Location: Mac OS X
Has thanked: 25 times
Been thanked: 68 times

Re: Code from slapshot5

Postby slapshot5 » 07 Apr 2010, 02:54

Like they say, Karma is a bitch.

in GameActionUtil.java:

Code: Select all
private static void upkeep_Karma() {
        final String player = AllZone.Phase.getActivePlayer();
        String opponent = AllZone.GameAction.getOpponent(player);
       
        PlayerZone opponentPlayZone = AllZone.getZone(Constant.Zone.Play, opponent);
       
        CardList karma = new CardList(opponentPlayZone.getCards());
        karma = karma.getName("Karma");
       
        PlayerZone activePlayZone = AllZone.getZone(Constant.Zone.Play, player);
        CardList swamps = new CardList(activePlayZone.getCards());
        swamps = swamps.getType("Swamp");
       
        // determine how much damage to deal the current player
        final int damage = swamps.size();
       
        // if there are 1 or more Karmas owned by the opponent of the
        // current player have each of them deal damage.
        if(0 < karma.size()) {
            for(int i = 0; i < karma.size(); i++) {
                Ability ability = new Ability(karma.get(0), "0") {
                    @Override
                    public void resolve() {
                       if(damage>0){
                          PlayerLife life = AllZone.GameAction.getPlayerLife(player);
                          life.setLife(life.getLife() - damage);
                       }
                    }
                };// Ability
                if(damage>0){
                   ability.setStackDescription("Karma deals " + damage + " damage to " + player);
                   AllZone.Stack.add(ability);
                }
            }
        }// if
    }// upkeep_Karma()
Then, of course, add the call to executeUpkeepEffects()

cards.txt:

Code: Select all
Karma
2 W W
Enchantment
At the beginning of each player's upkeep, Karma deals damage to that player equal to the number of Swamps he or she controls.
URL:
Code: Select all
http://www.wizards.com/global/images/magic/general/karma.jpg
This is tested.

-slapshot5

Edit: Added a couple if checks to prevent unnecessary stack info.
Last edited by slapshot5 on 07 Apr 2010, 03:34, edited 2 times in total.
slapshot5
Programmer
 
Posts: 1391
Joined: 03 Jan 2010, 17:47
Location: Mac OS X
Has thanked: 25 times
Been thanked: 68 times

Re: Code from slapshot5

Postby slapshot5 » 07 Apr 2010, 02:56

slapshot5
Programmer
 
Posts: 1391
Joined: 03 Jan 2010, 17:47
Location: Mac OS X
Has thanked: 25 times
Been thanked: 68 times

Re: Code from slapshot5

Postby slapshot5 » 07 Apr 2010, 03:37

Flashfires

add to CardFactory.java:

Code: Select all
//*************** START *********** START **************************
        else if(cardName.equals("Flashfires")) {
            final SpellAbility spell = new Spell(card) {
                private static final long serialVersionUID = -5951776277564352958L;
               
                @Override
                public void resolve() {
                    CardList all = new CardList();
                    all.addAll(AllZone.Human_Play.getCards());
                    all.addAll(AllZone.Computer_Play.getCards());
                   
                    for(int i = 0; i < all.size(); i++) {
                        Card c = all.get(i);
                        if(c.getType().contains("Plains")) AllZone.GameAction.destroy(c);
                    }
                }//resolve()
               
                @Override
                public boolean canPlayAI() {
                    CardList list = new CardList(AllZone.Human_Play.getCards());
                    list = list.getType("Plains");
                   
                    return 3 < list.size();
                }
            };//SpellAbility
            spell.setStackDescription(card.getName() + " - destroy all Plains.");
            card.clearSpellAbility();
            card.addSpellAbility(spell);
        }//*************** END ************ END **************************
cards.txt:

Code: Select all
Flashfires
3 R
Sorcery
Destroy all Plains.
URL:
Code: Select all
http://www.wizards.com/global/images/magic/general/flashfires.jpg
This is tested.

-slapshot5
slapshot5
Programmer
 
Posts: 1391
Joined: 03 Jan 2010, 17:47
Location: Mac OS X
Has thanked: 25 times
Been thanked: 68 times

Re: Code from slapshot5

Postby slapshot5 » 07 Apr 2010, 04:34

Here's Crumble

add to CardFactory.java:

Code: Select all
//*************** START *********** START **************************
        else if(cardName.equals("Crumble")) {
            SpellAbility spell = new Spell(card) {
                private static final long serialVersionUID = 4752943254606319269L;
               
                @Override
                public void resolve() {
                    if(AllZone.GameAction.isCardInPlay(getTargetCard())
                            && CardFactoryUtil.canTarget(card, getTargetCard())) {
                        //add life
                        String player = getTargetCard().getController();
                        PlayerLife life = AllZone.GameAction.getPlayerLife(player);
                        life.addLife(CardUtil.getConvertedManaCost(getTargetCard()));
                       
                        //remove card from play
                        AllZone.GameAction.removeFromGame(getTargetCard());
                    }
                }//resolve()
               
                @Override
                public boolean canPlayAI() {
                    CardList artifacts = new CardList(AllZone.Human_Play.getCards());
                    artifacts = artifacts.getType("Artifact");
                    artifacts = artifacts.filter(new CardListFilter() {
                        public boolean addCard(Card c) {
                            return CardFactoryUtil.canTarget(card, c);
                        }
                    });
                    return artifacts.size() != 0 && (AllZone.Phase.getTurn() > 4);
                }
               
                @Override
                public void chooseTargetAI() {
                    CardList play = new CardList(AllZone.Human_Play.getCards());
                    Card target = CardFactoryUtil.AI_getBestArtifact(play);
                    if(target != null) setTargetCard(target);
                }
            };
            spell.setBeforePayMana(CardFactoryUtil.input_targetType(spell, "Artifact"));
           
            card.clearSpellAbility();
            card.addSpellAbility(spell);
        }//*************** END ************ END **************************
cards.txt:

Code: Select all
Crumble
G
Instant
Destroy target artifact. It can't be regenerated. That artifact's controller gains life equal to its converted mana cost.
URL:
Code: Select all
http://www.wizards.com/global/images/magic/general/crumble.jpg
This is mostly tested.

-slapshot5
slapshot5
Programmer
 
Posts: 1391
Joined: 03 Jan 2010, 17:47
Location: Mac OS X
Has thanked: 25 times
Been thanked: 68 times

Re: Code from slapshot5

Postby slapshot5 » 07 Apr 2010, 22:20

Here's Channel the Suns

CardFactory.java:
Code: Select all
//*************** START *********** START **************************
        else if(cardName.equals("Channel the Suns")) {
            final SpellAbility spell = new Spell(card) {
               
                private static final long serialVersionUID = -8509187529151755266L;
               
                @Override
                public void resolve() {
                    Card mp = AllZone.ManaPool;
                    mp.addExtrinsicKeyword("ManaPool:W");
                    mp.addExtrinsicKeyword("ManaPool:U");
                    mp.addExtrinsicKeyword("ManaPool:B");
                    mp.addExtrinsicKeyword("ManaPool:R");
                    mp.addExtrinsicKeyword("ManaPool:G");
                }
               
                @Override
                public boolean canPlayAI() {
                    return false;
                }
            };
           
            spell.setStackDescription(cardName + " adds W U B R G to your mana pool");
            card.clearSpellAbility();
            card.addSpellAbility(spell);
           
            return card;
        }//*************** END ************ END **************************
cards.txt:
Code: Select all
Channel the Suns
3 G
Sorcery
Add W U B R G to your mana pool.
URL
Code: Select all
http://www.wizards.com/global/images/magic/general/channel_the_suns.jpg
This is tested.

-slapshot5
slapshot5
Programmer
 
Posts: 1391
Joined: 03 Jan 2010, 17:47
Location: Mac OS X
Has thanked: 25 times
Been thanked: 68 times

Re: Code from slapshot5

Postby zerker2000 » 08 Apr 2010, 00:29

Why not "mp.addMana("WUBRG");"?
O forest, hold thy wand'ring son
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.


--Eladamri, the Seed of Freyalise
zerker2000
Programmer
 
Posts: 569
Joined: 09 May 2009, 21:40
Location: South Pasadena, CA
Has thanked: 0 time
Been thanked: 0 time

Re: Code from slapshot5

Postby slapshot5 » 08 Apr 2010, 02:35

zerker2000 wrote:Why not "mp.addMana("WUBRG");"?
Just mindlessly copied Dark Ritual. The Mana Pool stuff is all new to me. I haven't dug into it enough to do anything intelligent.

-slapshot5
slapshot5
Programmer
 
Posts: 1391
Joined: 03 Jan 2010, 17:47
Location: Mac OS X
Has thanked: 25 times
Been thanked: 68 times

Re: Code from slapshot5

Postby slapshot5 » 08 Apr 2010, 02:48

First pass at City of Brass

Add the following function to GameActionUtil.java:
Code: Select all
public static void executeTapSideEffects(Card c) {
       
       /* cards with Tap side effects can be listed here, just like in
        * the CardFactory classes
        */
       if(c.getName().equals("City of Brass")) {
          final String player = c.getOwner();
          Ability ability = new Ability(c, "0") {
                @Override
                public void resolve() {
                   PlayerLife life = AllZone.GameAction.getPlayerLife(player);
                  life.setLife(life.getLife() - 1);
                }
            };// Ability
            ability.setStackDescription("City of Brass deals 1 damage to " + player);
            AllZone.Stack.add(ability);
       }//end City of Brass
       
    }
Then, change the tap() method in Card.java to be:
Code: Select all
public void tap() {
       GameActionUtil.executeTapSideEffects(this);
        setTapped(true);
    }
cards.txt:
Code: Select all
City of Brass
no cost
Land
Whenever City of Brass becomes tapped, it deals 1 damage to you.
tap: add W
tap: add B
tap: add U
tap: add R
tap: add G
URL:
Code: Select all
http://www.wizards.com/global/images/magic/general/city_of_brass.jpg
Can someone review and commit? It looks ok in my general testing.

(Also, note this provides a general mechanism for cards that have a side effect when tapped.)

-slapshot5
slapshot5
Programmer
 
Posts: 1391
Joined: 03 Jan 2010, 17:47
Location: Mac OS X
Has thanked: 25 times
Been thanked: 68 times

Re: Code from slapshot5

Postby slapshot5 » 08 Apr 2010, 03:21

Here's Storm Seeker from Legends:

CardFactory.java:
Code: Select all
//*************** START *********** START **************************
        else if(cardName.equals("Storm Seeker")) {
            SpellAbility spell = new Spell(card) {
                private static final long serialVersionUID = -5456164079435151319L;
               
                @Override
                public void resolve() {
                    PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, getTargetPlayer());
                    int damage = hand.size();
                   
                    //sanity check
                    if( damage < 0 )
                       damage = 0;
                   
                    PlayerLife life = AllZone.GameAction.getPlayerLife(getTargetPlayer());
                  life.setLife(life.getLife() - damage);
                   
                }
            };
            spell.setChooseTargetAI(CardFactoryUtil.AI_targetHuman());
           
            spell.setBeforePayMana(CardFactoryUtil.input_targetPlayer(spell));
           
            card.clearSpellAbility();
            card.addSpellAbility(spell);
        }//*************** END ************ END **************************
cards.txt:
Code: Select all
Storm Seeker
3 G
Instant
Storm Seeker deals damage equal to the number of cards in target player's hand to that player.
URL:
Code: Select all
http://www.wizards.com/global/images/magic/general/storm_seeker.jpg
-slapshot5
slapshot5
Programmer
 
Posts: 1391
Joined: 03 Jan 2010, 17:47
Location: Mac OS X
Has thanked: 25 times
Been thanked: 68 times

Re: Code from slapshot5

Postby slapshot5 » 08 Apr 2010, 04:02

This is Wall of Tears

In CombatUtil.java, change the same line with AEther Membrane to this:

Code: Select all
else if(b.getName().equals("AEther Membrane") || b.getName().equals("Aether Membrane") || b.getName().equals("Wall of Tears")) {
 
cards.txt:
Code: Select all
Wall of Tears
1 U
Creature Wall
Whenever Wall of Tears blocks a creature, return that creature to its owner's hand at end of combat.
0/4
Defender
URL:
Code: Select all
http://www.wizards.com/global/images/magic/general/wall_of_tears.jpg
This is tested.

-slapshot5
slapshot5
Programmer
 
Posts: 1391
Joined: 03 Jan 2010, 17:47
Location: Mac OS X
Has thanked: 25 times
Been thanked: 68 times

Re: Code from slapshot5

Postby Rob Cashwalker » 08 Apr 2010, 05:22

. Storm Seeker should be done by tweaking the spDamageTgt keyword and adding "TgtPHand" or something to CardFactoryUtil.xCount().

spDamageTgt:X:Storm Seeker deals damage equal to the number of cards in target player's hand to that player.:Storm Seeker - deals X damage
SVar:X:Count$TgtPHand
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: Code from slapshot5

Postby slapshot5 » 08 Apr 2010, 12:48

Rob Cashwalker wrote:. Storm Seeker should be done by tweaking the spDamageTgt keyword and adding "TgtPHand" or something to CardFactoryUtil.xCount().
Thanks Rob. I haven't dug into the keyword stuff yet. Probably a good chance to learn and see what's there. I'll futz with it tonight and see if I can get the same functionality working in keywords.

-slapshot5
slapshot5
Programmer
 
Posts: 1391
Joined: 03 Jan 2010, 17:47
Location: Mac OS X
Has thanked: 25 times
Been thanked: 68 times

Re: Code from slapshot5

Postby DennisBergkamp » 08 Apr 2010, 20:39

Hm, it look like City of Brass should work fine (I made a few changes though: it's probably good to check if the card is untapped before executing the tap side effects, and I used GameAction.addDamage(player, damage, src) since we want to move in the direction of separation between lifeloss and damage).

I'll just include it with the next release, we'll hear if there's any bugs :)
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Re: Code from slapshot5

Postby slapshot5 » 08 Apr 2010, 23:03

Thanks Dennis. I'll keep the damage/lifeloss stuff in mind as I continue coding.

-slapshot5
slapshot5
Programmer
 
Posts: 1391
Joined: 03 Jan 2010, 17:47
Location: Mac OS X
Has thanked: 25 times
Been thanked: 68 times

Next

Return to Developer's Corner

Who is online

Users browsing this forum: No registered users and 29 guests

Main Menu

User Menu

Our Partners


Who is online

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

Login Form