It is currently 31 May 2025, 09:29
   
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 » 31 Oct 2011, 13:51

moomarc wrote: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.
Take a look at the beloved Revered Unicorn. Note the SVar:TriggeredCard part.
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 » 31 Oct 2011, 14:05

moomarc wrote: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:
Nah, just sloppy scripting. SubAbilities need to be DB (Drawbacks) designations.

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:DB$PutCounter | Defined$ Self | CounterType$ AGE | CounterNum$ 1 | SubAbility$ Survivor
SVar:Survivor:DB$Token | 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:DB$PutCounter | Defined$ Self | CounterType$ AGE | CounterNum$ 1 | SubAbility$ Sacrifice
SVar:Sacrifice:DB$ Sacrifice | 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 moomarc » 31 Oct 2011, 14:22

Thanks Jeff. As per my initial comment, I had already tried adding SVar:TriggeredCard to no avail. But I realised one difference was that I had also copied the TriggerZones$ Battlefield. As soon as I removed this and added the TriggeredCard back, it worked perfectly. Removing it from Grief Tyrrant also fixed him. Before I commit, does anyone have any idea why it was there in the first place?
-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 jeffwadsworth » 31 Oct 2011, 14:23

slowe wrote:
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, are you going to commit your code and script here?
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, 14:38

And Thanks Sol. I'm getting the hang of scripting so should notice things like that and correct on the fly. It works perfectly now. :D

Can I use it as a template for scripting similar cards or rather wait until the cumulative upkeep keyword supports alternate costs better?
-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 moomarc » 31 Oct 2011, 14:55

Do we have any way to track which card put a token into play? If so then I can try tackle Saproling Burst and Tombstone Stairwell.

Edit: With Tombstone Stairwell would it be fine to cheat a little. No other card creates tokens named Tombspawn and we don't have any cards that change the name of permanents, so could we just destroy tokens named Tombspawn?
-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 Sloth » 31 Oct 2011, 15:16

moomarc wrote:Edit: With Tombstone Stairwell would it be fine to cheat a little. No other card creates tokens named Tombspawn and we don't have any cards that change the name of permanents, so could we just destroy tokens named Tombspawn?
If you have two Tombstone Stairwells and one leaves the battlefield all tokens would die. [-X

moomarc wrote:And Thanks Sol. I'm getting the hang of scripting so should notice things like that and correct on the fly. It works perfectly now. :D
I also have to nit-pick here: The token making of Varchild's War-Riders is a cost, which makes the following differences:
1. It can't be Stifle d.
2. It won't be affected by Doubling Season.

I won't be upset if Varchild's War-Riders stays like this, but wanted to point it out.

moomarc wrote:As soon as I removed this and added the TriggeredCard back, it worked perfectly. Removing it from Grief Tyrrant also fixed him. Before I commit, does anyone have any idea why it was there in the first place?
We have lots of errors like this. They just happen.
User avatar
Sloth
Programmer
 
Posts: 3498
Joined: 23 Jun 2009, 19:40
Has thanked: 125 times
Been thanked: 507 times

Re: Card Development Questions

Postby Hellfish » 31 Oct 2011, 15:26

For Tombstone Stairwell and Saproling Burst, a RememberToken parameter in AF_Token could work, couldn't it? It would add all created tokens to the host cards remembered list.
So now you're
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
User avatar
Hellfish
Programmer
 
Posts: 1297
Joined: 07 Jun 2009, 10:41
Location: South of the Pumphouse
Has thanked: 110 times
Been thanked: 169 times

Re: Card Development Questions

Postby friarsol » 31 Oct 2011, 15:49

moomarc wrote:And Thanks Sol. I'm getting the hang of scripting so should notice things like that and correct on the fly. It works perfectly now. :D

Can I use it as a template for scripting similar cards or rather wait until the cumulative upkeep keyword supports alternate costs better?
No problem. How else are you going to learn if you are interested in doing it? A lot of times it's more about problem solving then scripting in a straight line. Or asking for a specific feature to be added.

I think it's ok as a template for non-standard Costs (such as Braid of Fire which is currently hardcoded). But I'd prefer to wait on the Standardized Costs.
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, 15:59

Sloth wrote:I also have to nit-pick here: The token making of Varchild's War-Riders is a cost, which makes the following differences:
1. It can't be Stifle d.
2. It won't be affected by Doubling Season.

I won't be upset if Varchild's War-Riders stays like this, but wanted to point it out.
1. While technically correct, the Cumulative Upkeep trigger could be targeted by Stifle which is how this would work out. No age counter, no Survivor.
2. That's a small, yet valid concern. We might be able to add a small bit of code to ignore Doubling Season in this case, just like we do in CostPutCounter.
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, 16:04

Hellfish wrote:For Tombstone Stairwell and Saproling Burst, a RememberToken parameter in AF_Token could work, couldn't it? It would add all created tokens to the host cards remembered list.
Yep, sounds right. There aren't that many cards that reference things they spawn. But these are two of them. (Tetravus is another)
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, 16:25

Sloth wrote:
moomarc wrote:Edit: With Tombstone Stairwell would it be fine to cheat a little. No other card creates tokens named Tombspawn and we don't have any cards that change the name of permanents, so could we just destroy tokens named Tombspawn?
If you have two Tombstone Stairwells and one leaves the battlefield all tokens would die. [-X
Good point. Consider the idea trashed.

friarsol wrote:
Sloth wrote:I also have to nit-pick here: The token making of Varchild's War-Riders is a cost, which makes the following differences:
1. It can't be Stifle d.
2. It won't be affected by Doubling Season.

I won't be upset if Varchild's War-Riders stays like this, but wanted to point it out.
1. While technically correct, the Cumulative Upkeep trigger could be targeted by Stifle which is how this would work out. No age counter, no Survivor.
2. That's a small, yet valid concern. We might be able to add a small bit of code to ignore Doubling Season in this case, just like we do in CostPutCounter.
I'd considered those but obviously my comprehensive rules knowledge is a little lacking. I had interpreted Doubling Season's "when an effect puts...into play" as accepting the upkeep cost as an effect much the same way as something tapping for mana would trigger an effect looking for "when such-and-such becomes tapped". With Stifle, I saw it much the same as Sol(I just didn't know it wasn't technically correct). I'll try keep a closer eye out for fringe-cases like this in future.

Sloth wrote:
moomarc wrote:As soon as I removed this and added the TriggeredCard back, it worked perfectly. Removing it from Grief Tyrrant also fixed him. Before I commit, does anyone have any idea why it was there in the first place?
We have lots of errors like this. They just happen.
Just thought I'd check with the people in the know first. :wink: Fix committed.

Hellfish wrote:For Tombstone Stairwell and Saproling Burst, a RememberToken parameter in AF_Token could work, couldn't it? It would add all created tokens to the host cards remembered list.
Is this implemented yet? If so how do I structure it in the script?

Thanks everyone for the help and support!
-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 Hellfish » 31 Oct 2011, 16:30

Hah, turns out we already have that parameter. No idea when that happened :lol: Marc, use RememberTokens$ True. :)
So now you're
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
User avatar
Hellfish
Programmer
 
Posts: 1297
Joined: 07 Jun 2009, 10:41
Location: South of the Pumphouse
Has thanked: 110 times
Been thanked: 169 times

Re: Card Development Questions

Postby moomarc » 31 Oct 2011, 16:40

Hellfish wrote:Hah, turns out we already have that parameter. No idea when that happened :lol: Marc, use RememberTokens$ True. :)
How do I call it in the trigger? Would I use ValidTgts$ Remembered or is there some other syntax?
-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 Hellfish » 31 Oct 2011, 16:54

IsRemembered will match cards that are in the host cards remembered list.
So now you're
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
User avatar
Hellfish
Programmer
 
Posts: 1297
Joined: 07 Jun 2009, 10:41
Location: South of the Pumphouse
Has thanked: 110 times
Been thanked: 169 times

PreviousNext

Return to Developer's Corner

Who is online

Users browsing this forum: No registered users and 28 guests


Who is online

In total there are 28 users online :: 0 registered, 0 hidden and 28 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 28 guests

Login Form