It is currently 31 May 2025, 09:05
   
Text Size

Card Development Questions

Post MTG Forge Related Programming Questions Here

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

Re: Card Development Questions

Postby jeffwadsworth » 29 Oct 2011, 23:11

Looking at Power Conduit in light of Sol's Wandering Mage. Would something like SubCounter<1/Any/Permanent.YouCtrl/a permanent you control> be doable?

Also testing Ghave, Guru of Spores. Its SubCounter<1/P1P1/Creature.YouCtrl/a creature you control> does not let you choose a creature. I take it that AddCounter was the only cost type coded for this?
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

Postby slowe » 29 Oct 2011, 23:56

friarsol wrote:Ah. Well ChosenX is right for the Variable. CMC (as well as power and toughness) just don't use variables in the right manner.

Code: Select all
            if (property.substring(z).equals("X")) {
                x = CardFactoryUtil.xCount(source, source.getSVar("X"));
            } else if (property.substring(z).equals("Y")) {
                x = CardFactoryUtil.xCount(source, source.getSVar("Y"));
            } else {
                x = Integer.parseInt(property.substring(z));
            }
I just worked through all of these Tezzeret scripting issues myself ... wish I'd checked here in the middle. Anyway, I used Hellfish's ValidCard-counters solution to fix the cmc/p/t comparison:
Code: Select all
else if (property.startsWith("power") ||
                property.startsWith("toughness") || property.startsWith("cmc")) {
            int x = 0;
            int y = 0;
            String rhs = "";

            if (property.startsWith("power")) {
                rhs = property.substring(7);
                y = getNetAttack();
            } else if (property.startsWith("toughness")) {
                rhs = property.substring(11);
                y = getNetDefense();
            } else if (property.startsWith("cmc")) {
                 rhs = property.substring(5);
                y = getCMC();
            }
            try {
                x = Integer.parseInt(rhs);
            } catch (NumberFormatException e) {
                x = CardFactoryUtil.xCount(source, source.getSVar(rhs));
            }

            if (!AllZoneUtil.compare(y, property, x)) {
                return false;
            }
With that, it's worked in the tests I did.
script | Open
Name:Tezzeret the Seeker
ManaCost:3 U U
Types:Planeswalker Tezzeret
Text:no text
Loyalty:4
A:AB$ Untap | Cost$ AddCounter<1/LOYALTY> | Planeswalker$ True | ValidTgts$ Artifact | TgtPrompt$ Select target artifact | TargetMin$ 0 | TargetMax$ 2 | SpellDescription$ Untap up to two target artifacts.
A:AB$ ChangeZone | Cost$ SubCounter<X/LOYALTY> | Origin$ Library | Destination$ Battlefield | ChangeType$ Artifact.cmcLEChosenX | ChangeNum$ 1 | Shuffle$ True | Planeswalker$ True | SpellDescription$ Search your library for an artifact with converted mana cost X or less and put it onto the battlefield.
A:AB$ AnimateAll | Cost$ SubCounter<5/LOYALTY> | ValidCards$ Artifact.YouCtrl | Types$ Artifact,Creature | Power$ 5 | Toughness$ 5 | Planeswalker$ True | Ultimate$ True | SpellDescription$ Artifacts you control become 5/5 artifact creatures until end of turn.
#ChosenX SVar created by Cost payment
SVar:X:XChoice
SVar:Rarity:Mythic
SVar:Picture:http://www.wizards.com/global/images/magic/general/tezzeret_the_seeker.jpg
SetInfo:ALA|Mythic|http://magiccards.info/scans/en/ala/60.jpg
Oracle:[+1] Untap up to two target artifacts.\n-X: Search your library for an artifact card with converted mana cost X or less and put it onto the battlefield. Then shuffle your library.\n[-5] Artifacts you control become 5/5 artifact creatures until end of turn.
End
slowe
 
Posts: 127
Joined: 05 Jan 2010, 14:04
Has thanked: 6 times
Been thanked: 10 times

Re: Card Development Questions

Postby jeffwadsworth » 30 Oct 2011, 01:14

Nice work!
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

Postby friarsol » 30 Oct 2011, 03:24

friarsol wrote:
jeffwadsworth wrote:I do not believe that is the correct conditional.

Thus, I think we need your Condition script code here...otherwise the spell does not fire.
I see what the problem is. The same "CheckSVar" parameter is listed in both Conditionals and Restrictions. We'll need to rename the Conditional one to ConditionCheckSVar so it's only checked on resolution, and not checked in both slots. I wonder if there's a bug with cards that use this that you can Activate them when the CheckSVar passes, but don't resolve if the CheckSVar fails during Resolution.
Jeff,
Try out ConditionCheckSVar and ConditionSVarCompare now.
friarsol
Global Moderator
 
Posts: 7593
Joined: 15 May 2010, 04:20
Has thanked: 243 times
Been thanked: 965 times

Re: Card Development Questions

Postby friarsol » 30 Oct 2011, 03:26

jeffwadsworth wrote:Looking at Power Conduit in light of Sol's Wandering Mage. Would something like SubCounter<1/Any/Permanent.YouCtrl/a permanent you control> be doable?

Also testing Ghave, Guru of Spores. Its SubCounter<1/P1P1/Creature.YouCtrl/a creature you control> does not let you choose a creature. I take it that AddCounter was the only cost type coded for this?
Yea SubCounter doesn't quite have that capability yet. I even noted which cards would benefit from adding it:

// Here are the cards that have RemoveCounter<Type>
// Ion Storm, Noviken Sages, Ghave, Guru of Spores, Power Conduit (any
// Counter is tough),
// Quillspike, Rift Elemental, Sage of Fables, Spike Rogue
friarsol
Global Moderator
 
Posts: 7593
Joined: 15 May 2010, 04:20
Has thanked: 243 times
Been thanked: 965 times

Re: Card Development Questions

Postby Iran » 30 Oct 2011, 05:49

friarsol wrote:
jeffwadsworth wrote:Looking at Power Conduit in light of Sol's Wandering Mage. Would something like SubCounter<1/Any/Permanent.YouCtrl/a permanent you control> be doable?

Also testing Ghave, Guru of Spores. Its SubCounter<1/P1P1/Creature.YouCtrl/a creature you control> does not let you choose a creature. I take it that AddCounter was the only cost type coded for this?
Yea SubCounter doesn't quite have that capability yet. I even noted which cards would benefit from adding it:

// Here are the cards that have RemoveCounter<Type>
// Ion Storm, Noviken Sages, Ghave, Guru of Spores, Power Conduit (any
// Counter is tough),
// Quillspike, Rift Elemental, Sage of Fables, Spike Rogue
Others cards that I remember are Fate Transfer, Clockspinning, Jhoira's TimeBug, Dust of Moments

Are the cards Curse of the Cabal, Martyr's Bond and Charmed Pendant scriptable?

thanks
Iran
 
Posts: 251
Joined: 11 Jul 2011, 04:36
Has thanked: 61 times
Been thanked: 4 times

Re: Card Development Questions

Postby friarsol » 30 Oct 2011, 14:06

Iran wrote:Others cards that I remember are Fate Transfer, Clockspinning, Jhoira's TimeBug, Dust of Moments

Are the cards Curse of the Cabal, Martyr's Bond and Charmed Pendant scriptable?

thanks
These aren't the same as they don't remove counters as a cost.
friarsol
Global Moderator
 
Posts: 7593
Joined: 15 May 2010, 04:20
Has thanked: 243 times
Been thanked: 965 times

Re: Card Development Questions

Postby jeffwadsworth » 30 Oct 2011, 23:49

Testing Essence Leak. First the script:

| Open
Name:Essence Leak
ManaCost:U
Types:Enchantment Aura
Text:no text
K:Enchant permanent
A:SP$ Attach | Cost$ U | ValidTgts$ Permanent | AILogic$ Curse
S:Mode$ Continuous | Affected$ Permanent.EnchantedBy+Red,Permanent.EnchantedBy+Green | AddTrigger$ TrigPhase | AddSVar$ TrigSac,X | Description$ As long as enchanted permanent is red or green, it has "At the beginning of your upkeep, sacrifice this permanent unless you pay its mana cost."
SVar:TrigPhase:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | Execute$ TrigSac | TriggerDescription$ At the beginning of your upkeep, sacrifice this permanent unless you pay its mana cost.
SVar:TrigSac:AB$ Sacrifice | Cost$ 0 | Defined$ Self | UnlessCost$ X | UnlessPayer$ You
SVar:X:Count$CardManaCost
SVar:Picture:http://www.wizards.com/global/images/magic/general/essence_leak.jpg
End



I get this error during the upkeep of the enchanted permanent's controller...in this case it is a Deep-Slumber Titan, but it happens on any permanent.

| Open
java.lang.RuntimeException: AbilityFactory : getAbility -- abString too short in Deep-Slumber Titan: []
at forge.card.abilityFactory.AbilityFactory.getMapParams(AbilityFactory.java:217)
at forge.card.abilityFactory.AbilityFactory.getAbility(AbilityFactory.java:268)
at forge.card.trigger.TriggerHandler.runSingleTrigger(TriggerHandler.java:430)
at forge.card.trigger.TriggerHandler.runTrigger(TriggerHandler.java:292)
at forge.Phase.handleBeginPhase(Phase.java:405)
at forge.gui.input.InputControl.updateInput(InputControl.java:184)
at forge.GuiInput.update(GuiInput.java:34)
at java.util.Observable.notifyObservers(Unknown Source)
at java.util.Observable.notifyObservers(Unknown Source)
at forge.MyObservable.updateObservers(MyObservable.java:21)
at forge.Phase.nextPhase(Phase.java:508)
at forge.Phase.nextPhase(Phase.java:511)
at forge.Phase.nextPhase(Phase.java:511)
at forge.GuiDisplay4$33.actionPerformed(GuiDisplay4.java:1141)
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.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$000(Unknown Source)
at java.awt.EventQueue$1.run(Unknown Source)
at java.awt.EventQueue$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$2.run(Unknown Source)
at java.awt.EventQueue$2.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(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

Postby slapshot5 » 31 Oct 2011, 00:12

jeffwadsworth wrote:Testing Essence Leak. First the script:
I don't think Essence Leak can be done right now unless you've got some special code coming with it. You need to pay its mana cost (3 G G for example), not its converted mana cost (5).

-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

Postby jeffwadsworth » 31 Oct 2011, 00:44

Yeah. Overlooked that point.
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

Postby moomarc » 31 Oct 2011, 12:05

I'm trying to code Varchild's War-Riders in my quest to include all types of tokens in Forge. So far I have the following:
Code: Select all
Name:Varchild's War-Riders
ManaCost:1 R
Types:Creature Human Warrior
Text:no text
PT:3/4
K:Trample
K:Rampage 1
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ Put an age counter on CARDNAME.
SVar:TrigPutCounter:AB$PutCounter | Cost$ 0 | Defined$ Self | CounterType$ AGE | CounterNum$ 1
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigCharm | TriggerDescription$ Cumulative upkeep - Put a 1/1 red Survivor creature token onto the battlefield under an opponent's control; or sacrifice CARDNAME unless you pay its upkeep cost for each age counter on it.
SVar:TrigCharm:AB$ Charm | Cost$ 0 | Choices$ TrigToken,DBSacrifice | SpellDescription$ Cumulative upkeep-Pay upkeep cost for each age counter on CARDNAME or sacrifice it.
SVar:TrigToken:DB$Token | Cost$ 0 | TokenAmount$ X | TokenName$ Survivor | TokenTypes$ Creature,Survivor | TokenOwner$ Opponent | TokenColors$ Red | TokenPower$ 1 | TokenToughness$ 1 | SpellDescription$ Put a 1/1 red Survivor creature token onto the battlefield under an opponent's control.
SVar:X:Count$CardCounters.AGE
SVar:DBSacrifice:DB$ Sacrifice | Cost$ 0 | Defined$ Self | SpellDescription$ Sacrifice CARDNAME.
SVar:RemAIDeck:True
SVar:Rarity:Rare
SVar:Picture:http://www.wizards.com/global/images/magic/general/varchilds_war_riders.jpg
SetInfo:ALL|Rare|http://magiccards.info/scans/en/ai/122.jpg
End
It's a bit of a hacked together solution because we don't support non-mana cumulative upkeep costs at the moment. It works well but to get the cumulative upkeep effect working properly it has to have the 2 triggers: 1 to add the age counter and the other a charm-type trigger to either pay the upkeep cost or sacrifice it. The issue I have is that you can select the stack order of the 2 triggers so can essentially buy an extra turn. Is there any way to force a stack order or to have the charm trigger as a sub-ability. I tried but don't know the API well enough.

If I get that working, is there any rules issues that anyone can see? If not there are quite a few cards that could use this template.
Last edited by moomarc on 31 Oct 2011, 12:18, edited 1 time in total.
-Marc
User avatar
moomarc
Pixel Commander
 
Posts: 2091
Joined: 04 Jun 2010, 15:22
Location: Johannesburg, South Africa
Has thanked: 371 times
Been thanked: 372 times

Re: Card Development Questions

Postby slapshot5 » 31 Oct 2011, 12:18

Cumulative upkeep only supports mana costs because it's hard to multiply generic Costs. (At least that's the roadblock I hit when I looked at converting this ages ago). With the new CostParts and all, it may work to just string costs together.

Is something like "2 R Sac<1/Goblin> 2 R Sac<1/Goblin>" prompted and paid for correctly? If so, it should be pretty easy to convert cumulative upkeep to a Cost object. That would be a huge step towards getting Varchild's War-Riders scriptable.

Edit: And maybe it's even simpler than that. Just loop over adding CostParts to a new Cost? Maybe possible? Maybe Sol can chime in on the feasibility. If it's currently feasible, converting cumulative upkeep to Cost object would be a project I'd look into.

-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

Postby friarsol » 31 Oct 2011, 12:31

You could put the Charm first and just repeat the PutCounter each with a different SubAbility. I'm sure this feels clunky, I don't know what support Charm has for being a SubAbility itself.

Code: Select all
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigCumUpkeep | TriggerDescription$ Cumulative Upkeep - Put a 1/1 red Survivor creature token onto the battlefield under an opponent's control.
SVar:TrigCumUpkeep:AB$ Charm | Cost$ 0 | Choices$ TrigAgeSurvivor,TrigAgeSacrifice | CharmNum$ 1
SVar:TrigAgeSurvivor:AB$PutCounter | Cost$ 0 | Defined$ Self | CounterType$ AGE | CounterNum$ 1 | SubAbility$ Survivor
SVar:Survivor:DB$Token | Cost$ 0 | TokenAmount$ X | TokenName$ Survivor | TokenTypes$ Creature,Survivor | TokenOwner$ Opponent | TokenColors$ Red | TokenPower$ 1 | TokenToughness$ 1 | SpellDescription$ Put a 1/1 red Survivor creature token onto the battlefield under an opponent's control.
SVar:X:Count$CardCounters.AGE
SVar:TrigAgeSacrifice:AB$PutCounter | Cost$ 0 | Defined$ Self | CounterType$ AGE | CounterNum$ 1 | SubAbility$ Sacrifice
SVar:Sacrifice:DB$ Sacrifice | Cost$ 0 | Defined$ Self | SpellDescription$ Sacrifice CARDNAME.
friarsol
Global Moderator
 
Posts: 7593
Joined: 15 May 2010, 04:20
Has thanked: 243 times
Been thanked: 965 times

Re: Card Development Questions

Postby friarsol » 31 Oct 2011, 12:45

slapshot5 wrote:Cumulative upkeep only supports mana costs because it's hard to multiply generic Costs. (At least that's the roadblock I hit when I looked at converting this ages ago). With the new CostParts and all, it may work to just string costs together.

Is something like "2 R Sac<1/Goblin> 2 R Sac<1/Goblin>" prompted and paid for correctly? If so, it should be pretty easy to convert cumulative upkeep to a Cost object. That would be a huge step towards getting Varchild's War-Riders scriptable.

Edit: And maybe it's even simpler than that. Just loop over adding CostParts to a new Cost? Maybe possible? Maybe Sol can chime in on the feasibility. If it's currently feasible, converting cumulative upkeep to Cost object would be a project I'd look into.

-slapshot5
The new cost part would handle that, but it might feel weird to pay a Cost separately for each Age Counter. Especially for your example with a mana payment and a Sacrifice, which would then require you to make 2X payments and could easily lead to sacrificing a Llanowar Elf instead of tapping for Green mana.

Probably the best way to handle it would be to add a multiply function that takes a Cost and an integer.

However, this might not really be feasible until a Cost Object can be used in similar places (such as Unless). The Resolution of the Ability basically needs to stop while this payment is going on, but the structure for that isn't really in place yet.

http://cardforge.org/bugz/view.php?id=167
friarsol
Global Moderator
 
Posts: 7593
Joined: 15 May 2010, 04:20
Has thanked: 243 times
Been thanked: 965 times

Re: Card Development Questions

Postby moomarc » 31 Oct 2011, 13:31

Okay, so for now I'll try Sol's suggestion. @friarsol: I tried what you suggested but I'm getting a similar error to what I was getting when trying to make the charm trigger a subability.
Code: Select all
java.lang.ClassCastException: forge.card.abilityFactory.AbilityFactory_Counters$1 cannot be cast to forge.card.spellability.Ability_Sub
   at forge.card.abilityFactory.AbilityFactory_Charm.setupCharmSAs(AbilityFactory_Charm.java:154)
   at forge.card.trigger.TriggerHandler.runSingleTrigger(TriggerHandler.java:444)
   at forge.card.trigger.TriggerHandler.runTrigger(TriggerHandler.java:292)
   at forge.Phase.handleBeginPhase(Phase.java:405)
I'm guessing SubAbility and Charm don't play nicely. :cry:

In the meanwhile I was working on Jotun Owl Keeper. The script should be
Code: Select all
Name:Jotun Owl Keeper
ManaCost:2 W
Types:Creature Giant
Text:no text
PT:3/3
K:Cumulative upkeep:WU
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME dies, put a 1/1 white Bird creature token with flying onto the battlefield for each age counter on it.
SVar:TrigToken:AB$Token | Cost$ 0 | TokenAmount$ X | TokenName$ W 1 1 Bird Flying | TokenTypes$ Creature,Bird | TokenOwner$ You | TokenColors$ White | TokenPower$ 1 | TokenToughness$ 1 | TokenKeywords$ Flying
SVar:X:Count$CardCounters.AGE
SVar:Rarity:Uncommon
SVar:Picture:http://www.wizards.com/global/images/magic/general/jotun_owl_keeper.jpg
SetInfo:CSP|Uncommon|http://magiccards.info/scans/en/cs/9.jpg
End
But the timing is strange. Basically if you sac the owlkeeper instead of paying the upkeep cost, he dies, and only once he's in the graveyard (and hence has no counters left on him) does the trigger fire so no bird tokens are created. Is there a way to make it check the value of X earlier? I tried changing SVar:X:Count$CardCounters.AGE to SVar:X:TriggeredCard$CardCounters.AGE to mimic Grief Tyrant, but that didn't help (in fact further testing shows Grief Tyrant to have the same problem). Any help would be appreciated.
-Marc
User avatar
moomarc
Pixel Commander
 
Posts: 2091
Joined: 04 Jun 2010, 15:22
Location: Johannesburg, South Africa
Has thanked: 371 times
Been thanked: 372 times

PreviousNext

Return to Developer's Corner

Who is online

Users browsing this forum: No registered users and 26 guests


Who is online

In total there are 26 users online :: 0 registered, 0 hidden and 26 guests (based on users active over the past 10 minutes)
Most users ever online was 4143 on 23 Jan 2024, 08:21

Users browsing this forum: No registered users and 26 guests

Login Form