Adding similar cards
Post MTG Forge Related Programming Questions Here
Moderators: timmermac, Agetian, friarsol, Blacksmith, KrazyTheFox, CCGHQ Admins
27 posts
• Page 1 of 2 • 1, 2
Adding similar cards
by Chris H. » 15 Sep 2009, 18:07
I have a new card to submit. It may be too late to get it in for the next release, we can always add it to the following release.
Add this to cards.txt:
The following replaces the code for Soul Feast (I am combining Soul Feast with the new spell Last Caress):
Add this to cards-pictures.txt:
.
Add this to cards.txt:
- Code: Select all
Last Caress
2 B
Sorcery
Target player loses 1 life and you gain 1 life. Draw a card.
Cantrip
The following replaces the code for Soul Feast (I am combining Soul Feast with the new spell Last Caress):
- Code: Select all
////////////////////////////////////////////////////////////
if (cardName.equals("Soul Feast") || cardName.equals("Last Caress"))
{
final SpellAbility spell = new Spell(card)
{
private static final long serialVersionUID = -8277174319360648715L;
public void resolve()
{
int n = 4;
if (cardName.equals("Last Caress"))
n = 1;
AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(n);
PlayerLife life = AllZone.GameAction.getPlayerLife(card.getController());
life.addLife(n);
}//resolve()
};//SpellAbility
spell.setChooseTargetAI(CardFactoryUtil.AI_targetHuman());
spell.setBeforePayMana(CardFactoryUtil.input_targetPlayer(spell));
card.clearSpellAbility();
card.addSpellAbility(spell);
return card;
}
//////////////////////////////////////////////////////////
Add this to cards-pictures.txt:
.
- Attachments
-
Last Caress pic url.zip- (661 Bytes) Downloaded 363 times
-

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: Adding similar cards
by mtgrares » 15 Sep 2009, 18:11
It looks good. I'm sure you were very happy when you got to use the card that YOU programmed. Its a great feeling.
And by the way, I just use the lines ////////////////////////////////////////////////// to make SURE that I notice that I'm starting or ending a specific card, because it is really easy to make mistakes when a card is longer than a screen and I accidentally hit pageUp or pageDown and end up messing up a different card.
And by the way, I just use the lines ////////////////////////////////////////////////// to make SURE that I notice that I'm starting or ending a specific card, because it is really easy to make mistakes when a card is longer than a screen and I accidentally hit pageUp or pageDown and end up messing up a different card.
- mtgrares
- DEVELOPER
- Posts: 1352
- Joined: 08 Sep 2008, 22:10
- Has thanked: 3 times
- Been thanked: 12 times
Re: Adding similar cards
by Rob Cashwalker » 15 Sep 2009, 19:34
This mechanic is begging for a keyword.
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: Adding similar cards
by DennisBergkamp » 15 Sep 2009, 20:02
Nice. No it's not too late for the next release, in fact I'm still in the process of adding some new cards (from the latest set).
-

DennisBergkamp - AI Programmer
- Posts: 2602
- Joined: 09 Sep 2008, 15:46
- Has thanked: 0 time
- Been thanked: 0 time
Re: Adding similar cards
by silly freak » 15 Sep 2009, 20:37
i personally don't think it is a good idea to release new cards before wizards does. but i don't fear we are faster anyways ^^
for the keyword: i don't know for life drain, but with damage, there is "equal to the ammount of damage dealt this way" which is slightly different from "deal X, gain X". if possible, maybe there should be two versions for this difference?
for the keyword: i don't know for life drain, but with damage, there is "equal to the ammount of damage dealt this way" which is slightly different from "deal X, gain X". if possible, maybe there should be two versions for this difference?
___
where's the "trust me, that will work!" switch for the compiler?
Laterna Magica - blog, forum, project, 2010/09/06 release!
where's the "trust me, that will work!" switch for the compiler?
Laterna Magica - blog, forum, project, 2010/09/06 release!
- silly freak
- DEVELOPER
- Posts: 598
- Joined: 26 Mar 2009, 07:18
- Location: Vienna, Austria
- Has thanked: 93 times
- Been thanked: 25 times
Re: Adding similar cards
by Chris H. » 15 Sep 2009, 21:37
I hope to get my level of training and understanding to a point where I can make a contribution by making a keyword. I feel like I am trying to graduate from first grade and make it to second grade.
They should change my status from tester to Jr. Wannabee Code-Hacker Trainee.
There are several cards that use this mechanic, all but Soul Feast and Last Caress have other abilities like the Morsel Theft spell. At least the Last Caress spell makes good use of Rob' cantrip keyword.
I noticed that Dennis had created a second method for Goldmeadow Harrier rather than combining it with Squall Drifter. So I went and did some research and came up with a long list of creatures that are very similar. Talk about begging for a keyword.
There is no AI for this type of card at this time … it has got me to thinking …
Check to see if the computer has the Royal Assassin Combo in play?
How about tapping the Human's biggest creatures so they can't block for an up-coming attack?
Unfortunately, the computer can't use this before the human attacks.
They should change my status from tester to Jr. Wannabee Code-Hacker Trainee.
There are several cards that use this mechanic, all but Soul Feast and Last Caress have other abilities like the Morsel Theft spell. At least the Last Caress spell makes good use of Rob' cantrip keyword.
I noticed that Dennis had created a second method for Goldmeadow Harrier rather than combining it with Squall Drifter. So I went and did some research and came up with a long list of creatures that are very similar. Talk about begging for a keyword.
There is no AI for this type of card at this time … it has got me to thinking …
Check to see if the computer has the Royal Assassin Combo in play?
How about tapping the Human's biggest creatures so they can't block for an up-coming attack?
Unfortunately, the computer can't use this before the human attacks.
-

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: Adding similar cards
by Chris H. » 16 Sep 2009, 01:24
Let there be tokens, tokens and more tokens. The spell Dragon Fodder uses the Raise the Alarm spell as a template. I decided to keep these two spells separate since there is enough important data in the method that we do not want to become confused.
Add this to cards.txt:
Add this code to CardFactory.java (below the Raise the Alarm method?) :
This spell creates r_1_1_goblin creature tokens and we already have a jpg for these Goblins.
EDIT:
I see that I forgot to include the jpg url for the Dragon Fodder spell:
.
Add this to cards.txt:
- Code: Select all
Dragon Fodder
1 R
Sorcery
Put two 1/1 red Goblin creature tokens onto the battlefield.
Add this code to CardFactory.java (below the Raise the Alarm method?) :
- Code: Select all
//*************** START *********** START **************************
if(cardName.equals("Dragon Fodder"))
{
SpellAbility spell = new Spell(card)
{
private static final long serialVersionUID = -6704097906643840324L;
public void resolve()
{
PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController());
for (int i = 0; i < 2; i++)
{
Card c = new Card();
c.setOwner(card.getController());
c.setController(card.getController());
c.setName("R 1 1 Goblin");
c.setManaCost("R");
c.setToken(true);
c.addType("Creature");
c.addType("Goblin");
c.setBaseAttack(1);
c.setBaseDefense(1);
play.add(c);
}//for
}//resolve()
};
card.clearSpellAbility();
card.addSpellAbility(spell);
}//*************** END ************ END **************************
This spell creates r_1_1_goblin creature tokens and we already have a jpg for these Goblins.
EDIT:
I see that I forgot to include the jpg url for the Dragon Fodder spell:
.
- Attachments
-
Dragon Fodder pic url.zip- (671 Bytes) Downloaded 353 times
-

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: Adding similar cards
by Rob Cashwalker » 16 Sep 2009, 03:40
I'd have to think lose life/gain life spells are common enough to warrant a keyword. And honestly at this stage, we should refrain from adding card code which isn't at least 75% unique from any other card. Soul Feast is one that is so simple that I've put it off for a while.
Just make up the shouldLoseLife() function, and copy the DamageCP parser for the damage, then add the spellability from soul feast, substituting the explicit number for a variable.
I'll come along later sometime to dress it up with extra abilities
Deal damage/gain life is different, and I'm including it in an enhanced damage spell keyword handler.
Token generation is another ability I want to keyword. The only difference between many token generating spells is the number of tokens, the type and p/t and sometimes the name. All stuff that's easy to parse.
Just make up the shouldLoseLife() function, and copy the DamageCP parser for the damage, then add the spellability from soul feast, substituting the explicit number for a variable.
I'll come along later sometime to dress it up with extra abilities
Deal damage/gain life is different, and I'm including it in an enhanced damage spell keyword handler.
Token generation is another ability I want to keyword. The only difference between many token generating spells is the number of tokens, the type and p/t and sometimes the name. All stuff that's easy to parse.
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: Adding similar cards
by Chris H. » 18 Sep 2009, 12:28
OK, I have found the DamageCP parser and I modified a copy to become the parser for a keyword that we can call spLoseLifeGainLife. The parser looks like this and I think it is OK:Rob Cashwalker wrote:Just make up the shouldLoseLife() function, and copy the DamageCP parser for the damage, then add the spellability from soul feast, substituting the explicit number for a variable.
- Code: Select all
private final int shouldSpLoseLifeGainLife(Card c){
ArrayList<String> a = c.getKeyword();
for (int i = 0; i < a.size(); i++)
if (a.get(i).toString().startsWith("spLoseLifeGainLife"))
return i;
return -1;
}
Farther down I have the following unfinished code:
- Code: Select all
//Spell gain life lose life cards (like Soul Feast)
if (shouldSpLoseLifeGainLife(card) != -1)
{
int n = shouldSpLoseLifeGainLife(card);
if (n != -1)
{
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
card.clearSpellAbility();
String k[] = parse.split(":");
final String life = k[1];
// need to add Soul Feast code here or access code from CardFactoryUtil
}
}// spLoseLifeGainLife
Note the comment "// need to add Soul Feast code here or access code from CardFactoryUtil".
I tried to add the Soul Feast code here and I had problems in reference to something related to a class and I could not get rid of the errors.
Looking at the code for spDamageCP, it looks like I need to have a statement:
- Code: Select all
card.addSpellAbility(CardFactoryUtil.spellability_spLoseLifeGainLife(card, life));
which would pass some parameters to some new code that I would have to add to CardFactoryUtil.
I am somewhat confused. I think that I should be able to add the Soul Feast code here and not have to access CardFactoryUtil.
-

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: Adding similar cards
by Rob Cashwalker » 18 Sep 2009, 15:23
In Soul Feast, there is a SpellAbility defined. Copy that ability into your parser after the part which extracts the number. Modify the spell Ability resolve() method, such that the number of life lost/gained is the variable that contains the extracted number.
Set the descriptions of the SpellAbility (assembled on the fly, like this: "string" + numLife + "string") and then use the addSpellAbility() method to add the SpellAbility object to the card.
Set the descriptions of the SpellAbility (assembled on the fly, like this: "string" + numLife + "string") and then use the addSpellAbility() method to add the SpellAbility object to the card.
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: Adding similar cards
by frwololo » 28 Sep 2009, 03:34
I dream of the day we can have compatibility for keywords between Forge and WagicRob Cashwalker wrote:Token generation is another ability I want to keyword. The only difference between many token generating spells is the number of tokens, the type and p/t and sometimes the name. All stuff that's easy to parse.
Here's how we write tokens in Wagic:
[card]
text=Kicker
(You may pay an additional
as you cast this spell.) Put six 1/1 white Kor Soldier creature tokens onto the battlefield. If Conqueror's Pledge was kicked, put twelve of those tokens onto the battlefield instead.id=195626
name=Conqueror's Pledge
mana={2}{W}{W}{W}
kicker={6}
auto=token(Kor Soldier,Creature Kor Soldier,1/1,white)*6
auto=kicker token(Kor Soldier,Creature Kor Soldier,1/1,white)*6
type=Sorcery
rarity=R
[/card]
first is the name, then type and subtypes, P/T, last one is colors and abilities (flying and stuff like this...). *n is optional and indicates the number of tokens
Re: Adding similar cards
by mtgrares » 30 Sep 2009, 19:25
Well MTG Forge supports more keywords and scripting than I ever thought it would. Scripting is nice since it saves on coding if you don't mind working on just individual "script words" that can be combined in a large variety of ways.I dream of the day we can have compatibility for keywords between Forge and Wagic.
I dream of scripting all of MTG Forge's cards
- Code: Select all
Shock.txt
Shock
R
Instant
Spell
Text: Shock deals 2 damage to target creature or player.
Target: creature or player
Resolve: damage target creature or player, 2
- Code: Select all
Prodigal_Pyromancer.txt
Prodigal Pyromancer
2 R
Creature Human Wizard
1/1
Activated Ability
Text: tap: Prodigal Pyromancer deals 1 damage to target creature or player.
Target: creature or player
Cost: tap
Resolve: damage target creature or player, 1
- mtgrares
- DEVELOPER
- Posts: 1352
- Joined: 08 Sep 2008, 22:10
- Has thanked: 3 times
- Been thanked: 12 times
Re: Adding similar cards
by Marek14 » 30 Sep 2009, 19:48
You know, you don't really need the "damage target creature or player" in resolve... why not simply "damage target"?mtgrares wrote:Well MTG Forge supports more keywords and scripting than I ever thought it would. Scripting is nice since it saves on coding if you don't mind working on just individual "script words" that can be combined in a large variety of ways.I dream of the day we can have compatibility for keywords between Forge and Wagic.
I dream of scripting all of MTG Forge's cards
- Code: Select all
Shock.txt
Shock
R
Instant
Spell
Text: Shock deals 2 damage to target creature or player.
Target: creature or player
Resolve: damage target creature or player, 2The idea is to divide cards into targets, costs, and resolves that can be reused and separated. That way Shock and Prodigal Pyromancer could share the same targeting and resolve code. What a wonderful dream. (I really need to sit my butt down and try to just code these two cards like this.)
- Code: Select all
Prodigal_Pyromancer.txt
Prodigal Pyromancer
2 R
Creature Human Wizard
1/1
Activated Ability
Text: tap: Prodigal Pyromancer deals 1 damage to target creature or player.
Target: creature or player
Cost: tap
Resolve: damage target creature or player, 1
Then, Lava Spike would be
- Code: Select all
Lava Spike.txt
Lava Spike
R
Sorcery
Spell
Text: Lava Spike deals 3 damage to target player.
Target: player
Resolve: damage target, 3
Re: Adding similar cards
by mtgrares » 30 Sep 2009, 20:07
Both strings can mean the same thing. I tend to be a little too wordy or verbose when I'm not sure what I'm doing.You know, you don't really need the "damage target creature or player" in resolve... why not simply "damage target"?
- mtgrares
- DEVELOPER
- Posts: 1352
- Joined: 08 Sep 2008, 22:10
- Has thanked: 3 times
- Been thanked: 12 times
Re: Adding similar cards
by Chris H. » 18 Oct 2009, 01:47
A new spell:
(NOTE: In my tests I could not get the computer to cast this spell even though it was attacking with four 1/1 creatures. I copied the AI code from the block of code which covers most of these cards. I modified the code from Titanic Ultimatum for the rest of this spell. I also tried the test with Glorious Charge and the computer once again failed to cast this spell even though it was attacking with four creatures.)
(NOTE: In my tests I could not get the computer to cast this spell even though it was attacking with four 1/1 creatures. I copied the AI code from the block of code which covers most of these cards. I modified the code from Titanic Ultimatum for the rest of this spell. I also tried the test with Glorious Charge and the computer once again failed to cast this spell even though it was attacking with four creatures.)
- Code: Select all
Marshaling Cry
1 W W
Sorcery
Creatures you control get +1/+1 and gain vigilance until end of turn.
Cycling:2
- Code: Select all
//*************** START *********** START **************************
if (cardName.equals("Marshaling Cry"))
{
SpellAbility spell = new Spell(card)
{
private static final long serialVersionUID = -8141210741282528210L;
public boolean canPlayAI()
{
return getAttacker() != null;
}
public Card getAttacker()
{
//target creature that is going to attack
Combat c = ComputerUtil.getAttackers();
Card[] att = c.getAttackers();
if (att.length > 1) // Effect best used on at least a couple creatures
return att[0];
else
return null;
}//getAttacker()
public void resolve()
{
PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController());
CardList list = new CardList(play.getCards());
@SuppressWarnings("unused") // c
Card c;
for (int i = 0; i < list.size(); i++)
{
final Card[] target = new Card[1];
target[0] = list.get(i);
final Command untilEOT = new Command()
{
private static final long serialVersionUID = 6075570541463641361L;
public void execute()
{
if (AllZone.GameAction.isCardInPlay(target[0]))
{
target[0].addTempAttackBoost(-1);
target[0].addTempDefenseBoost(-1);
target[0].removeExtrinsicKeyword("Vigilance");
}
}
};//Command
if (AllZone.GameAction.isCardInPlay(target[0]))
{
target[0].addTempAttackBoost(1);
target[0].addTempDefenseBoost(1);
target[0].addExtrinsicKeyword("Vigilance");
AllZone.EndOfTurn.addUntil(untilEOT);
}//if
}//for
}//resolve()
};
spell.setStackDescription(card.getController() + " creatures get +1/+1 and gain vigilance until end of turn.");
card.setFlashback(true);
card.clearSpellAbility();
card.addSpellAbility(spell);
spell.setDescription("Creatures you control get +1/+1 and gain vigilance until end of turn.");
card.addSpellAbility(CardFactoryUtil.ability_Flashback(card, "3 W", "0"));
}//*************** END ************ END **************************
-

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
27 posts
• Page 1 of 2 • 1, 2
Who is online
Users browsing this forum: No registered users and 40 guests
