Trigger discussion (was WheneverKeyword reference)
Post MTG Forge Related Programming Questions Here
Moderators: timmermac, Blacksmith, KrazyTheFox, Agetian, friarsol, CCGHQ Admins
Trigger discussion (was WheneverKeyword reference)
by Hellfish » 09 Jan 2011, 13:45
Do we have a reference for how to do things with the WheneverKeyword? I was looking at the Zendikar Quests and was trying to figure out for which ones I'd have to hardcode the circumstances in which you could put a counter on them. (I'm thinking Quest for Pure Flame and Quest for Ula's Temple hardcoded at the very least.)
Last edited by Hellfish on 10 Jan 2011, 11:51, edited 1 time in total.
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: WheneverKeyword reference
by Sloth » 09 Jan 2011, 15:15
I say the whenever keyword needs a complete rewrite (or at least a very big cleanup) more than a documentation, because the syntax is so random and the AI is flaky for some effects. BeachedAs wrote everything from scratch without using existing structures (and in a chaotic undocumented way).
-
Sloth - Programmer
- Posts: 3498
- Joined: 23 Jun 2009, 19:40
- Has thanked: 125 times
- Been thanked: 507 times
Re: WheneverKeyword reference
by Chris H. » 09 Jan 2011, 15:52
I examined the code on several occasions but I do not understand most of it. I like the way Sol designed the AFs. They have keys and values that are fairly easy to see and understand. The old style of keywords is OK but can be hard to interpret if there are many input parameters.
-
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: WheneverKeyword reference
by friarsol » 09 Jan 2011, 15:55
I think anything the Whenever keyword can do, we can do using the AbilityFactory triggering and SubAbilities. If someone wants to give it a shot, they can go for it. I'm currently swamped in overhauling Mana Abilities.
- friarsol
- Global Moderator
- Posts: 7593
- Joined: 15 May 2010, 04:20
- Has thanked: 243 times
- Been thanked: 965 times
Re: WheneverKeyword reference
by Hellfish » 09 Jan 2011, 16:44
Yeah okay, working on triggers for AFs might be better right now then? And maybe ripping out the WheneverKeyword code afterwards.
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: WheneverKeyword reference
by friarsol » 09 Jan 2011, 18:04
My lofty idealism says yes.Hellfish wrote:Yeah okay, working on triggers for AFs might be better right now then? And maybe ripping out the WheneverKeyword code afterwards.
- friarsol
- Global Moderator
- Posts: 7593
- Joined: 15 May 2010, 04:20
- Has thanked: 243 times
- Been thanked: 965 times
Re: WheneverKeyword reference
by DennisBergkamp » 09 Jan 2011, 23:11
The scariest parts in the WheneverKeyword code:
1. It's really fricking long.
2. All of the objects start with capitals, which for whatever reason, confused me to no end.
Usually I'm pretty good at understanding code just by reading it, but in this case I really had to use a debugger to even see what the heck was going on
1. It's really fricking long.
2. All of the objects start with capitals, which for whatever reason, confused me to no end.
Usually I'm pretty good at understanding code just by reading it, but in this case I really had to use a debugger to even see what the heck was going on

-
DennisBergkamp - AI Programmer
- Posts: 2602
- Joined: 09 Sep 2008, 15:46
- Has thanked: 0 time
- Been thanked: 0 time
Re: WheneverKeyword reference
by friarsol » 09 Jan 2011, 23:56
The thing that bothers me the most is the spacing. If it was tabbed properly I think I could understand it a lot better.
- friarsol
- Global Moderator
- Posts: 7593
- Joined: 15 May 2010, 04:20
- Has thanked: 243 times
- Been thanked: 965 times
Re: WheneverKeyword reference
by Hellfish » 10 Jan 2011, 11:44
Okay, stayed up all night coding and put together something experimental and a bit more easy to read:
Then, in an SVar, a regular ability is written and referenced by the trigger, i.e. "The What". (Cost$ should usually be 0, unless it's a "Whenever X, you may pay Y to..."-type deal. Triggers have 3 universal parameters currently: Mode,Execute and Optional.Mode specifies what kind of trigger it is, Execute specifies which SVar contains the ability to trigger and Optional is kind of self-explanatory
. All other parameters depend on which Mode is used.
When adding a new trigger-mode, you'd have to do these 3 steps:
Things I'm still working on:
Of course, this is just an experimental draft, please do point out flaws or suggest alterations.
- Code: Select all
Name:Abyssal Horror
ManaCost:4 B B
Types:Creature Horror
Text:When Abyssal Horror enters the battlefield, target player discards two cards.
PT:2/2
K:Flying
T:Mode$ ChangesZone | From$ Any | To$ Battlefield | ValidCard$ Self | Execute$ ETBDiscard | StackDescription$ Target player discards 2 cards.
SVar:ETBDiscard:AB$Discard | Cost$ 0 | ValidTgts$ Player | TgtPrompt$ Select target player. | NumCards$ 2 | Mode$ TgtChoose
SVar:Rarity:Rare
SVar:Picture:http://www.wizards.com/global/images/magic/general/abyssal_horror.jpg
SetInfo:USG|Rare|http://magiccards.info/scans/en/us/115.jpg
SetInfo:S99|Rare|http://magiccards.info/scans/en/st/63.jpg
SetInfo:7ED|Rare|http://magiccards.info/scans/en/7e/115.jpg
End
Then, in an SVar, a regular ability is written and referenced by the trigger, i.e. "The What". (Cost$ should usually be 0, unless it's a "Whenever X, you may pay Y to..."-type deal. Triggers have 3 universal parameters currently: Mode,Execute and Optional.Mode specifies what kind of trigger it is, Execute specifies which SVar contains the ability to trigger and Optional is kind of self-explanatory

When adding a new trigger-mode, you'd have to do these 3 steps:
- Add a new private boolean XTest(Trigger trigger,HashMap<String,Object> runParams) method to the new TriggerHandler class, where X is the name of the mode.
- Add a call to that method from TriggerHandler.runTrigger.
- Add calls to TriggerHandler.runTrigger from where the trigger should be uh triggered, where you must also fill out the runParams map with all objects that will be needed for the test to work.
Things I'm still working on:
- SpellDescriptions: At this time, a description of the triggered ability is not added to the card's text box.
- Parse triggers only once: Right now, they're parsed again and again whenever they are registered with the handler, which is when their host card comes into play. Speaking of which...
- Parse and register certain triggers before they come into play: There are probably cards with triggered abilities that function outside the battlefield that I just can't recall right now.
- More modes: DamageDone is in it's infant stages. CastSpell is a possibility. Suggestions welcome!
Of course, this is just an experimental draft, please do point out flaws or suggest alterations.
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: Trigger discussion (was WheneverKeyword reference)
by Sloth » 10 Jan 2011, 14:19
That looks pretty well thought out to me. Well done Hellfish.
I would like to have additional Conditions (like Threshold, isPresent) as a universal parameter (but maybe this can be handled in the SVar by the conditions of the Abilityfactory).
A few other random thoughts:
1. Does the Optional parameter handle opponents choice (for example Sibilant Spirit)?
2. Does the AI always choose to use the ability (when given the option)?
I would like to have additional Conditions (like Threshold, isPresent) as a universal parameter (but maybe this can be handled in the SVar by the conditions of the Abilityfactory).
A few other random thoughts:
1. Does the Optional parameter handle opponents choice (for example Sibilant Spirit)?
2. Does the AI always choose to use the ability (when given the option)?
-
Sloth - Programmer
- Posts: 3498
- Joined: 23 Jun 2009, 19:40
- Has thanked: 125 times
- Been thanked: 507 times
Re: Trigger discussion (was WheneverKeyword reference)
by friarsol » 10 Jan 2011, 14:32
Could I request that ChangesZone use Origin and Destination instead of From/To to replicate AF$ChangeZone?
- friarsol
- Global Moderator
- Posts: 7593
- Joined: 15 May 2010, 04:20
- Has thanked: 243 times
- Been thanked: 965 times
Re: Trigger discussion (was WheneverKeyword reference)
by Hellfish » 10 Jan 2011, 14:54
1.Currently the Optional parameter causes the TriggerHandler to ask the hostCards controller wether to trigger the ability at all. I will look deeper into this.Sloth wrote:That looks pretty well thought out to me. Well done Hellfish.
I would like to have additional Conditions (like Threshold, isPresent) as a universal parameter (but maybe this can be handled in the SVar by the conditions of the Abilityfactory).
A few other random thoughts:
1. Does the Optional parameter handle opponents choice (for example Sibilant Spirit)?
2. Does the AI always choose to use the ability (when given the option)?
2.Currently AI always accepts if the canPlayAI of the resulting spellability returns true. Something could probably be arranged here.
(Currently is the word of the day

Very yes.friarsol wrote:Could I request that ChangesZone use Origin and Destination instead of From/To to replicate AF$ChangeZone?

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: Trigger discussion (was WheneverKeyword reference)
by friarsol » 10 Jan 2011, 15:08
So far it's looking good. I would look into the SpellAbility_Restriction class to get some ideas of what might restrict when things could activate (or be triggered). I definitely think "TriggerZone" would be an important one. For cards like: Auntie's Snitch or Bridge from Below
- friarsol
- Global Moderator
- Posts: 7593
- Joined: 15 May 2010, 04:20
- Has thanked: 243 times
- Been thanked: 965 times
Re: Trigger discussion (was WheneverKeyword reference)
by Hellfish » 10 Jan 2011, 17:27
I think I've almost got it licked, at least as far as the ChangesZone mode is concerned.Now, triggers are only parsed once and registered upon starting a new game (GameAction.newGame()), then restricted with the optional TriggerZone parameter suggested by Sol. Now I just gotta figure out what's bugging the card text
The (apparently faulty) code I've used so far is just to loop through the triggers a card has in it's getAbilityText() method and extract the (now obligatory) TriggerDescription parameter, which works exactly like a SpellDescription. I'm not sure what's so wrong with that.

The (apparently faulty) code I've used so far is just to loop through the triggers a card has in it's getAbilityText() method and extract the (now obligatory) TriggerDescription parameter, which works exactly like a SpellDescription. I'm not sure what's so wrong with that.
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: Trigger discussion (was WheneverKeyword reference)
by friarsol » 10 Jan 2011, 17:36
If you use something that can make Patches, you can Patch up your changes and post it to the boards. Then you can get a few more eyes on it. Without seeing anything else, what you are trying to do sounds right, so it must be a "mundane detail" as the boys from Office Space would say.
- friarsol
- Global Moderator
- Posts: 7593
- Joined: 15 May 2010, 04:20
- Has thanked: 243 times
- Been thanked: 965 times
Who is online
Users browsing this forum: No registered users and 8 guests