Card Development Questions
Post MTG Forge Related Programming Questions Here
Moderators: timmermac, Blacksmith, KrazyTheFox, Agetian, friarsol, CCGHQ Admins
Re: Card Development Questions
by jeffwadsworth » 31 Oct 2011, 13:51
Take a look at the beloved Revered Unicorn. Note the SVar:TriggeredCard part.moomarc wrote:In the meanwhile I was working on Jotun Owl Keeper. The script should beBut 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.
- 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
- 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 » 31 Oct 2011, 14:05
Nah, just sloppy scripting. SubAbilities need to be DB (Drawbacks) designations.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.I'm guessing SubAbility and Charm don't play nicely.
- 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)![]()
- 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
by 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
-
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
by jeffwadsworth » 31 Oct 2011, 14:23
Slowe, are you going to commit your code and script here?slowe wrote: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: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));
}With that, it's worked in the tests I did.
- 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;
}
- 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
- 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 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. 
Can I use it as a template for scripting similar cards or rather wait until the cumulative upkeep keyword supports alternate costs better?

Can I use it as a template for scripting similar cards or rather wait until the cumulative upkeep keyword supports alternate costs better?
-Marc
-
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
by 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?
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
-
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
by Sloth » 31 Oct 2011, 15:16
If you have two Tombstone Stairwells and one leaves the battlefield all tokens would die.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?

I also have to nit-pick here: The token making of Varchild's War-Riders is a cost, which makes the following differences: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.
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.
We have lots of errors like this. They just happen.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?
-
Sloth - Programmer
- Posts: 3498
- Joined: 23 Jun 2009, 19:40
- Has thanked: 125 times
- Been thanked: 507 times
Re: Card Development Questions
by 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
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
-
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
by friarsol » 31 Oct 2011, 15:49
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.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.
Can I use it as a template for scripting similar cards or rather wait until the cumulative upkeep keyword supports alternate costs better?
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
by friarsol » 31 Oct 2011, 15:59
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.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.
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
by friarsol » 31 Oct 2011, 16:04
Yep, sounds right. There aren't that many cards that reference things they spawn. But these are two of them. (Tetravus is another)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.
- friarsol
- Global Moderator
- Posts: 7593
- Joined: 15 May 2010, 04:20
- Has thanked: 243 times
- Been thanked: 965 times
Re: Card Development Questions
by moomarc » 31 Oct 2011, 16:25
Good point. Consider the idea trashed.Sloth wrote:If you have two Tombstone Stairwells and one leaves the battlefield all tokens would die.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?![]()
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.friarsol wrote: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.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.
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.
Just thought I'd check with the people in the know first.Sloth wrote:We have lots of errors like this. They just happen.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?

Is this implemented yet? If so how do I structure it in the script?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.
Thanks everyone for the help and support!
-Marc
-
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
by Hellfish » 31 Oct 2011, 16:30
Hah, turns out we already have that parameter. No idea when that happened
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
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
-
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
by moomarc » 31 Oct 2011, 16:40
How do I call it in the trigger? Would I use ValidTgts$ Remembered or is there some other syntax?Hellfish wrote:Hah, turns out we already have that parameter. No idea when that happenedMarc, use RememberTokens$ True.
-Marc
-
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
by 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
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
-
Hellfish - Programmer
- Posts: 1297
- Joined: 07 Jun 2009, 10:41
- Location: South of the Pumphouse
- Has thanked: 110 times
- Been thanked: 169 times
Who is online
Users browsing this forum: No registered users and 28 guests