It is currently 31 Oct 2025, 09:04
   
Text Size

If you cast it any time a sorcery couldn't have been cast

Post MTG Forge Related Programming Questions Here

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

If you cast it any time a sorcery couldn't have been cast

Postby moomarc » 20 Sep 2012, 09:52

I'm trying to add a macro for "You may cast CARDNAME as though it had flash. If you cast it any time a sorcery couldn't have been cast, the controller of the permanent it becomes sacrifices it at the beginning of the next cleanup step." I've got everything set up and working except for one thing that may not be broken depending on the ruling.

Is this a static trigger on the stack? I can't seem to find anything about this anywhere but I'm assuming it must be seeing as the templating is similar to Evoke.

Rundown of what I've got so far:
- The spell can be cast as though it has flash, but doesn't actually have it.
- I've set up a SpellCast trigger condition that checks whether it was cast at any time a sorcery couldn't be cast. This is where the issue lies. It works perfectly if the trigger doesn't have a Static$ True param. But if it does the animate has no effect (even if the conditions are removed, so I know the problem isn't there).
- If cast at instant speed, an Animate AF adds the sacrifice self.

Script and code additions | Open
The script created by the macro is this:
Code: Select all
T:Mode$ SpellCast | ValidCard$ Card.Self | Execute$ TrigDelayedSac | SpellSpeed$ NotSorcerySpeed | TriggerDescription$ Test    <<<Static$ True here causes problem
SVar:TrigDelayedSac:AB$ Animate | Cost$ 0 | Defined$ Self | Triggers$ CleanupTrig | sVars$ Sac | Permanent$ True
SVar:CleanupTrig:Mode$ Phase | Phase$ Cleanup | TriggerZones$ Battlefield | Execute$ Sac | TriggerDescription$ At the beginning of the next cleanup step, sacrifice CARDNAME.
SVar:Sac:AB$ Sacrifice | Cost$ 0 | Defined$ Self
This code added to TriggerSpellAbilityCast:
Code: Select all
        if (this.getMapParams().containsKey("SpellSpeed")) {
            if (this.getMapParams().get("SpellSpeed").equals("NotSorcerySpeed")
                    && PhaseHandler.couldCastSorcery(this.getHostCard().getController(), spellAbility)) {
                return false;
            }
        }
And this added to PhaseHandler (imports SpellAbility):
Code: Select all
    public static boolean couldCastSorcery(final Player player, final SpellAbility sa) {
        PhaseHandler now = Singletons.getModel().getGameState().getPhaseHandler();
        final Card source = sa.getRootSpellAbility().getSourceCard();
        if (AllZone.getStack().size() != 0) {
            for (final Card card : AllZoneUtil.getCardsIn(ZoneType.Stack)) {
                if (card != source) {
                    return false;
                }
            }
        }
        return now.isPlayerTurn(player) && now.getPhase().isMain();
    }
-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: If you cast it any time a sorcery couldn't have been cas

Postby moomarc » 20 Sep 2012, 14:08

I think this whole concept has to be scrapped anyway. In the current form it wouldn't interact properly with Vedalken Orrey according to the rulings. Not quite sure how it could be achieved. Only way I can think of is that if this keyword is present, make a duplicate of the sa, but it has to have the timing restriction NotSorcerySpeed and the casting restriction that the card does not have Flash (or HIDDEN Flash).

I'll see if I can work it out and get it working.

EDIT: This is beyond my skills it seems. First attempt was waaay more successful and I realized I can just check for flash there anyway. So I just need to get past the problem with the animate not working off of the static trigger. Does anyone have any clues, tips or tricks?
-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: If you cast it any time a sorcery couldn't have been cas

Postby Sloth » 20 Sep 2012, 16:16

My guess:
The static trigger will animate the card while it is still on the stack and the information gets lost once it hits play. A non-static trigger will trigger after the spell resolves (and the permanent is in play already).

Solution:
Maybe use an effect?
User avatar
Sloth
Programmer
 
Posts: 3498
Joined: 23 Jun 2009, 19:40
Has thanked: 125 times
Been thanked: 507 times

Re: If you cast it any time a sorcery couldn't have been cas

Postby friarsol » 20 Sep 2012, 16:34

I think I did something similar to this ability for Suspend, since a permanent cast via Suspend gains haste until it changes controllers (or leaves the battlefield). I don't think my solution was all that great, so maybe using an Effect will work out a little better.
friarsol
Global Moderator
 
Posts: 7593
Joined: 15 May 2010, 04:20
Has thanked: 243 times
Been thanked: 965 times

Re: If you cast it any time a sorcery couldn't have been cas

Postby moomarc » 21 Sep 2012, 07:08

Sloth wrote:My guess:
The static trigger will animate the card while it is still on the stack and the information gets lost once it hits play. A non-static trigger will trigger after the spell resolves (and the permanent is in play already).

Solution:
Maybe use an effect?
Animating the card while it's still on the stack isn't the problem - it does that anyway on my one test card (Armor of Thorns). Without the static trigger it animates the card on the stack perfectly and with the Permanent flag it carries through onto the battlefield just fine. So I'm guessing it's trying to animate it before it leaves the hand or wherever it's being cast from.

On the bright side I have everything interacting properly with Vedalken Orrey and other cards that might give it Flash (although there might still be one or two cases I've missed, I'm not sure of all the keywords that might let it be cast at instant speed).

Anyway, I'll give the Effect method a quick try. Will just have to think of some smart way to cover the spell being countered so that the effect isn't lying around. I don't think I can cover all situations but Exiling the effect if the card is moved from Stack to Exile or Graveyard.

EDIT: :( No love for the Effect method either. I guess there's a problem parsing the SpellCast trigger when it's static and checking for itself.
-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: If you cast it any time a sorcery couldn't have been cas

Postby Sloth » 21 Sep 2012, 19:49

Marc, can you commit your additions to TriggerSpellAbilityCast and PhaseHandler and post a full card script, so i can test around a bit?
User avatar
Sloth
Programmer
 
Posts: 3498
Joined: 23 Jun 2009, 19:40
Has thanked: 125 times
Been thanked: 507 times

Re: If you cast it any time a sorcery couldn't have been cas

Postby moomarc » 21 Sep 2012, 20:04

I'll have to commit the changes in the morning because there's a huge storm overhead and its getting late here anyway. I'll just post the script here so that if you can't get it working then we won't get bug reports about it when we release the beta next week (assuming that is still happening). Thanks for looking into it.
-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: If you cast it any time a sorcery couldn't have been cas

Postby moomarc » 22 Sep 2012, 15:33

Just committed the code for the trigger and timing restrictions. I originally added the extra triggers in CardFactoryUtil with this
code | Open
Code: Select all
if (card.hasKeyword("You may cast CARDNAME as though it had flash. If you cast it any time a sorcery couldn't have been "
                    + "cast, the controller of the permanent it becomes sacrifices it at the beginning of the next cleanup step.")) {
            final String name = card.toString(); //didn't use getName() so we know which card is referenced by UID
            final String nonSorcTrig = "Mode$ SpellCast | ValidCard$ Card.Self | Execute$ TrigDelayedSac | SpellSpeed$ NotSorcerySpeed | TriggerDescription$ Test";
            //final String addSacTrig = "AB$ Animate | Cost$ 0 | Defined$ Self | Triggers$ CleanupTrig | sVars$ Sac | Permanent$ True";
            final String addSacTrig = "AB$ Effect | Cost$ 0 | Triggers$ CleanupTrig | SVars$ Sac | Permanent$ True";
            final String triggerSac = "Mode$ Phase | Phase$ Cleanup | TriggerZones$ Battlefield | Execute$ Sac | "
                    + "TriggerDescription$ At the beginning of the next cleanup step, sacrifice " + name + ".";
            final String sacrifice = "AB$ Sacrifice | Cost$ 0 | Defined$ EffectSource";
            final Trigger parsedTrigger = TriggerHandler.parseTrigger(nonSorcTrig, card, true);
            card.addTrigger(parsedTrigger);
            card.setSVar("TrigDelayedSac", addSacTrig);
            card.setSVar("CleanupTrig", triggerSac);
            card.setSVar("Sac", sacrifice);
        }
Otherwise here's a script with everything in the card already:
Armor of Thorns | Open
Code: Select all
Name:Armor of Thorns
ManaCost:1 G
Types:Enchantment Aura
Text:no text
K:You may cast CARDNAME as though it had flash. If you cast it any time a sorcery couldn't have been cast, the controller of the permanent it becomes sacrifices it at the beginning of the next cleanup step.
T:Mode$ SpellCast | ValidCard$ Card.Self | Execute$ TrigDelayedSac | SpellSpeed$ NotSorcerySpeed | TriggerDescription$ Test
#Add Static$ True to above trigger to see the issue

#Use either of these 2 below
SVar:TrigDelayedSac:AB$ Animate | Cost$ 0 | Defined$ Self | Triggers$ CleanupTrig | sVars$ Sac | Permanent$ True
SVar:CleanupTrig:Mode$ Phase | Phase$ Cleanup | TriggerZones$ Battlefield | Execute$ Sac | TriggerDescription$ At the beginning of the next cleanup step, sacrifice CARDNAME.
SVar:Sac:AB$ Sacrifice | Cost$ 0 | Defined$ Self

#SVar:TrigDelayedSac:AB$ Effect | Cost$ 0 | Triggers$ CleanupTrig | SVars$ Sac | Duration$ Permanent
#SVar:CleanupTrig:Mode$ Phase | Phase$ Cleanup | TriggerZones$ Battlefield | Execute$ Sac | TriggerDescription$ At the beginning of the next cleanup step, sacrifice CARDNAME.
#SVar:Sac:AB$ Sacrifice | Cost$ 0 | Defined$ EffectSource

K:Enchant nonblack creature
A:SP$ Attach | Cost$ 1 G | ValidTgts$ Creature.nonBlack | AILogic$ Pump
S:Mode$ Continuous | Affected$ Creature.EnchantedBy | AddPower$ 2 | AddToughness$ 2 | Description$ Enchanted creature gets +2/+2.
SVar:RemAIDeck:True
SVar:Rarity:Common
SVar:Picture:http://www.wizards.com/global/images/magic/general/armor_of_thorns.jpg
SetInfo:MIR|Common|http://magiccards.info/scans/en/mr/104.jpg
Oracle:You may cast Armor of Thorns as though it had flash. If you cast it any time a sorcery couldn't have been cast, the controller of the permanent it becomes sacrifices it at the beginning of the next cleanup step.\nEnchant nonblack creature\nEnchanted creature gets +2/+2.
End
-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: If you cast it any time a sorcery couldn't have been cas

Postby Chris H. » 22 Sep 2012, 15:49

moomarc wrote:when we release the beta next week (assuming that is still happening).
 
I will release the next beta on Monday the 24th unless we find a reason not to. :)
User avatar
Chris H.
Forge Moderator
 
Posts: 6320
Joined: 04 Nov 2008, 12:11
Location: Mac OS X Yosemite
Has thanked: 644 times
Been thanked: 643 times

Re: If you cast it any time a sorcery couldn't have been cas

Postby Sloth » 22 Sep 2012, 19:02

moomarc wrote:Just committed the code for the trigger and timing restrictions. I originally added the extra triggers in CardFactoryUtil with this
code | Open
Code: Select all
if (card.hasKeyword("You may cast CARDNAME as though it had flash. If you cast it any time a sorcery couldn't have been "
                    + "cast, the controller of the permanent it becomes sacrifices it at the beginning of the next cleanup step.")) {
            final String name = card.toString(); //didn't use getName() so we know which card is referenced by UID
            final String nonSorcTrig = "Mode$ SpellCast | ValidCard$ Card.Self | Execute$ TrigDelayedSac | SpellSpeed$ NotSorcerySpeed | TriggerDescription$ Test";
            //final String addSacTrig = "AB$ Animate | Cost$ 0 | Defined$ Self | Triggers$ CleanupTrig | sVars$ Sac | Permanent$ True";
            final String addSacTrig = "AB$ Effect | Cost$ 0 | Triggers$ CleanupTrig | SVars$ Sac | Permanent$ True";
            final String triggerSac = "Mode$ Phase | Phase$ Cleanup | TriggerZones$ Battlefield | Execute$ Sac | "
                    + "TriggerDescription$ At the beginning of the next cleanup step, sacrifice " + name + ".";
            final String sacrifice = "AB$ Sacrifice | Cost$ 0 | Defined$ EffectSource";
            final Trigger parsedTrigger = TriggerHandler.parseTrigger(nonSorcTrig, card, true);
            card.addTrigger(parsedTrigger);
            card.setSVar("TrigDelayedSac", addSacTrig);
            card.setSVar("CleanupTrig", triggerSac);
            card.setSVar("Sac", sacrifice);
        }
Otherwise here's a script with everything in the card already:
Armor of Thorns | Open
Code: Select all
Name:Armor of Thorns
ManaCost:1 G
Types:Enchantment Aura
Text:no text
K:You may cast CARDNAME as though it had flash. If you cast it any time a sorcery couldn't have been cast, the controller of the permanent it becomes sacrifices it at the beginning of the next cleanup step.
T:Mode$ SpellCast | ValidCard$ Card.Self | Execute$ TrigDelayedSac | SpellSpeed$ NotSorcerySpeed | TriggerDescription$ Test
#Add Static$ True to above trigger to see the issue

#Use either of these 2 below
SVar:TrigDelayedSac:AB$ Animate | Cost$ 0 | Defined$ Self | Triggers$ CleanupTrig | sVars$ Sac | Permanent$ True
SVar:CleanupTrig:Mode$ Phase | Phase$ Cleanup | TriggerZones$ Battlefield | Execute$ Sac | TriggerDescription$ At the beginning of the next cleanup step, sacrifice CARDNAME.
SVar:Sac:AB$ Sacrifice | Cost$ 0 | Defined$ Self

#SVar:TrigDelayedSac:AB$ Effect | Cost$ 0 | Triggers$ CleanupTrig | SVars$ Sac | Duration$ Permanent
#SVar:CleanupTrig:Mode$ Phase | Phase$ Cleanup | TriggerZones$ Battlefield | Execute$ Sac | TriggerDescription$ At the beginning of the next cleanup step, sacrifice CARDNAME.
#SVar:Sac:AB$ Sacrifice | Cost$ 0 | Defined$ EffectSource

K:Enchant nonblack creature
A:SP$ Attach | Cost$ 1 G | ValidTgts$ Creature.nonBlack | AILogic$ Pump
S:Mode$ Continuous | Affected$ Creature.EnchantedBy | AddPower$ 2 | AddToughness$ 2 | Description$ Enchanted creature gets +2/+2.
SVar:RemAIDeck:True
SVar:Rarity:Common
SVar:Picture:http://www.wizards.com/global/images/magic/general/armor_of_thorns.jpg
SetInfo:MIR|Common|http://magiccards.info/scans/en/mr/104.jpg
Oracle:You may cast Armor of Thorns as though it had flash. If you cast it any time a sorcery couldn't have been cast, the controller of the permanent it becomes sacrifices it at the beginning of the next cleanup step.\nEnchant nonblack creature\nEnchanted creature gets +2/+2.
End
Should be ready for take off.
User avatar
Sloth
Programmer
 
Posts: 3498
Joined: 23 Jun 2009, 19:40
Has thanked: 125 times
Been thanked: 507 times

Re: If you cast it any time a sorcery couldn't have been cas

Postby moomarc » 23 Sep 2012, 04:25

Thanks Sloth. I'll try get the rest of these instaments scripted next week.
-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: If you cast it any time a sorcery couldn't have been cas

Postby Doublestrike » 24 Sep 2012, 00:38

Chris H. wrote:I will release the next beta on Monday the 24th unless we find a reason not to. :)
I'm predicting a day or two on the keyboard shortcut thing...if we can afford it?
---
A joke is a very serious thing.
User avatar
Doublestrike
UI Programmer
 
Posts: 715
Joined: 08 Aug 2011, 09:07
Location: Bali
Has thanked: 183 times
Been thanked: 161 times

Re: If you cast it any time a sorcery couldn't have been cas

Postby Chris H. » 24 Sep 2012, 01:15

Doublestrike wrote:
Chris H. wrote:I will release the next beta on Monday the 24th unless we find a reason not to. :)
 
I'm predicting a day or two on the keyboard shortcut thing...if we can afford it?
 
Yeah, for that we can wait. :) No problem.
User avatar
Chris H.
Forge Moderator
 
Posts: 6320
Joined: 04 Nov 2008, 12:11
Location: Mac OS X Yosemite
Has thanked: 644 times
Been thanked: 643 times

Re: If you cast it any time a sorcery couldn't have been cas

Postby Doublestrike » 24 Sep 2012, 04:26

Done (see bug report thread).
---
A joke is a very serious thing.
User avatar
Doublestrike
UI Programmer
 
Posts: 715
Joined: 08 Aug 2011, 09:07
Location: Bali
Has thanked: 183 times
Been thanked: 161 times

Re: If you cast it any time a sorcery couldn't have been cas

Postby friarsol » 25 Sep 2012, 15:06

Hey Moomarc, I saw you post a few more of these. I think you might have missed at least Parapet. I count 10 of these cards in Mirage/Visions total.
friarsol
Global Moderator
 
Posts: 7593
Joined: 15 May 2010, 04:20
Has thanked: 243 times
Been thanked: 965 times

Next

Return to Developer's Corner

Who is online

Users browsing this forum: No registered users and 21 guests

Main Menu

User Menu

Our Partners


Who is online

In total there are 21 users online :: 0 registered, 0 hidden and 21 guests (based on users active over the past 10 minutes)
Most users ever online was 9298 on 10 Oct 2025, 12:54

Users browsing this forum: No registered users and 21 guests

Login Form