It is currently 24 Jun 2025, 09:18
   
Text Size

Magic Duels tests and results

Moderator: CCGHQ Admins

Re: Magic Duels tests and results

Postby Xander9009 » 20 Jan 2017, 04:21

Ah, ok. I more or less understand it now. Regardless, I noticed it doesn't appear in the properly decompiled ones; it just returns the tables.

Another thing I noticed was that it does, in fact, follow the pattern I'd listed out, which is good. It means it really is pretty simple going from one to the other. Just need to map the various XML tags to their LUA element name counterparts (the attributes are all identical I think, but I didn't verify).

I did notice your decompiler changed the semi-colons to commas. I doubt it would have any effect in-game, but it's worth noting just in case.

Also, I'm now amused. I actually had a reply typed out before I went to be earlier, but I decided to give you some time to work on it before plaguing you with possibly unnecessary suggestions. One of those suggestions was to make a dummy T function, but I wasn't sure if that would even really do anything. However, is it possible to force the decompiler not to put the function in-line? I wouldn't know how to do that, but even if it's not, you could even manage it in Notepad++, since each instance of T very specifically follows an instance of "data = ". Nothing more than a simple search and replace on a regex:
Find: data = (.*?),$
Replace with: data = T\($1\),
Replace all.
No that it would necessarily make them compile correctly, but just to add the T functions for viewing them...
_______________________________
Community Wad - Community Wad Website - How to Help and Report Bugs
Discord: discord.gg/4AXvHzW
User avatar
Xander9009
Programmer
 
Posts: 2905
Joined: 29 Jun 2013, 07:44
Location: Indiana, United States
Has thanked: 121 times
Been thanked: 445 times

Re: Magic Duels tests and results

Postby thefiremind » 20 Jan 2017, 09:11

Xander9009 wrote:Ah, ok. I more or less understand it now. Regardless, I noticed it doesn't appear in the properly decompiled ones; it just returns the tables.
That's because those files aren't decompiled: I ran them through the Lua console and then retrieved just the table through the dumper I linked earlier. Different dumpers can give different results (the one I chose prefixes the table with "return" so that the file can be actually executed in the Lua console in order to retrieve the table again).

Xander9009 wrote:Just need to map the various XML tags to their LUA element name counterparts (the attributes are all identical I think, but I didn't verify).
That's the part that worries me more, since it's very easy to forget one. I should try and get the possible tags from the executable before starting, so that I can see them all together.

Xander9009 wrote:I did notice your decompiler changed the semi-colons to commas. I doubt it would have any effect in-game, but it's worth noting just in case.
I hope it doesn't have any effect.

Xander9009 wrote:One of those suggestions was to make a dummy T function, but I wasn't sure if that would even really do anything.
My function was
Code: Select all
T = function(s) return s end
It couldn't be dummier than that, but it did its job. :D

Xander9009 wrote:Nothing more than a simple search and replace on a regex:
Find: data = (.*?),$
Replace with: data = T\($1\),
Replace all.
No that it would necessarily make them compile correctly, but just to add the T functions for viewing them...
For the existing cards I just wanted to look at the structure without worrying about T: we know it exists from the card I decompiled and it's enough.

EDIT: Something that would be incredibly useful: finding a way to "merge" all card tables together. Let me explain: input all the tables and have a single table in output that has all the possible sub-tables and attributes (their values wouldn't matter). We would be still missing sub-tables that aren't used in official cards, but those wouldn't be many.
It appears that there's a library for that. I need to try. ;)
EDIT 2: Here's the result of merging. I got some errors about non-iterable things, but the output seems OK to me.
All card tables merged | Open
Code: Select all
return {
   art_id = "160671",
   artist = "Jason Rainville",
   card_name = "ZULAPORT_CUTTHROAT",
   casting_cost = "{1}{B}",
   colour = "W",
   expansion = "BFZ",
   export_version = "1",
   file_name = "ZULAPORT_CUTTHROAT_385353",
   is_backside = "True",
   landgroup = "1",
   loyalty = "5",
   multiverse_id = "385353",
   power = "1",
   rarity = "U",
   set_id = "BFZ",
   token = "True",
   toughness = "1",
   ai_counter_scores = {
      ai_counter_score_0 = {
         max_counters = "1",
         score = "600",
         type = "+1/+1",
      },
   },
   ai_custom_scores = {
      ai_custom_score_0 = {
         code = "\t\t\t\tlocal filter = ClearFilter()\n\t\t\t\tfilter:Add(FE_SUB_TYPE, OP_IS, ARTIFACT_TYPE_EQUIPMENT)\n\t\t\t\tfilter:Add(FE_CONTROLLER, OP_IS, EffectController())\n\t\t\t\tif filter:CountStopAt(1) ~= 1 then\n\t\t\t\t\tEffectSource():AddScore(100)\n\t\t\t\tend\n\t\t\t",
      },
   },
   ai_loyalty_ability_scores = {
      ai_loyalty_ability_score_0 = {
         cost = "1",
         score = "400",
      },
      ai_loyalty_ability_score_1 = {
         cost = "-2",
         score = "1200",
      },
      ai_loyalty_ability_score_2 = {
         cost = "-7",
         score = "4600",
      },
   },
   ai_simplified_targetings = {
      ai_simplified_targeting_0 = {
         compartment = "0",
         hint = "HINT_ENEMY_ONLY",
      },
   },
   archetypes = {
      archetype_0 = {
         type = "Monster",
      },
   },
   combat_kill_scores = {
      combat_kill_score_0 = {
         code = "\t\t\t\tlocal linkedDC = LinkedDC()\n\t\t\t\tif linkedDC ~= nil then\n\t\t\t\t\tlocal linkedChest = linkedDC:Get_Chest(0)\n\t\t\t\t\tif linkedChest ~= nil then\n\t\t\t\t\t\tlocal stolenCard = linkedChest:Get_CardPtr(0)\n\t\t\t\t\t\tif stolenCard == nil then\n\t\t\t\t\t\t  return 0\n\t\t\t\t\t\telse\n\t\t\t\t\t\t  return ((stolenCard:CalcScore())*2)\n\t\t\t\t\t\tend\n\t\t\t\t\telse\n\t\t\t\t\t\treturn 0\n\t\t\t\t\tend\n\t\t\t\telse\n\t\t\t\t\treturn 0\n\t\t\t\tend\n\t\t\t",
         linked_ability_group = "0",
      },
   },
   costs = {
      cost_0 = {
         amount = "£Value£",
         type = "Energy",
      },
      cost_1 = {
         type = "TapSelf",
      },
   },
   deckbuilding_activation_levels = {
      deckbuilding_activation_level_0 = {
         base_score = "1100",
      },
      deckbuilding_activation_level_1 = {
         base_score = "0",
         {
            max_amount = "24",
            min_amount = "12",
            resource_subtype = "ALLY",
            score_per_unit = "13",
         },
         {
            max_amount = "12",
            resource_subtype = "ALLY",
            score_per_unit = "7",
         },
      },
   },
   deckbuilding_metadatas = {
      deckbuilding_metadata_0 = {
         defensive = "1",
      },
   },
   deckbuilding_synergy_resources = {
      deckbuilding_synergy_resource_0 = {
         amount = "1",
         resource_name = "Sacrifice",
      },
   },
   derived_infos = {
      derived_info_0 = {
         code = "\t\t\t\tlocal filter = ClearFilter()\n\t\t\t\tlocal player = EffectController()\n\t\t\t\tfilter:SetZone( ZONE_GRAVEYARD, player )\n\t\t\t\tlocal subfilter = filter:AddSubFilter_Or()\n\t\t\t\t\tsubfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_INSTANT )\n\t\t\t\t\tsubfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_SORCERY )\n\t\t\t\treturn filter:Count()\n\t\t\t",
         plural2_tag = "£DerivedInfoPlural2Tag£",
         plural_tag = "£DerivedInfoPluralTag£",
         tag = "£DerivedInfoTag£",
      },
   },
   explain = {
      is_removal = "false",
   },
   filters = {
      filter_0 = {
         code = "\t\t\t\tlocal player = EffectDC():Get_Targets(0):Get_PlayerPtr(0)\n\t\t\t\tif player ~= nil then\n\t\t\t\t\tlocal target_player = EffectDC():Get_Targets(0):Get_PlayerPtr(0)\n\t\t\t\t\t\n\t\t\t\t\tlocal filter = ClearFilter()\n\t\t\t\t\tfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_CREATURE )\n\t\t\t\t\tfilter:Add( FE_CONTROLLER, OP_IS, target_player )\n\t\t\t\telse\n\t\t\t\t\tlocal target_player = EffectDC():Get_Targets(0):Get_CardPtr(0):GetPlayer()\n\t\t\t\t\t\n\t\t\t\t\tlocal filter = ClearFilter()\n\t\t\t\t\tfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_CREATURE )\n\t\t\t\t\tfilter:Add( FE_CONTROLLER, OP_IS, target_player )\n\t\t\t\tend\n\t\t\t",
         filter_id = "0",
      },
   },
   flavour_text = {
      text = {
         {
            data = "“Eldrazi? Ha! Try walking through Zulaport at night with your pockets full. Now |that’s |dangerous.”",
            language_code = "en-US",
         },
         {
            data = "« Les Eldrazi ? Quelle blague ! Essayez donc de traverser Zulaport de nuit avec les poches pleines. |Ça |c’est dangereux. »",
            language_code = "fr-FR",
         },
         {
            data = "“¿Eldrazi? ¡Ja! Prueba a caminar por Zulaport de noche con los bolsillos llenos. Eso |sí |es peligroso”.",
            language_code = "es-ES",
         },
         {
            data = "„Eldrazi? Ha! Versuch mal, nachts mit vollen Taschen durch Zulaport zu laufen. |Das |ist gefährlich!“",
            language_code = "de-DE",
         },
         {
            data = "“Eldrazi? Ah! Prova a camminare di notte per Zulaport con le tasche piene. Ecco, quello è pericoloso.”<i></i>",
            language_code = "it-IT",
         },
         {
            data = "「エルドラージ?どうってことねぇな。ポケット膨らまして夜中のズーラポートを歩いてみな。それが身の危険さ。」",
            language_code = "jp-JA",
         },
         {
            data = "\"엘드라지? 웃기는군! 지갑을 두둑이 채우고 한밤중에 줄라포트를 지나가 보라구. |그런 게 |위험한 거지.\"",
            language_code = "ko-KR",
         },
         {
            data = "«Эльдрази? Ха! Попробуй прогуляться вечером по Зулапорту с полными карманами. Вот это — |настоящая опасность|».",
            language_code = "ru-RU",
         },
         {
            data = "“Eldrazi? Que nada! Tente andar por Zulaport à noite com os bolsos cheios. Isso |sim |é perigoso.”",
            language_code = "pt-BR",
         },
         {
            data = "「奥札奇?呵呵!不妨腰缠万贯时在夜晚来筑拉波走一遭。这才叫危险。」",
            language_code = "zh-CN",
         },
         {
            data = "「奧札奇?呵呵!不妨腰纏萬貫時在夜晚來筑拉波走一遭。|這|才叫危險。」",
            language_code = "zh-HK",
         },
      },
   },
   target_definitions = {
      target_definition_0 = {
         code = "\t\t\t\tlocal filter = ClearFilter()\n\t\t\t\tfilter:SetFilterType( FILTER_TYPE_PLAYERS )\n\t\t\t\tfilter:Add( FE_TEAM, OP_NOT, EffectController():GetTeam() )\n\t\t\t",
      },
   },
   targets = {
      target_0 = {
         compartment = "0",
         count = "1",
         definition = "0",
         tag = "£TargetString£",
      },
   },
   title = {
      text = {
         {
            data = "Zulaport Cutthroat",
            language_code = "en-US",
         },
         {
            data = "Surineur de Zulaport",
            language_code = "fr-FR",
         },
         {
            data = "Degollador de Zulaport",
            language_code = "es-ES",
         },
         {
            data = "Zulaport-Mordgeselle",
            language_code = "de-DE",
         },
         {
            data = "Tagliagole di Zulaport",
            language_code = "it-IT",
         },
         {
            data = "ズーラポートの殺(ころ)し屋(や)",
            language_code = "jp-JA",
         },
         {
            data = "줄라포트 살인귀",
            language_code = "ko-KR",
         },
         {
            data = "Головорез из Зулапорта",
            language_code = "ru-RU",
         },
         {
            data = "Degolador de Zulaport",
            language_code = "pt-BR",
         },
         {
            data = "筑拉波割喉客",
            language_code = "zh-CN",
         },
         {
            data = "筑拉波割喉客",
            language_code = "zh-HK",
         },
      },
   },
   transformation = {
      icon = "CMOON",
      value = "HANWEIR_MILITIA_CAPTAIN_386629",
   },
   abilities = {
      {
         type = "triggered",
         {
            priority = "150",
            actions = {
               {
                  type = "resolution_time",
                  {
                     code = "\t\t\t\t\t\t\t\tif FilteredPlayer() ~= nil then   \n\t\t\t\t\t\t\t\t\tFilteredPlayer():LoseLife( 1 )\n\t\t\t\t\t\t\t\tend\n\t\t\t\t\t\t\t",
                     filter_id = "0",
                  },
               },
               {
                  type = "resolution_time",
                  {
                     code = "\t\t\t\t\t\t\t\tEffectController():GainLife( 1 )\n\t\t\t\t\t\t\t",
                  },
               },
            },
            filters = {
               {
                  code = "\t\t\t\t\t\t\tlocal filter = ClearFilter()\n\t\t\t\t\t\t\tfilter:SetFilterType( FILTER_TYPE_PLAYERS )\n\t\t\t\t\t\t\tfilter:Add( FE_TEAM, OP_NOT, EffectController():GetTeam() )\n\t\t\t\t\t\t",
                  filter_id = "0",
               },
            },
            text = {
               {
                  data = "Whenever Zulaport Cutthroat or another creature you control dies, each opponent loses 1 life and you gain 1 life.",
                  language_code = "en-US",
               },
               {
                  data = "À chaque fois que le Surineur de Zulaport ou qu’une autre créature que vous contrôlez meurt, chaque adversaire perd 1 point de vie et vous gagnez 1 point de vie.",
                  language_code = "fr-FR",
               },
               {
                  data = "Siempre que el Degollador de Zulaport u otra criatura que controlas muera, cada oponente pierde 1 vida y tú ganas 1 vida.",
                  language_code = "es-ES",
               },
               {
                  data = "Immer wenn der Zulaport-Mordgeselle oder eine andere Kreatur, die du kontrollierst, stirbt, verliert jeder Gegner 1 Lebenspunkt, und du erhältst 1 Lebenspunkt dazu.",
                  language_code = "de-DE",
               },
               {
                  data = "Ogniqualvolta il Tagliagole di Zulaport o un’altra creatura che controlli muoiono, ogni avversario perde 1 punto vita e tu guadagni 1 punto vita.",
                  language_code = "it-IT",
               },
               {
                  data = "ズーラポートの殺し屋かあなたがコントロールする他のクリーチャーが1体死亡するたび、各対戦相手はそれぞれ1点のライフを失い、あなたは1点のライフを得る。",
                  language_code = "jp-JA",
               },
               {
                  data = "줄라포트 살인귀나 당신이 조종하는 다른 생물이 죽을 때마다, 각 상대는 생명 1점을 잃고 당신은 생명 1점을 얻는다.",
                  language_code = "ko-KR",
               },
               {
                  data = "Каждый раз, когда Головорез из Зулапорта или другое существо под вашим контролем умирает, каждый оппонент теряет 1 жизнь, а вы получаете 1 жизнь.",
                  language_code = "ru-RU",
               },
               {
                  data = "Toda vez que Degolador de Zulaport ou outra criatura que você controla morre, cada oponente perde 1 ponto de vida e você ganha 1 ponto de vida.",
                  language_code = "pt-BR",
               },
               {
                  data = "每当筑拉波割喉客或另一个由你操控的生物死去时,每位对手各失去1点生命且你获得1点生命。",
                  language_code = "zh-CN",
               },
               {
                  data = "每當筑拉波割喉客或另一個由你操控的生物死去時,每位對手各失去1點生命且你獲得1點生命。",
                  language_code = "zh-HK",
               },
            },
            triggers = {
               {
                  from_zone = "ZONE_BATTLEFIELD",
                  simple_qualifier = "self",
                  to_zone = "ZONE_GRAVEYARD",
                  value = "ZONECHANGE_BEGIN",
               },
               {
                  code = "\t\t\t\t\t\t\treturn ((TriggerObject() ~= EffectSource() and TriggerObject():GetCardType():Test( CARD_TYPE_CREATURE )) and (TriggerObject():GetPlayer() == EffectController()))\n\t\t\t\t\t\t",
                  from_zone = "ZONE_BATTLEFIELD",
                  simple_qualifier = "objectyoucontrol",
                  to_zone = "ZONE_GRAVEYARD",
                  value = "ZONECHANGE_BEGIN",
               },
            },
         },
      },
   },
   actions = {
      {
         type = "resolution_time",
         {
            code = "\t\t\t\t\tlocal answerDC = EffectDC():Get_Targets( 2 )\n\t\t\t\t\tlocal spellsToCast = answerDC:Count()\n\t\t\t\t\tlocal effectController = EffectController()\n\t\t\t\t\tif spellsToCast == nil then\n\t\t\t\t\t\treturn\n\t\t\t\t\tend\n\t\t\t\t\tfor i = (spellsToCast-1), 0, -1 do\n\t\t\t\t\t\tlocal card = answerDC:Get_CardPtr(i)\n\t\t\t\t\t\tif card ~= nil and effectController:CanCastSpellForFree( card ) then\n\t\t\t\t\t\t\teffectController:CastSpellForFree( card )\n\t\t\t\t\t\tend\n\t\t\t\t\tend\n\t\t\t\t",
         },
      },
      {
         type = "resolution_time",
         {
            code = "\t\t\t\t\tlocal targetPlayer = EffectDC():Get_Targets(0):Get_PlayerPtr(0)\n\t\t\t\t\tlocal answerDC = EffectDC():Make_Targets(2)\n\t\t\t\t\tlocal queryDC = EffectDC():Make_Chest(1)\n\t\t\t\t\tlocal cardsToSelect = 0\n\t\t\t\t\tlocal effectController = EffectController()\n\t\t\t\t\tif targetPlayer == nil then\n\t\t\t\t\t\treturn\n\t\t\t\t\tend\n\t\t\t\t\t-- Mill 7 cards and store them in queryDC. Deselect permanent cards.\n\t\t\t\t\tlocal lib_count = targetPlayer:Library_Count()\n\t\t\t\t\tif MTG():IsMainDuel() == false then -- Anti-Cheat script\n\t\t\t\t\t\tfor i = 0,(6) do\n\t\t\t\t\t\t\tlocal card = targetPlayer:Library_GetNth( math.random( 1, lib_count ) )\n\t\t\t\t\t\t\tif card ~= nil then\n\t\t\t\t\t\t\t\tqueryDC:Set_CardPtr(i, card)\n\t\t\t\t\t\t\t\tqueryDC:Protect_CardPtr(i)\n\t\t\t\t\t\t\t\tcard:PutInGraveyard()\n\t\t\t\t\t\t\t\tif card:GetCardType():Test( CARD_TYPE_SORCERY ) or card:GetCardType():Test( CARD_TYPE_INSTANT ) then\n\t\t\t\t\t\t\t\t\tif effectController:CanCastSpellForFree( card ) then\t\n\t\t\t\t\t\t\t\t\t\tcardsToSelect = cardsToSelect+1\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\tqueryDC:QueryUnselect_CardPtr(i)\n\t\t\t\t\t\t\t\t\tend\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\tqueryDC:QueryUnselect_CardPtr(i)\n\t\t\t\t\t\t\t\tend\n\t\t\t\t\t\t\tend\n\t\t\t\t\t\tend\n\t\t\t\t\telse\n\t\t\t\t\t\tfor i = 0, 6 do\n\t\t\t\t\t\t\tlocal card = targetPlayer:Library_GetNth(0)\n\t\t\t\t\t\t\tif card ~= nil then\n\t\t\t\t\t\t\t\tqueryDC:Set_CardPtr(i, card)\n\t\t\t\t\t\t\t\tqueryDC:Protect_CardPtr(i)\n\t\t\t\t\t\t\t\tcard:PutInGraveyard()\n\t\t\t\t\t\t\t\tif card:GetCardType():Test( CARD_TYPE_SORCERY ) or card:GetCardType():Test( CARD_TYPE_INSTANT ) then\n\t\t\t\t\t\t\t\t\tif effectController:CanCastSpellForFree( card ) then\t\n\t\t\t\t\t\t\t\t\t\tcardsToSelect = cardsToSelect+1\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\tqueryDC:QueryUnselect_CardPtr(i)\n\t\t\t\t\t\t\t\t\tend\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\tqueryDC:QueryUnselect_CardPtr(i)\n\t\t\t\t\t\t\t\tend\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tbreak\t\n\t\t\t\t\t\t\tend\n\t\t\t\t\t\tend\n\t\t\t\t\tend\n\t\t\t\t\t-- Spell Mastery check\n\t\t\t\t\tlocal filter = ClearFilter()\n\t\t\t\t\tfilter:SetZone(ZONE_GRAVEYARD, effectController)\n\t\t\t\t\tlocal subfilter = filter:AddSubFilter_Or()\n\t\t\t\t\t\tsubfilter:Add(FE_TYPE, OP_IS, CARD_TYPE_INSTANT)\n\t\t\t\t\t\tsubfilter:Add(FE_TYPE, OP_IS, CARD_TYPE_SORCERY)\n\t\t\t\t\tif (filter:CountStopAt( 2 ) == 2) then\n\t\t\t\t\t\tEffectDC():Set_Int( 3, 1 )\n\t\t\t\t\tend\n\t\t\t\t\t-- If Spell Mastery is fulfilled, the player selects 2 cards. If Spell Mastery is not fulfilled, the player selects up to one card.\n\t\t\t\t\tif (EffectDC():Get_Int(3) == 1) then\n\t\t\t\t\t\teffectController:SetItemCount( 2 )\n\t\t\t\t\t\tfor j = 0, 1 do  \n\t\t\t\t\t\t\teffectController:SetItemPrompt( j, \"£QuerySpellMastery£\" )\n\t\t\t\t\t\tend\n\t\t\t\t\t\teffectController:ChooseItemsFromDC( queryDC, answerDC, QUERY_FLAG_MAY + QUERY_FLAG_ORDERED_SELECTION )\n\t\t\t\t\telse\n\t\t\t\t\t\teffectController:ChooseItemFromDC( \"£Query£\", queryDC, answerDC, QUERY_FLAG_MAY )\n\t\t\t\t\tend\n\t\t\t\t",
         },
      },
   },
   ai_availabilitys = {
      {
         type = "window",
         window_step = "STEP_DECLARE_BLOCKERS",
      },
      {
         response_target = "1",
         type = "in_response",
      },
      {
         response_source = "1",
         type = "in_response",
      },
   },
   ai_base_scores = {
      {
         score = "450",
         zone = "ZONE_BATTLEFIELD",
      },
   },
   more_info = {
      {
         body = "MORE_INFO_BODY_COHORT",
         title = "MORE_INFO_TITLE_COHORT",
         zone = "ZONE_ANY",
      },
   },
   query_text = {
      {
         tag = "CARD_QUERY_CHOOSE_ALLY_YOU_CONTROL_TO_TAP",
         text = {
            {
               data = "Choose an Ally you control to tap.",
               language_code = "en-US",
            },
            {
               data = "Choisissez un allié que vous contrôlez pour l'engager.",
               language_code = "fr-FR",
            },
            {
               data = "Elige un Aliado que controlas para girarlo.",
               language_code = "es-ES",
            },
            {
               data = "Bestimme einen Verbündeten, den du kontrollierst und der getappt werden soll.",
               language_code = "de-DE",
            },
            {
               data = "Scegli un Alleato che controlli da TAPpare.",
               language_code = "it-IT",
            },
            {
               data = "タップする、あなたがコントロールするアンタップ状態の同盟者を1体選んでください。",
               language_code = "jp-JA",
            },
            {
               data = "탭할 당신이 조종하는 동맹 한 개를 고르십시오.",
               language_code = "ko-KR",
            },
            {
               data = "Выберите Союзника под вашим контролем для поворота.",
               language_code = "ru-RU",
            },
            {
               data = "Escolha um Aliado que você controla para virar.",
               language_code = "pt-BR",
            },
            {
               data = "选择一个由你操控的伙伴,以将之横置。",
               language_code = "zh-CN",
            },
            {
               data = "選擇一個由你操控的伙伴,以將其橫置。",
               language_code = "zh-HK",
            },
         },
      },
      {
         tag = "CARD_QUERY_CHOOSE_OPPONENT_LOSE_2_LIFE",
         text = {
            {
               data = "Choose an opponent to lose 2 life.",
               language_code = "en-US",
            },
            {
               data = "Choisissez un adversaire pour qu'il perde 2 points de vie.",
               language_code = "fr-FR",
            },
            {
               data = "Elige un oponente para que pierda 2 vidas.",
               language_code = "es-ES",
            },
            {
               data = "Bestimme einen Gegner, der 2 Lebenspunkte verlieren soll.",
               language_code = "de-DE",
            },
            {
               data = "Scegli un avversario che perde 2 punti vita.",
               language_code = "it-IT",
            },
            {
               data = "2点のライフを失う対戦相手を1人選んでください。",
               language_code = "jp-JA",
            },
            {
               data = "생명 2점을 잃을 상대를 고르십시오.",
               language_code = "ko-KR",
            },
            {
               data = "Выберите оппонента, который должен потерять 2 жизни.",
               language_code = "ru-RU",
            },
            {
               data = "Escolha um oponente para perder 2 pontos de vida.",
               language_code = "pt-BR",
            },
            {
               data = "选择一位对手,以让其失去2点生命。",
               language_code = "zh-CN",
            },
            {
               data = "選擇一個對手來使其失去2點生命。",
               language_code = "zh-HK",
            },
         },
      },
   },
   sfx = {
      {
         name = "COMBAT_SLASH_LARGE_ATTACK",
         power_boundary_max = "-1",
         power_boundary_min = "4",
      },
      {
         name = "COMBAT_SLASH_SMALL_ATTACK",
         power_boundary_max = "3",
         power_boundary_min = "1",
      },
   },
   sub_types = {
      {
         metaname = "Human",
         order_deDE = "0",
         order_esES = "1",
         order_frFR = "0",
         order_itIT = "2",
         order_jpJA = "0",
         order_koKR = "0",
         order_ptBR = "0",
         order_ruRU = "0",
         order_zhCN = "0",
         order_zhHK = "0",
      },
      {
         metaname = "Rogue",
         order_deDE = "1",
         order_esES = "0",
         order_frFR = "1",
         order_itIT = "1",
         order_jpJA = "1",
         order_koKR = "1",
         order_ptBR = "1",
         order_ruRU = "1",
         order_zhCN = "1",
         order_zhHK = "1",
      },
      {
         metaname = "Ally",
         order_deDE = "2",
         order_esES = "2",
         order_frFR = "2",
         order_itIT = "0",
         order_jpJA = "2",
         order_koKR = "2",
         order_ptBR = "2",
         order_ruRU = "2",
         order_zhCN = "2",
         order_zhHK = "2",
      },
   },
   super_types = {
      {
         metaname = "Legendary",
      },
   },
   token_registrations = {
      {
         reservation = "1",
         type = "TOKEN_ELEMENTAL_2_2_G_389855",
      },
   },
   types = {
      {
         metaname = "Creature",
      },
   },
}
-- vi: ft=lua
The outer "costs", "targets" and "derived_infos" seem spurious to me (besides not making sense there, I wouldn't understand what the "£"-enclosed strings refer to). Maybe they are the result of a bug in the converter Stainless used themselves. Anyway, in this table we have (almost) all the possible sub-tables and attributes.

EDIT 3: A heads-up on the conversion task: I finally found a working Lua 5.1 library for C# so I decided that, before trying to make the lol<->xml conversion, I want to be able to "translate" lol files into plain Lua scripts that (hopefully) can produce the exact same result as the compiled ones. Theoretically, I just have to add the module function call at the beginning, add the T's and maybe make the code more human-friendly (Lua supports multiline strings by enclosing them in double square brackets, [[...]] so I should be able to unescape \t and \n inside).

I was also wondering if this new format can open new possibilities. We can mess with the code that loads the whole card now. For example, knowing that the card module becomes a global variable, would it be possible to get the mana cost of a card directly rather than trying to guess it through custom functions? It might be! :)

EDIT 4: It appears that this library doesn't handle UTF-8 properly. #-o Back to the drawing board...

EDIT 5: I enhanced the old extraction script, you can download the results from the updated link in my old post.

EDIT 6: I'm sorry for the delay, but I don't want to make just a converter for nothing. I think it's time to make a new tool, specific for Magic Duels, which will have an xml->lol converter (I probably won't add the backwards conversion, but we'll see) as feature. By the way, I just discovered the incredible "HTML Agility Pack" library which would make the process of reading from Gatherer much more... "agile". :mrgreen:
Last edited by thefiremind on 28 Jan 2017, 15:23, edited 1 time in total.
< 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: 722 times

Re: Magic Duels tests and results

Postby Tejahn » 24 Jan 2017, 23:31

I apologize in advance for this post being off topic but WoTC released this statement a few days ago and I didn't want to start a new thread. I suppose this is the correct place to put this since it needs to be tested. I've run into several people using this exploit.

'Hey there everyone. Posting here to let everyone know that we've identified potential fixes for issues related to Unbridled Growth and a deck building exploit that allows players to break the Duels deck building limit. We're working on them now so that we can release a patch to the Aether Revolt release. We don't have an exact timeline to when a patch can be released, but it would be far in advance of our next set release. As soon as we have more details about the contents of the patch and its release date, we'll let everyone know.'

Also, what do I need to start looking under the hood after the AER update? What's the new method?

EDIT: I just realized I didn't explain how this works. I'm not sure how Unbridled Growth allows two or more copies of each card but another exploit is to attach it to any colorless land such as Wastes or Crumbling Vestige. Afterwards, you can use any creature with a unrestricted mana-cost activated ability, such as Freejam Regent, and Ember-Eye Wolf. It doesn't work for creatures with conditions such as Defiant Salvager and Herald of Anguish unless you have enough of the required artifacts.

I'm only interested in how it allows people to circumvent to rarity restriction.
Tejahn
 
Posts: 430
Joined: 14 May 2013, 01:35
Has thanked: 25 times
Been thanked: 25 times

Re: Magic Duels tests and results

Postby Nick26 » 25 Jan 2017, 08:44

Tejahn wrote:
I'm only interested in how it allows people to circumvent to rarity restriction.
They are two different bugs. I don't know exactly how it works but it is an issue of the new deck builder, specifically of its filters. Not only it let you circumvent the rarity restrictions but it allows you to have unlimited copies of a single card in the deck.

Image

To be honest I never dug into this bug, after all using spirolone's tool we can build the decks we want without any restriction. Anyway, according to a certain forum, these are the steps to exploit this bug:

Step 1. Buy a booster pack
Step 2. Open deck editor
Step 3. Select "new cards" filter
Step 4. Add any number of those new cards to your deck
Step 5. Fill it with other cards as needed. Those cards have rarity restrictions in place
Step 6. Profit
Nick26
 
Posts: 71
Joined: 23 Mar 2015, 16:40
Has thanked: 14 times
Been thanked: 0 time

Re: Magic Duels tests and results

Postby thefiremind » 25 Jan 2017, 09:37

Tejahn wrote:what do I need to start looking under the hood after the AER update? What's the new method?
There are no new methods, just a change of formats. For now, just download the "interpreted" cards from here so you can see how they are structured. I say "interpreted" because I didn't use the decompiler: I processed the .lol files through a Lua 5.1.5 command line interpreter and then dumped the tables.

Tejahn wrote:I'm not sure how Unbridled Growth allows two or more copies of each card
They probably meant that they are 2 unrelated exploits they are trying to fix. I was expecting Unbridled Growth to have problems because I know well how adding multiple mana abilities to a card breaks the auto-tapping mechanic. Better than Stainless themselves, apparently... :mrgreen:
< 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: 722 times

Re: Magic Duels tests and results

Postby Tejahn » 25 Jan 2017, 18:40

Thanks for the info Nick26 and TFM. I'll d/l fom that link in a moment.
Tejahn
 
Posts: 430
Joined: 14 May 2013, 01:35
Has thanked: 25 times
Been thanked: 25 times

Re: Magic Duels tests and results

Postby Tejahn » 25 Jan 2017, 20:42

TFM, have the other folders been extracted as well? I'm looking forward to seeing what's in the Campaign, Decks, and ExploreDecks folder.
Tejahn
 
Posts: 430
Joined: 14 May 2013, 01:35
Has thanked: 25 times
Been thanked: 25 times

Re: Magic Duels tests and results

Postby thefiremind » 25 Jan 2017, 20:52

Tejahn wrote:TFM, have the other folders been extracted as well? I'm looking forward to seeing what's in the Campaign, Decks, and ExploreDecks folder.
The procedure for extracting DATA_006 is still the same as it has always been: if you have been able to see what was inside the previous ZED files, you can open this one as well.
< 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: 722 times

Re: Magic Duels tests and results

Postby Tejahn » 25 Jan 2017, 21:06

It seems I didn't visit the front page yet. I'll grab the .BIN and start probing. Thanks!
Tejahn
 
Posts: 430
Joined: 14 May 2013, 01:35
Has thanked: 25 times
Been thanked: 25 times

Re: Magic Duels tests and results

Postby Nick26 » 01 Feb 2017, 16:56

Hi everyone,
I have a question: do you know if there is a way to add emblems to decks, I mean, to have them at the beginning of the game like in the final match of Oath of the Gatewatch? May be these kind of informations are stored in the deck file and we can change it. I was trying to re-ruild a gold farming deck when I realized that 4x chandra's emblems would get the job done pretty well :D
Nick26
 
Posts: 71
Joined: 23 Mar 2015, 16:40
Has thanked: 14 times
Been thanked: 0 time

Re: Magic Duels tests and results

Postby thefiremind » 02 Feb 2017, 09:18

Nick26 wrote:do you know if there is a way to add emblems to decks, I mean, to have them at the beginning of the game like in the final match of Oath of the Gatewatch?
That information is not in the campaign XML file and not in the campaign deck's XML file. To be honest, I don't know where it is. But even if I knew, it's something that is possible only in campaign mode. Sure I can code a card that spawns an emblem at the beginning of the first turn, but adding it wouldn't let you play online. Emblems are not in the card pool (otherwise you would see them in your collection) so they have no ID to insert in a player deck.
< 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: 722 times

Re: Magic Duels tests and results

Postby Nick26 » 02 Feb 2017, 13:03

I farm gold only offline, I would never cheat online ;)
Wait, is it possible to code new cards right now? :shock: I have been trying to do it since the Aether Revolt realease with no results. If that's the case, could you please make a 0 cost 20 damage burn spell for me? With that I could rebuild my gold farm deck! :D
Nick26
 
Posts: 71
Joined: 23 Mar 2015, 16:40
Has thanked: 14 times
Been thanked: 0 time

Re: Magic Duels tests and results

Postby thefiremind » 02 Feb 2017, 13:52

Nick26 wrote:I farm gold only offline, I would never cheat online ;)
I was assuming that you needed online capabilities in order to get gold. I gave up farming gold because I don't play online and I can already unlock all cards offline, so I'm not up-to-date with how it works.

Nick26 wrote:Wait, is it possible to code new cards right now? :shock:
It was possible since day one, provided we used the new structure properly. My latest extraction of the cards (posted here) should be fully compliant so you should be able to modify any of them and repack it in a new ZED (for example, make the Shock deal 20 damage if you wish). I haven't tried it myself yet, though. Just remember to change the extension from .txt back to .lol.
< 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: 722 times

Re: Magic Duels tests and results

Postby Nick26 » 02 Feb 2017, 15:37

I missed those post somehow. It's great you already figured out how to convert cards! Anyway, I am trying to use them but they are not working for me. I tried to edit a couple of cards, then I renamed them as .lol but they don't show up ingame :(
Nick26
 
Posts: 71
Joined: 23 Mar 2015, 16:40
Has thanked: 14 times
Been thanked: 0 time

Re: Magic Duels tests and results

Postby thefiremind » 02 Feb 2017, 15:58

Well now I tried myself and there's definitely a problem but I can't understand what it is. I tried to change the title of a card, but I still see the original one. My ZED is being read by the game since it shows the AI cards I added to the pool, but it seems like my Cards folder is being ignored.

EDIT: Even if I copy an untouched .lol file to my Cards folder and I change some characters of the title by hex-editing (so that the structure is totally preserved) I cannot see the changes. I don't know what else to try. If there's a new way to override cards (it would seem weird, but hey, it's Stainless :mrgreen:) the upcoming patch might shed some light onto it.

EDIT 2: Strangely enough, the patch didn't add new files. It seems to have updated the executable (of course), AUDIO_003-004-006, and DATA_003-004-006. I can understand patching the AER ZED files, but why updating 003 and 004, too? :-k
I looked for the differences with WinMerge. Here are the reports:
  • What changed in DATA_006:
    • Art_Assets\Textures\Persona\45.tdx (different)
    • UI\Logic\frontend\free_play\two_headed_giant_multiplayer_launch.lol (different)
    • UI\Logic\frontend\free_play\explore_launch.lol (new)
    • UI\Logic\frontend\free_play\multiplayer_launch.lol (new)
  • What changed in DATA_003:
    • A bunch of CNT files in Art_Assets\Models\Card (different)
    • UI\Logic\frontend\initial_flow\quest_log.lol (different)
    • UI\Layout\h1080_default\frontend\initial_flow\quest_log_layout.lol (new)
    • UI\Logic\in_game\zc_buttons.lol (removed)
  • What changed in DATA_004: only .METADATA\FileData.xml. I omitted it from the other 2 reports because it's obvious that it changes if the files change, but in this case only FileData changed: the HightDate and LowDate attributes all have different values. It's like they rebuilt DATA_004 and the position of the contents changed somehow, but not the contents themselves.
Anyway, no help for our problem, unfortunately, and as I wrote before, I'm out of ideas: I'll wait for yours. :(
< 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: 722 times

PreviousNext

Return to Magic Duels

Who is online

Users browsing this forum: No registered users and 0 guests

Main Menu

User Menu

Our Partners


Who is online

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

Login Form