pylivemaker
pylivemaker copied to clipboard
Errors with extracting menus
- pylivemaker version: 1.0.4
- Python version: 3.10.6
- Operating System: Windows
- LiveMaker game: トライアド・リリーティア
Description
I've been trying to extract the menus from this game, and running into difficulties. A few extract with no problem, but others give an error message: "No matching jump for menu choice."
What I Did
I used the command lmlsb extractmenu on one of the extracted lsb files. I got the following Traceback:
Extracting 00001886.lsb ... Traceback (most recent call last): File "C:\Users\User\AppData\Local\Programs\Python\Python310\li s\livemaker\lsb\menu.py", line 315, in from_lsb_command target, target_index = jumps[text] KeyError: '瑠奈をリーダーにする'
During handling of the above exception, another exception occurred
Traceback (most recent call last):
File "C:\Users\User\AppData\Local\Programs\Python\Python310\li
ine 196, in _run_module_as_main
return _run_code(code, main_globals, None,
File "C:\Users\User\AppData\Local\Programs\Python\Python310\li
ine 86, in run_code
exec(code, run_globals)
File "C:\Users\User\AppData\Local\Programs\Python\Python310\Sc
e_main.py", line 7, in
I used lmlsb dump to examine the .lsb file. The pertinent area seems to be to do with this menu choice:
Label 0000188F 275: Wait ((GetProp("メッセージボックス", 81) | GetProp("メッセージボックス", 138)) & Not(選択実行中)) 0 0 276: Calc 選択実行中 = 1 277: VarNew _tmp ParamType.Str 2 278: VarNew _tmpno ParamType.Int 2 279: VarNew _tmpid ParamType.Str 2 280: If (リリーティアフラグ[1] == "FALSE" & パーティ管理[0][1] == "TRUE") 281: Calc AddArray(_tmp, "瑠奈をリーダーにする") 282: Calc _tmpno = 0 283: Calc _tmpid = AddDelimiter("\r\n", _tmpid) ++ _tmpno 284: If (リリーティアフラグ[1] == "FALSE" & パーティ管理[0][2] == "TRUE") 285: Calc AddArray(_tmp, "愛梨をリーダーにする") 286: Calc _tmpno = 1 287: Calc _tmpid = AddDelimiter("\r\n", _tmpid) ++ _tmpno 288: If (リリーティアフラグ[1] == "FALSE" & パーティ管理[0][3] == "TRUE") 289: Calc AddArray(_tmp, "透華をリーダーにする") 290: Calc _tmpno = 2 291: Calc _tmpid = AddDelimiter("\r\n", _tmpid) ++ _tmpno 292: If (リリーティアフラグ[1] == "FALSE" & パーティ管理[0][4] == "TRUE") 293: Calc AddArray(_tmp, "心羽をリーダーにする") 294: Calc _tmpno = 3 295: Calc _tmpid = AddDelimiter("\r\n", _tmpid) ++ _tmpno 296: If リリーティアフラグ[1] == "TRUE" 297: Calc AddArray(_tmp, "リリーティアをリーダーにする") 298: Calc _tmpno = 4 299: Calc _tmpid = AddDelimiter("\r\n", _tmpid) ++ _tmpno 300: Calc AddArray(_tmp, "キャンセル") 301: Calc _tmpno = 5 302: Calc _tmpid = AddDelimiter("\r\n", _tmpid) ++ _tmpno 303: Calc TrimArray(_tmp) 304: If ArrayToString(_tmp) != "" 305: If 1 306: Call ノベルシステム\選択メニュー\■選択実行.lsb:0 1 ArrayToString(_tmp) 0 "C" "C" 0 "サウンド\SE\po.ogg" "" 1 307: Calc 選択実行中 = 0 308: Calc StringToArray(_tmpid, _tmpid) 309: If 選択番号 >= 0 310: Calc 選択番号 = _tmpid[選択番号] 311: Else 312: Calc 選択値 = _tmp 313: Calc 選択番号 = _tmpno 314: Calc 選択実行中 = 0 315: Calc 右クリックメニュー一時禁止 = 0 316: Call ノベルシステム\メッセージボックス\終了.lsb:0 1 317: Wait GetProp("メッセージボックス", 50) != "" 0 0 318: ObjDel "VOICE" 319: VarDel _tmp 320: VarDel _tmpno 321: VarDel _tmpid 322: Jump 00001886.lsb:315 ((((選択値 == "瑠奈をリーダーにする" | 選択値 == "愛梨をリーダーにする") | 選択値 == "透華をリーダーにする") | 選択値 == "心羽をリーダーにする") | 選択値 == "リリーティアをリーダーにする") 323: Jump 00001886.lsb:226 選択値 == "キャンセル" 324: Wait 1 0 0
322: Jump 00001886.lsb:315 ((((選択値 == "瑠奈をリーダーにする" | 選択値 == "愛梨をリーダーにする") | 選択値 == "透華をリーダーにする") | 選択値 == "心羽をリーダーにする") | 選択値 == "リリーティアをリーダーにする")
Issue is because this jump statement contains multiple OR'd conditions but pylm expects them to all be broken up into separate jumps.
@Djweish Would you be able to upload/attach 00001886.lsb to the github issue? (you should be able to just drag and drop it into the comment box)
Sure, find attached. I also found a few of the lsb files don't seem to have a matching jump for menu choices at all, like 00001606.lsb which has a section: 00001606.zip
360: Calc 選択実行中 = 1 361: VarNew _tmp ParamType.Str 2 362: VarNew _tmpno ParamType.Int 2 363: VarNew _tmpid ParamType.Str 2 364: Calc AddArray(_tmp, "装備する") 365: Calc _tmpno = 0 366: Calc _tmpid = AddDelimiter("\r\n", _tmpid) ++ _tmpno 367: Calc AddArray(_tmp, "廃棄する") 368: Calc _tmpno = 1 369: Calc _tmpid = AddDelimiter("\r\n", _tmpid) ++ _tmpno 370: Calc AddArray(_tmp, "複数廃棄する") 371: Calc _tmpno = 2 372: Calc _tmpid = AddDelimiter("\r\n", _tmpid) ++ _tmpno 373: Calc AddArray(_tmp, "キャンセル") 374: Calc _tmpno = 3 375: Calc _tmpid = AddDelimiter("\r\n", _tmpid) ++ _tmpno 376: Calc TrimArray(_tmp) 377: If ArrayToString(_tmp) != "" 378: If 1 379: Call ノベルシステム\選択メニュー\■選択実行.lsb:0 1 ArrayToString(_tmp) 0 "C" "C" 0 "" "" 1 380: Calc 選択実行中 = 0 381: Calc StringToArray(_tmpid, _tmpid) 382: If 選択番号 >= 0 383: Calc 選択番号 = _tmpid[選択番号] 384: Else 385: Calc 選択値 = _tmp 386: Calc 選択番号 = _tmpno 387: Calc 選択実行中 = 0 388: Calc 右クリックメニュー一時禁止 = 0 389: Call ノベルシステム\メッセージボックス\終了.lsb:0 1 390: Wait GetProp("メッセージボックス", 50) != "" 0 0 391: ObjDel "VOICE" 392: VarDel _tmp 393: VarDel _tmpno 394: VarDel _tmpid 395: Jump 00001606.lsb:445 選択値 == "キャンセル" 396: Wait 1 0 0 397: Label 00001620
Thanks for the examples, I should be able to take a look into it over the weekend
Thanks! I'm not sure it can be fixed for translation purposes, without going through and changing the whole game; it seems to use whatever you pick in the menu as a variable, which it then queries all over the game, so you'd have to either go through and change every variable, or add some commands telling it to change the variable from the English menu choice back to the original Japanese version after the menu.
Yes, that's how the menu patching works. It patches the actual UI menu choice string as well as the places that string is checked against the 選択値 variable (which is the lm system variable used for menu choice selection).
If your game is also setting an additional variable (that is not 選択値) to use the choice string, you may need to manually patch all of those other locations to use the translated string. In some cases, the internal variable that gets set by the menu choice does not actually need to be translated/patched. The UI menu string/var combination may be completely separate from the internal flag variable, but it depends on the game.
In a lot of cases the logic will look like
If choice == 'はい', set flag == 'はい'
where the flag variable is checked in several other places in the game. But usually it doesn't actually matter that choice and flag both contain the same string. So you may be able to get away with only patching the menu choice parts (i.e. choice == 'yes'), but you can leave all of the flag == 'はい' places alone.
Basically you just want the result of your menu to be
If choice == 'yes', set flag == 'はい'
since as long as that internal flag はい is not actually being shown in the UI anywhere, it doesn't matter whether or not you translate it
But yes, in some cases games may use a choice menu for something like setting the protagonist's name at the beginning of the game, in which case you do need to manually translate all of the places that gets used everywhere else in the game as well.
In this case you can use lmlsb edit to patch them. Another user has also made some helper scripts for replacing all of the instances of specific internal strings in a game, but it's not something I officially support, see https://pylivemaker.readthedocs.io/en/latest/usage.html#pylivemaker-tools
Ok, so looking at the LSB files, I don't think it's going to be possible to make the generic CSV patching work for your game. As you noted, it's using a lot of custom logic based on the menu choices.
After the menu selection is handled, it does
328: Calc リーダー = JCopy(m, 1, 2)
...
343: If リーダー == "瑠奈"
344: Calc キャラ番号 = 1
345: Calc キャラ名 = "瑠奈"
346: If リーダー == "愛梨"
347: Calc キャラ番号 = 2
348: Calc キャラ名 = "愛梨"
...
Which copies the first two characters in the selected choice string into the リーダー variable and then does a bunch of other things based on those two characters.
In the original JP this works because everyone's name is two characters, but if you are going to translate this you would need to also patch all of the subsequent commands to work properly.
This is something that you could at least partially script/automate using pylm, but you essentially need to make a custom version of the CSV extract/insert scripts that works specifically for your game. This isn't really something I can do for you, and honestly I think it may just be easier to use lmlsb edit to patch everything yourself manually.
I'll keep this issue open for now since I'm not sure whether or not the multiple OR'd menu jump conditions are custom for this game or if it's actually a generic LM feature that can occur in other game.