It is currently 19 Jul 2019, 22:45
   
Text Size

General DotP 2014 Coding Questions

Moderators: Xander9009, CCGHQ Admins

Re: General DotP 2014 Coding Questions

Postby Xander9009 » 04 Jun 2016, 05:41

Alright, I've got an odd problem that I can't seem to figure out. Kozilek, the Great Distortion.

| Open
Code: Select all
<?xml version="1.0"?>
<CARD_V2 ExportVersion="1">
   <FILENAME text="KOZILEK_THE_GREAT_DISTORTION_CW_407514" />
   <CARDNAME text="KOZILEK_THE_GREAT_DISTORTION" />
   <TITLE>
      <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Kozilek, the Great Distortion]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[Kozilek, la Grande Distorsion]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[Kozilek, la Gran Distorsión]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[Kozilek, Verzerrung der Realität]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[Kozilek, la Grande Distorsione]]></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[Kozilek, a Grande Distorção]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="zh-CN"><![CDATA[无际曲相寇基雷]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="zh-HK"><![CDATA[無際曲相寇基雷]]></LOCALISED_TEXT>
   </TITLE>
   <MULTIVERSEID value="407514" />
   <ARTID value="KOZILEK_THE_GREAT_DISTORTION" />
   <ARTIST name="Aleksi Briclot" />
   <CASTING_COST cost="{8}{1}{1}" />
   <FLAVOURTEXT>
      <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[A void as cryptic as reality itself.]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[Un vide aussi énigmatique que la réalité elle-même.]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[Un vacío tan críptico como la propia realidad.]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[Eine Leere, so rätselhaft wie die Realität selbst.]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[Un vuoto criptico come la realtà stessa.]]></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[Um vazio tão enigmático quanto a própria realidade.]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="zh-CN"><![CDATA[如现实般神秘的虚无。]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="zh-HK"><![CDATA[如現實般神秘的虛無。]]></LOCALISED_TEXT>
   </FLAVOURTEXT>
   <SUPERTYPE metaname="Legendary" />
   <TYPE metaname="Creature" />
   <SUB_TYPE metaname="Eldrazi" />
   <EXPANSION value="OGW" />
   <RARITY metaname="M" />
   <POWER value="12" />
   <TOUGHNESS value="12" />
   <SPELL_ABILITY>
      <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Mana cost: {8}{Q}{Q}]]></LOCALISED_TEXT>
      <AVAILABILITY>
         return CW_Mana_CanPayColorlessCost(2)
      </AVAILABILITY>
   </SPELL_ABILITY>
   <TRIGGERED_ABILITY active_zone="ZONE_ANY">
      <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[When you cast Kozilek, the Great Distortion, if you have fewer than seven cards in hand, draw cards equal to the difference.]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[Quand vous lancez Kozilek, la Grande Distorsion, si vous avez moins de sept cartes en main, piochez un nombre de cartes égal à la différence.]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[Cuando lanzas a Kozilek, la Gran Distorsión, si tienes menos de siete cartas en tu mano, roba una cantidad de cartas igual a la diferencia.]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[Wenn du Kozilek, Verzerrung der Realität, wirkst und falls du weniger als sieben Karten auf deiner Hand hast, ziehe so viele Karten, wie die Differenz beträgt.]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[Quando lanci Kozilek, la Grande Distorsione, se hai meno di sette carte in mano, pesca carte pari alla differenza.]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="jp-JA"><![CDATA[あなたが大いなる歪み、コジレックを唱えたとき、あなたの手札にあるカードの枚数が7枚未満である場合、その差に等しい枚数のカードを引く。]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="ko-KR"><![CDATA[거대한 왜곡 코질렉을 발동할 때, 당신의 손에 있는 카드가 일곱 장보다 적으면 그 차이만큼 카드를 뽑는다.]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="ru-RU"><![CDATA[Когда вы разыгрываете Козилека, Великое Искажение, если у вас в руке меньше семи карт, возьмите количество карт, равное разнице.]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="pt-BR"><![CDATA[Quando você conjurar Kozilek, a Grande Distorção, se tiver menos de sete cards na mão, compre um número de cards igual à diferença.]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="zh-CN"><![CDATA[当你施放无际曲相寇基雷时,若你的手牌数量少于七张,则抓等同于该差距数量的牌。]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="zh-HK"><![CDATA[當你施放無際曲相寇基雷時,若你的手牌數量少於七張,則抽等同於該差距數量的牌。]]></LOCALISED_TEXT>
      <TRIGGER value="SPELL_PLAYED" simple_qualifier="self" />
      <INTERVENING_IF>
         return EffectController():Hand_Count() &lt; 7
      </INTERVENING_IF>
      <RESOLUTION_TIME_ACTION>
         EffectController():DrawCards(7-EffectController():Hand_Count())
      </RESOLUTION_TIME_ACTION>
   </TRIGGERED_ABILITY>
   <STATIC_ABILITY>
      <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Menace]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[Menace]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[Amenaza.]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[Bedrohlich]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[Minacciare]]></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[Ameaçar]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="zh-CN"><![CDATA[威慑]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="zh-HK"><![CDATA[威懾]]></LOCALISED_TEXT>
      <CONTINUOUS_ACTION layer="6">
         if EffectSource() ~= nil then
            RSN_Characteristics_Set(EffectSource(), CW_CHARACTERISTIC_MENACE, 1)
         end
      </CONTINUOUS_ACTION>
   </STATIC_ABILITY>
   <TRIGGERED_ABILITY replacement_effect="1" active_zone="ZONE_LIBRARY">
      <TRIGGER value="BEGINNING_OF_STEP">
         return MTG():GetStep() == STEP_UPKEEP and MTG():GetTurnNumber() == 0
      </TRIGGER>
      <RESOLUTION_TIME_ACTION>
         RSN_Characteristics_CreateManagers()
      </RESOLUTION_TIME_ACTION>
   </TRIGGERED_ABILITY>
   <ACTIVATED_ABILITY>
      <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Discard a card with converted mana cost X: Counter target spell with converted mana cost X.]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[Défaussez-vous d’une carte avec un coût converti de mana de X : Contrecarrez un sort ciblé avec un coût converti de mana de X.]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[Descartar una carta con coste de maná convertido de X: Contrarresta el hechizo objetivo con coste de maná convertido de X.]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[Wirf eine Karte mit umgewandelten Manakosten von X ab: Neutralisiere einen Zauberspruch deiner Wahl mit umgewandelten Manakosten von X.]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[Scarta una carta con costo di mana convertito pari a X: Neutralizza una magia bersaglio con costo di mana convertito pari a X.]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="jp-JA"><![CDATA[点数で見たマナ・コストがXであるカードを1枚捨てる:点数で見たマナ・コストがXである呪文1つを対象とし、それを打ち消す。]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="ko-KR"><![CDATA[전환마나비용이 X인 카드 한 장을 버린다: 전환마나비용이 X인 주문을 목표로 정한다. 그 주문을 무효화한다.]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="ru-RU"><![CDATA[Сбросьте карту с конвертированной мана-стоимостью X: отмените целевое заклинание с конвертированной мана-стоимостью X.]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="pt-BR"><![CDATA[Descarte um card com custo de mana convertido igual a X: Anule a mágica alvo com custo de mana convertido igual a X.]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="zh-CN"><![CDATA[弃一张总法术力费用为X的牌:反击目标总法术力费用为X的咒语。]]></LOCALISED_TEXT>
      <LOCALISED_TEXT LanguageCode="zh-HK"><![CDATA[棄一張總魔法力費用為X的牌:反擊目標總魔法力費用為X的咒語。]]></LOCALISED_TEXT>
      <TARGET tag="CARD_QUERY_CHOOSE_SPELL_TO_COUNTER" definition="0" compartment="0" count="1" />
      <TARGET_DEFINITION id="0">
         local filter = ClearFilter()
         filter:SetZone(ZONE_STACK)
         filter:Add(FE_LUA_CONDITION, 1, EffectController(), EffectDC())
      </TARGET_DEFINITION>
      <FILTER_CONDITION id="1">
         local Spell = FilteredCard()
         if Spell ~= nil then
            SpellCMC = Spell:GetConvertedManaCost()
            local filter = ClearFilter()
            filter:SetZone(ZONE_HAND, EffectController())
            filter:Add(FE_CMC, OP_EQUALS, Spell:GetConvertedManaCost())
            return filter:CountStopAt(1) == 1
         end
         return false
      </FILTER_CONDITION>
      <COST type="Discard" query_tag="CARD_QUERY_CHOOSE_CARD_TO_DISCARD" definition="2" compartment="2" item_count="1" />
      <COST_DEFINITION id="2">
         local Target = EffectDC():Get_Targets(0) and EffectDC():Get_Targets(0):Get_CardPtr(0)
         local filter = ClearFilter()
         if Target ~= nil then
            filter:SetZone(ZONE_HAND, EffectController())
            filter:Add(FE_CMC, OP_EQUALS, Target:GetConvertedManaCost())
         end
      </COST_DEFINITION>
      <RESOLUTION_TIME_ACTION>
         local Target = EffectDC():Get_Targets(0) and EffectDC():Get_Targets(0):Get_CardPtr(0)
         if Target ~= nil then
            Debug("RTA: "..Target:GetCardName())
            Target:CounterSpell()
         else
            Debug("RTA: Target is nil")
         end
      </RESOLUTION_TIME_ACTION>
      <AI_SIMPLIFIED_TARGETING compartment="0" hint="HINT_ENEMY_ONLY" />
   </ACTIVATED_ABILITY>
   <TOKEN_REGISTRATION reservation="1" type="_MANAGER_CHARACTERISTICS" />
   <HELP title="CW_MORE_INFO_TITLE_MENACE" body="CW_MORE_INFO_BODY_MENACE" zone="ZONE_ANY" />
   <SFX text="COMBAT_BLUNT_LARGE_ATTACK" power_boundary_min="4" power_boundary_max="-1" />
   <SFX text="COMBAT_BLUNT_SMALL_ATTACK" power_boundary_min="1" power_boundary_max="3" />
   <AUTHOR><![CDATA[Xander9009]]></AUTHOR>
   <EDITORS><![CDATA[Xander9009]]></EDITORS>
   <DATE><![CDATA[10-02-16]]></DATE>
</CARD_V2>
The counterspell ability is giving me trouble. I've gotten it to behave relatively well. If you remove the lua condition, then it behaves like this:
-Spell is cast, ability becomes activable.
-Activate ability
-Choose target
-Choose card with target's CMC to discard
-Card is discarded
-Timer
-Spell is countered.

That's almost perfect, except that if you don't have a matching card in hand, it can still be activated and you can still target the spell. The ability never goes on the stack, because as soon as it gets to the cost, it registers that you can't pay it, and it invalidates.

I added the lua condition to try and make the spell only able to target spells whose CMC matches a card in your hand. This worked fine, and now that's exactly what it does. It now works like this:
-Spell is cast, ability becomes activable IF it's a valid target
-Activate ability
-Choose valid target
-Choose matching card to discard
-Card is discarded
-Timer
-Spell resolves with no effect

I put in a debug message (which you'll need to replace, remove, or define, if you don't have the CW, it's just a shorthand message function), and it never runs. I even removed the entire code block in the RTA and replaced it with "MTG():MessageAllPlayers("RTA")", but it didn't appear. I'm not sure what would cause that to happen, and now I'm at a loss. Any advice?
_______________________________
Community Wad - Community Wad Website - How to Help and Report Bugs
Discord: discord.gg/4AXvHzW
User avatar
Xander9009
Programmer
 
Posts: 2887
Joined: 29 Jun 2013, 07:44
Location: Indiana, United States
Has thanked: 119 times
Been thanked: 437 times

Re: General DotP 2014 Coding Questions

Postby RiiakShiNal » 04 Jun 2016, 23:11

The problem is probably that you are clearing the filter inside of a filter. You will probably have to rewrite your Lua condition to use a loop instead of a filter. There is only a single filter for a single card at any given time, when you call ClearFilter() it clears the current filter (regardless of where it is) and returns a new filter. The ClearFilter() function is essentially and alias for:
Code: Select all
MTG():GetCurrentObject():ClearFilter()
So you should try this as your Lua condition:
Code: Select all
      <FILTER_CONDITION id="1">
         local Spell = FilteredCard()
         if Spell ~= nil then
            SpellCMC = Spell:GetConvertedManaCost()
            local bFoundValid = false
            local nCount = EffectController():Hand_Count()
            local i = 0
            for i = 0, nCount-1 do
               local oCard = EffectController():Hand_GetNth(i)
               if (oCard ~= nil) then
                  if (oCard:GetConvertedManaCost() == SpellCMC) then
                     bFoundValid = true
                     break
                  end
               end
            end
            return bFoundValid
         end
         return false
      </FILTER_CONDITION>
Problems with base game cards: DotP 2014 Core Fixes
Need a deck builder: DotP 2014 Deck Builder
Problems Modding: DotP 2014 Frequent Modding Mistakes
RiiakShiNal
Programmer
 
Posts: 2120
Joined: 16 May 2011, 21:37
Has thanked: 73 times
Been thanked: 471 times

Re: General DotP 2014 Coding Questions

Postby Xander9009 » 04 Jun 2016, 23:31

RiiakShiNal wrote:The problem is probably that you are clearing the filter inside of a filter. You will probably have to rewrite your Lua condition to use a loop instead of a filter. There is only a single filter for a single card at any given time, when you call ClearFilter() it clears the current filter (regardless of where it is) and returns a new filter. The ClearFilter() function is essentially and alias for:
Code: Select all
MTG():GetCurrentObject():ClearFilter()
So you should try this as your Lua condition:
Code: Select all
      <FILTER_CONDITION id="1">
         local Spell = FilteredCard()
         if Spell ~= nil then
            SpellCMC = Spell:GetConvertedManaCost()
            local bFoundValid = false
            local nCount = EffectController():Hand_Count()
            local i = 0
            for i = 0, nCount-1 do
               local oCard = EffectController():Hand_GetNth(i)
               if (oCard ~= nil) then
                  if (oCard:GetConvertedManaCost() == SpellCMC) then
                     bFoundValid = true
                     break
                  end
               end
            end
            return bFoundValid
         end
         return false
      </FILTER_CONDITION>
I tried your suggestion, but no change. The RTA still doesn't run. I removed the lua condition just to make sure that was in fact the source of the problem, and it worked. I then realized what the issue is and tested to confirm it. The problem is that once you discard the card from you hand to pay the cost, the target is checked for validity when the ability resolves, but now you don't have any cards for that condition to return true, so the target is invalid, and the ability fizzles.

I'm thinking that since the ability is successfully put onto the stack, a PTA should fire. So, an EffectDC int that informs the lua condition to return true because the cost was already paid should be enough to fix it.

EDIT: Tested with the PTA and it now works like it should. I didn't notice before that it only failed when the discarded card was the only one with that CMC in my hand. Kozilek, the Great Distortion is now working. Thank you. :)
_______________________________
Community Wad - Community Wad Website - How to Help and Report Bugs
Discord: discord.gg/4AXvHzW
User avatar
Xander9009
Programmer
 
Posts: 2887
Joined: 29 Jun 2013, 07:44
Location: Indiana, United States
Has thanked: 119 times
Been thanked: 437 times

Re: General DotP 2014 Coding Questions

Postby thefiremind » 05 Jun 2016, 18:26

You know, this is interesting: Magic Duels has Kozilek as an official card and it uses a different approach, but now that I think about it, it probably has a flaw.
Instead of using a standard discard cost, it uses a generic cost that allows you to choose only cards from your hand that have the same cmc as your target. The PREREQUISITE block of the generic cost checks that you have at least a card in your hand with cmc that matches a spell on the stack.
But what happens when there are multiple spells on the stack? Let's say that there's a spell with cmc=3 and another one with cmc=4. You have only one card in hand with cmc=4: the PREREQUISITE block returns true. There are no restrictions on the TARGET block so you are allowed to choose the spell with cmc=3... boom! I haven't tested what happens, but I'd guess it would end countering the spell without discarding any card.

Here's the official implementation, for reference:
Official implementation of Kozilek's activated ability (probably flawed) | Open
Code: Select all
  <ACTIVATED_ABILITY>
    <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Discard a card with converted mana cost X: Counter target spell with converted mana cost X.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[Défaussez-vous d’une carte avec un coût converti de mana de X : Contrecarrez un sort ciblé avec un coût converti de mana de X.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[Descartar una carta con coste de maná convertido de X: Contrarresta el hechizo objetivo con coste de maná convertido de X.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[Wirf eine Karte mit umgewandelten Manakosten von X ab: Neutralisiere einen Zauberspruch deiner Wahl mit umgewandelten Manakosten von X.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[Scarta una carta con costo di mana convertito pari a X: Neutralizza una magia bersaglio con costo di mana convertito pari a X.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="jp-JA"><![CDATA[点数で見たマナ・コストがXであるカードを1枚捨てる:点数で見たマナ・コストがXである呪文1つを対象とし、それを打ち消す。]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ko-KR"><![CDATA[전환마나비용이 X인 카드 한 장을 버린다: 전환마나비용이 X인 주문을 목표로 정한다. 그 주문을 무효화한다.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ru-RU"><![CDATA[Сбросьте карту с конвертированной мана-стоимостью X: отмените целевое заклинание с конвертированной мана-стоимостью X.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="pt-BR"><![CDATA[Descarte um card com custo de mana convertido igual a X: Anule a mágica alvo com custo de mana convertido igual a X.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="zh-CN"><![CDATA[弃一张总法术力费用为X的牌:反击目标总法术力费用为X的咒语。]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="zh-HK"><![CDATA[棄一張總魔法力費用為X的牌:反擊目標總魔法力費用為X的咒語。]]></LOCALISED_TEXT>
    <SFX text="TARGET_ELDRAZI_PLAY" />
    <COST type="Generic">
      <PREREQUISITE>
    local stackFilter = ClearFilter()
    stackFilter:SetZone(ZONE_STACK)
    local numItemsOnStack = stackFilter:EvaluateObjects()
    for i = 0, (numItemsOnStack-1) do
       --Iterate through items on sstack
       local currentCMC = stackFilter:GetNthEvaluatedObject(i):GetConvertedManaCost()
       --Store CMC as a var
       for j = 0, (EffectController():Hand_Count()-1) do
       --Iterate through items in hand
          if EffectController():Hand_GetNth(j):GetConvertedManaCost() == currentCMC then
          --if we have matching CMCs we can use the ability
             return true
          end
       end
    end
    -- been through everything on the stack and in hand with no matches so cannot use ability
    return false
    </PREREQUISITE>
      <RESOLUTION_TIME_ACTION>
    local filter = ClearFilter()
    local target = EffectDC():Get_Targets(0):Get_CardPtr(0)
    if target == nil then
       return
    end
    local targetCMC = target:GetConvertedManaCost()
    filter:SetZone( ZONE_HAND, EffectController() )
    filter:Add( FE_CMC, OP_EQUALS, targetCMC )
    EffectController():ChooseItem( "CARD_QUERY_CHOOSE_A_CARD_TO_DISCARD_WITH_CMC_EQUAL_TO_TARGET", EffectDC():Make_Targets(1), QUERY_FLAG_DISCARD )
    </RESOLUTION_TIME_ACTION>
      <RESOLUTION_TIME_ACTION>
    local targetDC = EffectDC():Get_Targets(1)
    if targetDC == nil then
       return
    end
    local player = EffectController()
    if player ~= nil then
       local target_card = EffectDC():Get_Targets(1):Get_CardPtr(0)
       if target_card ~= nil  then
          target_card:Discard()
       end
    end
    </RESOLUTION_TIME_ACTION>
    </COST>
    <TARGET tag="CARD_QUERY_CHOOSE_SPELL_TO_COUNTER" definition="0" compartment="0" count="1" />
    <TARGET_DEFINITION id="0">
    local filter = ClearFilter()
    filter:SetZone( ZONE_STACK )
    </TARGET_DEFINITION>
    <RESOLUTION_TIME_ACTION>
    local target = EffectDC():Get_Targets(0):Get_CardPtr(0)
    if target ~= nil then
       target:CounterSpell()
    end
    </RESOLUTION_TIME_ACTION>
  </ACTIVATED_ABILITY>
In case someone wants to test the code in a previous installment, the only non-retro-compatible part should be QUERY_FLAG_DISCARD, which in Magic Duels instructs the game on making the cards with madness glow blue instead of red (or at least that's what I think it does).
< 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: 717 times

Re: General DotP 2014 Coding Questions

Postby Xander9009 » 05 Jun 2016, 19:35

thefiremind wrote:You know, this is interesting: Magic Duels has Kozilek as an official card and it uses a different approach, but now that I think about it, it probably has a flaw.
Instead of using a standard discard cost, it uses a generic cost that allows you to choose only cards from your hand that have the same cmc as your target. The PREREQUISITE block of the generic cost checks that you have at least a card in your hand with cmc that matches a spell on the stack.
But what happens when there are multiple spells on the stack? Let's say that there's a spell with cmc=3 and another one with cmc=4. You have only one card in hand with cmc=4: the PREREQUISITE block returns true. There are no restrictions on the TARGET block so you are allowed to choose the spell with cmc=3... boom! I haven't tested what happens, but I'd guess it would end countering the spell without discarding any card.

Here's the official implementation, for reference:
Official implementation of Kozilek's activated ability (probably flawed) | Open
Code: Select all
  <ACTIVATED_ABILITY>
    <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Discard a card with converted mana cost X: Counter target spell with converted mana cost X.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[Défaussez-vous d’une carte avec un coût converti de mana de X : Contrecarrez un sort ciblé avec un coût converti de mana de X.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[Descartar una carta con coste de maná convertido de X: Contrarresta el hechizo objetivo con coste de maná convertido de X.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[Wirf eine Karte mit umgewandelten Manakosten von X ab: Neutralisiere einen Zauberspruch deiner Wahl mit umgewandelten Manakosten von X.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[Scarta una carta con costo di mana convertito pari a X: Neutralizza una magia bersaglio con costo di mana convertito pari a X.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="jp-JA"><![CDATA[点数で見たマナ・コストがXであるカードを1枚捨てる:点数で見たマナ・コストがXである呪文1つを対象とし、それを打ち消す。]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ko-KR"><![CDATA[전환마나비용이 X인 카드 한 장을 버린다: 전환마나비용이 X인 주문을 목표로 정한다. 그 주문을 무효화한다.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="ru-RU"><![CDATA[Сбросьте карту с конвертированной мана-стоимостью X: отмените целевое заклинание с конвертированной мана-стоимостью X.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="pt-BR"><![CDATA[Descarte um card com custo de mana convertido igual a X: Anule a mágica alvo com custo de mana convertido igual a X.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="zh-CN"><![CDATA[弃一张总法术力费用为X的牌:反击目标总法术力费用为X的咒语。]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="zh-HK"><![CDATA[棄一張總魔法力費用為X的牌:反擊目標總魔法力費用為X的咒語。]]></LOCALISED_TEXT>
    <SFX text="TARGET_ELDRAZI_PLAY" />
    <COST type="Generic">
      <PREREQUISITE>
    local stackFilter = ClearFilter()
    stackFilter:SetZone(ZONE_STACK)
    local numItemsOnStack = stackFilter:EvaluateObjects()
    for i = 0, (numItemsOnStack-1) do
       --Iterate through items on sstack
       local currentCMC = stackFilter:GetNthEvaluatedObject(i):GetConvertedManaCost()
       --Store CMC as a var
       for j = 0, (EffectController():Hand_Count()-1) do
       --Iterate through items in hand
          if EffectController():Hand_GetNth(j):GetConvertedManaCost() == currentCMC then
          --if we have matching CMCs we can use the ability
             return true
          end
       end
    end
    -- been through everything on the stack and in hand with no matches so cannot use ability
    return false
    </PREREQUISITE>
      <RESOLUTION_TIME_ACTION>
    local filter = ClearFilter()
    local target = EffectDC():Get_Targets(0):Get_CardPtr(0)
    if target == nil then
       return
    end
    local targetCMC = target:GetConvertedManaCost()
    filter:SetZone( ZONE_HAND, EffectController() )
    filter:Add( FE_CMC, OP_EQUALS, targetCMC )
    EffectController():ChooseItem( "CARD_QUERY_CHOOSE_A_CARD_TO_DISCARD_WITH_CMC_EQUAL_TO_TARGET", EffectDC():Make_Targets(1), QUERY_FLAG_DISCARD )
    </RESOLUTION_TIME_ACTION>
      <RESOLUTION_TIME_ACTION>
    local targetDC = EffectDC():Get_Targets(1)
    if targetDC == nil then
       return
    end
    local player = EffectController()
    if player ~= nil then
       local target_card = EffectDC():Get_Targets(1):Get_CardPtr(0)
       if target_card ~= nil  then
          target_card:Discard()
       end
    end
    </RESOLUTION_TIME_ACTION>
    </COST>
    <TARGET tag="CARD_QUERY_CHOOSE_SPELL_TO_COUNTER" definition="0" compartment="0" count="1" />
    <TARGET_DEFINITION id="0">
    local filter = ClearFilter()
    filter:SetZone( ZONE_STACK )
    </TARGET_DEFINITION>
    <RESOLUTION_TIME_ACTION>
    local target = EffectDC():Get_Targets(0):Get_CardPtr(0)
    if target ~= nil then
       target:CounterSpell()
    end
    </RESOLUTION_TIME_ACTION>
  </ACTIVATED_ABILITY>
In case someone wants to test the code in a previous installment, the only non-retro-compatible part should be QUERY_FLAG_DISCARD, which in Magic Duels instructs the game on making the cards with madness glow blue instead of red (or at least that's what I think it does).
Getting a head start on a Magic Duels Core Fixes mod? :lol:

The code they used suffers from the issue I was having before I added in the target lua condition. You're allowed to choose a target for which you can't discard a matching card, but upon doing so, the ability exits. So, it's not bugged such that you can counter illegal spells, but it is a bit off. There are no spells that I know of that act like illusions on the stack (something happens as a result of merely being targeted), so I can't easily test if /that/ would behave wrongly.

Interesting to know I got mine working better than theirs thanks to Riiak (while his suggestion didn't fix the issue I was seeing, it was still the right way to go).
_______________________________
Community Wad - Community Wad Website - How to Help and Report Bugs
Discord: discord.gg/4AXvHzW
User avatar
Xander9009
Programmer
 
Posts: 2887
Joined: 29 Jun 2013, 07:44
Location: Indiana, United States
Has thanked: 119 times
Been thanked: 437 times

Re: General DotP 2014 Coding Questions

Postby Xander9009 » 05 Jun 2016, 22:55

Alright, new question.

Awhile back, I got annoyed at having 6 different soldier tokens that are identical except for their art and their filename, so I made CW_Tokens(). It produces random tokens from the base name given. Feed in "SOLDIER_C_1_1_W" and it'll make a random token from TOKEN_SOLDIER_C_1_1_W_CW_1 to TOKEN_SOLDIER_C_1_1_W_CW_6 (there's a table lookup for how many there are).

However, this left a different minor annoyance: stacking. Because they aren't identical, they don't stack. I thought today I'd give a go at solving the issue. I decided to try making TOKEN_SOLDIER_C_1_1_W_CW_1 (I'd make it something slightly different in the end, but this was for testing), and that token would spawn a random token and the use its copiable values instead. I was hoping that the fact that they're the same card (same filename) and everything else EXCEPT art, that they'd stack up. But, after some time getting it to work right and copy the image, I discovered that it didn't work. They still won't stack.

Can anyone think of a way to make them have different art but still stack? I'm out of ideas...
_______________________________
Community Wad - Community Wad Website - How to Help and Report Bugs
Discord: discord.gg/4AXvHzW
User avatar
Xander9009
Programmer
 
Posts: 2887
Joined: 29 Jun 2013, 07:44
Location: Indiana, United States
Has thanked: 119 times
Been thanked: 437 times

Previous

Return to Programming Talk

Who is online

Users browsing this forum: No registered users and 1 guest


Who is online

In total there is 1 user online :: 0 registered, 0 hidden and 1 guest (based on users active over the past 10 minutes)
Most users ever online was 287 on 31 Mar 2019, 04:11

Users browsing this forum: No registered users and 1 guest

Login Form