Page 68 of 141

Re: Card Development Questions

PostPosted: 31 Oct 2011, 13:51
by jeffwadsworth
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.

Re: Card Development Questions

PostPosted: 31 Oct 2011, 14:05
by friarsol
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.

Re: Card Development Questions

PostPosted: 31 Oct 2011, 14:22
by moomarc
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?

Re: Card Development Questions

PostPosted: 31 Oct 2011, 14:23
by jeffwadsworth
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?

Re: Card Development Questions

PostPosted: 31 Oct 2011, 14:38
by moomarc
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?

Re: Card Development Questions

PostPosted: 31 Oct 2011, 14:55
by moomarc
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?

Re: Card Development Questions

PostPosted: 31 Oct 2011, 15:16
by Sloth
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.

Re: Card Development Questions

PostPosted: 31 Oct 2011, 15:26
by Hellfish
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.

Re: Card Development Questions

PostPosted: 31 Oct 2011, 15:49
by friarsol
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.

Re: Card Development Questions

PostPosted: 31 Oct 2011, 15:59
by friarsol
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.

Re: Card Development Questions

PostPosted: 31 Oct 2011, 16:04
by friarsol
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)

Re: Card Development Questions

PostPosted: 31 Oct 2011, 16:25
by moomarc
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!

Re: Card Development Questions

PostPosted: 31 Oct 2011, 16:30
by Hellfish
Hah, turns out we already have that parameter. No idea when that happened :lol: Marc, use RememberTokens$ True. :)

Re: Card Development Questions

PostPosted: 31 Oct 2011, 16:40
by moomarc
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?

Re: Card Development Questions

PostPosted: 31 Oct 2011, 16:54
by Hellfish
IsRemembered will match cards that are in the host cards remembered list.