Card Development Questions
Post MTG Forge Related Programming Questions Here
Moderators: timmermac, Blacksmith, KrazyTheFox, Agetian, friarsol, CCGHQ Admins
Re: Card Development Questions
by friarsol » 11 Jun 2011, 02:58
Are you sure about that? It doesn't have the same wording as Unearth does.jeffwadsworth wrote:Now this works fine, but to be 100%, the chosen dragon permanent must be exiled from anywhere, not just the battlefield. If Any is used, it just fizzles. Perhaps there is another way that doesn't require silly hacky SubAbilities that check every zone?
- friarsol
- Global Moderator
- Posts: 7593
- Joined: 15 May 2010, 04:20
- Has thanked: 243 times
- Been thanked: 965 times
Re: Card Development Questions
by jeffwadsworth » 11 Jun 2011, 04:00
well, i will add and see what happens.friarsol wrote:Are you sure about that? It doesn't have the same wording as Unearth does.jeffwadsworth wrote:Now this works fine, but to be 100%, the chosen dragon permanent must be exiled from anywhere, not just the battlefield. If Any is used, it just fizzles. Perhaps there is another way that doesn't require silly hacky SubAbilities that check every zone?
- jeffwadsworth
- Super Tester Elite
- Posts: 1172
- Joined: 20 Oct 2010, 04:47
- Location: USA
- Has thanked: 287 times
- Been thanked: 70 times
Re: Card Development Questions
by Sloth » 11 Jun 2011, 07:58
I think what sol meant is that it is correct ruleswise that the dragon permanent doesn't get exiled from anywhere but the battlefield. And I agree.jeffwadsworth wrote:well, i will add and see what happens.friarsol wrote:Are you sure about that? It doesn't have the same wording as Unearth does.jeffwadsworth wrote:Now this works fine, but to be 100%, the chosen dragon permanent must be exiled from anywhere, not just the battlefield. If Any is used, it just fizzles. Perhaps there is another way that doesn't require silly hacky SubAbilities that check every zone?
-
Sloth - Programmer
- Posts: 3498
- Joined: 23 Jun 2009, 19:40
- Has thanked: 125 times
- Been thanked: 507 times
Re: Card Development Questions
by friarsol » 11 Jun 2011, 13:03
Good thing Sloth is here to translate for meSloth wrote:I think what sol meant is that it is correct ruleswise that the dragon permanent doesn't get exiled from anywhere but the battlefield. And I agree.

- friarsol
- Global Moderator
- Posts: 7593
- Joined: 15 May 2010, 04:20
- Has thanked: 243 times
- Been thanked: 965 times
Re: Card Development Questions
by Starcrash » 15 Jun 2011, 03:00
I'm having a hard time getting Forge to recognize the various "pulse" conditions for the various pulse spells from Darksteel. For instance, I tried this with Pulse of the Fields (the white life-gaining spell)
A:SP$ GainLife | Cost$ 1 W W | Defined$ You | LifeAmount$ 4 | SubAbility$ SVar=TrigReturn | SpellDescription$ You gain 4 life. Then if an opponent has more life than you, return CARDNAME to its owner's hand.
SVar:TrigReturn:DB$ ChangeZone | ConditionPresent$ X | ConditionCompare$ LTY | Defined$ Self | Origin$ Stack | Destination$ Hand | ConditionDescription$ If an opponent has more life than you,
SVar:X:Count$YourLifeTotal
SVar:Y:Count$OppLifeTotal
The program completely ignores the condition and instead gives back Pulse of the Fields every time. I tried IsPresent$ instead (and even LifeAmount$, though I'm pretty certain that's trigger-only), and got the same outcome - no matter what I set as the conditions, they just get ignored. Is this why Pulse of the Tangle doesn't have code in the card itself? Are these cards - seemingly easy to code - still uncodeable?
A:SP$ GainLife | Cost$ 1 W W | Defined$ You | LifeAmount$ 4 | SubAbility$ SVar=TrigReturn | SpellDescription$ You gain 4 life. Then if an opponent has more life than you, return CARDNAME to its owner's hand.
SVar:TrigReturn:DB$ ChangeZone | ConditionPresent$ X | ConditionCompare$ LTY | Defined$ Self | Origin$ Stack | Destination$ Hand | ConditionDescription$ If an opponent has more life than you,
SVar:X:Count$YourLifeTotal
SVar:Y:Count$OppLifeTotal
The program completely ignores the condition and instead gives back Pulse of the Fields every time. I tried IsPresent$ instead (and even LifeAmount$, though I'm pretty certain that's trigger-only), and got the same outcome - no matter what I set as the conditions, they just get ignored. Is this why Pulse of the Tangle doesn't have code in the card itself? Are these cards - seemingly easy to code - still uncodeable?
Re: Card Development Questions
by jeffwadsworth » 15 Jun 2011, 03:49
Catacomb Dragon script:
During the declare blockers step it produces a NPE.
- | Open
- Name:Catacomb Dragon
ManaCost:4 B B
Types:Creature Dragon
Text:no text
PT:4/4
K:Flying
T:Mode$ AttackerBlocked | ValidCard$ Card.Self | ValidBlocker$ Creature.nonArtifact+nonDragon | TriggerZones$ Battlefield | Execute$ TrigPump | TriggerDescription$ Whenever CARDNAME becomes blocked by a nonartifact, non-Dragon creature, that creature gets -X/-0 until end of turn, where X is half the creature's power, rounded down.
SVar:TrigPump:AB$Pump | Cost$ 0 | Defined$ TriggeredBlocker | NumAtt$ -X
SVar:X:TriggeredBlocker$CardPower/HalfDown
SVar:Rarity:Rare
SVar:Picture:http://www.wizards.com/global/images/magic/general/catacomb_dragon.jpg
End
During the declare blockers step it produces a NPE.
- | Open
- An error has occurred. You can copy/paste this message or save it to a file.
Please report this, plus what you tried to do, to:
viewforum.php?f=26
If you don't want to register an account, you can mail it directly to
mtgerror@yahoo.com
null
Version:
Forge -- official beta: $Date: 2011-01-06 10:34:48 -0600 (Thu, 06 Jan 2011) $, SVN revision: $Revision: 4891 $
OS: Windows 7 Version: 6.1 Architecture: amd64
Java Version: 1.6.0_22 Vendor: Sun Microsystems Inc.
Detailed error trace:
java.lang.NullPointerException
at forge.card.abilityFactory.AbilityFactory.getDefinedCards(AbilityFactory.java:1043)
at forge.CombatUtil.predictPowerBonusOfBlocker(CombatUtil.java:921)
at forge.CombatUtil.canDestroyBlocker(CombatUtil.java:1177)
at forge.ComputerUtil_Block2.getSafeBlockers(ComputerUtil_Block2.java:35)
at forge.ComputerUtil_Block2.makeGoodBlocks(ComputerUtil_Block2.java:106)
at forge.ComputerUtil_Block2.getBlockers(ComputerUtil_Block2.java:402)
at forge.ComputerAI_General.declare_blockers(ComputerAI_General.java:284)
at forge.gui.input.InputControl.updateInput(InputControl.java:116)
at forge.gui.input.InputControl.updateInput(InputControl.java:98)
at forge.GuiInput.update(GuiInput.java:21)
at java.util.Observable.notifyObservers(Unknown Source)
at java.util.Observable.notifyObservers(Unknown Source)
at forge.MyObservable.updateObservers(MyObservable.java:9)
at forge.Phase.nextPhase(Phase.java:374)
at forge.GuiDisplay3$27.actionPerformed(GuiDisplay3.java:781)
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.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(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.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(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)
- jeffwadsworth
- Super Tester Elite
- Posts: 1172
- Joined: 20 Oct 2010, 04:47
- Location: USA
- Has thanked: 287 times
- Been thanked: 70 times
Re: Card Development Questions
by friarsol » 15 Jun 2011, 04:11
Ugh. Looks like getDefined is sending in null in CombatUtil.predictPowerBonusOfBlocker for the SpellAbility which is needed to get the Triggered card.
- friarsol
- Global Moderator
- Posts: 7593
- Joined: 15 May 2010, 04:20
- Has thanked: 243 times
- Been thanked: 965 times
Re: Card Development Questions
by slapshot5 » 15 Jun 2011, 05:07
Investigation notes: predictPowerBonusOfBlocker passes in null for the sa. When getting Defined, it sees "Triggered" which calls sa.getTriggeringObject() and Bam! NPE.jeffwadsworth wrote:Catacomb Dragon script:
- | Open
- Name:Catacomb Dragon
ManaCost:4 B B
Types:Creature Dragon
Text:no text
PT:4/4
K:Flying
T:Mode$ AttackerBlocked | ValidCard$ Card.Self | ValidBlocker$ Creature.nonArtifact+nonDragon | TriggerZones$ Battlefield | Execute$ TrigPump | TriggerDescription$ Whenever CARDNAME becomes blocked by a nonartifact, non-Dragon creature, that creature gets -X/-0 until end of turn, where X is half the creature's power, rounded down.
SVar:TrigPump:AB$Pump | Cost$ 0 | Defined$ TriggeredBlocker | NumAtt$ -X
SVar:X:TriggeredBlocker$CardPower/HalfDown
SVar:Rarity:Rare
SVar:Picture:http://www.wizards.com/global/images/magic/general/catacomb_dragon.jpg
End
During the declare blockers step it produces a NPE.
- | Open
- An error has occurred. You can copy/paste this message or save it to a file.
Please report this, plus what you tried to do, to:
viewforum.php?f=26
If you don't want to register an account, you can mail it directly to
mtgerror@yahoo.com
null
Version:
Forge -- official beta: $Date: 2011-01-06 10:34:48 -0600 (Thu, 06 Jan 2011) $, SVN revision: $Revision: 4891 $
OS: Windows 7 Version: 6.1 Architecture: amd64
Java Version: 1.6.0_22 Vendor: Sun Microsystems Inc.
Detailed error trace:
java.lang.NullPointerException
at forge.card.abilityFactory.AbilityFactory.getDefinedCards(AbilityFactory.java:1043)
at forge.CombatUtil.predictPowerBonusOfBlocker(CombatUtil.java:921)
at forge.CombatUtil.canDestroyBlocker(CombatUtil.java:1177)
at forge.ComputerUtil_Block2.getSafeBlockers(ComputerUtil_Block2.java:35)
at forge.ComputerUtil_Block2.makeGoodBlocks(ComputerUtil_Block2.java:106)
at forge.ComputerUtil_Block2.getBlockers(ComputerUtil_Block2.java:402)
at forge.ComputerAI_General.declare_blockers(ComputerAI_General.java:284)
at forge.gui.input.InputControl.updateInput(InputControl.java:116)
at forge.gui.input.InputControl.updateInput(InputControl.java:98)
at forge.GuiInput.update(GuiInput.java:21)
at java.util.Observable.notifyObservers(Unknown Source)
at java.util.Observable.notifyObservers(Unknown Source)
at forge.MyObservable.updateObservers(MyObservable.java:9)
at forge.Phase.nextPhase(Phase.java:374)
at forge.GuiDisplay3$27.actionPerformed(GuiDisplay3.java:781)
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.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(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.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(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)
-slapshot5
- slapshot5
- Programmer
- Posts: 1391
- Joined: 03 Jan 2010, 17:47
- Location: Mac OS X
- Has thanked: 25 times
- Been thanked: 68 times
Re: Card Development Questions
by Sloth » 15 Jun 2011, 08:03
ConditionPresent counts the number of cards on the battlefield that match the given restrictions, nothing more. It would need some extra coding.Starcrash wrote:I'm having a hard time getting Forge to recognize the various "pulse" conditions for the various pulse spells from Darksteel. For instance, I tried this with Pulse of the Fields (the white life-gaining spell)
A:SP$ GainLife | Cost$ 1 W W | Defined$ You | LifeAmount$ 4 | SubAbility$ SVar=TrigReturn | SpellDescription$ You gain 4 life. Then if an opponent has more life than you, return CARDNAME to its owner's hand.
SVar:TrigReturn:DB$ ChangeZone | ConditionPresent$ X | ConditionCompare$ LTY | Defined$ Self | Origin$ Stack | Destination$ Hand | ConditionDescription$ If an opponent has more life than you,
SVar:X:Count$YourLifeTotal
SVar:Y:Count$OppLifeTotal
The program completely ignores the condition and instead gives back Pulse of the Fields every time. I tried IsPresent$ instead (and even LifeAmount$, though I'm pretty certain that's trigger-only), and got the same outcome - no matter what I set as the conditions, they just get ignored. Is this why Pulse of the Tangle doesn't have code in the card itself? Are these cards - seemingly easy to code - still uncodeable?
-
Sloth - Programmer
- Posts: 3498
- Joined: 23 Jun 2009, 19:40
- Has thanked: 125 times
- Been thanked: 507 times
Re: Card Development Questions
by slapshot5 » 15 Jun 2011, 13:15
Ok, I was just thinking about this very thing, then I read this post. I guess that means I should just get to it, huh? I'll take a look at making this doable.Sloth wrote:ConditionPresent counts the number of cards on the battlefield that match the given restrictions, nothing more. It would need some extra coding.Starcrash wrote:I'm having a hard time getting Forge to recognize the various "pulse" conditions for the various pulse spells from Darksteel. For instance, I tried this with Pulse of the Fields (the white life-gaining spell)
A:SP$ GainLife | Cost$ 1 W W | Defined$ You | LifeAmount$ 4 | SubAbility$ SVar=TrigReturn | SpellDescription$ You gain 4 life. Then if an opponent has more life than you, return CARDNAME to its owner's hand.
SVar:TrigReturn:DB$ ChangeZone | ConditionPresent$ X | ConditionCompare$ LTY | Defined$ Self | Origin$ Stack | Destination$ Hand | ConditionDescription$ If an opponent has more life than you,
SVar:X:Count$YourLifeTotal
SVar:Y:Count$OppLifeTotal
The program completely ignores the condition and instead gives back Pulse of the Fields every time. I tried IsPresent$ instead (and even LifeAmount$, though I'm pretty certain that's trigger-only), and got the same outcome - no matter what I set as the conditions, they just get ignored. Is this why Pulse of the Tangle doesn't have code in the card itself? Are these cards - seemingly easy to code - still uncodeable?
-slapshot5
- slapshot5
- Programmer
- Posts: 1391
- Joined: 03 Jan 2010, 17:47
- Location: Mac OS X
- Has thanked: 25 times
- Been thanked: 68 times
Re: Card Development Questions
by slapshot5 » 15 Jun 2011, 18:53
Ok, after I check in my rework of the conditions stuff, you'll do it like this:slapshot5 wrote:Ok, I was just thinking about this very thing, then I read this post. I guess that means I should just get to it, huh? I'll take a look at making this doable.Sloth wrote:ConditionPresent counts the number of cards on the battlefield that match the given restrictions, nothing more. It would need some extra coding.Starcrash wrote:I'm having a hard time getting Forge to recognize the various "pulse" conditions for the various pulse spells from Darksteel. For instance, I tried this with Pulse of the Fields (the white life-gaining spell)
A:SP$ GainLife | Cost$ 1 W W | Defined$ You | LifeAmount$ 4 | SubAbility$ SVar=TrigReturn | SpellDescription$ You gain 4 life. Then if an opponent has more life than you, return CARDNAME to its owner's hand.
SVar:TrigReturn:DB$ ChangeZone | ConditionPresent$ X | ConditionCompare$ LTY | Defined$ Self | Origin$ Stack | Destination$ Hand | ConditionDescription$ If an opponent has more life than you,
SVar:X:Count$YourLifeTotal
SVar:Y:Count$OppLifeTotal
The program completely ignores the condition and instead gives back Pulse of the Fields every time. I tried IsPresent$ instead (and even LifeAmount$, though I'm pretty certain that's trigger-only), and got the same outcome - no matter what I set as the conditions, they just get ignored. Is this why Pulse of the Tangle doesn't have code in the card itself? Are these cards - seemingly easy to code - still uncodeable?
-slapshot5
- Code: Select all
A:SP$ GainLife | Cost$ 1 W W | Defined$ You | LifeAmount$ 4 | SubAbility$ SVar=TrigReturn | SpellDescription$ You gain 4 life. Then if an opponent has more life than you, return CARDNAME to its owner's hand.
SVar:TrigReturn:DB$ ChangeZone | ConditionLifeTotal$ You | ConditionLifeAmount$ LTX | Defined$ Self | Origin$ Stack | Destination$ Hand | ConditionDescription$ If an opponent has more life than you,
SVar:X:Count$OppLifeTotal
- slapshot5
- Programmer
- Posts: 1391
- Joined: 03 Jan 2010, 17:47
- Location: Mac OS X
- Has thanked: 25 times
- Been thanked: 68 times
Re: Card Development Questions
by slapshot5 » 16 Jun 2011, 14:08
Just saw this. Yes, this is now implemented.jeffwadsworth wrote:CopyPermanent. Any plans to include an option to make multiple copies like tokenamount$?
- slapshot5
- Programmer
- Posts: 1391
- Joined: 03 Jan 2010, 17:47
- Location: Mac OS X
- Has thanked: 25 times
- Been thanked: 68 times
Re: Card Development Questions
by jeffwadsworth » 16 Jun 2011, 16:53
Fantastic...now if I could just remember what card required it.slapshot5 wrote:Just saw this. Yes, this is now implemented.jeffwadsworth wrote:CopyPermanent. Any plans to include an option to make multiple copies like tokenamount$?

- jeffwadsworth
- Super Tester Elite
- Posts: 1172
- Joined: 20 Oct 2010, 04:47
- Location: USA
- Has thanked: 287 times
- Been thanked: 70 times
Re: Card Development Questions
by friarsol » 16 Jun 2011, 17:15
Rite of Replication? Which was already converted.jeffwadsworth wrote:Fantastic...now if I could just remember what card required it.slapshot5 wrote:Just saw this. Yes, this is now implemented.jeffwadsworth wrote:CopyPermanent. Any plans to include an option to make multiple copies like tokenamount$?
- friarsol
- Global Moderator
- Posts: 7593
- Joined: 15 May 2010, 04:20
- Has thanked: 243 times
- Been thanked: 965 times
Re: Card Development Questions
by jeffwadsworth » 16 Jun 2011, 21:23
Clockwork Hydra script:
The counter is not being removed even though the trigger fires.
- | Open
- Name:Clockwork Hydra
ManaCost:5
Types:Artifact Creature Hydra
Text:no text
K:etbCounter:P1P1:4
A:AB$ PutCounter | Cost$ T | CounterType$ P1P1 | CounterNum$ 1 | SpellDescription$ Put a +1/+1 counter on CARDNAME.
T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigRemoveCounter | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME attacks or blocks, remove a +1/+1 counter from it. If you do, CARDNAME deals 1 damage to target creature or player.
T:Mode$ Blocks | ValidCard$ Card.Self | Execute$ TrigRemoveCounter | TriggerZones$ Battlefield | Secondary$ True | TriggerDescription$ Whenever CARDNAME attacks or blocks, remove a +1/+1 counter from it. If you do, CARDNAME deals 1 damage to target creature or player.
SVar:TrigRemoveCounter:AB$RemoveCounter | Cost$ 0 | CounterType$ P1P1 | CounterNum$ 1 | SubAbility$ DBDamage
SVar:DBDamage:DB$DealDamage | Tgt$ TgtCP | NumDmg$ 1
SVar:Rarity:Uncommon
SVar:Picture:http://www.wizards.com/global/images/magic/general/clockwork_hydra.jpg
End
The counter is not being removed even though the trigger fires.
- jeffwadsworth
- Super Tester Elite
- Posts: 1172
- Joined: 20 Oct 2010, 04:47
- Location: USA
- Has thanked: 287 times
- Been thanked: 70 times
Who is online
Users browsing this forum: No registered users and 36 guests