It is currently 24 Apr 2024, 18:20
   
Text Size

Magic Duels tests and results

Moderator: CCGHQ Admins

Re: Magic Duels tests and results

Postby logoliv » 03 Nov 2016, 08:30

I don't understand either, here it is.

Could you please send me your MagicDuels.exe ? I would like to test if it works with it in my system.
Attachments
shot2.jpg
shot1.jpg
Last edited by logoliv on 03 Nov 2016, 08:35, edited 2 times in total.
User avatar
logoliv
 
Posts: 130
Joined: 26 Jul 2010, 11:15
Has thanked: 4 times
Been thanked: 1 time

Re: Magic Duels tests and results

Postby Xander9009 » 03 Nov 2016, 08:31

logoliv wrote:I don't understand either, here it is :
[img]C:/Users/Olivier/Desktop/shot1.jpg[/img]
[img]C:/Users/Olivier/Desktop/shot2.jpg[/img]

Could you please send me your MagicDuels.exe ? I would like to test if it works with it in my system.
You'll need to upload the image to some site like photobucket.com and link to it from there or upload it as an attachment.
_______________________________
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 logoliv » 03 Nov 2016, 08:36

thanks Xander I forgot the upload ability, I was modifying my post when you quoted me

By the way here is the content of my ALI213.ini too, as you can see FullBlockNetwork = 1, but the executable don't seem to read the ini file at all, neither to call the modified dlls.

I am successfully using the emulator with the latest Steam version of the game, otherwise how could I have tested the correct way to override the Kaladesh shoebox card pool?
Perhaps you don't have the LAST version (it seems there was an update since Kaladesh release)
Attachments
shot3.jpg
Last edited by logoliv on 03 Nov 2016, 10:36, edited 2 times in total.
User avatar
logoliv
 
Posts: 130
Joined: 26 Jul 2010, 11:15
Has thanked: 4 times
Been thanked: 1 time

Re: Magic Duels tests and results

Postby thefiremind » 03 Nov 2016, 09:03

Everything seems in order to me, I don't know what to suggest anymore. My executable is the same as yours, the icon indicates that it's the latest one and they weigh the same. Stainless will never release updates outside of the expansion releases so there's no way to remain outdated without knowing.

If you want to check anyway, I used WinMD5 in order to generate my executable's MD5 and it's the following:
Code: Select all
903a7d527f9b8b035a2318e9c2cdd718
You can check with any tool that does the same and see if they are identical. It's faster than uploading the whole file, with my crappy connection. :)
< 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: Magic Duels tests and results

Postby logoliv » 03 Nov 2016, 09:23

Same MD5 here, so WTF with my config ? unsolvable problem :shock:
@firemind : when you launch Duels executable, does Steam open and is it online or offline ?
User avatar
logoliv
 
Posts: 130
Joined: 26 Jul 2010, 11:15
Has thanked: 4 times
Been thanked: 1 time

Re: Magic Duels tests and results

Postby thefiremind » 03 Nov 2016, 09:32

If Steam isn't already open (which happens a lot, that's why I have never noticed before), it opens normally, as it would open through normal means, so I suppose it's online. But the game isn't, as you can see.
< 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: Magic Duels tests and results

Postby logoliv » 03 Nov 2016, 10:27

If I launch the game with Steam already open, it's offline.
What's strange is that it updates the profile in Steam userdata but not the one in ALI213 folder :(

I don't know if I'll take the risk to change the card collection or create new decks in this configuration...
User avatar
logoliv
 
Posts: 130
Joined: 26 Jul 2010, 11:15
Has thanked: 4 times
Been thanked: 1 time

Re: Magic Duels tests and results

Postby thefiremind » 03 Nov 2016, 13:20

I updated the emulator section in the first post: now you have 2 to choose from, and the one by ALI213 is updated (it doesn't open Steam anymore).
< 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: Magic Duels tests and results

Postby thefiremind » 19 Jan 2017, 10:14

Sorry for double posting, but this is a very important change that has happened with the AER expansion:
Now the cards are in LOL format as well!!!
As usual, the decompiler outputs a mess of local variables so it takes some time to understand the real structure behind.
About how to decompile them: since those LOL files contain the card text, if you want a correct output, the decompiler needs to work with UTF-8 encoding, so it needs the argument
Code: Select all
-se UTF8
(I updated my batch files in the decompiler pack so that they include the argument.)

Here's a sample of what you obtain by decompiling Ayli, Eternal Pilgrim (no particular reason why I chose that card, it was just one of the earlier ones in alphabetical order):
| Open
Code: Select all
-- Decompiled using luadec 2.2 rev:  for Lua 5.1 from https://github.com/viruscamp/luadec
-- Command line: -se UTF8 D:\Magic DotP modding\luadec\AYLI_ETERNAL_PILGRIM_391432.lol

-- params : ...
-- function num : 0
local l_0_0 = module
local l_0_1, l_0_2 = ...
l_0_2 = package
l_0_2 = l_0_2.seeall
l_0_0(l_0_1, l_0_2)
l_0_2 = {metaname = "Legendary"}
l_0_1 = {l_0_2}
l_0_2 = {metaname = "Creature"}
l_0_1 = {l_0_2}
local l_0_3 = {}
l_0_3.metaname = "Cleric"
l_0_3.order_deDE = "1"
l_0_3.order_esES = "0"
l_0_3.order_frFR = "1"
l_0_3.order_itIT = "0"
l_0_3.order_jpJA = "1"
l_0_3.order_koKR = "1"
l_0_3.order_ptBR = "1"
l_0_3.order_ruRU = "1"
l_0_3.order_zhCN = "1"
l_0_3.order_zhHK = "1"
l_0_2 = {metaname = "Kor", order_deDE = "0", order_esES = "1", order_frFR = "0", order_itIT = "1", order_jpJA = "0", order_koKR = "0", order_ptBR = "0", order_ruRU = "0", order_zhCN = "0", order_zhHK = "0"}
l_0_1 = {l_0_2, l_0_3}
local l_0_4 = {}
l_0_4.language_code = "fr-FR"
l_0_4.data = T("Ayli, pèlerine éternelle")
local l_0_5 = {}
l_0_5.language_code = "es-ES"
l_0_5.data = T("Ayli, Peregrina Eterna")
local l_0_6 = {}
l_0_6.language_code = "de-DE"
l_0_6.data = T("Ayli, die Ewige Pilgerin")
local l_0_7 = {}
l_0_7.language_code = "it-IT"
l_0_7.data = T("Ayli, Pellegrina Eterna")
local l_0_8 = {}
l_0_8.language_code = "jp-JA"
l_0_8.data = T("永(えい)代(たい)巡(じゅん)礼(れい)者(しゃ)、アイリ")
local l_0_9 = {}
l_0_9.language_code = "ko-KR"
l_0_9.data = T("영원의 순례자 아일리")
local l_0_10 = {}
l_0_10.language_code = "ru-RU"
l_0_10.data = T("Айли, Вечная Паломница")
local l_0_11 = {}
l_0_11.language_code = "pt-BR"
l_0_11.data = T("Ayli, Peregrina Eterna")
local l_0_12 = {}
l_0_12.language_code = "zh-CN"
l_0_12.data = T("坚信朝圣客艾栗")
local l_0_13 = {}
l_0_13.language_code = "zh-HK"
l_0_13.data = T("堅信朝聖客艾栗")
l_0_3 = {language_code = "en-US", data = T("Ayli, Eternal Pilgrim")}
l_0_2 = {l_0_3, l_0_4, l_0_5, l_0_6, l_0_7, l_0_8, l_0_9, l_0_10, l_0_11, l_0_12, l_0_13}
l_0_1 = {text = l_0_2}
l_0_6 = T
l_0_7 = "Deathtouch"
l_0_6 = l_0_6(l_0_7)
l_0_7 = T
l_0_8 = "Contact mortel"
l_0_7 = l_0_7(l_0_8)
l_0_8 = T
l_0_9 = "Toque mortal."
l_0_8 = l_0_8(l_0_9)
l_0_9 = T
l_0_10 = "Todesberührung"
l_0_9 = l_0_9(l_0_10)
l_0_10 = T
l_0_11 = "Tocco letale"
l_0_10 = l_0_10(l_0_11)
l_0_11 = T
l_0_12 = "接死"
l_0_11 = l_0_11(l_0_12)
l_0_12 = T
l_0_13 = "치명타"
l_0_12 = l_0_12(l_0_13)
l_0_13 = T
l_0_13 = l_0_13("Смертельное касание")
local l_0_14 = {}
l_0_14.language_code = "zh-CN"
l_0_14.data = T("死触")
local l_0_15 = {}
l_0_15.language_code = "zh-HK"
l_0_15.data = T("死觸")
l_0_13, l_0_12, l_0_11, l_0_10, l_0_9, l_0_8, l_0_7, l_0_6, l_0_5 = {language_code = "pt-BR", data = T("Toque mortífero")}, {language_code = "ru-RU", data = l_0_13}, {language_code = "ko-KR", data = l_0_12}, {language_code = "jp-JA", data = l_0_11}, {language_code = "it-IT", data = l_0_10}, {language_code = "de-DE", data = l_0_9}, {language_code = "es-ES", data = l_0_8}, {language_code = "fr-FR", data = l_0_7}, {language_code = "en-US", data = l_0_6}
l_0_4 = {l_0_5, l_0_6, l_0_7, l_0_8, l_0_9, l_0_10, l_0_11, l_0_12, l_0_13, l_0_14, l_0_15}
l_0_5 = {characteristic = "CHARACTERISTIC_DEATHTOUCH"}
l_0_4 = {l_0_5}
l_0_3 = {text = l_0_4, intrinsics = l_0_4}
l_0_7 = T
l_0_8 = "{1}, Sacrifice another creature: You gain life equal to the sacrificed creature’s toughness."
l_0_7 = l_0_7(l_0_8)
l_0_8 = T
l_0_9 = "{1}, sacrifiez une autre créature : Vous gagnez un nombre de points de vie égal à l’endurance de la créature sacrifiée."
l_0_8 = l_0_8(l_0_9)
l_0_9 = T
l_0_10 = "{1}, sacrificar otra criatura: Ganas una cantidad de vidas igual a la resistencia de la criatura sacrificada."
l_0_9 = l_0_9(l_0_10)
l_0_10 = T
l_0_11 = "{1}, opfere eine andere Kreatur: Du erhältst Lebenspunkte in Höhe der Widerstandskraft der geopferten Kreatur dazu."
l_0_10 = l_0_10(l_0_11)
l_0_11 = T
l_0_12 = "{1}, Sacrifica un’altra creatura: Guadagni punti vita pari alla costituzione della creatura sacrificata."
l_0_11 = l_0_11(l_0_12)
l_0_12 = T
l_0_13 = "{1}, 他のクリーチャーを1体生け贄に捧げる:あなたは生け贄に捧げたクリーチャーのタフネスに等しい点数のライフを得る。"
l_0_12 = l_0_12(l_0_13)
l_0_13 = T
l_0_14 = "{1}, 다른 생물 한 개를 희생한다: 당신은 희생된 생물의 방어력만큼 생명점을 얻는다."
l_0_13 = l_0_13(l_0_14)
l_0_14 = T
l_0_15 = "{1}, пожертвуйте другое существо: вы получаете количество жизней, равное выносливости пожертвованного существа."
l_0_14 = l_0_14(l_0_15)
l_0_15 = T
l_0_15 = l_0_15("{1}, Sacrifique outra criatura: Você ganha uma quantidade de pontos de vida igual à resistência da criatura sacrificada.")
local l_0_16 = {}
l_0_16.language_code = "zh-HK"
l_0_16.data = T("{1},犧牲另一個生物:你獲得等同於所犧牲生物之防禦力的生命。")
l_0_15, l_0_14, l_0_13, l_0_12, l_0_11, l_0_10, l_0_9, l_0_8, l_0_7, l_0_6 = {language_code = "zh-CN", data = T("{1},牺牲另一个生物:你获得等同于所牺牲生物之防御力的生命。")}, {language_code = "pt-BR", data = l_0_15}, {language_code = "ru-RU", data = l_0_14}, {language_code = "ko-KR", data = l_0_13}, {language_code = "jp-JA", data = l_0_12}, {language_code = "it-IT", data = l_0_11}, {language_code = "de-DE", data = l_0_10}, {language_code = "es-ES", data = l_0_9}, {language_code = "fr-FR", data = l_0_8}, {language_code = "en-US", data = l_0_7}
l_0_5 = {l_0_6, l_0_7, l_0_8, l_0_9, l_0_10, l_0_11, l_0_12, l_0_13, l_0_14, l_0_15, l_0_16}
l_0_6 = {name = "Lifegain"}
l_0_5 = {l_0_6}
l_0_11, l_0_10, l_0_9, l_0_8, l_0_7, l_0_6 = {restriction_type = "none", response_triggersource = "1"}, {window_step = "STEP_END_OF_TURN", window_turn = "their_turn", type = "window"}, {window_step = "STEP_DECLARE_BLOCKERS", type = "window"}, {type = "in_response", response_source = "1"}, {type = "in_response", response_source = "1"}, {window_step = "STEP_DECLARE_BLOCKERS", type = "window"}
l_0_5 = {l_0_6, l_0_7, l_0_8, l_0_9, l_0_10, l_0_11}
l_0_7, l_0_6 = {type = "Sacrifice", definition = "0", compartment = "1", query_tag = "CARD_QUERY_CHOOSE_CREATURE_TO_SACRIFICE", item_count = "1", LKI_shield = "1"}, {mana_cost = "{1}", type = "Mana"}
l_0_5 = {l_0_6, l_0_7}
l_0_6 = {id = "0", code = "\t\t\t\t\t\t\tlocal filter = ClearFilter()\n\t\t\t\t\t\t\tfilter:Add( FE_CARD_INSTANCE, OP_NOT, EffectSource())\n\t\t\t\t\t\t\tfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_CREATURE )\n\t\t\t\t\t\t"}
l_0_5 = {l_0_6}
l_0_6 = {play_tag = "HINT_ABILITY_LIFEGAIN_WHY_PLAY"}
l_0_5 = {l_0_6}
l_0_7 = {code = "\t\t\t\t\t\t\t\tlocal sacrificeDC = EffectDC():Get_Targets(1)\n\t\t\t\t\t\t\t\tif sacrificeDC ~= nil then\n\t\t\t\t\t\t\t\t\tlocal creature = sacrificeDC:Get_CardPtr(0)\n\t\t\t\t\t\t\t\t\tif creature ~= nil then\n\t\t\t\t\t\t\t\t\t\tlocal toughness = creature:GetCurrentCharacteristics():Toughness_Get()\n\t\t\t\t\t\t\t\t\t\tEffectController():GainLife( toughness )\n\t\t\t\t\t\t\t\t\tend\n\t\t\t\t\t\t\t\tend\n\t\t\t\t\t\t\t"}
l_0_6 = {l_0_7; type = "resolution_time"}
l_0_5 = {l_0_6}
l_0_4 = {text = l_0_5, categorys = l_0_5, ai_availabilitys = l_0_5, costs = l_0_5, cost_definitions = l_0_5, explains = l_0_5, actions = l_0_5}
l_0_8 = T
l_0_9 = "{1}{W}{B}, Sacrifice another creature: Exile target nonland permanent. Activate this ability only if you have at least 10 life more than your starting life total."
l_0_8 = l_0_8(l_0_9)
l_0_9 = T
l_0_10 = "{1}{W}{B}, sacrifiez une autre créature : Exilez le permanent non-terrain ciblé. N’activez cette capacité que si vous avez au moins 10 points de vie de plus que votre total de points de vie de départ."
l_0_9 = l_0_9(l_0_10)
l_0_10 = T
l_0_11 = "{1}{W}{B}, sacrificar otra criatura: Exilia el permanente objetivo que no sea tierra. Activa esta habilidad solo si tienes al menos 10 vidas más que tu total inicial de vidas."
l_0_10 = l_0_10(l_0_11)
l_0_11 = T
l_0_12 = "{1}{W}{B}, opfere eine andere Kreatur: Schicke eine bleibende Karte deiner Wahl, die kein Land ist, ins Exil. Aktiviere diese Fähigkeit nur, falls du mindestens 10 Lebenspunkte mehr als deine Startlebenspunktezahl hast."
l_0_11 = l_0_11(l_0_12)
l_0_12 = T
l_0_13 = "{1}{W}{B}, Sacrifica un’altra creatura: Esilia un permanente non terra bersaglio. Attiva questa abilità solo se hai almeno 10 punti vita in più rispetto ai tuoi punti vita iniziali."
l_0_12 = l_0_12(l_0_13)
l_0_13 = T
l_0_14 = "{1}{W}{B}, 他のクリーチャーを1体生け贄に捧げる:土地でないパーマネント1つを対象とし、それを追放する。この能力は、あなたのライフの総量がゲーム開始時よりも10点以上多いときにのみ起動できる。"
l_0_13 = l_0_13(l_0_14)
l_0_14 = T
l_0_15 = "{1}{W}{B}, 다른 생물 한 개를 희생한다: 대지가 아닌 지속물을 목표로 정한다. 그 지속물을 추방한다. 당신의 생명 총점이 게임을 시작했을 때의 생명 총점보다 10점 이상 높은 경우에만 이 능력을 활성화한다."
l_0_14 = l_0_14(l_0_15)
l_0_15 = T
l_0_16 = "{1}{W}{B}, пожертвуйте другое существо: изгоните целевой не являющийся землей перманент. Активируйте эту способность, только если количество ваших жизней превышает ваше начальное количество жизней как минимум на 10."
l_0_15 = l_0_15(l_0_16)
l_0_16 = T
l_0_16 = l_0_16("{1}{W}{B}, Sacrifique outra criatura: Exile a permanente alvo que não seja um terreno. Ative esta habilidade somente se tiver ao menos 10 pontos de vida a mais que seu total de pontos de vida inicial.")
local l_0_17 = {}
l_0_17.language_code = "zh-HK"
l_0_17.data = T("{1}{W}{B},犧牲另一個生物:放逐目標非地永久物。只能於你的總生命比你的起始總生命至少多10點時起動此異能。")
l_0_16, l_0_15, l_0_14, l_0_13, l_0_12, l_0_11, l_0_10, l_0_9, l_0_8, l_0_7 = {language_code = "zh-CN", data = T("{1}{W}{B},牺牲另一个生物:放逐目标非地永久物。只能于你的总生命比你的起始总生命至少多10点时起动此异能。")}, {language_code = "pt-BR", data = l_0_16}, {language_code = "ru-RU", data = l_0_15}, {language_code = "ko-KR", data = l_0_14}, {language_code = "jp-JA", data = l_0_13}, {language_code = "it-IT", data = l_0_12}, {language_code = "de-DE", data = l_0_11}, {language_code = "es-ES", data = l_0_10}, {language_code = "fr-FR", data = l_0_9}, {language_code = "en-US", data = l_0_8}
l_0_6 = {l_0_7, l_0_8, l_0_9, l_0_10, l_0_11, l_0_12, l_0_13, l_0_14, l_0_15, l_0_16, l_0_17}
l_0_15, l_0_14, l_0_13, l_0_12, l_0_11, l_0_10, l_0_9, l_0_8, l_0_7 = {restriction_type = "none", response_triggersource = "1"}, {type = "in_response", response_source = "1", response_target = "1"}, {window_step = "STEP_END_OF_TURN", type = "window"}, {window_step = "STEP_DECLARE_BLOCKERS", type = "window"}, {window_step = "STEP_MAIN_1", window_turn = "my_turn", type = "window"}, {window_step = "STEP_DECLARE_ATTACKERS", window_turn = "their_turn", type = "window"}, {window_step = "STEP_BEGIN_COMBAT", window_turn = "their_turn", type = "window"}, {type = "in_response", response_source = "1"}, {window_step = "STEP_DECLARE_BLOCKERS", type = "window"}
l_0_6 = {l_0_7, l_0_8, l_0_9, l_0_10, l_0_11, l_0_12, l_0_13, l_0_14, l_0_15}
l_0_7 = {compartment = "1", hint = "HINT_ENEMY_ONLY"}
l_0_6 = {l_0_7}
l_0_7 = {code = "\t\t\t\t\t\t\tlocal player = EffectController()\n\t\t\t\t\t\t\treturn (player:GetLifeTotal() >= player:GetStartingLifeTotal()+10)\n\t\t\t\t\t\t"}
l_0_6 = {l_0_7}
l_0_8, l_0_7 = {type = "Sacrifice", definition = "0", compartment = "1", query_tag = "CARD_QUERY_CHOOSE_CREATURE_TO_SACRIFICE", item_count = "1"}, {mana_cost = "{1}{W}{B}", type = "Mana"}
l_0_6 = {l_0_7, l_0_8}
l_0_7 = {id = "0", code = "\t\t\t\t\t\t\tlocal filter = ClearFilter()\n\t\t\t\t\t\t\tfilter:Add( FE_CARD_INSTANCE, OP_NOT, EffectSource())\n\t\t\t\t\t\t\tfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_CREATURE )\n\t\t\t\t\t\t"}
l_0_6 = {l_0_7}
l_0_7 = {is_removal = "1", play_tag = "HINT_ABILITY_REMOVAL_WHY_PLAY"}
l_0_6 = {l_0_7}
l_0_7 = {tag = "CARD_QUERY_CHOOSE_NONLAND_PERMANENT_TO_EXILE", definition = "0", compartment = "0", count = "1"}
l_0_6 = {l_0_7}
l_0_7 = {id = "0", code = "\t\t\t\t\t\t\tlocal filter = ClearFilter()\n\t\t\t\t\t\t\tfilter:Add( FE_TYPE, OP_NOT, CARD_TYPE_LAND )\n\t\t\t\t\t\t\tfilter:Add( FE_IS_PERMANENT, true )\n\t\t\t\t\t\t"}
l_0_6 = {l_0_7}
l_0_8 = {code = "\t\t\t\t\t\t\t\tlocal target = EffectDC():Get_Targets(0):Get_CardPtr(0)\n\t\t\t\t\t\t\t\tif target ~= nil then   \n\t\t\t\t\t\t\t\t\ttarget:Exile()  \n\t\t\t\t\t\t\t\tend\n\t\t\t\t\t\t\t"}
l_0_7 = {l_0_8; type = "resolution_time"}
l_0_6 = {l_0_7}
l_0_5 = {text = l_0_6, ai_availabilitys = l_0_6, ai_simplified_targetings = l_0_6, availabilitys = l_0_6, costs = l_0_6, cost_definitions = l_0_6, explains = l_0_6, targets = l_0_6, target_definitions = l_0_6, actions = l_0_6}
l_0_4, l_0_3, l_0_2 = {l_0_5; type = "activated"}, {l_0_4; type = "activated"}, {l_0_3; type = "static"}
l_0_1 = {l_0_2, l_0_3, l_0_4}
l_0_2 = {base_score = "1600"}
l_0_3 = {score_per_unit = "50", resource_name = "Sacrifice", amount_consumed = "1"}
l_0_2 = {l_0_3; base_score = "0"}
l_0_1 = {deckbuilding_activation_level_0 = l_0_2, deckbuilding_activation_level_1 = l_0_2}
l_0_2 = {defensive = "0.5"}
l_0_1 = {deckbuilding_metadata_0 = l_0_2}
l_0_2 = {resource_name = "Life", amount = "1"}
l_0_1 = {deckbuilding_synergy_resource_0 = l_0_2}
l_0_1 = {play_tag = "HINT_CREATURE_ABILITY_WHY_PLAY", removal_tag = "HINT_CREATURE_ABILITY_WHY_REMOVE", is_removal = "false"}
l_0_3, l_0_2 = {name = "COMBAT_SLASH_SMALL_ATTACK", power_boundary_min = "1", power_boundary_max = "3"}, {name = "COMBAT_SLASH_LARGE_ATTACK", power_boundary_min = "4", power_boundary_max = "-1"}
l_0_1 = {l_0_2, l_0_3}
l_0_2 = {score = "300", zone = "ZONE_BATTLEFIELD"}
l_0_1 = {l_0_2}
l_0_5 = T
l_0_6 = "Choose a creature to sacrifice."
l_0_5 = l_0_5(l_0_6)
l_0_6 = T
l_0_7 = "Choisissez une créature pour la sacrifier."
l_0_6 = l_0_6(l_0_7)
l_0_7 = T
l_0_8 = "Elige una criatura para sacrificarla."
l_0_7 = l_0_7(l_0_8)
l_0_8 = T
l_0_9 = "Bestimme eine Kreatur, die geopfert werden soll."
l_0_8 = l_0_8(l_0_9)
l_0_9 = T
l_0_10 = "Scegli una creatura da sacrificare."
l_0_9 = l_0_9(l_0_10)
l_0_10 = T
l_0_11 = "生け贄に捧げるクリーチャーを1体選んでください。"
l_0_10 = l_0_10(l_0_11)
l_0_11 = T
l_0_12 = "희생할 생물을 한 개 고르십시오."
l_0_11 = l_0_11(l_0_12)
l_0_12 = T
l_0_13 = "Выберите существо для пожертвования."
l_0_12 = l_0_12(l_0_13)
l_0_13 = T
l_0_14 = "Escolha uma criatura para sacrificar."
l_0_13 = l_0_13(l_0_14)
l_0_14 = T
l_0_15 = "选择一个要牺牲的生物。"
l_0_14 = l_0_14(l_0_15)
l_0_15 = T
l_0_16 = "選擇一個生物來犧牲。"
l_0_15 = l_0_15(l_0_16)
l_0_14, l_0_13, l_0_12, l_0_11, l_0_10, l_0_9, l_0_8, l_0_7, l_0_6, l_0_5, l_0_4 = {language_code = "zh-HK", data = l_0_15}, {language_code = "zh-CN", data = l_0_14}, {language_code = "pt-BR", data = l_0_13}, {language_code = "ru-RU", data = l_0_12}, {language_code = "ko-KR", data = l_0_11}, {language_code = "jp-JA", data = l_0_10}, {language_code = "it-IT", data = l_0_9}, {language_code = "de-DE", data = l_0_8}, {language_code = "es-ES", data = l_0_7}, {language_code = "fr-FR", data = l_0_6}, {language_code = "en-US", data = l_0_5}
l_0_3 = {l_0_4, l_0_5, l_0_6, l_0_7, l_0_8, l_0_9, l_0_10, l_0_11, l_0_12, l_0_13, l_0_14}
l_0_6 = T
l_0_7 = "Choose a nonland permanent to exile."
l_0_6 = l_0_6(l_0_7)
l_0_7 = T
l_0_8 = "Choisissez un permanent non-terrain à exiler."
l_0_7 = l_0_7(l_0_8)
l_0_8 = T
l_0_9 = "Elige un permanente que no sea tierra para exiliarlo."
l_0_8 = l_0_8(l_0_9)
l_0_9 = T
l_0_10 = "Bestimme eine bleibende Karte außer einem Land, die ins Exil geschickt werden soll."
l_0_9 = l_0_9(l_0_10)
l_0_10 = T
l_0_11 = "Scegli un permanente non terra da esiliare."
l_0_10 = l_0_10(l_0_11)
l_0_11 = T
l_0_12 = "追放する土地でないパーマネントを1つ選んでください。"
l_0_11 = l_0_11(l_0_12)
l_0_12 = T
l_0_13 = "추방할 대지가 아닌 지속물 한 개를 고르십시오."
l_0_12 = l_0_12(l_0_13)
l_0_13 = T
l_0_14 = "Выберите не являющийся землей перманент для изгнания."
l_0_13 = l_0_13(l_0_14)
l_0_14 = T
l_0_15 = "Escolha uma permanente que não seja terreno para exilar."
l_0_14 = l_0_14(l_0_15)
l_0_15 = T
l_0_16 = "选择一个要放逐的非地永久物。"
l_0_15 = l_0_15(l_0_16)
l_0_16 = T
l_0_17 = "選擇一個非地永久物來放逐。"
l_0_16 = l_0_16(l_0_17)
l_0_15, l_0_14, l_0_13, l_0_12, l_0_11, l_0_10, l_0_9, l_0_8, l_0_7, l_0_6, l_0_5 = {language_code = "zh-HK", data = l_0_16}, {language_code = "zh-CN", data = l_0_15}, {language_code = "pt-BR", data = l_0_14}, {language_code = "ru-RU", data = l_0_13}, {language_code = "ko-KR", data = l_0_12}, {language_code = "jp-JA", data = l_0_11}, {language_code = "it-IT", data = l_0_10}, {language_code = "de-DE", data = l_0_9}, {language_code = "es-ES", data = l_0_8}, {language_code = "fr-FR", data = l_0_7}, {language_code = "en-US", data = l_0_6}
l_0_4 = {l_0_5, l_0_6, l_0_7, l_0_8, l_0_9, l_0_10, l_0_11, l_0_12, l_0_13, l_0_14, l_0_15}
l_0_7 = T
l_0_8 = "Choose a creature to sacrifice."
l_0_7 = l_0_7(l_0_8)
l_0_8 = T
l_0_9 = "Choisissez une créature pour la sacrifier."
l_0_8 = l_0_8(l_0_9)
l_0_9 = T
l_0_10 = "Elige una criatura para sacrificarla."
l_0_9 = l_0_9(l_0_10)
l_0_10 = T
l_0_11 = "Bestimme eine Kreatur, die geopfert werden soll."
l_0_10 = l_0_10(l_0_11)
l_0_11 = T
l_0_12 = "Scegli una creatura da sacrificare."
l_0_11 = l_0_11(l_0_12)
l_0_12 = T
l_0_13 = "生け贄に捧げるクリーチャーを1体選んでください。"
l_0_12 = l_0_12(l_0_13)
l_0_13 = T
l_0_14 = "희생할 생물을 한 개 고르십시오."
l_0_13 = l_0_13(l_0_14)
l_0_14 = T
l_0_15 = "Выберите существо для пожертвования."
l_0_14 = l_0_14(l_0_15)
l_0_15 = T
l_0_16 = "Escolha uma criatura para sacrificar."
l_0_15 = l_0_15(l_0_16)
l_0_16 = T
l_0_17 = "选择一个要牺牲的生物。"
l_0_16 = l_0_16(l_0_17)
l_0_17 = T
l_0_17 = l_0_17("選擇一個生物來犧牲。")
l_0_16, l_0_15, l_0_14, l_0_13, l_0_12, l_0_11, l_0_10, l_0_9, l_0_8, l_0_7, l_0_6 = {language_code = "zh-HK", data = l_0_17}, {language_code = "zh-CN", data = l_0_16}, {language_code = "pt-BR", data = l_0_15}, {language_code = "ru-RU", data = l_0_14}, {language_code = "ko-KR", data = l_0_13}, {language_code = "jp-JA", data = l_0_12}, {language_code = "it-IT", data = l_0_11}, {language_code = "de-DE", data = l_0_10}, {language_code = "es-ES", data = l_0_9}, {language_code = "fr-FR", data = l_0_8}, {language_code = "en-US", data = l_0_7}
l_0_5 = {l_0_6, l_0_7, l_0_8, l_0_9, l_0_10, l_0_11, l_0_12, l_0_13, l_0_14, l_0_15, l_0_16}
l_0_4, l_0_3, l_0_2 = {tag = "CARD_QUERY_CHOOSE_CREATURE_TO_SACRIFICE", text = l_0_5}, {tag = "CARD_QUERY_CHOOSE_NONLAND_PERMANENT_TO_EXILE", text = l_0_4}, {tag = "CARD_QUERY_CHOOSE_CREATURE_TO_SACRIFICE", text = l_0_3}
l_0_1 = {l_0_2, l_0_3, l_0_4}
l_0_2 = {title = "MORE_INFO_BADGE_TITLE_3", body = "MORE_INFO_BADGE_BODY_3", zone = "ZONE_ANY"}
l_0_2 = {title = "MORE_INFO_TITLE_EXILE", body = "MORE_INFO_BODY_EXILE", zone = "ZONE_ANY"}
l_0_1 = {help_0 = l_0_2, help_1 = l_0_2}
card, l_0_0 = l_0_0, {export_version = "1", file_name = "AYLI_ETERNAL_PILGRIM_391432", card_name = "AYLI_ETERNAL_PILGRIM", multiverse_id = "391432", casting_cost = "{W}{B}", art_id = "161257", artist = "Cynthia Sheppard", rarity = "R", set_id = "OGW", expansion = "OGW", power = "2", toughness = "3", super_types = l_0_1, types = l_0_1, sub_types = l_0_1, title = l_0_1, abilities = l_0_1, deckbuilding_activation_levels = l_0_1, deckbuilding_metadatas = l_0_1, deckbuilding_synergy_resources = l_0_1, explain = l_0_1, sfx = l_0_1, ai_base_scores = l_0_1, query_text = l_0_1, more_info = l_0_1}
What I noticed is:
  • Did they reintroduce the sub-type ordering on a card basis? You can see that we have order_deDE, order_esES, etc.
  • All strings that might use UTF-8 encoding are enclosed in a T function. I'm not a Lua expert (I only know what I learned from modding) so it may be a standard function, perhaps it tells Lua to process the strings with non-ASCII encoding, I don't know. I tried to search for it on Google, but when the function is called just "T" it's hard to make a meaningful search term...
  • The code is written with escaped special characters (you can find lots of tabulations with \t and some new lines with \n). It's not actually important since Lua doesn't care about indentation (unlike Python, for example).
  • The main card structure is on the last line, but here the decompiler probably did something wrong because it seems to assign the same local variable l_0_1 to a bunch of things while that variable seems to be made for more_info only.
If someone manages to write a clean card structure before me, please don't hesitate to share it.

Aside from the card structure change, I also noticed that Constants.lol is now empty. Did they put all the constants inside the executable? Anyway, if they felt the need to make an empty copy of Constants.lol in order to override the old one, it probably means we can still add constants of our own as we always did.
< 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: Magic Duels tests and results

Postby RiiakShiNal » 19 Jan 2017, 12:11

The T function you are seeing probably functions similarly to _T from C++. In C++ it is a #define that varies depending on whether the program is compiled using ANSI or Wide character strings and adds the appropriate decoration to strings so that they are used as Wide character strings (2 bytes per character) when compiled with unicode and as ANSI strings (1 byte per character) when compiled without Unicode. Those of us familiar with C and C++ won't find the usage of T jarring, but it may take some getting used to for other people.
RiiakShiNal
Programmer
 
Posts: 2185
Joined: 16 May 2011, 21:37
Has thanked: 75 times
Been thanked: 497 times

Re: Magic Duels tests and results

Postby thefiremind » 19 Jan 2017, 13:02

Thanks, now it makes sense. Through the tests I'm currently doing I discovered that it wasn't a standard Lua function, in fact the Lua interpreter was complaining about it not being defined (although it may be inside a library that needs to be included).

I'm trying to find a way to output the card tables in a more understandable way by executing the .lol files in a Lua interpreter, rather than by decompiling them with luadec. I'll report back when I get something useful.
< 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: Magic Duels tests and results

Postby Xander9009 » 19 Jan 2017, 13:10

I doubt it'll get anywhere, but I'm currently piecing together how the decompiled one should look. It did improperly reuse various variable names and it split up a lot of simple things. It appears to be nothing more than a giant table. There isn't much in the way of functions going on.
_______________________________
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 » 19 Jan 2017, 13:36

Xander9009 wrote:I doubt it'll get anywhere, but I'm currently piecing together how the decompiled one should look. It did improperly reuse various variable names and it split up a lot of simple things. It appears to be nothing more than a giant table. There isn't much in the way of functions going on.
Yes, it's a table, just as the card pools, but a bit more complicated. If I can make a tool that uses a Lua interpreter and outputs the table by executing the .lol file it will be much easier.
< 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: Magic Duels tests and results

Postby Xander9009 » 19 Jan 2017, 14:56

  • All special characters are escaped or converted. (Newlines and tabs are escaped. "&gt;" becomes the proper ">".)
  • CDATA blocks are replaced by T(...contents of CDATA block...)
  • Each XML tag the game recognizes is converted to a table.
  • XML attributes and children tags become named elements of the parent tag's new table.
  • Most tags' names are the pluralized form of their XML tag names, but some are even more different: LOCALIZED_TEXT becomes "text" and "AVAILABILITY" becomes "availabilitys". (In other words, blocks that you can have more than one of, and even some I wouldn't expect more than one of, become plural.)
  • Tags of the same type within the same parent are grouped together into the same table.
  • Contents of an XML block to be executed as code goes in the element named "code".
  • Tags which define specific, singular attributes about a card such as casting cost, power, toughness, etc. are named elements of that type but are not tables: file_name = "AYLI_ETERNAL_PILGRIM_391432"
  • Actions and abilities are grouped as simply actions and abilities (RTAs and PTAs are both simply in "actions"), but consist of a "type" element and the table of everything else the ability contained.
  • As thefiremind noted, the subtypes have ordering info.
So, an ability's cost definition block, for example, would look like this:
Code: Select all
cost_definitions = {
   {
      id = "0",
      code = "\t\t\t\t\t\t\tlocal filter = ClearFilter()\n\t\t\t\t\t\t\tfilter:Add( FE_CARD_INSTANCE, OP_NOT, EffectSource())\n\t\t\t\t\t\t\tfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_CREATURE )\n\t\t\t\t\t\t"
   }
}
The "id" attribute becomes an element named "id" instead. The contents of the block become the "code" element.

Things that I don't understand:
  • The very beginning.
  • The very end.
  • Why some table separations (nearly all of them) use commas while some (the separator between an ability's contents and its "type" element) use semicolons.
Specifically, the beginning:
Code: Select all
local l_0_0 = module
local l_0_1, l_0_2 = ...
l_0_2 = package
l_0_2 = l_0_2.seeall
l_0_0(l_0_1, l_0_2)
The end:
Code: Select all
card, l_0_0 = l_0_0, {...all of the data tables...}
And then all table separators look like this:
Code: Select all
ai_availabilitys = {
   {restriction_type = "none", response_triggersource = "1"},
   {window_step = "STEP_END_OF_TURN", window_turn = "their_turn", type = "window"},
   {window_step = "STEP_DECLARE_BLOCKERS", type = "window"},
   {type = "in_response", response_source = "1"},
   {type = "in_response", response_source = "1"},
   {window_step = "STEP_DECLARE_BLOCKERS", type = "window"}
}
But ability types and action types are separated from ability contents and action contents like this:
Code: Select all
actions = {
   {
      {
         code = "\t\t\t\t\t\t\t\tlocal sacrificeDC = EffectDC():Get_Targets(1)\n\t\t\t\t\t\t\t\tif sacrificeDC ~= nil then\n\t\t\t\t\t\t\t\t\tlocal creature = sacrificeDC:Get_CardPtr(0)\n\t\t\t\t\t\t\t\t\tif creature ~= nil then\n\t\t\t\t\t\t\t\t\t\tlocal toughness = creature:GetCurrentCharacteristics():Toughness_Get()\n\t\t\t\t\t\t\t\t\t\tEffectController():GainLife( toughness )\n\t\t\t\t\t\t\t\t\tend\n\t\t\t\t\t\t\t\tend\n\t\t\t\t\t\t\t"
      };
      type = "resolution_time"
   }
}
Finally, here's a fully converted one, except I haven't changed the things I mentioned not understanding.
Ayli, Eternal Pilgrim | Open
Code: Select all
local l_sub_types =
{
   {metaname = "Cleric", order_deDE = "1", order_esES = "0", order_frFR = "1", order_itIT = "0", order_jpJA = "1", order_koKR = "1", order_ptBR = "1", order_ruRU = "1", order_zhCN = "1", order_zhHK = "1"},
   {metaname = "Kor", order_deDE = "0", order_esES = "1", order_frFR = "0", order_itIT = "1", order_jpJA = "0", order_koKR = "0", order_ptBR = "0", order_ruRU = "0", order_zhCN = "0", order_zhHK = "0"}
}

local l_title = {
   text = {
      {language_code = "en-US", data = T("Ayli, Eternal Pilgrim")},
      {language_code = "fr-FR" data = T("Ayli, pèlerine éternelle")},
      {language_code = "es-ES" data = T("Ayli, Peregrina Eterna")},
      {language_code = "de-DE" data = T("Ayli, die Ewige Pilgerin")},
      {language_code = "it-IT" data = T("Ayli, Pellegrina Eterna")},
      {language_code = "jp-JA" data = T("永(えい)代(たい)巡(じゅん)礼(れい)者(しゃ)、アイリ")},
      {language_code = "ko-KR" data = T("영원의 순례자 아일리")},
      {language_code = "ru-RU" data = T("Айли, Вечная Паломница")},
      {language_code = "pt-BR" data = T("Ayli, Peregrina Eterna")},
      {language_code = "zh-CN" data = T("坚信朝圣客艾栗")},
      {language_code = "zh-HK" data = T("堅信朝聖客艾栗")}
   }
}

local l_abilities = {
   {
      {
         text = {
            {language_code = "en-US", data = T("Deathtouch")},
            {language_code = "pt-BR", data = T("Toque mortífero")},
            {language_code = "ru-RU", data = T("Смертельное касание")},
            {language_code = "ko-KR", data = T("치명타")},
            {language_code = "jp-JA", data = T("接死")},
            {language_code = "it-IT", data = T("Tocco letale")},
            {language_code = "de-DE", data = T("Todesberührung")},
            {language_code = "es-ES", data = T("Toque mortal.")},
            {language_code = "fr-FR", data = T("Contact mortel")},
            {language_code = "zh-HK", data = T("死觸")},
            {language_code = "zh-CN", data = T("死触")}
         },
         intrinsics = {{characteristic = "CHARACTERISTIC_DEATHTOUCH"}}
      };
      type = "static"
   },
   {
      {
         text = {
            {language_code = "en-US", data = T("{1}, Sacrifice another creature: You gain life equal to the sacrificed creature’s toughness.")},
            {language_code = "pt-BR", data = T("{1}, Sacrifique outra criatura: Você ganha uma quantidade de pontos de vida igual à resistência da criatura sacrificada.")},
            {language_code = "ru-RU", data = T("{1}, пожертвуйте другое существо: вы получаете количество жизней, равное выносливости пожертвованного существа.")},
            {language_code = "ko-KR", data = T("{1}, 다른 생물 한 개를 희생한다: 당신은 희생된 생물의 방어력만큼 생명점을 얻는다.")},
            {language_code = "jp-JA", data = T("{1}, 他のクリーチャーを1体生け贄に捧げる:あなたは生け贄に捧げたクリーチャーのタフネスに等しい点数のライフを得る。")},
            {language_code = "it-IT", data = T("{1}, Sacrifica un’altra creatura: Guadagni punti vita pari alla costituzione della creatura sacrificata.")},
            {language_code = "de-DE", data = T("{1}, opfere eine andere Kreatur: Du erhältst Lebenspunkte in Höhe der Widerstandskraft der geopferten Kreatur dazu.")},
            {language_code = "es-ES", data = T("{1}, sacrificar otra criatura: Ganas una cantidad de vidas igual a la resistencia de la criatura sacrificada.")},
            {language_code = "fr-FR", data = T("{1}, sacrifiez une autre créature : Vous gagnez un nombre de points de vie égal à l’endurance de la créature sacrifiée.")},
            {language_code = "zh-HK", data = T("{1},犧牲另一個生物:你獲得等同於所犧牲生物之防禦力的生命。")},
            {language_code = "zh-CN", data = T("{1},牺牲另一个生物:你获得等同于所牺牲生物之防御力的生命。")}
         },
         categorys = {{name = "Lifegain"}},
         ai_availabilitys = {
            {restriction_type = "none", response_triggersource = "1"},
            {window_step = "STEP_END_OF_TURN", window_turn = "their_turn", type = "window"},
            {window_step = "STEP_DECLARE_BLOCKERS", type = "window"},
            {type = "in_response", response_source = "1"},
            {type = "in_response", response_source = "1"},
            {window_step = "STEP_DECLARE_BLOCKERS", type = "window"}
         },
         costs = {
            {mana_cost = "{1}", type = "Mana"},
            {type = "Sacrifice", definition = "0", compartment = "1", query_tag = "CARD_QUERY_CHOOSE_CREATURE_TO_SACRIFICE", item_count = "1", LKI_shield = "1"}
         },
         cost_definitions = {{id = "0", code = "\t\t\t\t\t\t\tlocal filter = ClearFilter()\n\t\t\t\t\t\t\tfilter:Add( FE_CARD_INSTANCE, OP_NOT, EffectSource())\n\t\t\t\t\t\t\tfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_CREATURE )\n\t\t\t\t\t\t"}},
         explains = {{play_tag = "HINT_ABILITY_LIFEGAIN_WHY_PLAY"}},
         actions = {
            {
               {
                  code = "\t\t\t\t\t\t\t\tlocal sacrificeDC = EffectDC():Get_Targets(1)\n\t\t\t\t\t\t\t\tif sacrificeDC ~= nil then\n\t\t\t\t\t\t\t\t\tlocal creature = sacrificeDC:Get_CardPtr(0)\n\t\t\t\t\t\t\t\t\tif creature ~= nil then\n\t\t\t\t\t\t\t\t\t\tlocal toughness = creature:GetCurrentCharacteristics():Toughness_Get()\n\t\t\t\t\t\t\t\t\t\tEffectController():GainLife( toughness )\n\t\t\t\t\t\t\t\t\tend\n\t\t\t\t\t\t\t\tend\n\t\t\t\t\t\t\t"
               };
               type = "resolution_time"
            }
         }
      };
      type = "activated"
   },
   {
      {
         text =
         {
            {language_code = "en-US", data = T("{1}{W}{B}, Sacrifice another creature: Exile target nonland permanent. Activate this ability only if you have at least 10 life more than your starting life total.")},
            {language_code = "fr-FR", data = T("{1}{W}{B}, sacrifiez une autre créature : Exilez le permanent non-terrain ciblé. N’activez cette capacité que si vous avez au moins 10 points de vie de plus que votre total de points de vie de départ.")},
            {language_code = "es-ES", data = T("{1}{W}{B}, sacrificar otra criatura: Exilia el permanente objetivo que no sea tierra. Activa esta habilidad solo si tienes al menos 10 vidas más que tu total inicial de vidas.")},
            {language_code = "de-DE", data = T("{1}{W}{B}, opfere eine andere Kreatur: Schicke eine bleibende Karte deiner Wahl, die kein Land ist, ins Exil. Aktiviere diese Fähigkeit nur, falls du mindestens 10 Lebenspunkte mehr als deine Startlebenspunktezahl hast.")},
            {language_code = "it-IT", data = T("{1}{W}{B}, Sacrifica un’altra creatura: Esilia un permanente non terra bersaglio. Attiva questa abilità solo se hai almeno 10 punti vita in più rispetto ai tuoi punti vita iniziali.")},
            {language_code = "jp-JA", data = T("{1}{W}{B}, 他のクリーチャーを1体生け贄に捧げる:土地でないパーマネント1つを対象とし、それを追放する。この能力は、あなたのライフの総量がゲーム開始時よりも10点以上多いときにのみ起動できる。")},
            {language_code = "ko-KR", data = T("{1}{W}{B}, 다른 생물 한 개를 희생한다: 대지가 아닌 지속물을 목표로 정한다. 그 지속물을 추방한다. 당신의 생명 총점이 게임을 시작했을 때의 생명 총점보다 10점 이상 높은 경우에만 이 능력을 활성화한다.")},
            {language_code = "ru-RU", data = T("{1}{W}{B}, пожертвуйте другое существо: изгоните целевой не являющийся землей перманент. Активируйте эту способность, только если количество ваших жизней превышает ваше начальное количество жизней как минимум на 10.")},
            {language_code = "pt-BR", data = T("{1}{W}{B}, Sacrifique outra criatura: Exile a permanente alvo que não seja um terreno. Ative esta habilidade somente se tiver ao menos 10 pontos de vida a mais que seu total de pontos de vida inicial.")},
            {language_code = "zh-HK" data = T("{1}{W}{B},犧牲另一個生物:放逐目標非地永久物。只能於你的總生命比你的起始總生命至少多10點時起動此異能。")},
            {language_code = "zh-CN", data = T("{1}{W}{B},牺牲另一个生物:放逐目标非地永久物。只能于你的总生命比你的起始总生命至少多10点时起动此异能。")}},
         ai_availabilitys = {
            {{restriction_type = "none", response_triggersource = "1"},
            {type = "in_response", response_source = "1", response_target = "1"},
            {window_step = "STEP_END_OF_TURN", type = "window"},
            {window_step = "STEP_DECLARE_BLOCKERS", type = "window"},
            {window_step = "STEP_MAIN_1", window_turn = "my_turn", type = "window"},
            {window_step = "STEP_DECLARE_ATTACKERS", window_turn = "their_turn", type = "window"},
            {window_step = "STEP_BEGIN_COMBAT", window_turn = "their_turn", type = "window"},
            {type = "in_response", response_source = "1"}, {window_step = "STEP_DECLARE_BLOCKERS", type = "window"}}},
         ai_simplified_targetings = {{compartment = "1", hint = "HINT_ENEMY_ONLY"}},
         availabilitys = {{code = "\t\t\t\t\t\t\tlocal player = EffectController()\n\t\t\t\t\t\t\treturn (player:GetLifeTotal() >= player:GetStartingLifeTotal()+10)\n\t\t\t\t\t\t"}},
         costs = {
            {mana_cost = "{1}{W}{B}", type = "Mana"},
            {type = "Sacrifice", definition = "0", compartment = "1", query_tag = "CARD_QUERY_CHOOSE_CREATURE_TO_SACRIFICE", item_count = "1"}},
         cost_definitions = {{id = "0", code = "\t\t\t\t\t\t\tlocal filter = ClearFilter()\n\t\t\t\t\t\t\tfilter:Add( FE_CARD_INSTANCE, OP_NOT, EffectSource())\n\t\t\t\t\t\t\tfilter:Add( FE_TYPE, OP_IS, CARD_TYPE_CREATURE )\n\t\t\t\t\t\t"}},
         explains = {{{is_removal = "1", play_tag = "HINT_ABILITY_REMOVAL_WHY_PLAY"}}},
         targets = {{{tag = "CARD_QUERY_CHOOSE_NONLAND_PERMANENT_TO_EXILE", definition = "0", compartment = "0", count = "1"}}},
         target_definitions = {{{id = "0", code = "\t\t\t\t\t\t\tlocal filter = ClearFilter()\n\t\t\t\t\t\t\tfilter:Add( FE_TYPE, OP_NOT, CARD_TYPE_LAND )\n\t\t\t\t\t\t\tfilter:Add( FE_IS_PERMANENT, true )\n\t\t\t\t\t\t"}}},
         actions = {{{{code = "\t\t\t\t\t\t\t\tlocal target = EffectDC():Get_Targets(0):Get_CardPtr(0)\n\t\t\t\t\t\t\t\tif target ~= nil then   \n\t\t\t\t\t\t\t\t\ttarget:Exile()  \n\t\t\t\t\t\t\t\tend\n\t\t\t\t\t\t\t"}; type = "resolution_time"}}}
      };
      type = "activated"
   }
}

local l_query_text = {
   {
      tag = "CARD_QUERY_CHOOSE_CREATURE_TO_SACRIFICE",
      text = {
         {language_code = "en-US", data = T("Choose a creature to sacrifice.")},
         {language_code = "fr-FR", data = T("Choisissez une créature pour la sacrifier.")},
         {language_code = "es-ES", data = T("Elige una criatura para sacrificarla.")},
         {language_code = "de-DE", data = T("Bestimme eine Kreatur, die geopfert werden soll.")},
         {language_code = "it-IT", data = T("Scegli una creatura da sacrificare.")},
         {language_code = "jp-JA", data = T("生け贄に捧げるクリーチャーを1体選んでください。")},
         {language_code = "ko-KR", data = T("희생할 생물을 한 개 고르십시오.")},
         {language_code = "ru-RU", data = T("Выберите существо для пожертвования.")},
         {language_code = "pt-BR", data = T("Escolha uma criatura para sacrificar.")},
         {language_code = "zh-HK", data = T("選擇一個生物來犧牲。")},
         {language_code = "zh-CN", data = T("选择一个要牺牲的生物。")},
      }
   },
   {
      tag = "CARD_QUERY_CHOOSE_NONLAND_PERMANENT_TO_EXILE",
      text = {
         {language_code = "zh-HK", data = T("選擇一個非地永久物來放逐。")},
         {language_code = "zh-CN", data = T("选择一个要放逐的非地永久物。")},
         {language_code = "pt-BR", data = T("Escolha uma permanente que não seja terreno para exilar.")},
         {language_code = "ru-RU", data = T("Выберите не являющийся землей перманент для изгнания.")},
         {language_code = "ko-KR", data = T("추방할 대지가 아닌 지속물 한 개를 고르십시오.")},
         {language_code = "jp-JA", data = T("追放する土地でないパーマネントを1つ選んでください。")},
         {language_code = "it-IT", data = T("Scegli un permanente non terra da esiliare.")},
         {language_code = "de-DE", data = T("Bestimme eine bleibende Karte außer einem Land, die ins Exil geschickt werden soll.")},
         {language_code = "es-ES", data = T("Elige un permanente que no sea tierra para exiliarlo.")},
         {language_code = "fr-FR", data = T("Choisissez un permanent non-terrain à exiler.")},
         {language_code = "en-US", data = T("Choose a nonland permanent to exile.")}
      }
   },
   {
      tag = "CARD_QUERY_CHOOSE_CREATURE_TO_SACRIFICE",
      text = {
         {language_code = "zh-HK", data = T("選擇一個生物來犧牲。")},
         {language_code = "zh-CN", data = T("选择一个要牺牲的生物。")},
         {language_code = "pt-BR", data = T("Escolha uma criatura para sacrificar.")},
         {language_code = "ru-RU", data = T("Выберите существо для пожертвования.")},
         {language_code = "ko-KR", data = T("희생할 생물을 한 개 고르십시오.")},
         {language_code = "jp-JA", data = T("生け贄に捧げるクリーチャーを1体選んでください。")},
         {language_code = "it-IT", data = T("Scegli una creatura da sacrificare.")},
         {language_code = "de-DE", data = T("Bestimme eine Kreatur, die geopfert werden soll.")},
         {language_code = "es-ES", data = T("Elige una criatura para sacrificarla.")},
         {language_code = "fr-FR", data = T("Choisissez une créature pour la sacrifier.")},
         {language_code = "en-US", data = T("Choose a creature to sacrifice.")}
      }
   }
}

local l_0_0 = module
local l_0_1, l_0_2 = ...
l_0_2 = package
l_0_2 = l_0_2.seeall
l_0_0(l_0_1, l_0_2)
card, l_0_0 = l_0_0,
{
   export_version = "1",
   card_name = "AYLI_ETERNAL_PILGRIM",
   multiverse_id = "391432",
   casting_cost = "{W}{B}",
   art_id = "161257",
   artist = "Cynthia Sheppard",
   rarity = "R",
   set_id = "OGW",
   expansion = "OGW",
   power = "2",
   toughness = "3",
   super_types = {{metaname = "Legendary"}},
   types = {{metaname = "Creature"}},
   sub_types = l_sub_types,
   title = l_title,
   abilities = l_abilities,
   deckbuilding_activation_levels = {deckbuilding_activation_level_0 = {base_score = "1600"}, deckbuilding_activation_level_1 = {{score_per_unit = "50", resource_name = "Sacrifice", amount_consumed = "1"}; base_score = "0"}},
   deckbuilding_metadatas = {deckbuilding_metadata_0 = {defensive = "0.5"}},
   deckbuilding_synergy_resources = {deckbuilding_synergy_resource_0 = {resource_name = "Life", amount = "1"}},
   explain = {play_tag = "HINT_CREATURE_ABILITY_WHY_PLAY", removal_tag = "HINT_CREATURE_ABILITY_WHY_REMOVE", is_removal = "false"},
   sfx = {{name = "COMBAT_SLASH_LARGE_ATTACK", power_boundary_min = "4", power_boundary_max = "-1"}, {name = "COMBAT_SLASH_SMALL_ATTACK", power_boundary_min = "1", power_boundary_max = "3"}},
   ai_base_scores = {{score = "300", zone = "ZONE_BATTLEFIELD"}},
   query_text = l_query_text,
   more_info = {help_0 = {title = "MORE_INFO_BADGE_TITLE_3", body = "MORE_INFO_BADGE_BODY_3", zone = "ZONE_ANY"}, help_1 = {title = "MORE_INFO_TITLE_EXILE", body = "MORE_INFO_BODY_EXILE", zone = "ZONE_ANY"}}
}
Note that all of the linebreaks and indents and stuff were done by me by hand, so they may take a small amount of adjustment to be uniform. But it's the basic setup of the cards as output by the decompiler in a much more user-friendly manner.

Of course, being nothing more than code at this point (no markup), the fact that some elements are contained in variables instead of being directly put into the card at the bottom was just my way of keeping the large portions separate. any generators could easily put them inline with no problem, I'd imagine.

EDIT:
Alright, so I learned what the semicolon does. Apparently, it mostly just prevents the elements appearing after it from being considered part of the iterative section of the table, and thus ignored by functions like ipairs. Please correct me if I'm wrong. I'm pulling this from:
http://lua-users.org/wiki/TableConstructors
http://www.luafaq.org/gotchas.html#T6.5
And the last paragraph of this: https://www.lua.org/pil/3.6.html
Last edited by Xander9009 on 19 Jan 2017, 15:41, edited 1 time in total.
_______________________________
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 » 19 Jan 2017, 15:30

Nice work!

Unfortunately I haven't made much progress: the problem I have is that I can't find a C# library for Lua 5.1 that works with our .lol files: almost all of them are based upon Lua 5.2, and the one based upon 5.1 (SharpLua) gives an array out of bounds error when trying to open the .lol file.
By using the command prompt interpreter for Lua 5.1.5 I have no problems getting the real table, but in order to do so I have to change that byte inside the .lol file so that its header becomes like the official ones: a proper tool could do that automatically and then extract all the tables in batch mode. Also, the command prompt doesn't support UTF-8, so special characters aren't properly parsed.

My last resort will be to write a Lua program to run in the command prompt itself. I don't know how well Lua manages binary files, but loading the .lol file and changing the header byte on-the-fly before parsing it would be nice.
EDIT: This last idea seems to work nicely, I just have to decide which table dumper I want to use. There are those who do "pretty printing" so that the table is easily human-readable, but they also sort the keys in alphabetical order, and that's not ideal for our purposes.

------------------

EDIT 2: The Lua script did its job. I'm not sharing it yet because it's not really user-friendly, but I'm sharing the card tables I extracted!
Code: Select all
http://www118.zippyshare.com/v/kKHNifHY/file.html
I used this dumper in order to output the tables to file.
Update: Version 2 is up. The "interpreted" cards should be 100% compliant to the original compiled files now, and the code parts are easily readable. The card sets have been extracted as well (even if they are never needed, it's just for completion's sake).

Now that the structure is well known, an xml-to-lol converter would definitely be possible... but it would take some time.

------------------

EDIT 3: I forgot to add an answer to this:
Xander9009 wrote:Specifically, the beginning:
Code: Select all
local l_0_0 = module
local l_0_1, l_0_2 = ...
l_0_2 = package
l_0_2 = l_0_2.seeall
l_0_0(l_0_1, l_0_2)
This can be condensed in just one line:
Code: Select all
module(..., package.seeall)
It appears that it's a way to start modules in Lua (now deprecated, but still used for Lua 5.1 which is the version used in all DotP installments). The 3 dots represent an argument to be passed to the .lol file: it's a string which will be used as name for the module. Look at the last paragraph of this page and it will be easy to understand.
Last edited by thefiremind on 23 Jan 2017, 10:59, edited 2 times 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: 721 times

PreviousNext

Return to Magic Duels

Who is online

Users browsing this forum: No registered users and 2 guests

cron

Who is online

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

Login Form