Page 1 of 1

What is different from DotP 2012 to 2013 cards?

PostPosted: 27 Feb 2013, 04:10
by NEMESiS
Ok, so I did a bit of looking through the forum and found nothing regarding this but I want to know what is different from 2012 cards to 2013. Now, its possible that this is too broad of a question to reply to as there might be dozens upon dozens of different variables out there to list. The main reason why I ask this is because I am trying to make some cards (Syphon Mind and Syphon Flesh spefically) from 2012 and looking at the cards I cannot quite understand what is the difference and at other parts I cannot understand what exactly its being referenced.

Now lets take a look at the crude code of Syphon Flesh:
Code: Select all
<?xml version='1.0'?>
<CARD_V2>
  <FILENAME text="SYPHON_FLESH_255809" />
  <CARDNAME text="SYPHON_FLESH" />
  <TITLE>
    <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Syphon Flesh]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[Fleischansauger]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[Extraer la carne]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[Siphonner la chair]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[Riflusso della Carne]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="jp-JA"><![CDATA[吸(きゅう)肉(にく)]]></LOCALISED_TEXT>
  </TITLE>
  <MULTIVERSEID value="255809" />
  <ARTID value="129237" />
  <FRAMECOLOUR name="B" />
  <COLOUR value="B" />
  <ARTIST name="Ironbrush" />
  <CASTING_COST cost="{4}{B}" />
  <FLAVOURTEXT>
    <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Necromancers deal in commodities far more precious than gold and grain.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[Nekromagier handeln mit Gütern, die deutlich wertvoller als Gold und Getreide sind.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[Los nigromantes comercian con mercancías más preciosas que el oro y el grano.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[Les nécromanciens négocient des commodités bien plus précieuses que l'or et le grain.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[I necromanti si occupano di merci ben più preziose dell'oro e del grano.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="jp-JA"><![CDATA[屍術士は取引の品物を、黄金や穀物などより遥かに丁寧に扱う。]]></LOCALISED_TEXT>
  </FLAVOURTEXT>
  <TYPE metaname="Sorcery" order_de-DE="0" order_es-ES="0" order_fr-FR="0" order_it-IT="0" order_jp-JA="0" />
  <EXPANSION value="DPE" />
  <RARITY metaname="U" />
  <TOKEN_REGISTRATION reservation="4" type="TOKEN_ZOMBIE_2_2_247076" />
  <SPELL_ABILITY>
    <LOCALISED_TEXT LanguageCode="en-US"><![CDATA[Each other player sacrifices a creature. You put a 2/2 black Zombie creature token onto the battlefield for each creature sacrificed this way.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="fr-FR"><![CDATA[Chaque autre joueur sacrifie une créature. Vous mettez sur le champ de bataille un jeton de créature 2/2 noire Zombie pour chaque créature sacrifiée de cette manière.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="de-DE"><![CDATA[Jeder andere Spieler opfert eine Kreatur. Du bringst für jede auf diese Weise geopferte Kreatur einen 2/2 schwarzen Zombie-Kreaturenspielstein ins Spiel.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="es-ES"><![CDATA[Cada otro jugador sacrifica una criatura. Pon en el campo de batalla una ficha de criatura Zombie negra 2/2 por cada criatura sacrificada de esta manera.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="it-IT"><![CDATA[Ogni altro giocatore sacrifica una creatura. Metti sul campo di battaglia una pedina creatura Zombie 2/2 nera per ogni creatura sacrificata in questo modo.]]></LOCALISED_TEXT>
    <LOCALISED_TEXT LanguageCode="jp-JA"><![CDATA[各プレイヤーはクリーチャーを1体生け贄に捧げる。 あなたがこれにより生け贄に捧げられたクリーチャー1体につき、黒の2/2のゾンビ・クリーチャー・トークンを1体戦場に出す。]]></LOCALISED_TEXT>
    <RESOLUTION_TIME_ACTION repeating="1">
    local n = MTG():GetActionRepCount()
         
    if n == 0 then
      MTG():EffectDataChest():Set_Int(0, 0)
    end
         
    local player = MTG():GetNthPlayer(n/2)
    local num_players = MTG():GetNumberOfPlayers()
    local parity = n % 2
         
    local filter = Object():GetFilter()
         
    if player ~= nil and n &lt; num_players*2 then
           
      if player ~= Object():GetPlayer() then
           
        if parity == 0 then
          filter:Clear()
          filter:NotTargetted()
          filter:SetPlayer( player )
          filter:AddCardType( CARD_TYPE_CREATURE )
         filter:PlayerAntiHint(player)
          filter:SetZone( ZONE_IN_PLAY )
             
          if filter:CountStopAt(1) &gt; 0 then
            player:ChooseTargetDC( "CARD_QUERY_CHOOSE_CREATURE_TO_SACRIFICE", MTG():EffectDataChest():Make_Targets((n/2)+1) )
          end
            
        else
            
         local targetDC = MTG():EffectDataChest():Get_Targets((n/2)+1)
             
         if targetDC ~= nil then
             
           local target_card = targetDC:Get_NthCardPtr(0)
              
           if target_card ~= nil and target_card:GetZone() == ZONE_IN_PLAY then
             target_card:Sacrifice()
             local sacced_so_far = MTG():EffectDataChest():Get_Int(0)
             MTG():EffectDataChest():Set_Int(0, sacced_so_far + 1)
           end
             
         end
            
        end
            
      end
           
      return true
     
    else
      return false
    end
    </RESOLUTION_TIME_ACTION>
    <RESOLUTION_TIME_ACTION>
    local num_zombies = MTG():EffectDataChest():Get_Int(0)
    if num_zombies &gt; 0 then
      PutTokensIntoPlay( "TOKEN_ZOMBIE_2_2_247076", num_zombies )
    end
    </RESOLUTION_TIME_ACTION>
    <AI_BASE_SCORE score="1500" zone="hand" />
  </SPELL_ABILITY>
</CARD_V2>
I can already see that "<COLOUR value="B" />" is not something we need as the 2013 automatically gives it its own coloration. Next "<TOKEN_REGISTRATION reservation="4" type="TOKEN_ZOMBIE_2_2_247076" />" I don't think I have seen a card register a token before, its this even needed? I know that 2013 uses token "TOKEN_ZOMBIE_2_2_277465" instead of the one listed. The thing that confuses me the most is chest "(n/2)" and each reference after it like "num_players*2" and "((n/2)+1)". Is this actually math or am I over thinking what I see here????

Re: What is different from DotP 2012 to 2013 cards?

PostPosted: 27 Feb 2013, 05:23
by RiiakShiNal
NEMESiS wrote:Ok, so I did a bit of looking through the forum and found nothing regarding this but I want to know what is different from 2012 cards to 2013. Now, its possible that this is too broad of a question to reply to as there might be dozens upon dozens of different variables out there to list. The main reason why I ask this is because I am trying to make some cards (Syphon Mind and Syphon Flesh spefically) from 2012 and looking at the cards I cannot quite understand what is the difference and at other parts I cannot understand what exactly its being referenced.
There are quite a few differences, but I can't really list them because I didn't really do any DotP 2012 modding.

NEMESiS wrote:I can already see that "<COLOUR value="B" />" is not something we need as the 2013 automatically gives it its own coloration. Next "<TOKEN_REGISTRATION reservation="4" type="TOKEN_ZOMBIE_2_2_247076" />" I don't think I have seen a card register a token before, its this even needed? I know that 2013 uses token "TOKEN_ZOMBIE_2_2_277465" instead of the one listed.
TOKEN_REGISTRATION is still needed, though I have found that it has issues with any reservation other than "1".

NEMESiS wrote:The thing that confuses me the most is chest "(n/2)" and each reference after it like "num_players*2" and "((n/2)+1)". Is this actually math or am I over thinking what I see here????
Yes, that is actually math. "n" is the number of times that action has been repeated, and since the action splits up the choosing and the sacrifice it ends up with double the repetitions to the number of players (hence the divide by 2). On even numbers of repetitions it asks a player which creature to sac, then on the odd repetitions it actually sacs the creature.

Note: PlayerAntiHint() is no longer a valid function instead use SetHint(HINT_ENEMY, player). Also you should use ChooseTarget() instead of ChooseTargetDC() since you aren't selecting from a data chest. Sacrifice() now takes a player as a parameter so it would become target_card:Sacrifice(player). You will need to change which index you are using for keeping track of how many you have sacced as index 0 is being used to hold the sac target for player 0. I don't know how the indexes worked in DotP 2012, but in DotP 2013 indexes refer to the same register whether you are storing targets, a chest, an integer, a float, or a card/player pointer.

Re: What is different from DotP 2012 to 2013 cards?

PostPosted: 01 Mar 2013, 02:37
by NEMESiS
RiiakShiNal wrote: You will need to change which index you are using for keeping track of how many you have sacced as index 0 is being used to hold the sac target for player 0. I don't know how the indexes worked in DotP 2012, but in DotP 2013 indexes refer to the same register whether you are storing targets, a chest, an integer, a float, or a card/player pointer.
Sorry, I don't know what index really is, sounds to me like a chest. Could you explain?

This is what I have done with what you have told me:

Code: Select all
    <RESOLUTION_TIME_ACTION repeating="1">
    local n = MTG():GetActionRepCount()
         
    if n == 0 then
      MTG():EffectDataChest():Set_Int(0, 0)
    end
         
    local player = MTG():GetNthPlayer(n/2)
    local num_players = MTG():GetNumberOfPlayers()
    local parity = n % 2
         
    local filter = Object():GetFilter()
         
    if player ~= nil and n &lt; num_players*2 then
           
      if player ~= Object():GetPlayer() then
           
        if parity == 0 then
          filter:Clear()
          filter:NotTargetted()
          filter:SetPlayer( player )
          filter:AddCardType( CARD_TYPE_CREATURE )
         filter:SetHint(HINT_ENEMY, player)
          filter:SetZone( ZONE_IN_PLAY )
             
          if filter:CountStopAt(1) &gt; 0 then
            player:ChooseTarget( "CARD_QUERY_CHOOSE_CREATURE_TO_SACRIFICE", MTG():EffectDataChest():Make_Targets((n/2)+1) )
          end
            
        else
            
         local target = MTG():EffectDataChest():Get_Targets((n/2)+1)
             
         if target ~= nil then
             
           local target_card = target:Get_NthCardPtr(0)
              
           if target_card ~= nil and target_card:GetZone() == ZONE_IN_PLAY then
             target_card:Sacrifice(player)
             local sacced_so_far = MTG():EffectDataChest():Get_Int(0)
             MTG():EffectDataChest():Set_Int(1, sacced_so_far + 1)
           end
             
         end
            
        end
            
      end
           
      return true
     
    else
      return false
    end
    </RESOLUTION_TIME_ACTION>
    <RESOLUTION_TIME_ACTION>
    local num_zombies = MTG():EffectDataChest():Get_Int(1)
    if num_zombies &gt; 0 then
      PutTokensIntoPlay( "TOKEN_ZOMBIE_2_2_277465", num_zombies )
    end
    </RESOLUTION_TIME_ACTION>
    <AI_BASE_SCORE score="1500" zone="hand" />
  </SPELL_ABILITY>
</CARD_V2>
What have I not done so far or what did I do wrong?

Re: What is different from DotP 2012 to 2013 cards?

PostPosted: 01 Mar 2013, 03:14
by RiiakShiNal
NEMESiS wrote:Sorry, I don't know what index really is, sounds to me like a chest. Could you explain?
Okay to put it in simple terms imagine a large filing cabinet with lots of drawers ordered from top to bottom. Each drawer can only hold one item (doesn't matter what it is just that each drawer can only hold one of something). The one item can be a card, player, number, etc....

(extremely simplified ascii graphics)
Code: Select all
---------
|       |
---------
|       |
---------
|       |
---------
|       |
---------
Now you need to be able to tell someone which drawer is which. In english we would probably tell someone the "top drawer" or "second from the bottom". An easier solution is to give each drawer a number:

Code: Select all
---------
|   0   |
---------
|   1   |
---------
|   2   |
---------
|   3   |
---------
Now we can simply tell someone "put this in drawer 2", "tell me what is in drawer 0", "empty drawer 3", etc.... These numbers are the "index" of the drawer.

Now is where things can get a bit dicey, earlier I said it doesn't matter what each drawer has in it as long as it is just one item, well we can put a filing cabinet into a drawer. Now the drawer has a filing cabinet that can have any number of drawers:

Code: Select all
---------
|   0   |
---------
|   1   |
---------
|---2---|
||  0  ||
||-----||
||  1  ||
||-----||
||  2  ||
|-------|
---------
|   3   |
---------
So that can cover things like Make_Targets(), Get_Targets(), Make_Chest(), etc....

NEMESiS wrote:This is what I have done with what you have told me:

Code: Select all
    <RESOLUTION_TIME_ACTION repeating="1">
    local n = MTG():GetActionRepCount()
         
    if n == 0 then
      MTG():EffectDataChest():Set_Int(0, 0)
    end
         
    local player = MTG():GetNthPlayer(n/2)
    local num_players = MTG():GetNumberOfPlayers()
    local parity = n % 2
         
    local filter = Object():GetFilter()
         
    if player ~= nil and n &lt; num_players*2 then
           
      if player ~= Object():GetPlayer() then
           
        if parity == 0 then
          filter:Clear()
          filter:NotTargetted()
          filter:SetPlayer( player )
          filter:AddCardType( CARD_TYPE_CREATURE )
         filter:SetHint(HINT_ENEMY, player)
          filter:SetZone( ZONE_IN_PLAY )
             
          if filter:CountStopAt(1) &gt; 0 then
            player:ChooseTarget( "CARD_QUERY_CHOOSE_CREATURE_TO_SACRIFICE", MTG():EffectDataChest():Make_Targets((n/2)+1) )
          end
            
        else
            
         local target = MTG():EffectDataChest():Get_Targets((n/2)+1)
             
         if target ~= nil then
             
           local target_card = target:Get_NthCardPtr(0)
              
           if target_card ~= nil and target_card:GetZone() == ZONE_IN_PLAY then
             target_card:Sacrifice(player)
             local sacced_so_far = MTG():EffectDataChest():Get_Int(0)
             MTG():EffectDataChest():Set_Int(1, sacced_so_far + 1)
           end
             
         end
            
        end
            
      end
           
      return true
     
    else
      return false
    end
    </RESOLUTION_TIME_ACTION>
    <RESOLUTION_TIME_ACTION>
    local num_zombies = MTG():EffectDataChest():Get_Int(1)
    if num_zombies &gt; 0 then
      PutTokensIntoPlay( "TOKEN_ZOMBIE_2_2_277465", num_zombies )
    end
    </RESOLUTION_TIME_ACTION>
    <AI_BASE_SCORE score="1500" zone="hand" />
  </SPELL_ABILITY>
</CARD_V2>
What have I not done so far or what did I do wrong?
I'm going to rewrite with notes (also apparently I was wrong after looking at the code closer, index 0 is not used for a player choice, so I'm changing them back to 0):
Code: Select all
    <RESOLUTION_TIME_ACTION repeating="1">
    local n = MTG():GetActionRepCount()
         
    if n == 0 then
      -- Here instead of MTG():EffectDataChest() it is easier to write EffectDC()
      --  so I'm going to replace all instances.
      EffectDC():Set_Int(0, 0)
    end
         
    local player = MTG():GetNthPlayer(n/2)
    local num_players = MTG():GetNumberOfPlayers()
    local parity = n % 2
         
    local filter = Object():GetFilter()
         
    if player ~= nil and n &lt; num_players*2 then

      -- Here I would prefer to use EffectController() instead of
      --  Object():GetPlayer() in case of a copied token that then
      --  ceases to exist.
      if player ~= EffectController() then
           
        if parity == 0 then
          filter:Clear()
          filter:NotTargetted()
          filter:SetPlayer( player )
          filter:AddCardType( CARD_TYPE_CREATURE )
         filter:SetHint(HINT_ENEMY, player)
          filter:SetZone( ZONE_IN_PLAY )
             
          if filter:CountStopAt(1) &gt; 0 then
            -- You don't have enough parameters here, the first parameter
            --  is supposed to be the TARGET_DEFINITION to use, but since
            --  we don't have one we can just use 0.
            player:ChooseTarget( 0, "CARD_QUERY_CHOOSE_CREATURE_TO_SACRIFICE", EffectDC():Make_Targets((n/2)+1) )
          end
        else
         local target = EffectDC():Get_Targets((n/2)+1)
             
         if target ~= nil then
           local target_card = target:Get_NthCardPtr(0)
              
           if target_card ~= nil and target_card:GetZone() == ZONE_IN_PLAY then
             target_card:Sacrifice(player)
             -- My mistake index 0 is not used for player's choice so I've
             --  changed it back.
             local sacced_so_far = EffectDC():Get_Int(0)
             EffectDC():Set_Int(0, sacced_so_far + 1)
           end
         end
        end
      end
           
      return true
    else
      return false
    end
    </RESOLUTION_TIME_ACTION>
    <RESOLUTION_TIME_ACTION>
    -- My mistake index 0 is not used for player's choice so I've changed it back.
    local num_zombies = EffectDC():Get_Int(0)
    if num_zombies &gt; 0 then
      PutTokensIntoPlay( "TOKEN_ZOMBIE_2_2_277465", num_zombies )
    end
    </RESOLUTION_TIME_ACTION>
    <AI_BASE_SCORE score="1500" zone="hand" />
  </SPELL_ABILITY>
</CARD_V2>
Now I haven't tested it, but that should now work, if not then I'll test it and see where I screwed up.

Re: What is different from DotP 2012 to 2013 cards?

PostPosted: 01 Mar 2013, 21:42
by NEMESiS
Thank you a ton, that worked as intended. So having a number in parenthesis is an index, and is anything that has parenthesis a chest correct? Or is it specified by adding DC (datachest) next to a function? Like EffectDC() for example.

Re: What is different from DotP 2012 to 2013 cards?

PostPosted: 01 Mar 2013, 21:59
by RiiakShiNal
NEMESiS wrote:Thank you a ton, that worked as intended. So having a number in parenthesis is an index, and is anything that has parenthesis a chest correct? Or is it specified by adding DC (datachest) next to a function? Like EffectDC() for example.
No, parenthesis are simply a way to pass parameters (data) to a function. EffectDC() is a function that takes no parameters, but returns a chest. Same with ObjectDC(). EffectDC():Make_Chest(1) creates a new data chest in "drawer" 1 of the Effect's already existing data chest. EffectDC():Get_Chest(1) would then retrieve that new data chest.

Object() is a function that takes no parameters, but returns a card pointer (not a data chest). MTG():PlusOnePlusOneCounters() is a function that takes no parameters, but returns an id for +1/+1 counters which can then be passed to other functions like Count_Counters().