It is currently 26 Apr 2024, 06:44
   
Text Size

FilteredCard() with independent DURATION

Moderator: CCGHQ Admins

FilteredCard() with independent DURATION

Postby Xander9009 » 18 Nov 2014, 18:54

I'm trying to help code a custom ability, and one of the things required is that all of the affected cards (chosen in a filter block) have a continuous ability applied to them. Upon becoming tapped for mana, the effect should end for that particular card, but it shouldn't affect the others. The cards being affected do not belong to EffectController. What's the easiest way to manage this kind of effect?

Initially, I had it using a duration that checked a LinkedDC() int, but the granted triggered ability for BECAME_TAPPED_FOR_MANA wont be able to set the int since it would be firing from a different card (I think).

I thought about using a delayed trigger upon BECAME_TAPPED_FOR_MANA, but I couldn't figure out how to make a separate delayed trigger for each FilteredCard(). I came closest with this approach, but the DURATION still exists as a single block which I think will apply to all of the cards, ending the effect on them all as soon as it's forced to end for one.

Finally, I thought about granting the SetController() ability to the affected card with the duration block included and using a linked_ability_group. This would probably work, but I can't figure out to grant an ability to SetController(), since it would still require knowing the person controlling the effect. This can be achieved with an ObjectDC, but I'm hoping to manage it without requiring any constants or otherwise risking interference.

If necessary, I'll use ObjectDC, but even so, does anyone have any advice on this?
_______________________________
Community Wad - Community Wad Website - How to Help and Report Bugs
Discord: discord.gg/4AXvHzW
User avatar
Xander9009
Programmer
 
Posts: 2905
Joined: 29 Jun 2013, 07:44
Location: Indiana, United States
Has thanked: 121 times
Been thanked: 445 times

Re: FilteredCard() with independent DURATION

Postby thefiremind » 18 Nov 2014, 19:00

Are you aware that the BECAME_TAPPED_FOR_MANA trigger doesn't work?
< Former DotP 2012/2013/2014 modder >
Currently busy with life...
User avatar
thefiremind
Programmer
 
Posts: 3515
Joined: 07 Nov 2011, 10:55
Has thanked: 118 times
Been thanked: 721 times

Re: FilteredCard() with independent DURATION

Postby Xander9009 » 18 Nov 2014, 19:06

thefiremind wrote:Are you aware that the BECAME_TAPPED_FOR_MANA trigger doesn't work?
The ability filter already requires that the affected permanents use Riiak's MM functions, and his functions manually fire the trigger. Although, no, I wasn't aware that it doesn't work for normal cards (but I'm lucky, 'cause in this case, it shouldn't matter).
_______________________________
Community Wad - Community Wad Website - How to Help and Report Bugs
Discord: discord.gg/4AXvHzW
User avatar
Xander9009
Programmer
 
Posts: 2905
Joined: 29 Jun 2013, 07:44
Location: Indiana, United States
Has thanked: 121 times
Been thanked: 445 times

Re: FilteredCard() with independent DURATION

Postby Xander9009 » 18 Nov 2014, 19:09

Unrelated to the previous (but I'm putting it here just 'cause I don't wanna spam the forum), shouldn't it theoretically be possible to produce a set of functions for declaring constants which aren't actually constants? As in, instead of declaring a constant, you declare the constant and then call a function on the constant. That function would set the constant to the first number not yet used by the function (which would require a manager).

In this way, everyone could just call something like "MY_CONST = InitConst()" and InitConst simply returns the one more than it did the last time it was called. That would mean everyone could be very certain they're not going to declare a constant that conflicts with anyone else's, and they don't even have to bother trying to track which numbers they've used before, because it doesn't matter what the number is, so long as it doesn't change throughout the game from the first time it's called.
_______________________________
Community Wad - Community Wad Website - How to Help and Report Bugs
Discord: discord.gg/4AXvHzW
User avatar
Xander9009
Programmer
 
Posts: 2905
Joined: 29 Jun 2013, 07:44
Location: Indiana, United States
Has thanked: 121 times
Been thanked: 445 times

Re: FilteredCard() with independent DURATION

Postby RiiakShiNal » 19 Nov 2014, 00:42

Xander9009 wrote:I'm trying to help code a custom ability, and one of the things required is that all of the affected cards (chosen in a filter block) have a continuous ability applied to them. Upon becoming tapped for mana, the effect should end for that particular card, but it shouldn't affect the others. The cards being affected do not belong to EffectController. What's the easiest way to manage this kind of effect?

Initially, I had it using a duration that checked a LinkedDC() int, but the granted triggered ability for BECAME_TAPPED_FOR_MANA wont be able to set the int since it would be firing from a different card (I think).

I thought about using a delayed trigger upon BECAME_TAPPED_FOR_MANA, but I couldn't figure out how to make a separate delayed trigger for each FilteredCard(). I came closest with this approach, but the DURATION still exists as a single block which I think will apply to all of the cards, ending the effect on them all as soon as it's forced to end for one.

Finally, I thought about granting the SetController() ability to the affected card with the duration block included and using a linked_ability_group. This would probably work, but I can't figure out to grant an ability to SetController(), since it would still require knowing the person controlling the effect. This can be achieved with an ObjectDC, but I'm hoping to manage it without requiring any constants or otherwise risking interference.

If necessary, I'll use ObjectDC, but even so, does anyone have any advice on this?
The easiest way I can think of to do this is to put all affected cards into a LinkedDC() when the effect starts along with the total number of affected cards. The STATIC_ABILITY that applies the CONTINUOUS_ACTION would then loop through the total number of cards stored in the LinkedDC() and apply the desired effect to any CardPtr that isn't nil. In a DelayedTrigger on BECAME_TAPPED_FOR_MANA you would search through the LinkedDC() (potentially looking through all registers until you hit the total number of affected cards) looking for the one that was tapped and upon finding that register it would clear the CardPtr (either by setting it to nil explicitly or setting an int value of 0 on that register). For the DelayedTrigger you can set the clean-up to happen once all of the CardPtrs are nil.

In that way once the card has been tapped for mana it is cleared from the LinkedDC() meaning it will no longer get the effect from the STATIC_ABILITY.

If you need this method to support multiple activations then you can assign each activation to use a separate chest in the LinkedDC() and have the STATIC_ABILITY loop through all of the chests that have been assigned. When a chest is emptied you can then set that register to nil and when looking for a new index to assign a chest to you look for the first register with a nil chest (which could be less than the previously set max number of chests). If you have to go beyond the previously set max number of chests you simply pick the next register create a chest there and increment the max number of chests and set that as the new max.

Xander9009 wrote:Unrelated to the previous (but I'm putting it here just 'cause I don't wanna spam the forum), shouldn't it theoretically be possible to produce a set of functions for declaring constants which aren't actually constants? As in, instead of declaring a constant, you declare the constant and then call a function on the constant. That function would set the constant to the first number not yet used by the function (which would require a manager).

In this way, everyone could just call something like "MY_CONST = InitConst()" and InitConst simply returns the one more than it did the last time it was called. That would mean everyone could be very certain they're not going to declare a constant that conflicts with anyone else's, and they don't even have to bother trying to track which numbers they've used before, because it doesn't matter what the number is, so long as it doesn't change throughout the game from the first time it's called.
This probably wouldn't work right unless you link the constant with some other identifier because global variable state is not preserved between actions (meaning "MY_CONST = InitConst()" would be called for every action resulting in lots of duplicate work and eventually running out registers). You could, however, create a set of functions such that if you call GetConst("MyConstIdentifier") it would return either a previously set constant for that identifier or set a new number and assign it to that identifier even without the need for a manager. This would allow people to use descriptive constant names to get a register index which would be less likely to conflict (you could still have a conflict if 2 different modders used the same string identifier). Though it should be noted that storing and retrieving strings to then compare is generally slow and it is just better to use unique indexes and set them statically. If people prefix the IDs they use for their constants with their reserved IdBlocks then conflicts really shouldn't happen.

Example:
Person A has IdBlock 1234 reserved and Person B has IdBlock 2345 reserved and they set the indexes like this:
Code: Select all
PERSON_A_CONST = 1234001
PERSON_B_CONST = 2345001
There shouldn't be any conflicts in this scenario and the overhead is almost non-existant.
RiiakShiNal
Programmer
 
Posts: 2185
Joined: 16 May 2011, 21:37
Has thanked: 75 times
Been thanked: 497 times

Re: FilteredCard() with independent DURATION

Postby Xander9009 » 21 Nov 2014, 17:52

Because of the complexity of this ability, we've changed how we're doing it. First up, here's the current code.
Current version - not working | Open
Code: Select all
  <ACTIVATED_ABILITY>
    <COST mana_cost="{0}" type="Mana" />
    <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[{0}:Exchange control of all cards target opponent controls with all cards you control. They gain hase. Activate this ability again to restore the permanents to their original controllers.]]></LOCALISED_TEXT>
    <SFX text="GLOBAL_WARP_PLAY" />
    <SFX text="GLOBAL_WARP_PLAY" />
    <TARGET tag="CARD_QUERY_CHOOSE_OPPONENT" definition="0" compartment="0" count="1" />
    <TARGET_DEFINITION id="0">
      local filter = ClearFilter()
      filter:SetFilterType( FILTER_TYPE_PLAYERS )
      filter:Add( FE_TEAM, OP_NOT, EffectController():GetTeam() )
    </TARGET_DEFINITION>
    <RESOLUTION_TIME_ACTION>
--EffectController():DisplayMessage("A")
      local ObjectDC = RSN_GetObjectDC(EffectSource(), true)
      if ObjectDC ~= nil then
--EffectController():DisplayMessage("B")
        local ability_active = ObjectDC:Get_Int(43322345)
        if ability_active == nil then
          ability_active = 0
        end
        if ability_active == 0 then
          ObjectDC:Set_Int(43322345, 1)
          ability_active = 1
--EffectController():DisplayMessage("B - 1: "..ability_active.." - "..ObjectDC:Get_Int(43322345))
        else
          ObjectDC:Set_Int(43322345, 0)
          ability_active = 0
--EffectController():DisplayMessage("B - 0: "..ability_active.." - "..ObjectDC:Get_Int(43322345))
        end
        if ability_active == 1 and EffectDC():Get_Targets(0) ~= nil and EffectDC():Get_Targets(0):Get_PlayerPtr(0) ~= nil then
--EffectController():DisplayMessage("C")
          local PlayerDC = EffectDC():Make_Chest(2)
          local TargetDC = EffectDC():Make_Chest(3)
          local target_player = EffectDC():Get_Targets(0):Get_PlayerPtr(0)
         
          PlayerDC:Set_PlayerPtr(0, target_player)
          TargetDC:Set_PlayerPtr(0, EffectController())
         
          local filter = ClearFilter()
          filter:Add( FE_CONTROLLER, OP_IS, EffectController() )
          filter:Add( FE_CARD_INSTANCE, OP_NOT, EffectSource() )
          filter:SetZone( ZONE_ANYWHERE )
          local filter_count = filter:EvaluateObjects()
          PlayerDC:Set_Int(0, filter_count)
          for i=0,filter_count-1 do
            local card = filter:GetNthEvaluatedObject(i)
            if card~= nil then
              PlayerDC:Set_CardPtr(i, card)
            end
          end
         
          filter = ClearFilter()
          filter:Add( FE_CONTROLLER, OP_IS, target_player )
          filter:Add( FE_CARD_INSTANCE, OP_NOT, EffectSource() )
          filter:SetZone( ZONE_ANYWHERE )
          filter_count = filter:EvaluateObjects()
          TargetDC:Set_Int(0, filter_count)
          for i=0,filter_count-1 do
            local card = filter:GetNthEvaluatedObject(i)
            if card~= nil then
              TargetDC:Set_CardPtr(i, card)
            end
          end
        end
      end
    </RESOLUTION_TIME_ACTION>
    <CONTINUOUS_ACTION layer="2">
--EffectController():SetLifeTotal(20)
      local ObjectDC = RSN_GetObjectDC(EffectSource())
      if ObjectDC ~= nil then
--EffectController():GainLife(1)
        local ability_active = ObjectDC:Get_Int(43322345)
        if ability_active ~= nil and ability_active == 1 then
--EffectController():GainLife(1)
          local PlayerDC = EffectDC():Get_Chest(2)
          local TargetDC = EffectDC():Get_Chest(3)

          if PlayerDC ~= nil and TargetDC ~= nil then
--EffectController():GainLife(1)
            local PlayerCount = PlayerDC:Get_Int(0)
            local TargetCount = TargetDC:Get_Int(0)
            local PlayerNewController = PlayerDC:Get_PlayerPtr(0)
            local TargetNewController = TargetDC:Get_PlayerPtr(0)
           
            if PlayerCount ~= nil and TargetCount ~= nil and PlayerNewController ~= nil and TargetNewController ~= nil then
--EffectController():GainLife(1)
              if PlayerCount &gt; 0 then
--EffectController():GainLife(1)
                for i = 0 , PlayerCount - 1 do
                  local card = TargetDC:Get_CardPtr(i)
                  if card ~= nil then
                    card:SetController(PlayerNewController)
                  end
                end
              end
              if TargetCount &gt; 0 then
                EffectController():GainLife(1)
                for i = 0 , TargetCount - 1 do
                  local card = PlayerDC:Get_CardPtr(i)
                  if card ~= nil then
                    card:SetController(TargetNewController)
                  end
                end
              end
            else
EffectController():SetLifeTotal(20)
              if PlayerCount == nil then
EffectController():GainLife(1)
              end
              if TargetCount == nil then
EffectController():GainLife(2)
              end 
              if PlayerNewController == nil then
EffectController():GainLife(4)
              end
              if TargetNewController == nil then
EffectController():GainLife(8)
              end
            end
          end
        end
      end
    </CONTINUOUS_ACTION>
    <CONTINUOUS_ACTION layer="6">
      local ObjectDC = RSN_GetObjectDC(EffectSource())
      if ObjectDC ~= nil then
        local ability_active = ObjectDC:Get_Int(43322345)
        if ability_active ~= nil and ability_active == 1 then
          local PlayerDC = EffectDC():Get_Chest(2)
          local TargetDC = EffectDC():Get_Chest(3)

          if PlayerDC ~= nil and TargetDC ~= nil then
            local PlayerCount = PlayerDC:Get_Int(0)
            local TargetCount = TargetDC:Get_Int(0)
            local PlayerNewController = PlayerDC:Get_PlayerPtr(0)
            local TargetNewController = TargetDC:Get_PlayerPtr(0)
           
            if PlayerCount ~= nil and TargetCount ~= nil and PlayerNewController ~= nil and TargetNewController ~= nil then
              if PlayerCount &gt; 0 then
                for i = 0 , PlayerCount - 1 do
                  local card = TargetDC:Get_CardPtr(i)
                  if card ~= nil then
                    local characteristics = card:GetCurrentCharacteristics()
                    characteristics:Bool_Set( CHARACTERISTIC_HASTE, 1 )
                  end
                end
              end
              if TargetCount &gt; 0 then
                for i = 0 , TargetCount - 1 do
                  card = PlayerDC:Get_CardPtr(i)
                  if card ~= nil then
                    local characteristics = card:GetCurrentCharacteristics()
                    characteristics:Bool_Set( CHARACTERISTIC_HASTE, 1 )
                  end
                end
              end
            end
          end
        end
      end
    </CONTINUOUS_ACTION>
    <DURATION>
      local ObjectDC = RSN_GetObjectDC(EffectSource())
      local PlayerDC = EffectDC():Get_Chest(2)
      local TargetDC = EffectDC():Get_Chest(3)

      if EffectSource() ~= nil and ObjectDC ~= nil and PlayerDC ~= nil and TargetDC~= nil then
        local ability_active = ObjectDC:Get_Int(43322345)
        local PlayerNewController = PlayerDC:Get_PlayerPtr(0)
        local TargetNewController = TargetDC:Get_PlayerPtr(0)
        if ability_active ~= nil and ability_active == 1 and PlayerNewController ~= nil and TargetNewController ~= nil then
          return true
        end
      end
      return false
    </DURATION>
  </ACTIVATED_ABILITY>
First up, the unindented lines are debug lines. They'll be removed when it's working. They're just there to let me know how far the code gets before failing. The first set of debug lines, the ones that print letters, prints all of the letters and the variables there are what they should be. The next section (at the beginning of the continuous action) gives me 23 life, telling me this check fails "if PlayerCount ~= nil and TargetCount ~= nil and PlayerNewController ~= nil and TargetNewController ~= nil then". The last set of debug code gives me 32 life, telling me PlayerNewController and TargetNewController are both nil. They're both stored from within the preceding RESOLUTION_TIME_ACTION, and the pointer which gets stored in TargetNewController is checked against nil before being stored (and the code continues after that, so it wasn't nil and should have worked). Anyone have any ideas?

Of interest here is the first continuous action.
_______________________________
Community Wad - Community Wad Website - How to Help and Report Bugs
Discord: discord.gg/4AXvHzW
User avatar
Xander9009
Programmer
 
Posts: 2905
Joined: 29 Jun 2013, 07:44
Location: Indiana, United States
Has thanked: 121 times
Been thanked: 445 times

Re: FilteredCard() with independent DURATION

Postby NeoAnderson » 21 Nov 2014, 18:01

Xander9009 wrote:Because of the complexity of this ability, we've changed how we're doing it. First up, here's the current code.

First up, the unindented lines are debug lines. They'll be removed when it's working. They're just there to let me know how far the code gets before failing. The first set of debug lines, the ones that print letters, prints all of the letters and the variables there are what they should be. The next section (at the beginning of the continuous action) gives me 23 life, telling me this check fails "if PlayerCount ~= nil and TargetCount ~= nil and PlayerNewController ~= nil and TargetNewController ~= nil then". The last set of debug code gives me 32 life, telling me PlayerNewController and TargetNewController are both nil. They're both stored from within the preceding RESOLUTION_TIME_ACTION, and the pointer which gets stored in TargetNewController is checked against nil before being stored (and the code continues after that, so it wasn't nil and should have worked). Anyone have any ideas?
Of interest here is the first continuous action.
Xander but you are trying to code this ability :
"Exchange control of all cards target opponent controls with all cards you control. They gain haste. Activate this ability again to restore the permanents to their original controllers" ???
Because falleangle asks to me about this ability and i have coded it for him :
Here you can find the code you are looking for :

Exchange control ability | Open
Code: Select all
<ACTIVATED_ABILITY linked_ability_group="1" >
        <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[{0}:Exchange control of all cards target opponent controls with all cards you control. They gain haste. Activate this ability again to restore the permanents to their original controlers.]]></LOCALISED_TEXT>
   <COST type="Generic">
     <PREREQUISITE>
             return true
        </PREREQUISITE>
        <PLAY_TIME_ACTION>
          if LinkedDC():Get_Int(20) ~= 2 then
             LinkedDC():Set_Int(20, 2)
          else
             LinkedDC():Set_Int(20, 1)
          end
        </PLAY_TIME_ACTION>
    </COST>
       <COST mana_cost="{0}" type="Mana" />
        <SFX text="GLOBAL_WARP_PLAY" />
    <TARGET tag="CARD_QUERY_CHOOSE_A_PLAYER_TO_TARGET" definition="0" compartment="0" count="1" />
     <TARGET_DEFINITION id="0">
    local filter = ClearFilter()
    filter:SetFilterType( FILTER_TYPE_PLAYERS )
    filter:Add( FE_TEAM, OP_NOT, EffectController():GetTeam() )
    </TARGET_DEFINITION>
      <FILTER filter_id="1">
    local target_player = EffectDC():Get_Targets(0):Get_PlayerPtr(0)
    local filter = ClearFilter()
    filter:Add( FE_CONTROLLER, OP_IS, target_player )
    local subfilter = filter:AddSubFilter_Or()
          subfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_ARTIFACT )
          subfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_CREATURE )
          subfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_ENCHANTMENT )
          subfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_LAND )
          subfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_PLANESWALKER )
    </FILTER>
      <FILTER filter_id="0">
    local filter = ClearFilter()
    filter:Add( FE_CONTROLLER, OP_IS, EffectController())
    filter:Add( FE_CARD_INSTANCE, OP_NOT, EffectSource() )
    local subfilter = filter:AddSubFilter_Or()
          subfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_ARTIFACT )
          subfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_CREATURE )
          subfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_ENCHANTMENT )
          subfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_LAND )
          subfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_PLANESWALKER )
    </FILTER>
      <CONTINUOUS_ACTION layer="2" filter_id="0">
    local targetPlayer = EffectDC():Get_Targets(0):Get_PlayerPtr(0)
    if targetPlayer ~= nil then
       FilteredCard():SetController( targetPlayer )
    end
    </CONTINUOUS_ACTION>
      <CONTINUOUS_ACTION layer="2" filter_id="1">
    if EffectController() ~= nil then
       FilteredCard():SetController( EffectController() )
    end
    </CONTINUOUS_ACTION>
      <CONTINUOUS_ACTION layer="6" filter_id="0">
    if FilteredCard() ~= nil then
        if FilteredCard():GetCardType():Test( CARD_TYPE_CREATURE ) then
            local characteristics = FilteredCard():GetCurrentCharacteristics()
          characteristics:Bool_Set( CHARACTERISTIC_HASTE, 1 )
        end
    end
    </CONTINUOUS_ACTION>
      <CONTINUOUS_ACTION layer="6" filter_id="1">
    if FilteredCard() ~= nil then
        if FilteredCard():GetCardType():Test( CARD_TYPE_CREATURE ) then
            local characteristics = FilteredCard():GetCurrentCharacteristics()
          characteristics:Bool_Set( CHARACTERISTIC_HASTE, 1 )
        end
    end
    </CONTINUOUS_ACTION>
      <CONTINUOUS_ACTION layer="8" filter_id="0">
    if FilteredCard() ~= nil then
       local characteristics = FilteredCard():GetCurrentCharacteristics()
       characteristics:AI_SetWorthless()
    end
    </CONTINUOUS_ACTION>
      <CONTINUOUS_ACTION layer="8" filter_id="1">
    if FilteredCard() ~= nil then
       local characteristics = FilteredCard():GetCurrentCharacteristics()
       characteristics:AI_SetWorthless()
    end
    </CONTINUOUS_ACTION>
      
            <DURATION>
             return LinkedDC():Get_Int(20) == 1
            </DURATION>
        </ACTIVATED_ABILITY>
Honestly i haven't understand if you want that also the card with this ability is exchanged, so now the code avoid that the card with this ability change controller but if you want to exchange also this card you have just to remove the line:
Code: Select all
    filter:Add( FE_CARD_INSTANCE, OP_NOT, EffectSource() )
inside the filter_id="0" block.
Hope is what you are looking for.
Obviously i have presumed you guys where talking of permanents onto battlefield.
Last edited by NeoAnderson on 21 Nov 2014, 18:22, edited 1 time in total.
NeoAnderson
 
Posts: 914
Joined: 10 Sep 2013, 07:49
Has thanked: 18 times
Been thanked: 139 times

Re: FilteredCard() with independent DURATION

Postby Xander9009 » 21 Nov 2014, 18:20

NeoAnderson wrote:
Xander9009 wrote:Because of the complexity of this ability, we've changed how we're doing it. First up, here's the current code.

First up, the unindented lines are debug lines. They'll be removed when it's working. They're just there to let me know how far the code gets before failing. The first set of debug lines, the ones that print letters, prints all of the letters and the variables there are what they should be. The next section (at the beginning of the continuous action) gives me 23 life, telling me this check fails "if PlayerCount ~= nil and TargetCount ~= nil and PlayerNewController ~= nil and TargetNewController ~= nil then". The last set of debug code gives me 32 life, telling me PlayerNewController and TargetNewController are both nil. They're both stored from within the preceding RESOLUTION_TIME_ACTION, and the pointer which gets stored in TargetNewController is checked against nil before being stored (and the code continues after that, so it wasn't nil and should have worked). Anyone have any ideas?
Of interest here is the first continuous action.
Xander but you are trying to code this ability :
"Exchange control of all cards target opponent controls with all cards you control. They gain haste. Activate this ability again to restore the permanents to their original controllers" ???
Because falleangle asks to me about this ability and i have coded it for him :
Here you can find the code you are looking for :

Exchange control ability | Open
Code: Select all
<ACTIVATED_ABILITY linked_ability_group="1" >
        <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[{0}:Exchange control of all cards target opponent controls with all cards you control. They gain haste. Activate this ability again to restore the permanents to their original controllers.]]></LOCALISED_TEXT>
   <COST type="Generic">
     <PREREQUISITE>
             return true
        </PREREQUISITE>
        <PLAY_TIME_ACTION>
          if LinkedDC():Get_Int(20) ~= 2 then
             LinkedDC():Set_Int(20, 2)
          else
             LinkedDC():Set_Int(20, 1)
          end
        </PLAY_TIME_ACTION>
    </COST>
       <COST mana_cost="{0}" type="Mana" />
        <SFX text="GLOBAL_WARP_PLAY" />
    <TARGET tag="CARD_QUERY_CHOOSE_A_PLAYER_TO_TARGET" definition="0" compartment="0" count="1" />
     <TARGET_DEFINITION id="0">
    local filter = ClearFilter()
    filter:SetFilterType( FILTER_TYPE_PLAYERS )
    filter:Add( FE_TEAM, OP_NOT, EffectController():GetTeam() )
    </TARGET_DEFINITION>
      <FILTER filter_id="1">
    local target_player = EffectDC():Get_Targets(0):Get_PlayerPtr(0)
    local filter = ClearFilter()
    filter:Add( FE_CONTROLLER, OP_IS, target_player )
    local subfilter = filter:AddSubFilter_Or()
          subfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_ARTIFACT )
          subfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_CREATURE )
          subfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_ENCHANTMENT )
          subfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_LAND )
          subfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_PLANESWALKER )
    </FILTER>
      <FILTER filter_id="0">
    local filter = ClearFilter()
    filter:Add( FE_CONTROLLER, OP_IS, EffectController())
    filter:Add( FE_CARD_INSTANCE, OP_NOT, EffectSource() )
    local subfilter = filter:AddSubFilter_Or()
          subfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_ARTIFACT )
          subfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_CREATURE )
          subfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_ENCHANTMENT )
          subfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_LAND )
          subfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_PLANESWALKER )
    </FILTER>
      <CONTINUOUS_ACTION layer="2" filter_id="0">
    local targetPlayer = EffectDC():Get_Targets(0):Get_PlayerPtr(0)
    if targetPlayer ~= nil then
       FilteredCard():SetController( targetPlayer )
    end
    </CONTINUOUS_ACTION>
      <CONTINUOUS_ACTION layer="2" filter_id="1">
    if EffectController() ~= nil then
       FilteredCard():SetController( EffectController() )
    end
    </CONTINUOUS_ACTION>
      <CONTINUOUS_ACTION layer="6" filter_id="0">
    if FilteredCard() ~= nil then
        if FilteredCard():GetCardType():Test( CARD_TYPE_CREATURE ) then
            local characteristics = FilteredCard():GetCurrentCharacteristics()
          characteristics:Bool_Set( CHARACTERISTIC_HASTE, 1 )
        end
    end
    </CONTINUOUS_ACTION>
      <CONTINUOUS_ACTION layer="6" filter_id="1">
    if FilteredCard() ~= nil then
        if FilteredCard():GetCardType():Test( CARD_TYPE_CREATURE ) then
            local characteristics = FilteredCard():GetCurrentCharacteristics()
          characteristics:Bool_Set( CHARACTERISTIC_HASTE, 1 )
        end
    end
    </CONTINUOUS_ACTION>
      <CONTINUOUS_ACTION layer="8" filter_id="0">
    if FilteredCard() ~= nil then
       local characteristics = FilteredCard():GetCurrentCharacteristics()
       characteristics:AI_SetWorthless()
    end
    </CONTINUOUS_ACTION>
      <CONTINUOUS_ACTION layer="8" filter_id="1">
    if FilteredCard() ~= nil then
       local characteristics = FilteredCard():GetCurrentCharacteristics()
       characteristics:AI_SetWorthless()
    end
    </CONTINUOUS_ACTION>
      
            <DURATION>
             return LinkedDC():Get_Int(20) == 1
            </DURATION>
        </ACTIVATED_ABILITY>
Honestly i haven't understand if you want that also the card with this ability is exchanged, so now the code avoid that the card with this ability change controller but if you want to exchange also this card you have just to remove the line:
Code: Select all
    filter:Add( FE_CARD_INSTANCE, OP_NOT, EffectSource() )
inside the filter_id="0" block.
Hope is what you are looking for.
I thought about doing it that way (since it's the simple way) but I didn't know how well it would work with the filters affecting multiple cards, all changing controllers. Anyway, I have no idea if the source should change control, but the ability text doesn't say 'other' so I didn't exclude it. And yeah, it's for fallenangel. However, I think the main thing about our conversation has been that I havent' been writing the code, I've been telling him how to write it. It's just that it got this point and now I don't know why those two things are returning nil.
_______________________________
Community Wad - Community Wad Website - How to Help and Report Bugs
Discord: discord.gg/4AXvHzW
User avatar
Xander9009
Programmer
 
Posts: 2905
Joined: 29 Jun 2013, 07:44
Location: Indiana, United States
Has thanked: 121 times
Been thanked: 445 times

Re: FilteredCard() with independent DURATION

Postby NeoAnderson » 21 Nov 2014, 18:25

Obviously i have presumed that you guys were talking of permanents onto battlefield.
If is not so i don't think you can exchange control of something into library or other zones.
NeoAnderson
 
Posts: 914
Joined: 10 Sep 2013, 07:49
Has thanked: 18 times
Been thanked: 139 times

Re: FilteredCard() with independent DURATION

Postby Xander9009 » 21 Nov 2014, 18:37

NeoAnderson wrote:Obviously i have presumed that you guys were talking of permanents onto battlefield.
If is not so i don't think you can exchange control of something into library or other zones.
Thank you. I didn't catch that. I also didn't catch that he'd in fact included the exclusion. I'll leave in the exclusion, but the ability text will need to have 'other' added to it. Either way, I was also assuming he was talking about cards on the battlefield. I just didn't catch the distinction. I'm still curious why those two variables would be nil, though... :?:
_______________________________
Community Wad - Community Wad Website - How to Help and Report Bugs
Discord: discord.gg/4AXvHzW
User avatar
Xander9009
Programmer
 
Posts: 2905
Joined: 29 Jun 2013, 07:44
Location: Indiana, United States
Has thanked: 121 times
Been thanked: 445 times


Return to Programming Talk

Who is online

Users browsing this forum: No registered users and 36 guests


Who is online

In total there are 36 users online :: 0 registered, 0 hidden and 36 guests (based on users active over the past 10 minutes)
Most users ever online was 4143 on 23 Jan 2024, 08:21

Users browsing this forum: No registered users and 36 guests

Login Form