Board index Programs with AI or Rules Enforcement Magic: The Gathering - Duels of the Planeswalkers Programming Talk
Approximating "counter target (activated) ability"
Moderator: CCGHQ Admins
Approximating "counter target (activated) ability"
by thefiremind » 20 Nov 2016, 20:24
I invented a way to make "counter target (activated) ability" possible. It's still barebone, and it suffers from approximations. My hope is to get new ideas from the other modders that will make it better.
Here are the currently known approximations:
The code uses my TFM_ObjectDC (which I made for Magic Duels), but you can use RSN_ObjectDC and obtain the same result. I'm not using LinkedDC because if you're planning to put the code on an activated ability (such as Azorius Guildmage's) you'll need to access the number of registered abilities in an AVAILABILITY block (so that you can't activate it if there are no targets), and LinkedDC can't be accessed from there.
The first part of the code registers the activated abilities in TFM_ObjectDC. You can put it into a manager if you wish, but then you should remember to access the manager's ObjectDC in the cards that use it.
The second part is the true ability that counters target activated ability. My example is for Azorius Guildmage:
What do you think?
Here are the currently known approximations:
- I wrote "activated" in brackets because my code works for activated abilities. You can try to generalize it for any ability, but it will start registering all of them, even replacement triggers, and it will become a mess, so I don't recommend to do it.
- You won't really "target" the ability, you'll just select it. This means that if you put my code on Squelch, you won't be able to change its target through other spells/abilities, unless you take the possibility into account on those other spells/abilities.
- The ability selection won't be very detailed: you will see the position in the stack (as a number) and the card title, that's all. A card choice from a chest would have been better, but how would I re-convert the chosen card to its position on the stack? The stack may contain multiple instances of activated abilities from the same card. I'm open to improvement suggestions.
The code uses my TFM_ObjectDC (which I made for Magic Duels), but you can use RSN_ObjectDC and obtain the same result. I'm not using LinkedDC because if you're planning to put the code on an activated ability (such as Azorius Guildmage's) you'll need to access the number of registered abilities in an AVAILABILITY block (so that you can't activate it if there are no targets), and LinkedDC can't be accessed from there.
The first part of the code registers the activated abilities in TFM_ObjectDC. You can put it into a manager if you wish, but then you should remember to access the manager's ObjectDC in the cards that use it.
- Code: Select all
<TRIGGERED_ABILITY replacement_effect="1">
<TRIGGER value="ACTIVATED_ABILITY_PLAYED" />
<RESOLUTION_TIME_ACTION>
TFM_ObjectDC():Set_Int( TFM_ObjectDC():Get_Int(-1111), TriggerStackObjectID() )
TFM_ObjectDC():Int_Add(-1111, 1) -- In DotP2014 you can use Int_Inc
</RESOLUTION_TIME_ACTION>
</TRIGGERED_ABILITY>
<TRIGGERED_ABILITY replacement_effect="1">
<TRIGGER value="STATE_BASED_EFFECTS">
local count = TFM_ObjectDC():Get_Int(-1111)
return count > 0 and MTG():GetStackObjectController( TFM_ObjectDC():Get_Int(count-1) ) == nil
</TRIGGER>
<RESOLUTION_TIME_ACTION>
TFM_ObjectDC():Int_Add(-1111, -1) -- In DotP2014 you can use Int_Dec
</RESOLUTION_TIME_ACTION>
</TRIGGERED_ABILITY>
The second part is the true ability that counters target activated ability. My example is for Azorius Guildmage:
- Code: Select all
<ACTIVATED_ABILITY>
<LOCALISED_TEXT LanguageCode="en-US"><![CDATA[{2}{U}: Counter target activated ability.]]></LOCALISED_TEXT>
<COST mana_cost="{2}{U}" type="Mana" />
<AVAILABILITY>
return TFM_ObjectDC():Get_Int(-1111) > 0
</AVAILABILITY>
<PLAY_TIME_ACTION>
local player = EffectController()
local first = 0
local count = TFM_ObjectDC():Get_Int(-1111)
if count > 7 then
first = count-7
end
EffectDC():Set_Int(0, first)
player:BeginNewMultipleChoice()
for i=count-1,first do
local id = TFM_ObjectDC():Get_Int(i)
local card = MTG():GetStackObjectCard(id)
if card ~= nil then
player:AddMultipleChoiceAnswer( "("..id..") "..card:GetCardName() )
end
end
player:AskMultipleChoiceQuestion("CARD_QUERY_CHOOSE_ABILITY_TO_COUNTER")
</PLAY_TIME_ACTION>
<PLAY_TIME_ACTION>
local first = EffectDC():Get_Int(0)
local id = TFM_ObjectDC():Get_Int( EffectController():GetMultipleChoiceResult()+first )
EffectDC():Set_Int(1, id)
</PLAY_TIME_ACTION>
<RESOLUTION_TIME_ACTION>
local id = EffectDC():Get_Int(1)
if MTG():GetStackObjectController(id) ~= nil then
MTG():CounterStackObject(id)
end
</RESOLUTION_TIME_ACTION>
<AI_AVAILABILITY type="in_response" />
</ACTIVATED_ABILITY>
What do you think?
< Former DotP 2012/2013/2014 modder >
Currently busy with life...
Currently busy with life...
-
thefiremind - Programmer
- Posts: 3515
- Joined: 07 Nov 2011, 10:55
- Has thanked: 118 times
- Been thanked: 721 times
Re: Approximating "counter target (activated) ability"
by Splinterverse2 » 28 Nov 2016, 21:36
I haven't read all of the code since I am on my phone but it looks/sounds good. It is nice to potentially have these cards be viable.thefiremind wrote:I invented a way to make "counter target (activated) ability" possible. It's still barebone, and it suffers from approximations. My hope is to get new ideas from the other modders that will make it better.
Here are the currently known approximations:
- I wrote "activated" in brackets because my code works for activated abilities. You can try to generalize it for any ability, but it will start registering all of them, even replacement triggers, and it will become a mess, so I don't recommend to do it.
- You won't really "target" the ability, you'll just select it. This means that if you put my code on Squelch, you won't be able to change its target through other spells/abilities, unless you take the possibility into account on those other spells/abilities.
- The ability selection won't be very detailed: you will see the position in the stack (as a number) and the card title, that's all. A card choice from a chest would have been better, but how would I re-convert the chosen card to its position on the stack? The stack may contain multiple instances of activated abilities from the same card. I'm open to improvement suggestions.
The code uses my TFM_ObjectDC (which I made for Magic Duels), but you can use RSN_ObjectDC and obtain the same result. I'm not using LinkedDC because if you're planning to put the code on an activated ability (such as Azorius Guildmage's) you'll need to access the number of registered abilities in an AVAILABILITY block (so that you can't activate it if there are no targets), and LinkedDC can't be accessed from there.
The first part of the code registers the activated abilities in TFM_ObjectDC. You can put it into a manager if you wish, but then you should remember to access the manager's ObjectDC in the cards that use it.I haven't been able to find a suitable trigger that's more specific than STATE_BASED_EFFECTS for removing abilities that left the stack from my list. STACK_POPPED seems broken, while ABILITY_RESOLVED fires too early (the ability is still on the stack) and doesn't bring a TriggerStackObjectID so I can't make any useful check with it. This happens on Magic Duels, results may vary on DotP2014: feel free to experiment.
- Code: Select all
<TRIGGERED_ABILITY replacement_effect="1">
<TRIGGER value="ACTIVATED_ABILITY_PLAYED" />
<RESOLUTION_TIME_ACTION>
TFM_ObjectDC():Set_Int( TFM_ObjectDC():Get_Int(-1111), TriggerStackObjectID() )
TFM_ObjectDC():Int_Add(-1111, 1) -- In DotP2014 you can use Int_Inc
</RESOLUTION_TIME_ACTION>
</TRIGGERED_ABILITY>
<TRIGGERED_ABILITY replacement_effect="1">
<TRIGGER value="STATE_BASED_EFFECTS">
local count = TFM_ObjectDC():Get_Int(-1111)
return count > 0 and MTG():GetStackObjectController( TFM_ObjectDC():Get_Int(count-1) ) == nil
</TRIGGER>
<RESOLUTION_TIME_ACTION>
TFM_ObjectDC():Int_Add(-1111, -1) -- In DotP2014 you can use Int_Dec
</RESOLUTION_TIME_ACTION>
</TRIGGERED_ABILITY>
The second part is the true ability that counters target activated ability. My example is for Azorius Guildmage:Since the limit for query choices in DotP2014 is 7, in case there are more than 7 activated abilities I'm picking the most recent 7 to get to the stack (it's quite a rare scenario anyway).
- Code: Select all
<ACTIVATED_ABILITY>
<LOCALISED_TEXT LanguageCode="en-US"><![CDATA[{2}{U}: Counter target activated ability.]]></LOCALISED_TEXT>
<COST mana_cost="{2}{U}" type="Mana" />
<AVAILABILITY>
return TFM_ObjectDC():Get_Int(-1111) > 0
</AVAILABILITY>
<PLAY_TIME_ACTION>
local player = EffectController()
local first = 0
local count = TFM_ObjectDC():Get_Int(-1111)
if count > 7 then
first = count-7
end
EffectDC():Set_Int(0, first)
player:BeginNewMultipleChoice()
for i=count-1,first do
local id = TFM_ObjectDC():Get_Int(i)
local card = MTG():GetStackObjectCard(id)
if card ~= nil then
player:AddMultipleChoiceAnswer( "("..id..") "..card:GetCardName() )
end
end
player:AskMultipleChoiceQuestion("CARD_QUERY_CHOOSE_ABILITY_TO_COUNTER")
</PLAY_TIME_ACTION>
<PLAY_TIME_ACTION>
local first = EffectDC():Get_Int(0)
local id = TFM_ObjectDC():Get_Int( EffectController():GetMultipleChoiceResult()+first )
EffectDC():Set_Int(1, id)
</PLAY_TIME_ACTION>
<RESOLUTION_TIME_ACTION>
local id = EffectDC():Get_Int(1)
if MTG():GetStackObjectController(id) ~= nil then
MTG():CounterStackObject(id)
end
</RESOLUTION_TIME_ACTION>
<AI_AVAILABILITY type="in_response" />
</ACTIVATED_ABILITY>
What do you think?
- Splinterverse2
- Posts: 52
- Joined: 20 Sep 2016, 13:52
- Has thanked: 13 times
- Been thanked: 0 time
Re: Approximating "counter target (activated) ability"
by Xander9009 » 21 Jun 2018, 22:43
I've kept this in the back of my mind until I finally had the chance to mess with it, and I finally put this to use. It wasn't for targeting an ability, so it wasn't quite how you had it set up, but it was for Sundial of the Infinite, which needed to counter everything on the stack, which needed to include abilities. It worked well, so I imagine it'll work well for the original purpose, too.
EDIT: I'm aware it should technically be "exiling" the ability, but we have limited stack-ability interaction, so I'll take what I can get.
EDIT: I'm aware it should technically be "exiling" the ability, but we have limited stack-ability interaction, so I'll take what I can get.
_______________________________
Community Wad - Community Wad Website - How to Help and Report Bugs
Discord: discord.gg/4AXvHzW
Community Wad - Community Wad Website - How to Help and Report Bugs
Discord: discord.gg/4AXvHzW
-
Xander9009 - Programmer
- Posts: 2905
- Joined: 29 Jun 2013, 07:44
- Location: Indiana, United States
- Has thanked: 121 times
- Been thanked: 445 times
3 posts
• Page 1 of 1
Who is online
Users browsing this forum: No registered users and 6 guests