Programming a card
Post MTG Forge Related Programming Questions Here
Moderators: timmermac, Blacksmith, KrazyTheFox, Agetian, friarsol, CCGHQ Admins
Re: Programming a card
by DennisBergkamp » 05 Dec 2009, 01:12
For the Lobotomist, you probably need two blocks of code, one for the removing of cards (similar to Fable of Wolf and Owl) + adding them to the list, then another block for constantly checking whatever card is banned (similar to Meddling Mage or Gaddock Teeg). But I don't know, the Lobotomist might be trickier...
I'd have to think about how to do Dovescape exactly, but I think you can use sa.isSpell(). So instead of:

I'd have to think about how to do Dovescape exactly, but I think you can use sa.isSpell(). So instead of:
- Code: Select all
SpellAbility sa = AllZone.Stack.pop();
AllZone.GameAction.moveToGraveyard(sa.getSourceCard());
- Code: Select all
SpellAbility sa = AllZone.Stack.peek();
while (!sa.isSpell() || AllZone.Stack.size() == 0 )
{
sa = AllZone.Stack.pop();
}
if (sa.isSpell())
{
AllZone.GameAction.moveToGraveyard(sa.getSourceCard());
}

-
DennisBergkamp - AI Programmer
- Posts: 2602
- Joined: 09 Sep 2008, 15:46
- Has thanked: 0 time
- Been thanked: 0 time
Re: Programming a card
by Triadasoul » 05 Dec 2009, 10:22
It doesn't work for me. I implemented it like this ( it may be not what you meant, cause i don't have full understanding of how it works ):
PS:But when i moved the code to the first palce of playCard(c) list, it doesn't crash the game. And it moved the ability of Dovescape to the card that should be countered in the stack. But when ability resolves it doesn't counter anything.
PS:But when i moved the code to the first palce of playCard(c) list, it doesn't crash the game. And it moved the ability of Dovescape to the card that should be countered in the stack. But when ability resolves it doesn't counter anything.
- Code: Select all
public static void playCard_Dovescape(Card c)
{
PlayerZone hplay = AllZone.getZone(Constant.Zone.Play,
Constant.Player.Human);
PlayerZone cplay = AllZone.getZone(Constant.Zone.Play,
Constant.Player.Computer);
CardList list = new CardList();
list.addAll(hplay.getCards());
list.addAll(cplay.getCards());
int cmc = CardUtil.getConvertedManaCost(c.getManaCost());
list = list.getName("Dovescape");
// SpellAbility sa = AllZone.Stack.peek();
if ( ! c.getType().contains("Creature") && list.size()>0 ) {
final Card card = list.get(0);
Ability ability2 = new Ability(card, "0")
{
public void resolve()
{
SpellAbility sa = AllZone.Stack.peek();
while (!sa.isSpell() || AllZone.Stack.size() == 0 )
{
sa = AllZone.Stack.pop();
}
if (sa.isSpell())
{
AllZone.GameAction.moveToGraveyard(sa.getSourceCard());
}
}
}; // ability2
ability2.setStackDescription("Dovescape Ability");
AllZone.Stack.add(ability2);
for (int j = 0; j < list.size()*cmc; j++)
{
Card crd = new Card();
String controller = c.getController();
crd.setOwner(controller);
crd.setController(controller);
crd.setName("Bird");
crd.setImageName("WU 1 1 Bird");
crd.setManaCost("WU");
crd.setToken(true);
crd.addType("Creature");
crd.addType("Bird");
crd.addIntrinsicKeyword("Flying");
crd.setBaseAttack(1);
crd.setBaseDefense(1);
PlayerZone play = AllZone.getZone(Constant.Zone.Play, controller);
play.add(crd);
}
}
} // Dovescape
- Code: Select all
Detailed error trace:
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.RangeCheck(Unknown Source)
at java.util.ArrayList.remove(Unknown Source)
at forge.MagicStack.pop(MagicStack.java:43)
at forge.GameActionUtil$178.resolve(GameActionUtil.java:855)
at forge.Input_StackNotEmpty.selectButtonOK(Input_StackNotEmpty.java:39)
at forge.GuiInput.selectButtonOK(GuiInput.java:32)
at forge.GuiDisplay3.okButtonActionPerformed(GuiDisplay3.java:1064)
at forge.GuiDisplay3.access$3(GuiDisplay3.java:1063)
at forge.GuiDisplay3$25.actionPerformed(GuiDisplay3.java:791)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.AbstractButton.doClick(Unknown Source)
at javax.swing.AbstractButton.doClick(Unknown Source)
at forge.GuiDisplay3$26.keyPressed(GuiDisplay3.java:810)
at java.awt.Component.processKeyEvent(Unknown Source)
at javax.swing.JComponent.processKeyEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.KeyboardFocusManager.redispatchEvent(Unknown Source)
at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(Unknown Source)
at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(Unknown Source)
at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(Unknown Source)
at java.awt.DefaultKeyboardFocusManager.dispatchEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
Last edited by Triadasoul on 05 Dec 2009, 11:24, edited 2 times in total.
- Triadasoul
- Posts: 223
- Joined: 21 Jun 2008, 20:17
- Has thanked: 0 time
- Been thanked: 4 times
Re: Programming a card
by Marek14 » 05 Dec 2009, 10:53
BTW, why is it necessary to set mana cost of a token? It's imprecise to say the least (effects checking mana cost, or at least converted mana cost, of permanents are dime a dozen).
Maybe a better solution would be to implement color overriding so you wouldn't be tied by the mana cost. This would also allow for more precise Ghostfire.
Maybe a better solution would be to implement color overriding so you wouldn't be tied by the mana cost. This would also allow for more precise Ghostfire.
Re: Programming a card
by zerker2000 » 05 Dec 2009, 21:01
The reason is that "CARDNAME is COLOR." was added quite recently, and noone has converted token code to use it yet. I think I did change Ghostfire and Kobolds to use it though.
EDIT: Also, should "Manland P/T:
" be a keyword, possibly even accepting keywords like First Strike and Changeling?
Also, something that has been bothering me a while: why isn't it possible to split off CardFactory_Keywords, and make its method parseKeywords(Card c, String[] keywords), which can be called by abilities as well as init (and of course would default to card.addKeyword).
EDIT: Also, should "Manland P/T:

Also, something that has been bothering me a while: why isn't it possible to split off CardFactory_Keywords, and make its method parseKeywords(Card c, String[] keywords), which can be called by abilities as well as init (and of course would default to card.addKeyword).
Last edited by zerker2000 on 05 Dec 2009, 21:10, edited 1 time in total.
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
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: Programming a card
by DennisBergkamp » 05 Dec 2009, 21:05
I think Zerker implemented color overriding (using keyword: "{cardName} is {color}"). In the current version, Ghostfire actually IS Colorless, and Kobolds of Kher Keep Red.
Hmm, I'll play around with Dovescape a bit, to see if I can get it working.
EDIT: you beat me to it, zerker
Yeah, it might be worth converting all tokens to use the keyword instead of manacost.
Hmm, I'll play around with Dovescape a bit, to see if I can get it working.
EDIT: you beat me to it, zerker

-
DennisBergkamp - AI Programmer
- Posts: 2602
- Joined: 09 Sep 2008, 15:46
- Has thanked: 0 time
- Been thanked: 0 time
Re: Programming a card
by zerker2000 » 05 Dec 2009, 21:14
Wait, didn't we reroute all tokens through a central makeToken code block recently, i.e. we'd need to change ~2 lines instead of 22? Also, considering idea in above edit: could that not be moved to card.addKeyword altogether, or possibly as addComplicatedKeywords()?
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
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: Programming a card
by Marek14 » 05 Dec 2009, 22:36
Don't forget specification of color/creature subtypes.zerker2000 wrote:EDIT: Also, should "Manland P/T:" be a keyword, possibly even accepting keywords like First Strike and Changeling?
BTW, thanks to technical details of layers, animated Mutavault actually doesn't have changeling - it just has all creature types. Adding changeling to an object does nothing (since the abilities are added in later layer than changing of subtypes, so it wouldn't apply anymore).
Re: Programming a card
by zerker2000 » 05 Dec 2009, 23:09
Err, I think it still works in forge
. So would the keyword be "Becomes P/T color Type Creature with keyword:
"?



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
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: Programming a card
by Marek14 » 06 Dec 2009, 06:28
Probably. And, if you add a similar keyword which will use converted mana cost instead of P/T, it will be usable for things like March of the Machines or Opalescence.zerker2000 wrote:Err, I think it still works in forge. So would the keyword be "Becomes P/T color Type Creature with keyword:
![]()
"?
There is one more thing, and that is that there should be a way to do a permanent effect like this - see Stalking Stones or Balduvian Frostwaker.
Re: Programming a card
by zerker2000 » 06 Dec 2009, 18:29
March of the Machines and Opalescence are static effects, though I think someone is working on keywording those as well. For "Becomes", you have a point: maybe "BecomesTillEOT" as the keyword above, and "Becomes" be permanent.
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
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: Programming a card
by Marek14 » 06 Dec 2009, 21:24
There are temporary effects that animate something with P/T equal to CMC as well - Karn's Touch, Karn, Silver Golem, Toymaker, and Xenic Poltergeistzerker2000 wrote:March of the Machines and Opalescence are static effects, though I think someone is working on keywording those as well. For "Becomes", you have a point: maybe "BecomesTillEOT" as the keyword above, and "Becomes" be permanent.
Re: Programming a card
by zerker2000 » 06 Dec 2009, 22:39
Ah yes, I remember Karn being used to blow up moxen and artifact lands.
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
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: Programming a card
by DennisBergkamp » 06 Dec 2009, 22:50
BTW, Triadasoul, what cards did you use to have Dovescape counter abilities?
-
DennisBergkamp - AI Programmer
- Posts: 2602
- Joined: 09 Sep 2008, 15:46
- Has thanked: 0 time
- Been thanked: 0 time
Re: Programming a card
by Triadasoul » 06 Dec 2009, 23:23
- Triadasoul
- Posts: 223
- Joined: 21 Jun 2008, 20:17
- Has thanked: 0 time
- Been thanked: 4 times
Re: Programming a card
by DennisBergkamp » 07 Dec 2009, 04:44
Hm, yeah Dovescape is a tricky fix. I'll keep trying.
Anyway, I did add the token generation block in the actual ability though, what would happen before was the ability would get put on the stack, but at the same time (ability didn't resolve yet) UW birds would be put onto the battlefield.
Anyway, I did add the token generation block in the actual ability though, what would happen before was the ability would get put on the stack, but at the same time (ability didn't resolve yet) UW birds would be put onto the battlefield.
-
DennisBergkamp - AI Programmer
- Posts: 2602
- Joined: 09 Sep 2008, 15:46
- Has thanked: 0 time
- Been thanked: 0 time
Who is online
Users browsing this forum: No registered users and 31 guests