It is currently 26 Apr 2024, 10:32
   
Text Size

General DotP 2014 Coding Questions

Moderator: CCGHQ Admins

Re: General DotP 2014 Coding Questions

Postby GrovyleXShinyCelebi » 18 Jan 2014, 14:45

thefiremind wrote:
GrovyleXShinyCelebi wrote:[lua] [string "TESTCARD2_TITLE (AVAILABILITY)~0x00000164"]:2: attempt to call global 'TFM_SuspendCheck' (a nil value)
There must be something strange going on, because in the code you posted you are using TFM_CanBeSuspended in the AVAILABILITY block, and not TFM_SuspendCheck (which might be how I called the function in the first version, I can't remember). So how can you get an error for a function you didn't use? Maybe you have an old version of your test card that you forgot about?
Oh yeah, I forgot to mention I renamed the function "TFM_CanBeSuspended" as "TFM_SuspendCheck" (as well as changing the name in the .LOL file), because the first one was also giving me a ton of errors, which didn't help at all.

I tried it again by changing both the function in the .LOL file and the one in my test card (which by the way I have NEVER kept an older copy around), I got:

[lua] [string "TESTCARD2_TITLE (AVAILABILITY)~0x00000171"]:2: attempt to call global 'TFM_CanBeSuspended' (a nil value)

The .LOL file I used:

Code: Select all
-- Functions that don't belong to a specific category

TFM_HasCounters = function(object)
-- returns true if object has at least one counter on it
   return object:GetBestOrWorstCounterType(1) ~= 0 or object:GetBestOrWorstCounterType(0) ~= 0
end

TFM_Proliferate = function()
-- runs the proliferate mechanic on permanents
   local filter = ClearFilter()
   TFM_FilterPermanents(filter)
   local filter_count = filter:EvaluateObjects()
   if filter_count > 0 then
      for i=0,filter_count-1 do
         local permanent = filter:GetNthEvaluatedObject(i)
         local suitable_counter_type = 0
         if permanent:GetController():GetTeam() == EffectController():GetTeam() then
            suitable_counter_type = permanent:GetBestOrWorstCounterType(1)
         else
            suitable_counter_type = permanent:GetBestOrWorstCounterType(0)
         end
         if suitable_counter_type ~= 0 then
            permanent:AddCounters(suitable_counter_type, 1)
         end
      end
   end
end

TFM_UntilMyNextTurn = function(currentTurn)
-- to be used in durations that last "until your next turn"
   if currentTurn ~= nil then
      local controller = EffectController()
      if controller ~= nil then
         return controller:MyTurn() and MTG():GetTurnNumber() > currentTurn
      else
         -- NOTE: This still fails if the effect is issued during another player's turn or if players skip turns or take extra turns.
         -- The solutions are too complicated to be worth using them so I decided to live with the approximation.
         return MTG():GetTurnNumber() >= currentTurn + MTG():GetNumberOfPlayers()
      end
   end
   return true
end

TFM_KinshipCheck = function(creature1, creature2)
-- returns true if creature1 and creature2 share at least a creature type
   if creature1 ~= nil and creature2 ~= nil then
      for subtype=1000,1230 do
         if creature1:GetSubType():Test(subtype) and creature2:GetSubType():Test(subtype) then
            return true
         end
      end
   end
   return false
end

TFM_AnyOpponentBloodied = function()
-- returns true if any of the controller's opponents have 10 or less life
   local myTeam = EffectController():GetTeam()
   for i=0,MTG():GetNumberOfPlayers()-1 do
      local nthPlayer = MTG():GetNthPlayer(i)
      if nthPlayer ~= nil and nthPlayer:GetTeam() ~= myTeam then
         if nthPlayer:GetLifeTotal() < 11 then
            return true
         end
      end
   end
   return false
end

TFM_TimeLimitedCloneEffectsFix_Condition = function()
-- to be used as trigger condition for the time-limited clone effects fix on Shapesharer and similar cards
   local tobj = TriggerObject()
   local filter = ClearFilter()
   filter:SetZone(ZONE_ANYWHERE)
   TFM_FilterNameSet(filter, "HAVE_TIME_LIMITED_CLONE_EFFECTS_FIX", true)
   filter:EvaluateObjects()
   return Object() == filter:GetNthEvaluatedObject(0) and TFM_IsInNameSet(tobj, "CLONES") == false and TFM_Transform().GetStatus(tobj) == 0
end

TFM_CanBeSuspended = function()
-- to be used in an AVAILABILITY block for the suspend ability
-- NOTE: there are uncovered scenarios (for example, "as though it has flash" property)
   return Object():GetOwner():GetCurrentCharacteristics():Bool_Get(PLAYER_CHARACTERISTIC_CANT_CAST_SPELLS) == false and
   Object():GetCurrentCharacteristics():Bool_Get(CHARACTERISTIC_CANT_BE_PLAYED) == false and
   ( Object():GetOwner():IsSorceryTime() or Object():GetCurrentCharacteristics():Bool_Get(CHARACTERISTIC_FLASH) )
end

TFM_AddSuspendScore = function(suspend_cost, casting_cost, alternative_score)
-- to be used in an AI_CUSTOM_SCORE block so that the AI considers suspending the card
   local source = EffectSource()
   if source ~= nil then
      local owner = source:GetOwner()
      local apply_alternative_score = true
      if owner:IsAI() then
         if TFM_CanBeSuspended() and owner:CanPayManaCost(suspend_cost) and
         (casting_cost == nil or owner:CanPayManaCost(casting_cost) == false) then
            apply_alternative_score = false
            local score = 1000
            if source:GetCardType():Test(CARD_TYPE_CREATURE) then
               local characteristics = source:GetCurrentCharacteristics()
               score = score + 200*characteristics:Power_Get() + 100*characteristics:Toughness_Get()
            end
            source:AddScore(-score)
         end
      end
      if alternative_score ~= nil and apply_alternative_score then
         source:AddScore(alternative_score)
      end
   end
end

TFM_RemoveCardType = function(object, type)
-- removes the specified type from object, re-applying the other ones when needed
   local characteristics = object and object:GetCurrentCharacteristics()
   if characteristics ~= nil then
      characteristics:SubType_GetWritable():ClearAllOfType(type)
      local old_types = {}
      for t=CARD_TYPE_ARTIFACT,CARD_TYPE_TRIBAL do
         old_types[t] = object:GetCardType():Test(t)
      end
      local card_type = characteristics:CardType_GetWritable()
      card_type:Clear()
      for t=CARD_TYPE_ARTIFACT,CARD_TYPE_TRIBAL do
         if old_types[t] and t ~= type then
            card_type:Add(t)
         end
      end
   end
end

TFM_IsTargetting = function(spell, ...)
-- returns true if the spell is targetting at least one of the other parameters (they can be either cards or players)
   local param_count = #arg
   if spell ~= nil and param_count > 0 then
      local spellDC = spell:GetDataChest()
      if spellDC ~= nil then
         for i=0,99 do
            local targetDC = spellDC:Get_NthTargets(i)
            if targetDC ~= nil and targetDC:Count() > 0 then
               for j=0,targetDC:Count()-1 do
                  local target_card = targetDC:Get_CardPtr(j)
                  local target_player = targetDC:Get_PlayerPtr(j)
                  for k=1,param_count do
                     local param = arg[k]
                     if param ~= nil and (param == target_card or param == target_player) then
                        return true
                     end
                  end
               end
            end
         end
      end
   end
   return false
end
P.S. The suspend ability from my test card:

Code: Select all
  <ACTIVATED_ABILITY forced_skip="1" active_zone="ZONE_HAND">
    <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Suspend 4—{W}{U}]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[Suspension 4 — {W}{U}]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[Suspender 4—{W}{U}.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[Aussetzen 4 {W}{U}]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[Sospendere 4-{W}{U}]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="jp-JA"><![CDATA[待機 4―{W}{U}]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ko-KR"><![CDATA[Suspend 4—{W}{U}]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ru-RU"><![CDATA[Отсрочка 4—{W}{U}]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="pt-BR"><![CDATA[Suspender 4—{W}{U}]]></LOCALISED_TEXT>
    <COUNTER_REGISTRATION name="Time" proliferate="11" />
    <AVAILABILITY>
    return TFM_CanBeSuspended()
    </AVAILABILITY>
    <PLAY_TIME_ACTION>
    EffectDC():Protect_CardPtr(COMPARTMENT_ID_EFFECT_SOURCE)
    </PLAY_TIME_ACTION>
    <COST type="ExileSelf" />
    <COST mana_cost="{1}" type="Mana" />
    <RESOLUTION_TIME_ACTION>
    if EffectSource() ~= nil then
       EffectSource():AddCounters( MTG():GetCountersType("Time"), 4 )
    end
    </RESOLUTION_TIME_ACTION>
    <CONTINUOUS_ACTION layer="8">
    if EffectSource() ~= nil then
       EffectSource():GetCurrentCharacteristics():Bool_Set(TFM_FAKE_SUSPEND_CHARACTERISTIC, 1)
    end
    </CONTINUOUS_ACTION>
    <CONTINUOUS_ACTION layer="6">
    if EffectSource() ~= nil then
       local characteristics = EffectSource():GetCurrentCharacteristics()
       characteristics:GrantAbility(0)
       characteristics:GrantAbility(1)
       --characteristics:GrantAbility(2)
    end
    </CONTINUOUS_ACTION>
    <DURATION>
    return EffectSource() == nil
    </DURATION>
    <AI_AVAILABILITY window_step="main_2" window_turn="my_turn" type="window" />
  </ACTIVATED_ABILITY>
  <TRIGGERED_ABILITY resource_id="0" active_zone="ZONE_EXILE">
    <TRIGGER value="BEGINNING_OF_PLAYERS_STEP" simple_qualifier="controller">
    return MTG():GetStep() == STEP_UPKEEP
    </TRIGGER>
    <INTERVENING_IF>
    return EffectSourceLKI():CountCounters( MTG():GetCountersType("Time") ) &gt; 0
    </INTERVENING_IF>
    <RESOLUTION_TIME_ACTION>
    if EffectSource() ~= nil then
       EffectSource():RemoveCounters( MTG():GetCountersType("Time"), 1 )   
    end
    </RESOLUTION_TIME_ACTION>
    <AUTO_SKIP always="1" />
  </TRIGGERED_ABILITY>
  <TRIGGERED_ABILITY resource_id="1" active_zone="ZONE_EXILE">
    <TRIGGER value="COUNTERS_CHANGED" simple_qualifier="self">
    return GetAmount() &lt; 0 and
    CounterTypeIndex() == MTG():GetCountersType("Time") and
    EffectSource():CountCounters( MTG():GetCountersType("Time") ) == 0
    </TRIGGER>
    <RESOLUTION_TIME_ACTION>
    local source = EffectSource()
    if source ~= nil and source:GetOwner():CanCastSpellForFree(source) then
       EffectDC():Protect_CardPtr(COMPARTMENT_ID_EFFECT_SOURCE)
       source:GetOwner():CastSpellForFree(source)
    end
    </RESOLUTION_TIME_ACTION>
    <RESOLUTION_TIME_ACTION>
    local source = EffectSource()
    if source ~= nil then
       local delayDC = EffectDC():Make_Chest(1)
       delayDC:Set_CardPtr(0, source)
       delayDC:Protect_CardPtr(0)
       delayDC:Set_PlayerPtr( 1, source:GetOwner() )
       --MTG():CreateDelayedTrigger(2, delayDC)
    end
    </RESOLUTION_TIME_ACTION>
  </TRIGGERED_ABILITY>
  <HELP title="MORE_INFO_TITLE_SUSPEND" body="MORE_INFO_BODY_SUSPEND" zone="ZONE_ANY" />
  <AI_CUSTOM_SCORE zone="ZONE_HAND">
  if Object():GetOwner():Hand_Count() &lt; 4 then
     TFM_AddSuspendScore("{1}")
  end
  </AI_CUSTOM_SCORE>
User avatar
GrovyleXShinyCelebi
 
Posts: 294
Joined: 12 Jun 2013, 18:23
Has thanked: 14 times
Been thanked: 37 times

Re: General DotP 2014 Coding Questions

Postby GrovyleXShinyCelebi » 19 Jan 2014, 17:20

OK, managed to fix the suspend issue, turns out it was an issue with making WADs with RSN's custom wad program in his deck editor.

Anyways, I have another question with card Psychotic Episode. It turns out the game engine won't let you show cards from two zones at the same time. So, I tried two different workarounds, one with a multiple choice allowing the user to select which zone to choose and another with choosing a card being optional and if the user doesn't choose anything the game assumes top card is what the user wants to put on the bottom of the library:

Code: Select all
   <SFX text="TARGET_PESTS_PLAY" />
    <TARGET tag="CARD_QUERY_CHOOSE_PLAYER_DISCARD_1" 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>
    local target = EffectDC():Get_Targets(0):Get_PlayerPtr(0)
    if target ~= nil then
       target:RevealHand()
    end
    </RESOLUTION_TIME_ACTION>
    <RESOLUTION_TIME_ACTION>
    local target = EffectDC():Get_Targets(0):Get_PlayerPtr(0)
    if target ~= nil then
   local card = target:Library_GetTop()
   if card ~= nil then
      card:Reveal()
   end
    end
    </RESOLUTION_TIME_ACTION>
    <RESOLUTION_TIME_ACTION>
    local target_player = EffectDC():Get_Targets(0):Get_PlayerPtr(0)
    if target_player ~= nil then
          local filter = ClearFilter()
      filter:SetZone( ZONE_HAND, target_player )
          EffectController():ChooseItem( "CARD_QUERY_CHOOSE_CARD_PSYCHOTIC", EffectDC():Make_Targets(1), QUERY_FLAG_MAY )
    end
    </RESOLUTION_TIME_ACTION>
    <RESOLUTION_TIME_ACTION>
    local target_player = EffectDC():Get_Targets(0):Get_PlayerPtr(0)
    if target_player ~= nil then
       local chosen_card = EffectDC():Get_Targets(1) and EffectDC():Get_Targets(1):Get_CardPtr(0)       
       if chosen_card ~= nil then
          chosen_card:PutOnBottomOfLibrary()
   else
      local card = target_player:Library_GetTop()
      if card ~= nil then
         card:PutOnBottomOfLibrary()
         EffectController():DisplayMessage( "MESSAGE_PSYCHOTIC" )
         target_player:DisplayMessage( "MESSAGE_PSYCHOTIC" )
      end
       end
    end
    </RESOLUTION_TIME_ACTION>   
The problem is that both requires that the target player's cards in hand and the card on the top of the library to be revealed. However, it seems that neither approaches specifically reveal the cards (as in, show everyone the cards without anything being selectable). I thought the first might be an issue with RevealHand()/Reveal() and queries but the second one I'm sure was done with Lobotomy. Know what might be the issue?
User avatar
GrovyleXShinyCelebi
 
Posts: 294
Joined: 12 Jun 2013, 18:23
Has thanked: 14 times
Been thanked: 37 times

Re: General DotP 2014 Coding Questions

Postby thefiremind » 19 Jan 2014, 17:34

As sumomole said once, some functions can interfere with other functions. Maybe two different reveals aren't meant to be used together (if you notice how Reveal() works, it waits for all the reveals to be called and then reveals everything at once, maybe the RevealHand() screws it up).

If I had to code Psychotic Episode, I would put the cards in hand and the top library card in a single chest, and show that to the player who needs to choose, maybe with a custom query text that specifies "the top card of the library is the leftmost" (or the rightmost, according to where you decide to put it in the chest). The problem of revealing the cards to the other players still persists, but you can use a dummy query that shows the same chest to all other players without caring about what they choose.
< 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: General DotP 2014 Coding Questions

Postby GrovyleXShinyCelebi » 25 Jan 2014, 00:23

Another little question, do you know if flashback in DOTP 2014 accepts payment for life? I made Spirit Flare but when I was testing it I noticed that I couldn't activate the flashback ability (it's highlighted but clicking on the ability won't do anything - also it's the "Tap target untapped creature" ability that's being highlighted, not the flashback ability).

Code: Select all
  <UTILITY_ABILITY qualifier="Additional" linked_ability_group="1">
    <COST type="generic">
      <PREREQUISITE>
      local filter = ClearFilter()
      filter:Add( FE_IS_TAPPED, false )
      filter:Add( FE_TYPE, OP_IS, CARD_TYPE_CREATURE )
      filter:Add( FE_CONTROLLER, OP_IS, EffectController() )
      return filter:CountStopAt(1) == 1
      </PREREQUISITE>
      <RESOLUTION_TIME_ACTION>
      local filter = ClearFilter()
      filter:Add( FE_IS_TAPPED, false )
      filter:Add( FE_CONTROLLER, OP_IS, EffectController() )
      filter:Add( FE_TYPE, OP_IS, CARD_TYPE_CREATURE )
      EffectController():ChooseItem( "CARD_QUERY_CHOOSE_CREATURE_TAP", EffectDC():Make_Targets(6) )
      </RESOLUTION_TIME_ACTION>
      <RESOLUTION_TIME_ACTION>
      local creature = EffectDC():Get_Targets(6):Get_CardPtr(0)
      if creature ~= nil then
        LinkedDC():Set_CardPtr(2, creature)
         LinkedDC():Set_Int( 1, creature:GetCurrentCharacteristics():Power_Get() )
         creature:Tap()
      end
      </RESOLUTION_TIME_ACTION>
    </COST>
  </UTILITY_ABILITY>
  <SPELL_ABILITY linked_ability_group="1">
    <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Tap target untapped creature you control. If you do, it deals damage equal to its power to target attacking or blocking creature an opponent controls.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[Engagez la créature dégagée que vous contrôlez. Si vous faites ainsi, elle inflige un nombre de blessures égal à sa force à la créature attaquante ou bloqueuse ciblée qu’un adversaire contrôle.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[Gira la criatura objetivo enderezada que controles. Si lo haces, esa criatura hace una cantidad de daño igual a su fuerza a la criatura atacante o bloqueadora que controle un oponente.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[Tappe eine ungetappte Kreatur deiner Wahl, die du kontrollierst. Falls du dies tust, fügt sie einer angreifenden oder blockenden Kreatur deiner Wahl, die ein Gegner kontrol-liert, Schadenspunkte in Höhe ihrer Stärke zu.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[TAPpa una creatura STAPpata bersaglio che controlli. Se lo fai, essa infligge un danno pari alla propria forza a una creatura attaccante o bloccante bersaglio controllata da un avversario.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="jp-JA"><![CDATA[Tap target untapped creature you control. If you do, it deals damage equal to its power to target attacking or blocking creature an opponent controls.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ko-KR"><![CDATA[Tap target untapped creature you control. If you do, it deals damage equal to its power to target attacking or blocking creature an opponent controls.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ru-RU"><![CDATA[Tap target untapped creature you control. If you do, it deals damage equal to its power to target attacking or blocking creature an opponent controls.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="pt-BR"><![CDATA[Vire uma criatura alvo desvirada que você controla. Se o fizer, ela causa uma quantidade de pontos de dano igual ao seu poder à criatura alvo atacante ou bloqueadora que um oponente controla.]]></LOCALISED_TEXT>
    <SFX text="TARGET_SUN_PLAY" /> 
    <TARGET tag="CARD_QUERY_CHOOSE_CREATURE_DEAL_DAMAGE" definition="0" compartment="0" count="1" />
    <TARGET_DEFINITION id="0">
    local filter = ClearFilter()
    filter:Add( FE_TYPE, OP_IS, CARD_TYPE_CREATURE )
    local subfilter = filter:AddSubFilter_Or()
    subfilter:Add( FE_IS_ATTACKING, true )
    subfilter:Add( FE_IS_BLOCKING, true )
    filter:Add( FE_TEAM, OP_NOT, EffectController():GetTeam() )
    </TARGET_DEFINITION>
    <RESOLUTION_TIME_ACTION>
     local card = LinkedDC():Get_CardPtr(2)
     local int = LinkedDC():Get_Int(1)
     local target = EffectDC():Get_Targets(0):Get_CardPtr(0)
     if card ~= nil and int ~= nil and target ~= nil then
   card:DealDamageTo( int, target)
     end
    </RESOLUTION_TIME_ACTION>
  </SPELL_ABILITY>
  <UTILITY_ABILITY qualifier="Flashback" active_zone="ZONE_GRAVEYARD">
    <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Flashback—{1}{W}, Pay 3 life.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[Flashback ]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[Retrospectiva o1oW, pagar 3 vidas.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[Rückblende—o1oW, bezahle 3 Lebenspunkte.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[Flashback-{1}{W}, Paga 3 punti vita.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="jp-JA"><![CDATA[Flashback—{1}{W}, Pay 3 life.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ko-KR"><![CDATA[Flashback—{1}{W}, Pay 3 life.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ru-RU"><![CDATA[Flashback—{1}{W}, Pay 3 life.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="pt-BR"><![CDATA[Recapitular – o1oW, Pague 3 pontos de vida.]]></LOCALISED_TEXT>
    <COST mana_cost="{1}{W}" type="Mana" />
    <COST type="Life" amount="3" />
  </UTILITY_ABILITY>
User avatar
GrovyleXShinyCelebi
 
Posts: 294
Joined: 12 Jun 2013, 18:23
Has thanked: 14 times
Been thanked: 37 times

Re: General DotP 2014 Coding Questions

Postby RiiakShiNal » 25 Jan 2014, 02:55

I haven't tried putting a like cost into a flashback ability, but I do notice that you have coded the card wrong. You made "Tap target untapped creature you control." a separate additional cost (it should tap at spell resolution time so if the spell is countered it should remain untapped), but it isn't it is part of the SPELL_ABILITY and not a cost so that could be part of the problem. The SPELL_ABILITY should have two targets one is the untapped creature you control the other is the attacking or blocking creature an opponent controls.
RiiakShiNal
Programmer
 
Posts: 2185
Joined: 16 May 2011, 21:37
Has thanked: 75 times
Been thanked: 497 times

Re: General DotP 2014 Coding Questions

Postby MC Brodie » 09 Feb 2014, 01:28

I'm getting a script log error on my code for Blood Clock. I know there is a workaround for what I'm trying to do but I can't remember where I saw it. The problem is if the player chooses to pay the life then I get a script log error for attempting to index a nil value for this line:
Code: Select all
local oPermanent = EffectDC():Get_Targets(0):Get_CardPtr(0)
I'm assuming this is because the Get_Targets(0) doesn't exist so I get the error when it checks for Get_CardPtr(0). Like I said, I think I've saw a one liner out there that covers this scenario but I can't find it. Thanks.

Blood Clock (gives errors) | Open
Code: Select all
  <TRIGGERED_ABILITY>
    <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[At the beginning of each player’s upkeep, that player returns a permanent he or she controls to its owner’s hand unless he or she pays 2 life.]]></LOCALISED_TEXT>
   <TRIGGER value="BEGINNING_OF_PLAYERS_STEP">
    return MTG():GetStep() == STEP_UPKEEP
    </TRIGGER>
   <RESOLUTION_TIME_ACTION>
   local player = TriggerPlayer()
    if player ~= nil and player:CanPayResourceCost(2) then
       player:BeginNewMultipleChoice()   
       player:AddMultipleChoiceAnswer( "CARD_QUERY_MCR_OPTION_PAY_2_LIFE" )   
       player:AddMultipleChoiceAnswer( "CARD_QUERY_CHOOSE_PERMANENT_TO_PUT_INTO_HAND" )
       player:AskMultipleChoiceQuestion( "CARD_QUERY_MCR_BLOOD_CRYPT", EffectSource() )
    end
    </RESOLUTION_TIME_ACTION>
   <RESOLUTION_TIME_ACTION>
   local player = TriggerPlayer()
    if player ~= nil then
      if player:CanPayResourceCost(2) and player:GetMultipleChoiceResult() ~= 1 then
         player:PayResourceCost(2)
      else
         local filter = ClearFilter()
         filter:Add( FE_CONTROLLER, OP_IS, player )
         MCR_FilterPermanents(filter)
         if filter:CountStopAt(1) == 1 then
            player:ChooseItem( "CARD_QUERY_CHOOSE_PERMANENT_TO_PUT_INTO_HAND", EffectDC():Make_Targets(0) )
         end
       end
    end
   </RESOLUTION_TIME_ACTION>
   <RESOLUTION_TIME_ACTION>
   local oPermanent = EffectDC():Get_Targets(0):Get_CardPtr(0)
    if oPermanent ~= nil then
      oPermanent:PutInHand()
    end
   </RESOLUTION_TIME_ACTION>
  </TRIGGERED_ABILITY>
-----------------------------------------------------------------------
Song of the Day: 46 and 2 (cover)
MC Brodie
 
Posts: 310
Joined: 01 Jun 2013, 00:10
Has thanked: 44 times
Been thanked: 34 times

Re: General DotP 2014 Coding Questions

Postby RiiakShiNal » 09 Feb 2014, 02:01

MC Brodie wrote:I'm getting a script log error on my code for Blood Clock. I know there is a workaround for what I'm trying to do but I can't remember where I saw it. The problem is if the player chooses to pay the life then I get a script log error for attempting to index a nil value for this line:
Code: Select all
local oPermanent = EffectDC():Get_Targets(0):Get_CardPtr(0)
I'm assuming this is because the Get_Targets(0) doesn't exist so I get the error when it checks for Get_CardPtr(0). Like I said, I think I've saw a one liner out there that covers this scenario but I can't find it. Thanks.

Blood Clock (gives errors) | Open
Code: Select all
  <TRIGGERED_ABILITY>
    <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[At the beginning of each player’s upkeep, that player returns a permanent he or she controls to its owner’s hand unless he or she pays 2 life.]]></LOCALISED_TEXT>
   <TRIGGER value="BEGINNING_OF_PLAYERS_STEP">
    return MTG():GetStep() == STEP_UPKEEP
    </TRIGGER>
   <RESOLUTION_TIME_ACTION>
   local player = TriggerPlayer()
    if player ~= nil and player:CanPayResourceCost(2) then
       player:BeginNewMultipleChoice()   
       player:AddMultipleChoiceAnswer( "CARD_QUERY_MCR_OPTION_PAY_2_LIFE" )   
       player:AddMultipleChoiceAnswer( "CARD_QUERY_CHOOSE_PERMANENT_TO_PUT_INTO_HAND" )
       player:AskMultipleChoiceQuestion( "CARD_QUERY_MCR_BLOOD_CRYPT", EffectSource() )
    end
    </RESOLUTION_TIME_ACTION>
   <RESOLUTION_TIME_ACTION>
   local player = TriggerPlayer()
    if player ~= nil then
      if player:CanPayResourceCost(2) and player:GetMultipleChoiceResult() ~= 1 then
         player:PayResourceCost(2)
      else
         local filter = ClearFilter()
         filter:Add( FE_CONTROLLER, OP_IS, player )
         MCR_FilterPermanents(filter)
         if filter:CountStopAt(1) == 1 then
            player:ChooseItem( "CARD_QUERY_CHOOSE_PERMANENT_TO_PUT_INTO_HAND", EffectDC():Make_Targets(0) )
         end
       end
    end
   </RESOLUTION_TIME_ACTION>
   <RESOLUTION_TIME_ACTION>
   local oPermanent = EffectDC():Get_Targets(0):Get_CardPtr(0)
    if oPermanent ~= nil then
      oPermanent:PutInHand()
    end
   </RESOLUTION_TIME_ACTION>
  </TRIGGERED_ABILITY>
I believe the one liner you are looking for is this:
Code: Select all
local oPermanent = EffectDC():Get_Targets(0) and EffectDC():Get_Targets(0):Get_CardPtr(0)
RiiakShiNal
Programmer
 
Posts: 2185
Joined: 16 May 2011, 21:37
Has thanked: 75 times
Been thanked: 497 times

Re: General DotP 2014 Coding Questions

Postby MC Brodie » 09 Feb 2014, 02:19

RiiakShiNal wrote:I believe the one liner you are looking for is this:
Code: Select all
local oPermanent = EffectDC():Get_Targets(0) and EffectDC():Get_Targets(0):Get_CardPtr(0)
Thanks that worked perfectly. Would you mind doing me another favor and explaining how that actually works? It's not that syntactic sugary to me :D .
-----------------------------------------------------------------------
Song of the Day: 46 and 2 (cover)
MC Brodie
 
Posts: 310
Joined: 01 Jun 2013, 00:10
Has thanked: 44 times
Been thanked: 34 times

Re: General DotP 2014 Coding Questions

Postby RiiakShiNal » 09 Feb 2014, 03:32

MC Brodie wrote:
RiiakShiNal wrote:I believe the one liner you are looking for is this:
Code: Select all
local oPermanent = EffectDC():Get_Targets(0) and EffectDC():Get_Targets(0):Get_CardPtr(0)
Thanks that worked perfectly. Would you mind doing me another favor and explaining how that actually works? It's not that syntactic sugary to me :D .
It is and isn't syntactic sugar. First the scripting language gets the value of EffectDC():Get_Targets(0) and stores it in oPermanent. If the value is nil then logical short-circuiting kicks in and prevents the "and"ed statement from being checked (much like in boolean logic if the first argument is false then it doesn't matter how many other checks are "and"ed together the whole thing will be false, nils will propagate). If Get_Targets(0) is not nil then the "and"ed statement will be checked and processed and EffectDC():Get_Targets(0):Get_CardPtr(0) will be stored in oPermanent.

The end result (in Lua) would be similar to this:
Code: Select all
local oPermanent = EffectDC():Get_Targets(0)
if (oPermanent ~= nil) then
  oPermanent = EffectDC():Get_Targets(0):Get_CardPtr(0)
end
Note that this does not work in all languages and should not be construed as normal behavior. Some languages will not allow statement short-circuiting if a preceding statement is nil, other languages do not allow value assignment in this fashion, and others do not allow doing a boolean logic operation on a nil (or null) value. For example in C++ to do something similar you would use something like this:
Code: Select all
CardPtr oPermanent = (EffectDC()->Get_Targets(0) ? EffectDC()->Get_Targets(0)->Get_CardPtr(0) : null)
Or this if working with object instances instead of pointers (or in C#):
Code: Select all
CardPtr oPermanent = (EffectDC().Get_Targets(0) ? EffectDC().Get_Targets(0).Get_CardPtr(0) : null)
Though that can lead to memory leaks in C++ if not using smart pointers as you could end up with objects that report that there are still pointers to them even if the actual pointers were already discarded.
RiiakShiNal
Programmer
 
Posts: 2185
Joined: 16 May 2011, 21:37
Has thanked: 75 times
Been thanked: 497 times

Re: General DotP 2014 Coding Questions

Postby braquio » 21 Feb 2014, 01:34

I'm coding Cyclonic Rift with overload and i have the code at 95%, but i still have 1 problem :twisted: , when i play a card with overload i still have to choose 1 target before its resolved
cyclonic rift | Open
Code: Select all
<?xml version='1.0' encoding='UTF-8'?>
<CARD_V2 ExportVersion="1">
  <FILENAME text="CYCLONIC_RIFT_666270798" />
  <CARDNAME text="CYCLONIC_RIFT" />
  <TITLE>
    <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Cyclonic Rift]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[Faille cyclonique]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[Grieta ciclónica]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[Rift des Sturmtiefs]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[Squarcio Ciclonico]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="jp-JA"><![CDATA[サイクロンの裂け目]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ko-KR"><![CDATA[회오리 균열]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ru-RU"><![CDATA[Циклонический Разлом]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="pt-BR"><![CDATA[Fenda Ciclônica]]></LOCALISED_TEXT>
  </TITLE>
  <MULTIVERSEID value="666270798" />
  <ARTID value="666270798" />
  <ARTIST name="Chris Rahn" />
  <CASTING_COST cost="{1}{U}" />
  <FLAVOURTEXT>
    <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[The Izzet specialize in unnatural disaster.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[Les Izzet sont spécialisés dans les catastrophes artificielles.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[Los ízzet se especializan en desastres no naturales.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[Die Izzet sind auf unnatürliche Katastrophen spezialisiert.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[Gli Izzet sono specializzati in catastrofi innaturali.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="jp-JA"><![CDATA[イゼット団は不自然災害を専門としている。]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ko-KR"><![CDATA[이젯 길드의 특기는 부자연스러운 재해다.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ru-RU"><![CDATA[Иззеты являются мастерами неприродных катастроф.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="pt-BR"><![CDATA[A especialidade dos Izzet são os desastres não naturais.]]></LOCALISED_TEXT>
  </FLAVOURTEXT>
  <TYPE metaname="Instant" />
  <EXPANSION value="RTR" />
  <RARITY metaname="R" />
  <UTILITY_ABILITY qualifier="Kicker">
    <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Overload {6}{U}]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[Surcharge {6}{U} » par « chaque ».)]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[Sobrecarga {6}{U}.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[Überlast {6}{U}]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[Sovraccarico {6}{U}]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="jp-JA"><![CDATA[超過 {6}{U}]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ko-KR"><![CDATA[과부하 {6}{U}]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ru-RU"><![CDATA[Перегрузка {6}{U}]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="pt-BR"><![CDATA[Sobrecarga {6}{U}]]></LOCALISED_TEXT>
    <COST mana_cost="{5}" type="Mana" />
    <ABILITY_TEXT tag="OVERLOAD_QUERY_CYCLONIC_RIFT_OVERLOADED" secondary_tag="OVERLOAD_QUERY_CYCLONIC_RIFT_NO_OVERLOADED" />
  </UTILITY_ABILITY>

  <SPELL_ABILITY>
    <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Return target nonland permanent you don’t control to its owner’s hand.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[Renvoyez un permanent non-terrain ciblé que vous ne contrôlez pas dans la main de son propriétaire.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[Regresa el permanente objetivo que no sea tierra que no controles a la mano de su propietario.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[Bringe eine bleibende Karte deiner Wahl, die kein Land ist und die du nicht kontrollierst, auf die Hand ihres Besitzers zurück.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[Fai tornare un permanente non terra bersaglio che non controlli in mano al suo proprietario.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="jp-JA"><![CDATA[あなたがコントロールしていない土地でないパーマネント1つを対象とし、それをオーナーの手札に戻す。]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ko-KR"><![CDATA[당신이 조종하지 않는 지속물 중 대지가 아닌 지속물 한 개를 목표로 정한다. 그 지속물을 소유자의 손으로 되돌린다.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ru-RU"><![CDATA[Верните целевой не являющийся землей перманент, который не находится под вашим контролем, в руку его владельца.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="pt-BR"><![CDATA[Devolva a permanente alvo que não seja um terreno e que você não controle para a mão de seu dono.]]></LOCALISED_TEXT>
    <SFX text="TARGET_MAELSTROM_PLAY" />

       <RESOLUTION_TIME_ACTION>
          if EffectSource():WasKicked() == false   then
         <TARGET tag="CARD_QUERY_CHOOSE_NONLAND_PERMANENT_TO_PUT_INTO_HAND" definition="0" compartment="0" count="1" />
      end
   </RESOLUTION_TIME_ACTION>
   <TARGET_DEFINITION id="0">
      if EffectSource():WasKicked() == false   then
         local filter = ClearFilter()
             filter:Add( FE_TYPE, OP_NOT, CARD_TYPE_LAND )
         filter:Add( FE_IS_PERMANENT, true )
         filter:Add(FE_CONTROLLER, OP_NOT, EffectController())
      end
       </TARGET_DEFINITION>
   <RESOLUTION_TIME_ACTION>
      if EffectSource():WasKicked() == false   then
             local target = EffectDC():Get_Targets(0):Get_CardPtr(0)
          if  target ~= nil then
              target:PutInHand()
          end 
       end 
    </RESOLUTION_TIME_ACTION>
   

   <FILTER filter_id="1">          
        local filter = ClearFilter()
             filter:Add( FE_TYPE, OP_NOT, CARD_TYPE_LAND )
           filter:Add( FE_IS_PERMANENT, true )
      filter:Add( FE_CONTROLLER, OP_NOT, EffectController())
             filter:SetZone( ZONE_BATTLEFIELD )
        </FILTER>
   <RESOLUTION_TIME_ACTION filter_id="1">
      if EffectSource():WasKicked()  then
           if FilteredCard() ~= nil then   
                FilteredCard():PutInHand()
         end
      end
   </RESOLUTION_TIME_ACTION>            
  </SPELL_ABILITY>

     <AI_AVAILABILITY type="in_response" response_source="1" />
   <AI_AVAILABILITY window_step="begin_combat" window_turn="their_turn" type="window" />
   <AI_AVAILABILITY window_step="declare_attackers" window_turn="their_turn" type="window" />
   <AI_AVAILABILITY window_step="main_1" window_turn="my_turn" type="window" />
   <AI_AVAILABILITY window_step="declare_blockers" type="window" />
   <AI_AVAILABILITY window_step="end_of_turn" type="window" />
   <AI_AVAILABILITY type="in_response" response_source="1" response_target="1" />
   <AI_BASE_SCORE score="900" zone="ZONE_HAND" />
</CARD_V2>
If someone could help me we can finish this hard ability.
____________________________________________________________________________________________________________________________
Braquio Dotp2014 DLC
Alternative Sealed Campaigns for DotP 2014
User avatar
braquio
 
Posts: 143
Joined: 16 Feb 2014, 19:21
Has thanked: 15 times
Been thanked: 9 times

Re: General DotP 2014 Coding Questions

Postby MC Brodie » 21 Feb 2014, 03:58

Unfortunately a complete rule compliant overload ability is not possible in DotP. GrovyleXShinyCelebi has come up with an approximation (I think it's discussed in this thread if you search for it) that works in most cases however it isn't compliant with things that care if a spell is targeting the permanent (like the Heroic ability) or copy effects (like Twincast). You can find some of his overload cards in this thread:

viewtopic.php?f=109&t=12934

Also, if for some reason you did want to make an overload card that works with Heroic, you might want to take a look at some cards NeoAnderson made. He created a DLC containing Bestow and Heroic creatures that are compatible together. Bestow has a similar issue to overload cards. You may be able to expand what he did with bestow for your overload cards. His DLC is herE:

viewtopic.php?f=109&t=13241
-----------------------------------------------------------------------
Song of the Day: 46 and 2 (cover)
MC Brodie
 
Posts: 310
Joined: 01 Jun 2013, 00:10
Has thanked: 44 times
Been thanked: 34 times

Re: General DotP 2014 Coding Questions

Postby braquio » 21 Feb 2014, 11:10

Hi i revised these links and in bestbow code i dont really understand nothing :D
The aproximation by GrovyleXShinyCelebi is very good and give me new ideas.

The problem is i'm a beginner and i dont know very well how to code my ideas, so i need some help but im sure is posibble to code correctly this abiliy.
Overload spells have to parts, first u have 1 target and scd u have no targets.
If we put the target selection in a block that only happens when no overload cost is selected we get the code complete and working.
Now, How we do that?
I try it isolating the target selection placing it into an if condition. But dont work properly.
Anyway if someone can reply my quiestions may be i could do it:
Wich instruction or block is exactly where make target?
a)
Code: Select all
<TARGET tag="CARD_QUERY_CHOOSE_NONLAND_PERMANENT_TO_PUT_INTO_HAND" definition="0" compartment="0" count="1" />
b)
Code: Select all
<TARGET_DEFINITION id="0">
      if EffectSource():WasKicked() == false   then
         local filter = ClearFilter()
             filter:Add( FE_TYPE, OP_NOT, CARD_TYPE_LAND )
         filter:Add( FE_IS_PERMANENT, true )
         filter:Add(FE_CONTROLLER, OP_NOT, EffectController())
      end
       </TARGET_DEFINITION>
c)
Code: Select all
<RESOLUTION_TIME_ACTION>
      if EffectSource():WasKicked() == false   then
             local target = EffectDC():Get_Targets(0):Get_CardPtr(0)
          if  target ~= nil then
              target:PutInHand()
          end 
       end 
    </RESOLUTION_TIME_ACTION>
Another question
is possible to do a trigger when the spell go to stack and only if i choose dont overload.
For example something like this?
Code: Select all
<TRIGGERED_ABILITY>
   <TRIGGER value="ZONE_HAND" simple_qualifier="self" to_zone="ZONE_STACK">
      if EffectSource():WasKicked() == false then
         return true      
      end
   </TRIGGER>
   <TARGET tag="CARD_QUERY_CHOOSE_NONLAND_PERMANENT_TO_PUT_INTO_HAND" definition="0" compartment="0" count="1" />
   <TARGET_DEFINITION id="0">   
      local filter = ClearFilter()
          filter:Add( FE_TYPE, OP_NOT, CARD_TYPE_LAND )
      filter:Add( FE_IS_PERMANENT, true )
      filter:Add( FE_CONTROLLER, OP_NOT, EffectController())
    </TARGET_DEFINITION>
  </TRIGGERED_ABILITY>
If i return false in a Trigger value definition, the trigger ability isn't resolved?
If we can do it we can put in the trigger the target selection and in the spell ability the rest of the resolutions that now works perfectly in my code.
Any ideas? :roll:
____________________________________________________________________________________________________________________________
Braquio Dotp2014 DLC
Alternative Sealed Campaigns for DotP 2014
User avatar
braquio
 
Posts: 143
Joined: 16 Feb 2014, 19:21
Has thanked: 15 times
Been thanked: 9 times

Re: General DotP 2014 Coding Questions

Postby RiiakShiNal » 21 Feb 2014, 14:34

braquio wrote:Hi i revised these links and in bestbow code i dont really understand nothing :D
The aproximation by GrovyleXShinyCelebi is very good and give me new ideas.

The problem is i'm a beginner and i dont know very well how to code my ideas, so i need some help but im sure is posibble to code correctly this abiliy.
Overload spells have two parts, first u have 1 target and second u have no targets.
If we put the target selection in a block that only happens when no overload cost is selected we get the code complete and working.
Now, How we do that?
You can't do that properly because there is no way to tell the engine we're only going to use this ability if we're not overloading or we're going to use this other ability if we are overloading. Both abilities will be checked and processed even if you have conditions inside the abilities that limit their use. Because they are both processed and checked, it will ask for you to pick a target regardless of how you want to cast it because targets are chosen before cast, it will allow for incorrect behavior in play. If not casting overloaded then it should only be possible to cast if there are valid targets in play (if there are no valid targets due to Hexproof and/or Shroud then it should not be possible to cast non-overloaded). If cast as non-overloaded and the targets become invalid before resolution then the spell should automatically be countered, an overloaded spell having no targets should not care about this.

braquio wrote:I try it isolating the target selection placing it into an if condition. But dont work properly.
Anyway if someone can reply my quiestions may be i could do it:
Wich instruction or block is exactly where make target?
a)
Code: Select all
<TARGET tag="CARD_QUERY_CHOOSE_NONLAND_PERMANENT_TO_PUT_INTO_HAND" definition="0" compartment="0" count="1" />
b)
Code: Select all
<TARGET_DEFINITION id="0">
      if EffectSource():WasKicked() == false   then
         local filter = ClearFilter()
             filter:Add( FE_TYPE, OP_NOT, CARD_TYPE_LAND )
         filter:Add( FE_IS_PERMANENT, true )
         filter:Add(FE_CONTROLLER, OP_NOT, EffectController())
      end
       </TARGET_DEFINITION>
c)
Code: Select all
<RESOLUTION_TIME_ACTION>
      if EffectSource():WasKicked() == false   then
             local target = EffectDC():Get_Targets(0):Get_CardPtr(0)
          if  target ~= nil then
              target:PutInHand()
          end 
       end 
    </RESOLUTION_TIME_ACTION>
A & B together define the target. The TARGET block references the TARGET_DEFINITION block through the definition="0" attribute and the TARGET_DEFINITION block's id="0" attribute.

C just retrieves the target and operates on it if necessary.

braquio wrote:Another question
is possible to do a trigger when the spell go to stack and only if i choose dont overload.
For example something like this?
Code: Select all
<TRIGGERED_ABILITY>
   <TRIGGER value="ZONE_HAND" simple_qualifier="self" to_zone="ZONE_STACK">
      if EffectSource():WasKicked() == false then
         return true      
      end
   </TRIGGER>
   <TARGET tag="CARD_QUERY_CHOOSE_NONLAND_PERMANENT_TO_PUT_INTO_HAND" definition="0" compartment="0" count="1" />
   <TARGET_DEFINITION id="0">   
      local filter = ClearFilter()
          filter:Add( FE_TYPE, OP_NOT, CARD_TYPE_LAND )
      filter:Add( FE_IS_PERMANENT, true )
      filter:Add( FE_CONTROLLER, OP_NOT, EffectController())
    </TARGET_DEFINITION>
  </TRIGGERED_ABILITY>
If i return false in a Trigger value definition, the trigger ability isn't resolved?
If we can do it we can put in the trigger the target selection and in the spell ability the rest of the resolutions that now works perfectly in my code.
Any ideas? :roll:
Your trigger here will never execute because ZONE_HAND is not a trigger. This relates back to the incorrect behavior I stated earlier in this post. Also the target here would never be used because it is being stored in EffectDC() which can't be accessed outside of it's effect (you would have to put in a RESOLUTION_TIME_ACTION which retrieves the target and puts in into another DC like the LinkedDC() though then you would need to alter your abilities to get access to the LinkedDC()).

Bottom line: There is no way to make a compliant overload in the DotP 2014 engine. The best that can be achieved is an approximation that will not work in all cases.
RiiakShiNal
Programmer
 
Posts: 2185
Joined: 16 May 2011, 21:37
Has thanked: 75 times
Been thanked: 497 times

Re: General DotP 2014 Coding Questions

Postby braquio » 21 Feb 2014, 15:44

The idea is to check the target after i choose overload or not, with a trigger block. then inside the spell ability i have both abilities, the ability with overload and without it, but only is resolved 1, thats its ok and works.
The only problem is that i dont know how to choose a target inside the trigger block, and i dont know how to compile correctly a trigger block

Something like this

Code dont' work | Open
Code: Select all
<?xml version='1.0' encoding='UTF-8'?>
<CARD_V2 ExportVersion="1">
  <FILENAME text="CYCLONIC_RIFT_666270798" />
  <CARDNAME text="CYCLONIC_RIFT" />
  <TITLE>
    <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Cyclonic Rift]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[Faille cyclonique]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[Grieta ciclónica]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[Rift des Sturmtiefs]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[Squarcio Ciclonico]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="jp-JA"><![CDATA[サイクロンの裂け目]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ko-KR"><![CDATA[회오리 균열]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ru-RU"><![CDATA[Циклонический Разлом]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="pt-BR"><![CDATA[Fenda Ciclônica]]></LOCALISED_TEXT>
  </TITLE>
  <MULTIVERSEID value="666270798" />
  <ARTID value="666270798" />
  <ARTIST name="Chris Rahn" />
  <CASTING_COST cost="{1}{U}" />
  <FLAVOURTEXT>
    <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[The Izzet specialize in unnatural disaster.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[Les Izzet sont spécialisés dans les catastrophes artificielles.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[Los ízzet se especializan en desastres no naturales.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[Die Izzet sind auf unnatürliche Katastrophen spezialisiert.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[Gli Izzet sono specializzati in catastrofi innaturali.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="jp-JA"><![CDATA[イゼット団は不自然災害を専門としている。]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ko-KR"><![CDATA[이젯 길드의 특기는 부자연스러운 재해다.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ru-RU"><![CDATA[Иззеты являются мастерами неприродных катастроф.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="pt-BR"><![CDATA[A especialidade dos Izzet são os desastres não naturais.]]></LOCALISED_TEXT>
  </FLAVOURTEXT>
  <TYPE metaname="Instant" />
  <EXPANSION value="RTR" />
  <RARITY metaname="R" />
  <UTILITY_ABILITY qualifier="Kicker">
    <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Overload {6}{U}]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[Surcharge {6}{U} » par « chaque ».)]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[Sobrecarga {6}{U}.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[Überlast {6}{U}]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[Sovraccarico {6}{U}]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="jp-JA"><![CDATA[超過 {6}{U}]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ko-KR"><![CDATA[과부하 {6}{U}]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ru-RU"><![CDATA[Перегрузка {6}{U}]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="pt-BR"><![CDATA[Sobrecarga {6}{U}]]></LOCALISED_TEXT>
    <ABILITY_TEXT tag="OVERLOAD_QUERY_CYCLONIC_RIFT_OVERLOADED" secondary_tag="OVERLOAD_QUERY_CYCLONIC_RIFT_NO_OVERLOADED" />
    <COST mana_cost="{5}" type="Mana" />
  </UTILITY_ABILITY>

  <TRIGGERED_ABILITY linked_ability_group="1">
   <TRIGGER value="TRIGGER_ZONECHANGE_BEGIN" simple_qualifier="self" to_zone="ZONE_STACK" pre_trigger="1"/>
         Return EffectSource():WasKicked()      
   </TRIGGER>
      <TARGET tag="CARD_QUERY_CHOOSE_NONLAND_PERMANENT_TO_PUT_INTO_HAND" definition="0" compartment="0" count="1" />
      <TARGET_DEFINITION id="0">   
         local filter = ClearFilter()
           filter:Add( FE_TYPE, OP_NOT, CARD_TYPE_LAND )
         filter:Add( FE_IS_PERMANENT, true )
         filter:Add( FE_CONTROLLER, OP_NOT, EffectController())
       </TARGET_DEFINITION>   
      <RESOLUTION_TIME_ACTION>
         LinkedDC() = EffectDC():Get_Targets(0):Get_CardPtr(0)
      </RESOLUTION_TIME_ACTION>
  </TRIGGERED_ABILITY>

  <SPELL_ABILITY linked_ability_group="1">
    <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Return target nonland permanent you don’t control to its owner’s hand.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[Renvoyez un permanent non-terrain ciblé que vous ne contrôlez pas dans la main de son propriétaire.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[Regresa el permanente objetivo que no sea tierra que no controles a la mano de su propietario.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[Bringe eine bleibende Karte deiner Wahl, die kein Land ist und die du nicht kontrollierst, auf die Hand ihres Besitzers zurück.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[Fai tornare un permanente non terra bersaglio che non controlli in mano al suo proprietario.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="jp-JA"><![CDATA[あなたがコントロールしていない土地でないパーマネント1つを対象とし、それをオーナーの手札に戻す。]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ko-KR"><![CDATA[당신이 조종하지 않는 지속물 중 대지가 아닌 지속물 한 개를 목표로 정한다. 그 지속물을 소유자의 손으로 되돌린다.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ru-RU"><![CDATA[Верните целевой не являющийся землей перманент, который не находится под вашим контролем, в руку его владельца.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="pt-BR"><![CDATA[Devolva a permanente alvo que não seja um terreno e que você não controle para a mão de seu dono.]]></LOCALISED_TEXT>
    <SFX text="TARGET_MAELSTROM_PLAY" />

   <RESOLUTION_TIME_ACTION>
      local target = LinkedDC()
      if EffectSource():WasKicked() == false then   
          if  target ~= nil then
              target:PutInHand()
          end
       end 
    </RESOLUTION_TIME_ACTION>

   <FILTER filter_id="1">          
        local filter = ClearFilter()
             filter:Add( FE_TYPE, OP_NOT, CARD_TYPE_LAND )
           filter:Add( FE_IS_PERMANENT, true )
      filter:Add( FE_CONTROLLER, OP_NOT, EffectController())
             filter:SetZone( ZONE_BATTLEFIELD )
        </FILTER>
   
   <RESOLUTION_TIME_ACTION filter_id="1">
      if EffectSource():WasKicked()  then
           if FilteredCard() ~= nil then   
                FilteredCard():PutInHand()
         end
      end
   </RESOLUTION_TIME_ACTION>      
  </SPELL_ABILITY>

   

     <AI_AVAILABILITY type="in_response" response_source="1" />
   <AI_AVAILABILITY window_step="begin_combat" window_turn="their_turn" type="window" />
   <AI_AVAILABILITY window_step="declare_attackers" window_turn="their_turn" type="window" />
   <AI_AVAILABILITY window_step="main_1" window_turn="my_turn" type="window" />
   <AI_AVAILABILITY window_step="declare_blockers" type="window" />
   <AI_AVAILABILITY window_step="end_of_turn" type="window" />
   <AI_AVAILABILITY type="in_response" response_source="1" response_target="1" />
   <AI_BASE_SCORE score="900" zone="ZONE_HAND" />
</CARD_V2>
I know this code dont work i put it only to talk about the idea.
And im learning too much :D
So more questions:
This trigger value should be trigger when i play the spell and before go to stack, so after the choice of to play with or without overload, isn it?
Code: Select all
<TRIGGER value="TRIGGER_ZONECHANGE_BEGIN" simple_qualifier="self" to_zone="ZONE_STACK" pre_trigger="1"/>
And..inside the trigger block when i return true or false i enable or disabled the entire trigger ability or only is to pass arguments?
Code: Select all
<TRIGGER value="TRIGGER_ZONECHANGE_BEGIN" simple_qualifier="self" to_zone="ZONE_STACK" pre_trigger="1"/>
         Return EffectSource():WasKicked()      
   </TRIGGER>
more things..Is really imposible to make a target choice inside the trigger block, save that target in a variable and pass it to the spell ability if ist necessary?
something like this but well compiled:
Target in trigger | Open
Code: Select all
<TRIGGERED_ABILITY linked_ability_group="1">
   <TRIGGER value="TRIGGER_ZONECHANGE_BEGIN" simple_qualifier="self" to_zone="ZONE_STACK" pre_trigger="1"/>
         Return EffectSource():WasKicked()      
   </TRIGGER>
      <TARGET tag="CARD_QUERY_CHOOSE_NONLAND_PERMANENT_TO_PUT_INTO_HAND" definition="0" compartment="0" count="1" />
      <TARGET_DEFINITION id="0">   
         local filter = ClearFilter()
           filter:Add( FE_TYPE, OP_NOT, CARD_TYPE_LAND )
         filter:Add( FE_IS_PERMANENT, true )
         filter:Add( FE_CONTROLLER, OP_NOT, EffectController())
       </TARGET_DEFINITION>   
      <RESOLUTION_TIME_ACTION>
         LinkedDC() = EffectDC():Get_Targets(0):Get_CardPtr(0)
      </RESOLUTION_TIME_ACTION>
  </TRIGGERED_ABILITY>
Spell ability | Open
Code: Select all
<SPELL_ABILITY linked_ability_group="1">
<RESOLUTION_TIME_ACTION>
      
      if EffectSource():WasKicked() == false then   
                        local target = LinkedDC()
          if  target ~= nil then
              target:PutInHand()
          end
       end 
.
.
...
    </RESOLUTION_TIME_ACTION>
I'm not sure what exactly do pre_trigger="1" and linked-ability group :)
Thanks to all for ur patience.
____________________________________________________________________________________________________________________________
Braquio Dotp2014 DLC
Alternative Sealed Campaigns for DotP 2014
User avatar
braquio
 
Posts: 143
Joined: 16 Feb 2014, 19:21
Has thanked: 15 times
Been thanked: 9 times

Re: General DotP 2014 Coding Questions

Postby RiiakShiNal » 22 Feb 2014, 01:50

braquio wrote:The idea is to check the target after i choose overload or not, with a trigger block. then inside the spell ability i have both abilities, the ability with overload and without it, but only is resolved 1, thats its ok and works.
As I explained before that will cause incorrect behavior with the ability to cast the spell, automatic countering, and target checking (things like Heroic and other cards that depend on checking targets when a spell is cast). You can probably manage a workaround for Heroic by making use of NeoAnderson's workaround, but it still doesn't solve other problems. As stated before a fully compliant overload can't be coded (solving one problem creates other problems).

braquio wrote:The only problem is that i dont know how to choose a target inside the trigger block, and i dont know how to compile correctly a trigger block

Something like this

Code dont' work | Open
Code: Select all
<?xml version='1.0' encoding='UTF-8'?>
<CARD_V2 ExportVersion="1">
  <FILENAME text="CYCLONIC_RIFT_666270798" />
  <CARDNAME text="CYCLONIC_RIFT" />
  <TITLE>
    <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Cyclonic Rift]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[Faille cyclonique]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[Grieta ciclónica]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[Rift des Sturmtiefs]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[Squarcio Ciclonico]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="jp-JA"><![CDATA[サイクロンの裂け目]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ko-KR"><![CDATA[회오리 균열]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ru-RU"><![CDATA[Циклонический Разлом]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="pt-BR"><![CDATA[Fenda Ciclônica]]></LOCALISED_TEXT>
  </TITLE>
  <MULTIVERSEID value="666270798" />
  <ARTID value="666270798" />
  <ARTIST name="Chris Rahn" />
  <CASTING_COST cost="{1}{U}" />
  <FLAVOURTEXT>
    <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[The Izzet specialize in unnatural disaster.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[Les Izzet sont spécialisés dans les catastrophes artificielles.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[Los ízzet se especializan en desastres no naturales.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[Die Izzet sind auf unnatürliche Katastrophen spezialisiert.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[Gli Izzet sono specializzati in catastrofi innaturali.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="jp-JA"><![CDATA[イゼット団は不自然災害を専門としている。]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ko-KR"><![CDATA[이젯 길드의 특기는 부자연스러운 재해다.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ru-RU"><![CDATA[Иззеты являются мастерами неприродных катастроф.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="pt-BR"><![CDATA[A especialidade dos Izzet são os desastres não naturais.]]></LOCALISED_TEXT>
  </FLAVOURTEXT>
  <TYPE metaname="Instant" />
  <EXPANSION value="RTR" />
  <RARITY metaname="R" />
  <UTILITY_ABILITY qualifier="Kicker">
    <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Overload {6}{U}]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[Surcharge {6}{U} » par « chaque ».)]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[Sobrecarga {6}{U}.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[Überlast {6}{U}]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[Sovraccarico {6}{U}]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="jp-JA"><![CDATA[超過 {6}{U}]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ko-KR"><![CDATA[과부하 {6}{U}]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ru-RU"><![CDATA[Перегрузка {6}{U}]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="pt-BR"><![CDATA[Sobrecarga {6}{U}]]></LOCALISED_TEXT>
    <ABILITY_TEXT tag="OVERLOAD_QUERY_CYCLONIC_RIFT_OVERLOADED" secondary_tag="OVERLOAD_QUERY_CYCLONIC_RIFT_NO_OVERLOADED" />
    <COST mana_cost="{5}" type="Mana" />
  </UTILITY_ABILITY>

  <TRIGGERED_ABILITY linked_ability_group="1">
   <TRIGGER value="TRIGGER_ZONECHANGE_BEGIN" simple_qualifier="self" to_zone="ZONE_STACK" pre_trigger="1"/>
         Return EffectSource():WasKicked()      
   </TRIGGER>
      <TARGET tag="CARD_QUERY_CHOOSE_NONLAND_PERMANENT_TO_PUT_INTO_HAND" definition="0" compartment="0" count="1" />
      <TARGET_DEFINITION id="0">   
         local filter = ClearFilter()
           filter:Add( FE_TYPE, OP_NOT, CARD_TYPE_LAND )
         filter:Add( FE_IS_PERMANENT, true )
         filter:Add( FE_CONTROLLER, OP_NOT, EffectController())
       </TARGET_DEFINITION>   
      <RESOLUTION_TIME_ACTION>
         LinkedDC() = EffectDC():Get_Targets(0):Get_CardPtr(0)
      </RESOLUTION_TIME_ACTION>
  </TRIGGERED_ABILITY>

  <SPELL_ABILITY linked_ability_group="1">
    <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Return target nonland permanent you don’t control to its owner’s hand.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[Renvoyez un permanent non-terrain ciblé que vous ne contrôlez pas dans la main de son propriétaire.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[Regresa el permanente objetivo que no sea tierra que no controles a la mano de su propietario.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[Bringe eine bleibende Karte deiner Wahl, die kein Land ist und die du nicht kontrollierst, auf die Hand ihres Besitzers zurück.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[Fai tornare un permanente non terra bersaglio che non controlli in mano al suo proprietario.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="jp-JA"><![CDATA[あなたがコントロールしていない土地でないパーマネント1つを対象とし、それをオーナーの手札に戻す。]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ko-KR"><![CDATA[당신이 조종하지 않는 지속물 중 대지가 아닌 지속물 한 개를 목표로 정한다. 그 지속물을 소유자의 손으로 되돌린다.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ru-RU"><![CDATA[Верните целевой не являющийся землей перманент, который не находится под вашим контролем, в руку его владельца.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="pt-BR"><![CDATA[Devolva a permanente alvo que não seja um terreno e que você não controle para a mão de seu dono.]]></LOCALISED_TEXT>
    <SFX text="TARGET_MAELSTROM_PLAY" />

   <RESOLUTION_TIME_ACTION>
      local target = LinkedDC()
      if EffectSource():WasKicked() == false then   
          if  target ~= nil then
              target:PutInHand()
          end
       end 
    </RESOLUTION_TIME_ACTION>

   <FILTER filter_id="1">          
        local filter = ClearFilter()
             filter:Add( FE_TYPE, OP_NOT, CARD_TYPE_LAND )
           filter:Add( FE_IS_PERMANENT, true )
      filter:Add( FE_CONTROLLER, OP_NOT, EffectController())
             filter:SetZone( ZONE_BATTLEFIELD )
        </FILTER>
   
   <RESOLUTION_TIME_ACTION filter_id="1">
      if EffectSource():WasKicked()  then
           if FilteredCard() ~= nil then   
                FilteredCard():PutInHand()
         end
      end
   </RESOLUTION_TIME_ACTION>      
  </SPELL_ABILITY>

   

     <AI_AVAILABILITY type="in_response" response_source="1" />
   <AI_AVAILABILITY window_step="begin_combat" window_turn="their_turn" type="window" />
   <AI_AVAILABILITY window_step="declare_attackers" window_turn="their_turn" type="window" />
   <AI_AVAILABILITY window_step="main_1" window_turn="my_turn" type="window" />
   <AI_AVAILABILITY window_step="declare_blockers" type="window" />
   <AI_AVAILABILITY window_step="end_of_turn" type="window" />
   <AI_AVAILABILITY type="in_response" response_source="1" response_target="1" />
   <AI_BASE_SCORE score="900" zone="ZONE_HAND" />
</CARD_V2>
I know this code dont work i put it only to talk about the idea.
And im learning too much :D
So more questions:
This trigger value should be trigger when i play the spell and before go to stack, so after the choice of to play with or without overload, isn it?
Code: Select all
<TRIGGER value="TRIGGER_ZONECHANGE_BEGIN" simple_qualifier="self" to_zone="ZONE_STACK" pre_trigger="1"/>
No, TRIGGER_ZONECHANGE_BEGIN is not valid in this way your trigger should be like this:
Code: Select all
<TRIGGER value="ZONECHANGE_BEGIN" simple_qualifier="self" to_zone="ZONE_STACK" from_zone="ZONE_ANY" pre_trigger="1">
braquio wrote:And..inside the trigger block when i return true or false i enable or disabled the entire trigger ability or only is to pass arguments?
Code: Select all
<TRIGGER value="TRIGGER_ZONECHANGE_BEGIN" simple_qualifier="self" to_zone="ZONE_STACK" pre_trigger="1"/>
         Return EffectSource():WasKicked()      
   </TRIGGER>
Trigger blocks determine whether or not anything other than the trigger will be processed in the ability. You must return either true or false for it to work properly. Again TRIGGER_ZONECHANGE_BEGIN is not valid in this context (you need to remove "TRIGGER_" from any TRIGGER constant to make it work in the value attribute). Also you can't close the TRIGGER block twice (once at the end of the TRIGGER line and again with /TRIGGER) that is invalid XML and will not work anywhere.

braquio wrote:more things..Is really imposible to make a target choice inside the trigger block, save that target in a variable and pass it to the spell ability if ist necessary?
something like this but well compiled:
Target in trigger | Open
Code: Select all
<TRIGGERED_ABILITY linked_ability_group="1">
   <TRIGGER value="TRIGGER_ZONECHANGE_BEGIN" simple_qualifier="self" to_zone="ZONE_STACK" pre_trigger="1"/>
         Return EffectSource():WasKicked()      
   </TRIGGER>
      <TARGET tag="CARD_QUERY_CHOOSE_NONLAND_PERMANENT_TO_PUT_INTO_HAND" definition="0" compartment="0" count="1" />
      <TARGET_DEFINITION id="0">   
         local filter = ClearFilter()
           filter:Add( FE_TYPE, OP_NOT, CARD_TYPE_LAND )
         filter:Add( FE_IS_PERMANENT, true )
         filter:Add( FE_CONTROLLER, OP_NOT, EffectController())
       </TARGET_DEFINITION>   
      <RESOLUTION_TIME_ACTION>
         LinkedDC() = EffectDC():Get_Targets(0):Get_CardPtr(0)
      </RESOLUTION_TIME_ACTION>
  </TRIGGERED_ABILITY>
Spell ability | Open
Code: Select all
<SPELL_ABILITY linked_ability_group="1">
<RESOLUTION_TIME_ACTION>
      
      if EffectSource():WasKicked() == false then   
                        local target = LinkedDC()
          if  target ~= nil then
              target:PutInHand()
          end
       end 
.
.
...
    </RESOLUTION_TIME_ACTION>
I never said it was impossible to get a target from a TRIGGERED_ABILITY, but it will cause interaction problems and incorrect behavior (as I have stated multiple times now). Getting a target inside a TRIGGER block probably is impossible due to engine handling.

Using a LinkedDC() is much like using the EffectDC() if you want to store a card pointer then you need to use Set_CardPtr() like this:
Code: Select all
      <RESOLUTION_TIME_ACTION>
         LinkedDC():Set_CardPtr(0, EffectDC():Get_Targets(0):Get_CardPtr(0) )
      </RESOLUTION_TIME_ACTION>
Then you would read it back in a similar fashion:
Code: Select all
                        local target = LinkedDC():Get_CardPtr(0)
braquio wrote:I'm not sure what exactly do pre_trigger="1" and linked-ability group :)
Thanks to all for ur patience.
pre_trigger="1" means that the TRIGGERED_ABILITY should execute before the actual event. This is useful for overriding events and making changes before something happens (like multiplying damage, preventing damage, etc...).

linked_ability_group="1" means that the LinkedDC() should be available (and initialized if not already done so) to this ability. If you don't include that then when you call LinkedDC() in that ability it will return nil.
RiiakShiNal
Programmer
 
Posts: 2185
Joined: 16 May 2011, 21:37
Has thanked: 75 times
Been thanked: 497 times

PreviousNext

Return to Programming Talk

Who is online

Users browsing this forum: No registered users and 43 guests

cron

Who is online

In total there are 43 users online :: 0 registered, 0 hidden and 43 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 43 guests

Login Form