It is currently 26 May 2018, 08:00
   
Text Size

Approximating "counter target (activated) ability"

Moderators: Xander9009, CCGHQ Admins

Approximating "counter target (activated) ability"

Postby 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:
  1. 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.
  2. 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.
  3. 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 &gt; 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>
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.

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) &gt; 0
    </AVAILABILITY>
    <PLAY_TIME_ACTION>
    local player = EffectController()
    local first = 0
    local count = TFM_ObjectDC():Get_Int(-1111)
    if count &gt; 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>
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).

What do you think? :)
< Former DotP 2012/2013/2014 modder >
Currently not really active.
User avatar
thefiremind
Programmer
 
Posts: 3513
Joined: 07 Nov 2011, 10:55
Has thanked: 117 times
Been thanked: 715 times

Re: Approximating "counter target (activated) ability"

Postby Splinterverse2 » 28 Nov 2016, 21:36

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:
  1. 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.
  2. 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.
  3. 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 &gt; 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>
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.

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) &gt; 0
    </AVAILABILITY>
    <PLAY_TIME_ACTION>
    local player = EffectController()
    local first = 0
    local count = TFM_ObjectDC():Get_Int(-1111)
    if count &gt; 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>
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).

What do you think? :)
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.
Splinterverse2
 
Posts: 52
Joined: 20 Sep 2016, 13:52
Has thanked: 13 times
Been thanked: 0 time


Return to Programming Talk

Who is online

Users browsing this forum: No registered users and 1 guest

cron

Who is online

In total there is 1 user online :: 0 registered, 0 hidden and 1 guest (based on users active over the past 10 minutes)
Most users ever online was 279 on 11 Jul 2013, 22:03

Users browsing this forum: No registered users and 1 guest

Login Form