求助,对魔忍rpgx解包问题

萌新自学想解包rpgx里的l2d皮肤,但是只能解出moc3和贴图,motion3文件解出来是.fade格式,请问有什么办法能将其转换为motion3格式好导入l2dviewer呢?

发帖前先看看有没有类似的帖子

谢谢大佬。我用node的脚本还原了motion文件,但是在l2dviewer中实际测试中发现motion文件不起作用 :sob:


下面附上源文件和我还原的motion文件,能麻烦看一下吗
通过网盘分享的文件:liv00496.zip
链接: 百度网盘 请输入提取码 提取码: gdj3

修复版,应该是没啥问题了

const fs = require('fs');
const path = require('path');

// 每层空格多少个
const spaceCeil = 2
const numRexg = /^-?\d+\.?\d*$/
const CubismPhysicsControllerRexg = /CubismPhysicsController/

function hangle(lines, index, ceil, falg) {
    let data = {}
    let arrayData = []
    for (let i = index; i < lines.length; i++) {
        let line = lines[i];
        let spaceNum = 0
        for (let j = 0; j < line.length && (line[j] === ' ' || line[j] === '-'); j++) {
            spaceNum++
        }
        if (spaceNum / spaceCeil < ceil) {
            return {
                value: arrayData.length ? arrayData : Object.keys(data).length ? data : [],
                index: i - 1
            }
        }
        if (line.trim() === '') {
            continue;
        }
        const parts = line.split(':');
        let key = parts[0].trim();
        if (key.startsWith('- ')) {
            // key = key.split("-")[1].trim()
            // arrayData.push(data)
            // line[ceil * spaceCeil] = ' '
            if (falg) {
                return {
                    value: data,
                    index: i - 1
                }
            } else {
                lines[i] = line = line.substring(0, ceil * spaceCeil - spaceCeil) + ' ' + line.substring(ceil * spaceCeil + 1 - spaceCeil)
                let result = hangle(lines, i, ceil, true)
                arrayData.push(result.value)
                i = result.index
            }
            continue
        }
        let value = parts[1].trim()
        if (value.length === 0) {
            // console.log(key);
            let result = hangle(lines, i + 1, ceil + 1, false)
            // console.log(result.value);
            i = result.index
            value = result.value
            // console.log(key + ":" + JSON.stringify(value));
        } else if (numRexg.test(value)) {
            value = Number(value)
        } else if (value === "[]") {
            value = []
        }
        data[key] = value;
    }
    return {
        value: arrayData.length ? arrayData : Object.keys(data).length ? data : [],
        index: lines.length
    }
}

function processFadeFiles(dirPath) {
    const files = fs.readdirSync(dirPath);
    for (const file of files) {
        const filePath = path.join(dirPath, file);
        const stat = fs.statSync(filePath);
        if (stat.isDirectory()) {
            processFadeFiles(filePath);

        } else if (file.endsWith('.fade.json')) {
            const fileName = path.basename(file, '.fade.json');
            const data = fs.readFileSync(filePath, 'utf8');
            const obj = JSON.parse(data);

            const motion3Json = {
                'Version': 3,
                "Meta": {
                    "Duration": obj.MotionLength,
                    "Fps": 60.0,
                    "Loop": true,
                    "AreBeziersRestricted": true,
                    "CurveCount": 0,
                    "TotalSegmentCount": 0,
                    "TotalPointCount": 0,
                    "UserDataCount": 0,
                    "TotalUserDataSize": 0
                },
                "Curves": [],
                "UserData": []
            };

            const parameterIds = obj.ParameterIds.Array;
            const parameterCurves = obj.ParameterCurves.Array;

            motion3Json.Meta.CurveCount = parameterCurves.length;
            let totalPointCount = 0;
            let totalSegmentCount = 0;

            for (let i = 0; i < parameterCurves.length; i++) {
                const curveData = parameterCurves[i].m_Curve.Array;
                if (!curveData || curveData.length === 0) continue;

                totalPointCount += curveData.length;
                const segments = [curveData[0].time, curveData[0].value];
                for (let j = 1; j < curveData.length; j++) {
                    const prevPoint = curveData[j - 1];
                    const currentPoint = curveData[j];
                    totalSegmentCount++;

                    const isLinear = (prevPoint.outSlope === 0 && currentPoint.inSlope === 0) ||
                        !isFinite(prevPoint.outSlope) || !isFinite(currentPoint.inSlope);

                    if (isLinear) {
                        segments.push(0, currentPoint.time, currentPoint.value);
                    } else {
                        const dt = currentPoint.time - prevPoint.time;
                        const cp1_time = prevPoint.time + dt / 3.0;
                        const cp1_value = prevPoint.value + (dt / 3.0) * prevPoint.outSlope;
                        const cp2_time = currentPoint.time - dt / 3.0;
                        const cp2_value = currentPoint.value - (dt / 3.0) * currentPoint.inSlope;

                        segments.push(1, cp1_time, cp1_value, cp2_time, cp2_value, currentPoint.time, currentPoint.value);
                    }
                }

                motion3Json.Curves.push({
                    "Target": "Parameter",
                    "Id": parameterIds[i],
                    "Segments": segments
                });
            }

            motion3Json.Meta.TotalPointCount = totalPointCount;
            motion3Json.Meta.TotalSegmentCount = totalSegmentCount;

            fs.writeFileSync(path.join(dirPath, `${fileName}.motion3.json`), JSON.stringify(motion3Json, null, 2));
            console.log(path.join(dirPath, `${fileName}.motion3.json`) + " 已生成");
        }
    }
}

processFadeFiles("Output");

1 个赞

太强了,谢谢大佬,这下没有问题了

大佬我有一些问题想问问你,太过于复杂,请问可以加个联系方式吗

我寻思这起码几千字的评论区够了吧,你的问题是造火箭吗?