{"record":{"id":"3b189d70821a1f1a","repo":"babalae/better-genshin-impact","slug":"error-3b189d","errorCode":null,"errorMessage":"战斗脚本格式错误，指令括号无法配对","messagePattern":"战斗脚本格式错误，指令括号无法配对","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"BetterGenshinImpact/GameTask/AutoFight/Script/CombatScriptParser.cs","lineNumber":246,"sourceCode":"        for (var i = 0; i < commandArray.Length; i++)\n        {\n            var command = commandArray[i];\n            if (string.IsNullOrEmpty(command))\n            {\n                continue;\n            }\n\n            if (command.Contains('(') && !command.Contains(')'))\n            {\n                var j = i + 1;\n                // 括号被逗号分隔，需要合并\n                while (j < commandArray.Length)\n                {\n                    command += \",\" + commandArray[j];\n                    if (command.Count(\"(\".Contains) > 1)\n                    {\n                        Logger.LogError(\"战斗脚本格式错误，指令 {Cmd} 括号无法配对\", command);\n                        throw new Exception(\"战斗脚本格式错误，指令括号无法配对\");\n                    }\n\n                    if (command.Contains(')'))\n                    {\n                        i = j;\n                        break;\n                    }\n\n                    j++;\n                }\n\n                if (!(command.Contains('(') && command.Contains(')')))\n                {\n                    Logger.LogError(\"战斗脚本格式错误，指令 {Cmd} 括号不完整\", command);\n                    throw new Exception(\"战斗脚本格式错误，指令括号不完整\");\n                }\n            }\n","sourceCodeStart":228,"sourceCodeEnd":264,"githubUrl":"https://github.com/babalae/better-genshin-impact/blob/a7cb36712dcb409be610257d877fcea3597e9d6b/BetterGenshinImpact/GameTask/AutoFight/Script/CombatScriptParser.cs#L228-L264","documentation":"Thrown by CombatScriptParser.ParseLinePart when merging comma-separated script fragments reveals more than one '(' in a single command token. The TXT combat script parser splits commands by comma, then re-merges fragments whose '(' has no matching ')'. During merge, if the accumulated command contains more than one '(', the parser concludes the parentheses are unbalanced/uncloseable and aborts. This means nested or malformed parenthesis structures are not supported in the legacy TXT script format.","triggerScenarios":"A TXT combat script line where a command token has an opening '(' that spans across commas, and after merging fragments the command contains two or more '(' characters. For example: `skill(long_attack(1)` split as `skill(long_attack(` and `1)` — the merge produces two '(' and triggers the guard. Also any typo adding an extra '(' like `e((1))`.","commonSituations":"User writes nested parentheses in a TXT combat script (e.g. copying JSON-style syntax into a .txt file), or has a stray extra '(' from manual editing. Also occurs when Chinese full-width '（' is mixed and only partially converted (the parser converts '（' to '(' at line 75 but double-conversion or partial conversion can leave stray parens).","solutions":["Check the logged command value ({Cmd}) to identify which instruction has the extra '('.","Rewrite the offending command to use flat single-level parentheses: one '(' per command, e.g. `skill(1)` not `skill(inner(1))`.","If you intended JSON-style complex strategies, switch to a .json strategy file instead of .txt.","Remove any stray or duplicated parentheses in the script line."],"exampleFix":"// before (broken — nested parens across commas)\n// 香菱 skill(long(1),e(2))\n\n// after (flat single-level)\n// 香菱 skill(1),e(2)","handlingStrategy":"validation","validationCode":"// Pre-validate a combat script line for balanced single-level parens\nstatic bool HasBalancedParens(string line)\n{\n    // Each comma-separated command should have at most one '(' and matching ')'\n    var parts = line.Split([','], StringSplitOptions.RemoveEmptyEntries);\n    int openPending = 0;\n    foreach (var part in parts)\n    {\n        openPending += part.Count(c => c == '(');\n        openPending -= part.Count(c => c == ')');\n        if (openPending < 0) return false;\n    }\n    return openPending == 0;\n}\n\n// Before parsing:\nif (!HasBalancedParens(scriptLine))\n    Log.LogWarning(\"Script line has unbalanced parens: {Line}\", scriptLine);","typeGuard":null,"tryCatchPattern":"// Wrap ParseContext in try-catch for user-facing script loading\ntry\n{\n    var script = CombatScriptParser.ParseContext(text);\n}\ncatch (Exception e) when (e.Message.Contains(\"括号无法配对\"))\n{\n    Logger.LogWarning(\"战斗脚本括号配对失败，请检查嵌套括号：{Msg}\", e.Message);\n    // Provide user with the specific failing line from logs\n}","preventionTips":["Avoid nested parentheses in TXT combat scripts — the format only supports flat single-level function calls.","For complex strategies with conditions, use the JSON strategy format instead.","Validate scripts in an editor that highlights unbalanced parentheses.","Watch the {Cmd} value in the log to pinpoint the exact failing command."],"tags":["combat-script","parser","txt-script","parentheses"],"backgroundTag":null,"analyzedSha":"a7cb36712dcb409be610257d877fcea3597e9d6b","analyzedAt":"2026-08-13T16:44:57.548Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}