Programming a card
Post MTG Forge Related Programming Questions Here
Moderators: timmermac, Blacksmith, KrazyTheFox, Agetian, friarsol, CCGHQ Admins
Re: Programming a card
by cyclope » 30 Sep 2009, 15:11
Thank you for your help and comments.
Now, i'm wondering if the enchant "undying rage" could be code like this:
//*************** START *********** START **************************
if(cardName.equals("Undying Rage"))
{
final SpellAbility spell = new Spell(card)
{
public boolean canPlayAI()
{
CardList list = new CardList(AllZone.Computer_Play.getCards());
list = list.getType("Creature");
if(list.isEmpty())
return false;
//else
CardListUtil.sortAttack(list);
CardListUtil.sortFlying(list);
setTargetCard(list.get(0));
return true;
}//canPlayAI()
public void resolve()
{
PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController());
play.add(card);
Card c = getTargetCard();
if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c) )
card.enchantCard(c);
}//resolve()
};//SpellAbility
card.clearSpellAbility();
card.addSpellAbility(spell);
Command onEnchant = new Command()
{
public void execute()
{
if (card.isEnchanting())
{
Card crd = card.getEnchanting().get(0);
crd.addSemiPermanentAttackBoost(+2);
crd.addSemiPermanentDefenseBoost(+2);
crd.addExtrinsicKeyword("This creature cannot block");
}
}//execute()
};//Command
Command onUnEnchant = new Command()
{
public void execute()
{
if (card.isEnchanting())
{
Card crd = card.getEnchanting().get(0);
crd.removeExtrinsicKeyword("This creature cannot block");
crd.addSemiPermanentAttackBoost(-1);
crd.addSemiPermanentDefenseBoost(-2);
}
}//execute()
};//Command
Command onLeavesPlay = new Command()
{
public void execute()
{
if (card.isEnchanting())
{
Card crd = card.getEnchanting().get(0);
card.unEnchantCard(crd);
}
}
};
card.setEnchant(onEnchant);
card.setUnEnchant(onUnEnchant);
card.setLeavesPlay(onLeavesPlay);
spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell));
}//*************** END ************ END **************************
I don't think the code takes care about "when this card is put in a graveyard from play, return it in its owner's hand"
Now, i'm wondering if the enchant "undying rage" could be code like this:
//*************** START *********** START **************************
if(cardName.equals("Undying Rage"))
{
final SpellAbility spell = new Spell(card)
{
public boolean canPlayAI()
{
CardList list = new CardList(AllZone.Computer_Play.getCards());
list = list.getType("Creature");
if(list.isEmpty())
return false;
//else
CardListUtil.sortAttack(list);
CardListUtil.sortFlying(list);
setTargetCard(list.get(0));
return true;
}//canPlayAI()
public void resolve()
{
PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController());
play.add(card);
Card c = getTargetCard();
if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c) )
card.enchantCard(c);
}//resolve()
};//SpellAbility
card.clearSpellAbility();
card.addSpellAbility(spell);
Command onEnchant = new Command()
{
public void execute()
{
if (card.isEnchanting())
{
Card crd = card.getEnchanting().get(0);
crd.addSemiPermanentAttackBoost(+2);
crd.addSemiPermanentDefenseBoost(+2);
crd.addExtrinsicKeyword("This creature cannot block");
}
}//execute()
};//Command
Command onUnEnchant = new Command()
{
public void execute()
{
if (card.isEnchanting())
{
Card crd = card.getEnchanting().get(0);
crd.removeExtrinsicKeyword("This creature cannot block");
crd.addSemiPermanentAttackBoost(-1);
crd.addSemiPermanentDefenseBoost(-2);
}
}//execute()
};//Command
Command onLeavesPlay = new Command()
{
public void execute()
{
if (card.isEnchanting())
{
Card crd = card.getEnchanting().get(0);
card.unEnchantCard(crd);
}
}
};
card.setEnchant(onEnchant);
card.setUnEnchant(onUnEnchant);
card.setLeavesPlay(onLeavesPlay);
spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell));
}//*************** END ************ END **************************
I don't think the code takes care about "when this card is put in a graveyard from play, return it in its owner's hand"
- cyclope
- Posts: 69
- Joined: 28 Sep 2009, 18:08
- Has thanked: 0 time
- Been thanked: 0 time
Re: Programming a card
by DennisBergkamp » 30 Sep 2009, 15:31
Yes, this should definitely work. Except:
The "when this card is put in a graveyard from play, return it in its owner's hand" part is easy to add. In GameAction.destroy():
Thanks, I'll add this card also
- Code: Select all
...
public void execute()
{
if (card.isEnchanting())
{
Card crd = card.getEnchanting().get(0);
crd.removeExtrinsicKeyword("This creature cannot block");
crd.addSemiPermanentAttackBoost(-1);
crd.addSemiPermanentDefenseBoost(-2);
}
...
The "when this card is put in a graveyard from play, return it in its owner's hand" part is easy to add. In GameAction.destroy():
- Code: Select all
if (c.getName().equals("Rancor") || c.getName().equals("Brilliant Halo") )
{
PlayerZone hand = AllZone.getZone(Constant.Zone.Hand,c.getOwner());
moveTo(hand, c);
}
Thanks, I'll add this card also

-
DennisBergkamp - AI Programmer
- Posts: 2602
- Joined: 09 Sep 2008, 15:46
- Has thanked: 0 time
- Been thanked: 0 time
Re: Programming a card
by Marek14 » 30 Sep 2009, 16:26
BTW, I think I had a creature with Brilliant Halo die, and the Halo wound up in my hand without ever going through triggered ability... it is not implemented as one?DennisBergkamp wrote:Yes, this should definitely work. Except:You have a -1 instead of a -2 (just a typo I assume).
- Code: Select all
...
public void execute()
{
if (card.isEnchanting())
{
Card crd = card.getEnchanting().get(0);
crd.removeExtrinsicKeyword("This creature cannot block");
crd.addSemiPermanentAttackBoost(-1);
crd.addSemiPermanentDefenseBoost(-2);
}
...
The "when this card is put in a graveyard from play, return it in its owner's hand" part is easy to add. In GameAction.destroy():Adding a '|| c.getName().equals("Undying Rage") ' into that if statement would take care of that.
- Code: Select all
if (c.getName().equals("Rancor") || c.getName().equals("Brilliant Halo") )
{
PlayerZone hand = AllZone.getZone(Constant.Zone.Hand,c.getOwner());
moveTo(hand, c);
}
Thanks, I'll add this card also
Anyways, here's a complete list of things with the same ability. Most of them seems that they could be added right away:
Aspect of Mongoose
Brilliant Halo
Cessation
Despondency
Endless Cockroaches
Fallen Ideal
Fiery Mantle
Fool's Demise
Fortitude
Launch
Rancor
Shivan Phoenix
Sleeper's Guile
Slow Motion
Sluggishness
Spirit Loop
Spreading Algae
Undying Rage
Weatherseed Treefolk
Re: Programming a card
by cyclope » 30 Sep 2009, 16:32
Thanks for your help Dennis...
So if my code is correct , this will also be correct:
So if my code is correct , this will also be correct:
- Code: Select all
//*************** START *********** START **************************
if(cardName.equals("Aspect of Mongouse"))
{
final SpellAbility spell = new Spell(card)
{
public boolean canPlayAI()
{
CardList list = new CardList(AllZone.Computer_Play.getCards());
list = list.getType("Creature");
if(list.isEmpty())
return false;
//else
CardListUtil.sortAttack(list);
CardListUtil.sortFlying(list);
setTargetCard(list.get(0));
return true;
}//canPlayAI()
public void resolve()
{
PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController());
play.add(card);
Card c = getTargetCard();
if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c) )
{
card.enchantCard(c);
System.out.println("Enchanted: " +getTargetCard());
}
}//resolve()
};//SpellAbility
card.clearSpellAbility();
card.addSpellAbility(spell);
Command onEnchant = new Command()
{
public void execute()
{
if (card.isEnchanting())
{
Card crd = card.getEnchanting().get(0);
crd.addExtrinsicKeyword("Shroud");
}
}//execute()
};//Command
Command onUnEnchant = new Command()
{
public void execute()
{
if (card.isEnchanting())
{
Card crd = card.getEnchanting().get(0);
crd.removeExtrinsicKeyword("Shroud");
}
}//execute()
};//Command
Command onLeavesPlay = new Command()
{
public void execute()
{
if (card.isEnchanting())
{
Card crd = card.getEnchanting().get(0);
card.unEnchantCard(crd);
}
}
};
card.setEnchant(onEnchant);
card.setUnEnchant(onUnEnchant);
card.setLeavesPlay(onLeavesPlay);
spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell));
}//*************** END ************ END **************************
- Code: Select all
if (c.getName().equals("Rancor") || c.getName().equals("Brilliant Halo") || c.getName().equals("Aspect of Mongoose"))
{
PlayerZone hand = AllZone.getZone(Constant.Zone.Hand,c.getOwner());
moveTo(hand, c);
}
- cyclope
- Posts: 69
- Joined: 28 Sep 2009, 18:08
- Has thanked: 0 time
- Been thanked: 0 time
Re: Programming a card
by DennisBergkamp » 30 Sep 2009, 16:34
Wow, didn't know there were that many. Maybe I'll just add it as a keyword:BTW, I think I had a creature with Brilliant Halo die, and the Halo wound up in my hand without ever going through triggered ability... it is not implemented as one?
Anyways, here's a complete list of things with the same ability. Most of them seems that they could be added right away:
Aspect of Mongoose
Brilliant Halo
Cessation
Despondency
Endless Cockroaches
Fallen Ideal
Fiery Mantle
Fool's Demise
Fortitude
Launch
Rancor
Shivan Phoenix
Sleeper's Guile
Slow Motion
Sluggishness
Spirit Loop
Spreading Algae
Undying Rage
Weatherseed Treefolk
"When this card is put into a graveyard from the battlefield, return this card to its owner's hand" ?
I'm not sure if it's possible to turn this into a triggered ability in MTGForge though, I'll give it a shot.
-
DennisBergkamp - AI Programmer
- Posts: 2602
- Joined: 09 Sep 2008, 15:46
- Has thanked: 0 time
- Been thanked: 0 time
Re: Programming a card
by DennisBergkamp » 30 Sep 2009, 16:39
Exactly, that should work too (Aspect of Mongoose though instead of Mongousecyclope wrote:Thanks for your help Dennis...
So if my code is correct , this will also be correct:and in GameActtion.destroy():
- Code: Select all
//*************** START *********** START **************************
if(cardName.equals("Aspect of Mongouse"))
{
final SpellAbility spell = new Spell(card)
{
public boolean canPlayAI()
{
CardList list = new CardList(AllZone.Computer_Play.getCards());
list = list.getType("Creature");
if(list.isEmpty())
return false;
//else
CardListUtil.sortAttack(list);
CardListUtil.sortFlying(list);
setTargetCard(list.get(0));
return true;
}//canPlayAI()
public void resolve()
{
PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController());
play.add(card);
Card c = getTargetCard();
if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c) )
{
card.enchantCard(c);
System.out.println("Enchanted: " +getTargetCard());
}
}//resolve()
};//SpellAbility
card.clearSpellAbility();
card.addSpellAbility(spell);
Command onEnchant = new Command()
{
public void execute()
{
if (card.isEnchanting())
{
Card crd = card.getEnchanting().get(0);
crd.addExtrinsicKeyword("Shroud");
}
}//execute()
};//Command
Command onUnEnchant = new Command()
{
public void execute()
{
if (card.isEnchanting())
{
Card crd = card.getEnchanting().get(0);
crd.removeExtrinsicKeyword("Shroud");
}
}//execute()
};//Command
Command onLeavesPlay = new Command()
{
public void execute()
{
if (card.isEnchanting())
{
Card crd = card.getEnchanting().get(0);
card.unEnchantCard(crd);
}
}
};
card.setEnchant(onEnchant);
card.setUnEnchant(onUnEnchant);
card.setLeavesPlay(onLeavesPlay);
spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell));
}//*************** END ************ END **************************But i can't find in which file the "GameAction.destroy()" is...
- Code: Select all
if (c.getName().equals("Rancor") || c.getName().equals("Brilliant Halo") || c.getName().equals("Aspect of Mongoose"))
{
PlayerZone hand = AllZone.getZone(Constant.Zone.Hand,c.getOwner());
moveTo(hand, c);
}

I was wrong about GameAction.destroy() (plus I misspelled it GameActtion), in fact it's in GameAction.sacrificeDestroy(Card c). Which is in the file GameAction.java, and starts on line 466 (the actual if statement is on line 516).
-
DennisBergkamp - AI Programmer
- Posts: 2602
- Joined: 09 Sep 2008, 15:46
- Has thanked: 0 time
- Been thanked: 0 time
Re: Programming a card
by cyclope » 30 Sep 2009, 16:47
Thanks to Dennis...
Thanks too , to Marek, i'll try to write the code for most of the cards that he requests...
And of course, i'll try to avoid typing errors...
Thanks too , to Marek, i'll try to write the code for most of the cards that he requests...
And of course, i'll try to avoid typing errors...
- cyclope
- Posts: 69
- Joined: 28 Sep 2009, 18:08
- Has thanked: 0 time
- Been thanked: 0 time
Re: Programming a card
by DennisBergkamp » 30 Sep 2009, 17:03
No problems, glad you're having fun Cyclope!
Probably the way to do this would be to change if statement in GameAction.java
Probably the way to do this would be to change if statement in GameAction.java
- Code: Select all
if (c.getName().equals("Rancor") || c.getName().equals("Brilliant Halo") || c.getName().equals("Aspect of Mongoose"))
{
PlayerZone hand = AllZone.getZone(Constant.Zone.Hand,c.getOwner());
moveTo(hand, c);
}
- Code: Select all
if (c.getKeyword().contains("When this card is put into a graveyard from the battlefield, return this card to its owner's hand"))
{
PlayerZone hand = AllZone.getZone(Constant.Zone.Hand,c.getOwner());
moveTo(hand, c);
}
- Code: Select all
Weatherseed Treefolk
2 G G G
Creature Treefolk
no text
5/3
Trample
When this card is put into a graveyard from the battlefield, return this card to its owner's hand
-
DennisBergkamp - AI Programmer
- Posts: 2602
- Joined: 09 Sep 2008, 15:46
- Has thanked: 0 time
- Been thanked: 0 time
Re: Programming a card
by cyclope » 30 Sep 2009, 17:10
Here are some more codes for:
- Spirit Loop
- Sluggishness
- Sleeper's Guile
and Launch.
- i say again that i don't know java programming and that i'm just trying to understand how to code magic cards for forge by copying some codes in CardFactoty.java
- so i don't know if the code you give will work fine , Dennis.
- Spirit Loop
- Sluggishness
- Sleeper's Guile
and Launch.
- Code: Select all
add in card fatory:
//*************** START *********** START **************************
if(cardName.equals("Spirit Loop"))
{
final SpellAbility spell = new Spell(card)
{
public boolean canPlayAI()
{
CardList list = new CardList(AllZone.Computer_Play.getCards());
list = list.getType("Creature");
if(list.isEmpty())
return false;
//else
CardListUtil.sortAttack(list);
CardListUtil.sortFlying(list);
setTargetCard(list.get(0));
return true;
}//canPlayAI()
public void resolve()
{
PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController());
play.add(card);
Card c = getTargetCard();
if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c) )
{
card.enchantCard(c);
System.out.println("Enchanted: " +getTargetCard());
}
}//resolve()
};//SpellAbility
card.clearSpellAbility();
card.addSpellAbility(spell);
Command onEnchant = new Command()
{
public void execute()
{
if (card.isEnchanting())
{
Card crd = card.getEnchanting().get(0);
crd.addExtrinsicKeyword("Lifelink");
}
}//execute()
};//Command
Command onUnEnchant = new Command()
{
public void execute()
{
if (card.isEnchanting())
{
Card crd = card.getEnchanting().get(0);
crd.removeExtrinsicKeyword("Lifelink");
}
}//execute()
};//Command
Command onLeavesPlay = new Command()
{
public void execute()
{
if (card.isEnchanting())
{
Card crd = card.getEnchanting().get(0);
card.unEnchantCard(crd);
}
}
};
card.setEnchant(onEnchant);
card.setUnEnchant(onUnEnchant);
card.setLeavesPlay(onLeavesPlay);
spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell));
}//*************** END ************ END **************************
//*************** START *********** START **************************
if(cardName.equals("Launch"))
{
final SpellAbility spell = new Spell(card)
{
public boolean canPlayAI()
{
CardList list = new CardList(AllZone.Computer_Play.getCards());
list = list.getType("Creature");
if(list.isEmpty())
return false;
//else
CardListUtil.sortAttack(list);
CardListUtil.sortFlying(list);
setTargetCard(list.get(0));
return true;
}//canPlayAI()
public void resolve()
{
PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController());
play.add(card);
Card c = getTargetCard();
if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c) )
{
card.enchantCard(c);
System.out.println("Enchanted: " +getTargetCard());
}
}//resolve()
};//SpellAbility
card.clearSpellAbility();
card.addSpellAbility(spell);
Command onEnchant = new Command()
{
public void execute()
{
if (card.isEnchanting())
{
Card crd = card.getEnchanting().get(0);
crd.addExtrinsicKeyword("Flying");
}
}//execute()
};//Command
Command onUnEnchant = new Command()
{
public void execute()
{
if (card.isEnchanting())
{
Card crd = card.getEnchanting().get(0);
crd.removeExtrinsicKeyword("Flying");
}
}//execute()
};//Command
Command onLeavesPlay = new Command()
{
public void execute()
{
if (card.isEnchanting())
{
Card crd = card.getEnchanting().get(0);
card.unEnchantCard(crd);
}
}
};
card.setEnchant(onEnchant);
card.setUnEnchant(onUnEnchant);
card.setLeavesPlay(onLeavesPlay);
spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell));
}//*************** END ************ END **************************
//*************** START *********** START **************************
if(cardName.equals("Sleeper's Guile"))
{
final SpellAbility spell = new Spell(card)
{
public boolean canPlayAI()
{
CardList list = new CardList(AllZone.Computer_Play.getCards());
list = list.getType("Creature");
if(list.isEmpty())
return false;
//else
CardListUtil.sortAttack(list);
CardListUtil.sortFlying(list);
setTargetCard(list.get(0));
return true;
}//canPlayAI()
public void resolve()
{
PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController());
play.add(card);
Card c = getTargetCard();
if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c) )
{
card.enchantCard(c);
System.out.println("Enchanted: " +getTargetCard());
}
}//resolve()
};//SpellAbility
card.clearSpellAbility();
card.addSpellAbility(spell);
Command onEnchant = new Command()
{
public void execute()
{
if (card.isEnchanting())
{
Card crd = card.getEnchanting().get(0);
crd.addExtrinsicKeyword("Fear");
}
}//execute()
};//Command
Command onUnEnchant = new Command()
{
public void execute()
{
if (card.isEnchanting())
{
Card crd = card.getEnchanting().get(0);
crd.removeExtrinsicKeyword("Fear");
}
}//execute()
};//Command
Command onLeavesPlay = new Command()
{
public void execute()
{
if (card.isEnchanting())
{
Card crd = card.getEnchanting().get(0);
card.unEnchantCard(crd);
}
}
};
card.setEnchant(onEnchant);
card.setUnEnchant(onUnEnchant);
card.setLeavesPlay(onLeavesPlay);
spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell));
}//*************** END ************ END **************************
//*************** START *********** START **************************
if(cardName.equals("Sluggishness"))
{
final SpellAbility spell = new Spell(card)
{
public boolean canPlayAI()
{
CardList list = new CardList(AllZone.Computer_Play.getCards());
list = list.getType("Creature");
if(list.isEmpty())
return false;
//else
CardListUtil.sortAttack(list);
CardListUtil.sortFlying(list);
setTargetCard(list.get(0));
return true;
}//canPlayAI()
public void resolve()
{
PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController());
play.add(card);
Card c = getTargetCard();
if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c) )
{
card.enchantCard(c);
System.out.println("Enchanted: " +getTargetCard());
}
}//resolve()
};//SpellAbility
card.clearSpellAbility();
card.addSpellAbility(spell);
Command onEnchant = new Command()
{
public void execute()
{
if (card.isEnchanting())
{
Card crd = card.getEnchanting().get(0);
crd.addExtrinsicKeyword("This creature can't block");
}
}//execute()
};//Command
Command onUnEnchant = new Command()
{
public void execute()
{
if (card.isEnchanting())
{
Card crd = card.getEnchanting().get(0);
crd.removeExtrinsicKeyword("This creature can't block");
}
}//execute()
};//Command
Command onLeavesPlay = new Command()
{
public void execute()
{
if (card.isEnchanting())
{
Card crd = card.getEnchanting().get(0);
card.unEnchantCard(crd);
}
}
};
card.setEnchant(onEnchant);
card.setUnEnchant(onUnEnchant);
card.setLeavesPlay(onLeavesPlay);
spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell));
}//*************** END ************ END **************************
add in GameAction.destroy(): where there is :
if (c.getName().equals("Rancor") || c.getName().equals("Brilliant Halo") || c.getName().equals("Aspect of Mongoose"))
{
PlayerZone hand = AllZone.getZone(Constant.Zone.Hand,c.getOwner());
moveTo(hand, c);
}
|| c.getName().equals("Spirit Loop")|| c.getName().equals("Sluggishness")|| c.getName().equals("Sleeper's Guile")|| c.getName().equals("Launch")
- i say again that i don't know java programming and that i'm just trying to understand how to code magic cards for forge by copying some codes in CardFactoty.java
- so i don't know if the code you give will work fine , Dennis.
- cyclope
- Posts: 69
- Joined: 28 Sep 2009, 18:08
- Has thanked: 0 time
- Been thanked: 0 time
Re: Programming a card
by Marek14 » 30 Sep 2009, 17:17
Well, it's not exactly a request. Let's just say that I'm a completist.cyclope wrote:Thanks to Dennis...
Thanks too , to Marek, i'll try to write the code for most of the cards that he requests...
And of course, i'll try to avoid typing errors...

I am pure Melvin, mind you. I don't play that much, I simply love the cards and their rules structure.
For the record, a card that works similarly to the current wording (without triggering), is Firestorm Phoenix. But that one has a complex condition later, so that's harder.
Similar to these cards is Enduring Renewal (which returns every creature that goes to your graveyard), but its first ability might prove to be problematic. Depends on if you wish to dive into a wondrous and complex world of draw replacement.
BTW, I noticed that AEtherflame Wall doesn't have the "blocks shadow creatures" ability implemented. I thought that perhaps a flag would work here (or even an ability), with the rules for shadow changed so creature with shadow can be blocked with creature with shadow or with "can block shadow" flag (but NOT both at once). This would be useful, apart from AEtherflame Wall, for AEther Web, Heartwood Dryad, and Wall of Diffusion.
Similarly, a flag could allow a creature to block landwalkers normally, enabling Guildpact card Street Savvy.
A group of six flags checked by landwalkers could allow to "switch off" landwalk abilities (five basic types plus one for all landwalk). This would allow Crevasse, Deadfall, Gosta Dirk, Great Wall, Lord Magnus, Quagmire, Staff of the Ages, Undertow and Ur-Drago.
A flag for "shroud exceptions" could allow Autumn Willow.
Flag "can't accept counters": Tatterkite.
Plus, some possible flags for players:
"Can block with tapped creatures": Masako the Humorless. Instead of having "untapped" as a condition for blockers, it's "untapped or controller has this flag"
"Can't gain life": Everlasting Torment (would also need a global "pseudo-wither" flag), Forsaken Wastes, Stigma Lasher.
Checked in lifegain routine, and stopping the gain if true.
"Doesn't lose at 0 life": Lich, Lich's Tomb, Soul Echo, Transcendence
Checked by the state-based effects.
"Doesn't lose, period": Angel's Grace, Platinum Angel (also needs corresponding "can't win" flag)
Checked by the state-based effects, as well as direct "you lose" and "you win" effects.
"Damage doesn't lower under 1": Ali from Cairo, Angel's Grace, Fortune Thief, Sustaining Spirit, Worship
This would be checked as a part of damage resolution. The trick here is that the full damage is dealt (for purpose of lifelink, etc.), it just doesn't reduce the life as it should. After computing the new life total, if this flag is present and the original life total was 1 or more, the life is actually set to maximum (computed value, 1), otherwise to computed value.
Re: Programming a card
by cyclope » 30 Sep 2009, 18:35
Here is , i think , the code for Fiery Mantle:
- Code: Select all
add in cardfactory.java:
//*************** START *********** START **************************
if(cardName.equals("Fiery Mantle"))
{
final SpellAbility spell = new Spell(card)
{
public boolean canPlayAI()
{
CardList list = new CardList(AllZone.Computer_Play.getCards());
list = list.getType("Creature");
if(list.isEmpty())
return false;
//else
CardListUtil.sortAttack(list);
CardListUtil.sortFlying(list);
setTargetCard(list.get(0));
return true;
}//canPlayAI()
public void resolve()
{
PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController());
play.add(card);
Card c = getTargetCard();
if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c) )
{
card.enchantCard(c);
System.out.println("Enchanted: " +getTargetCard());
}
}//resolve()
};//SpellAbility
card.clearSpellAbility();
card.addSpellAbility(spell);
Command onEnchant = new Command()
{
public void execute()
{
if (card.isEnchanting())
{
Card crd = card.getEnchanting().get(0);
crd.addExtrinsicKeyword("PTPump R:+1/+0");
}
}//execute()
};//Command
Command onUnEnchant = new Command()
{
public void execute()
{
if (card.isEnchanting())
{
Card crd = card.getEnchanting().get(0);
crd.removeExtrinsicKeyword("PTPump R:+1/+0");
}
}//execute()
};//Command
Command onLeavesPlay = new Command()
{
public void execute()
{
if (card.isEnchanting())
{
Card crd = card.getEnchanting().get(0);
card.unEnchantCard(crd);
}
}
};
card.setEnchant(onEnchant);
card.setUnEnchant(onUnEnchant);
card.setLeavesPlay(onLeavesPlay);
spell.setBeforePayMana(CardFactoryUtil.input_targetCreature(spell));
}//*************** END ************ END **************************
add in GameAction.sacrificeDestroy(card c): where there is :
if (c.getName().equals("Rancor") || c.getName().equals("Brilliant Halo") || c.getName().equals("Aspect of Mongoose"))
{
PlayerZone hand = AllZone.getZone(Constant.Zone.Hand,c.getOwner());
moveTo(hand, c);
}
|| c.getName().equals("Fiery Mantle")
- cyclope
- Posts: 69
- Joined: 28 Sep 2009, 18:08
- Has thanked: 0 time
- Been thanked: 0 time
Re: Programming a card
by cyclope » 30 Sep 2009, 18:58
I think a card like Dosan's Oldest Chant should be easy to code ? What do you think of that :
- Code: Select all
add in cardfactory.java :
//*************** START *********** START **************************
if(cardName.equals("Dosan's Oldest Chant"))
{
final SpellAbility ability = new Spell(card)
{
public void resolve()
{
Card c = card;
PlayerLife life = AllZone.GameAction.getPlayerLife(c.getController());
life.addLife(6);
}
};
Command intoPlay = new Command()
{
public void execute()
{
ability.setStackDescription(card.getName() + " - " +card.getController() +" gains 6 life");
AllZone.Stack.add(ability);
}
};
card.clearSpellAbility();
card.addSpellAbility(spell);
}//*************** END ************ END **************************
add in cards.tx:
Dosan's Oldest Chant
4 G
Sorcery
You gain 6 life
Cantrip
- cyclope
- Posts: 69
- Joined: 28 Sep 2009, 18:08
- Has thanked: 0 time
- Been thanked: 0 time
Re: Programming a card
by DennisBergkamp » 30 Sep 2009, 20:32
Cool, these all look good. I'll add them in 

-
DennisBergkamp - AI Programmer
- Posts: 2602
- Joined: 09 Sep 2008, 15:46
- Has thanked: 0 time
- Been thanked: 0 time
Re: Programming a card
by Rob Cashwalker » 01 Oct 2009, 02:56
Fiery Mantle doesn't work. Adding a scripting keyword (as PTPump is) doesn't grant the ability once the game is running. The script keywords only work when a card is created through CardFactory.
Adding an explicitly coded SpellAbility is simple enough, but I'm not sure how to go about simply removing it if the enchantment becomes detached/destroyed or the creature is bounced from/into play.
Adding an explicitly coded SpellAbility is simple enough, but I'm not sure how to go about simply removing it if the enchantment becomes detached/destroyed or the creature is bounced from/into play.
The Force will be with you, Always.
-
Rob Cashwalker - Programmer
- Posts: 2167
- Joined: 09 Sep 2008, 15:09
- Location: New York
- Has thanked: 5 times
- Been thanked: 40 times
Re: Programming a card
by cyclope » 01 Oct 2009, 16:21
Ok , Fiery Mantle code doesn't work...
Can anybody said me if the others are OK ?
Can anybody said me if the others are OK ?
- cyclope
- Posts: 69
- Joined: 28 Sep 2009, 18:08
- Has thanked: 0 time
- Been thanked: 0 time
Who is online
Users browsing this forum: No registered users and 55 guests