使用JS注入,实现互动影游的视频倍速播放,轻松刷剧情

查看 57|回复 10
作者:helory   


image-20250624174137965.png (1.65 MB, 下载次数: 0)
下载附件
2025-6-24 18:11 上传

更新
刷完了剧情,就开始研究怎么解锁各种剧情了。所以又继续研究了下,大部分的数据都存在了gamePlay这个全局变量里了。所以根据这个思路,整理了一下,用chatGPT更新了注入代码。现在包含以下几个功能:
[ol]
  • 视频播放控制(R键切换倍速,←/→ 快进快退5秒)
  • 左上角实时播放信息面板(当前时间/总时长,倍速)
  • L键切换显示人物关系面板(实时刷新)
  • K键切换显示当前分支选择对人物关系的影响
  • 捕捉 console.log 中包含 [conditionCheck] 的日志,并右上角 toast 提示(主要方便了解各种结局的解锁条件)
    [/ol]
    说实话,更新后的会有点影响游戏体验,还是建议通关一次过后再使用。
    因为代码比较多,现在分为两个文件,主要的逻辑都在inject-enhanced-tools.js中,main.loader.js文件中只是注入的入口。
    有一点要注意,main.loader.js中的最后一行代码require(path.join(__dirname, './bin/main-darwin-' + arch + '.jsc')); 是需要根据自己实际的操作系统来的,所以不要照抄,要根据原文件的内容修改。
    //main.loader.js
    require('bytenode');
    const fs = require('fs');
    const path = require('node:path');
    const arch = process.arch;
    const { app } = require('electron');
    app.commandLine.appendSwitch('remote-debugging-port', '9222');
    app.commandLine.appendSwitch('remote-allow-origins', '*');
    const injectionPath = path.join(__dirname, 'inject-enhanced-tools.js');
    const injectionScript = fs.readFileSync(injectionPath, 'utf8');
    app.on('web-contents-created', (event, contents) => {
      contents.on('did-finish-load', () => {
        contents.executeJavaScript(injectionScript)
          .then(() => console.log('[注入] 脚本成功加载'))
          .catch(console.error);
      });
    });
    require(path.join(__dirname, './bin/main-darwin-' + arch + '.jsc'));
    // inject-enhanced-tools.js
    /**
    * 注入脚本功能说明:
    * 1. 视频播放控制(R键切换倍速,←/→ 快进快退5秒)
    * 2. 左上角实时播放信息面板(当前时间/总时长,倍速)
    * 3. L键切换显示人物关系面板(实时刷新)
    * 4. K键切换显示当前分支选择对人物关系的影响
    * 5. 捕捉 console.log 中包含 [conditionCheck] 的日志,并右上角 toast 提示
    */
    (function () {
      if (window.__inject_inited__) return;
      window.__inject_inited__ = true;
      const rateList = [1.0, 1.5, 2.0, 3.0];
      let currentRateIndex = 0;
      let currentRate = rateList[currentRateIndex];
      // 中心 Toast 提示(可复用)
      const centerToast = document.createElement('div');
      Object.assign(centerToast.style, {
        position: 'fixed',
        top: '10px',
        left: '50%',
        transform: 'translateX(-50%)',
        background: 'rgba(0,0,0,0.7)',
        color: '#fff',
        padding: '8px 16px',
        borderRadius: '8px',
        fontSize: '16px',
        zIndex: 999999,
        opacity: '0',
        transition: 'opacity 0.3s ease'
      });
      document.body.appendChild(centerToast);
      function showToast(msg, duration = 1500) {
        centerToast.innerText = msg;
        centerToast.style.opacity = '1';
        clearTimeout(centerToast._t);
        centerToast._t = setTimeout(() => {
          centerToast.style.opacity = '0';
        }, duration);
      }
      function formatTime(seconds) {
        if (isNaN(seconds)) return '--:--';
        const m = Math.floor(seconds / 60).toString().padStart(2, '0');
        const s = Math.floor(seconds % 60).toString().padStart(2, '0');
        return `${m}:${s}`;
      }
      function getPlayingVideo() {
        const videos = document.querySelectorAll('.--player-video-root video');
        for (const video of videos) {
          const style = getComputedStyle(video);
          if (style.opacity === '1' && style.zIndex === '-10000') {
            return video;
          }
        }
        return null;
      }
      // 视频信息面板
      const infoPanel = document.createElement('div');
      Object.assign(infoPanel.style, {
        position: 'fixed',
        top: '10px',
        left: '100px',
        background: 'rgba(0, 0, 0, 0.7)',
        color: 'white',
        padding: '6px 12px',
        borderRadius: '6px',
        fontSize: '14px',
        fontFamily: 'monospace',
        zIndex: 999999
      });
      document.body.appendChild(infoPanel);
      setInterval(() => {
        const video = getPlayingVideo();
        if (video) {
          if (video.playbackRate !== currentRate) {
            video.playbackRate = currentRate;
          }
          infoPanel.innerText = `播放进度:${formatTime(video.currentTime)} / ${formatTime(video.duration)}\n播放速度:${currentRate}x`;
        } else {
          infoPanel.innerText = `未检测到正在播放的视频`;
        }
      }, 1000);
      document.addEventListener('keydown', (e) => {
        const video = getPlayingVideo();
        if (!video) return;
        if (e.key === 'ArrowLeft') {
          video.currentTime = Math.max(0, video.currentTime - 5);
          showToast(`⏪ 后退 5 秒:${formatTime(video.currentTime)}`);
        } else if (e.key === 'ArrowRight') {
          video.currentTime = Math.min(video.duration, video.currentTime + 5);
          showToast(`⏩ 前进 5 秒:${formatTime(video.currentTime)}`);
        } else if (e.key.toLowerCase() === 'r') {
          currentRateIndex = (currentRateIndex + 1) % rateList.length;
          currentRate = rateList[currentRateIndex];
          showToast(`当前播放速度:${currentRate}x`);
        }
      });
      // 监听 L 键:显示人物关系
      (function () {
        let isVisible = false;
        let intervalId = null;
        const relPanel = document.createElement('div');
        Object.assign(relPanel.style, {
          position: 'fixed',
          top: '300px',
          left: '20px',
          background: 'rgba(0,0,0,0.8)',
          color: 'white',
          padding: '10px 16px',
          borderRadius: '8px',
          fontSize: '14px',
          whiteSpace: 'pre',
          zIndex: 999999,
          fontFamily: 'monospace',
          display: 'none'
        });
        document.body.appendChild(relPanel);
        function updatePanel() {
          try {
            const relMap = gamePlay?.relationshipManager?.relationship;
            if (!relMap) {
              relPanel.innerText = '未找到人物关系数据';
              return;
            }
            const lines = ['【人物关系】'];
            for (const key in relMap) {
              const rel = relMap[key];
              if (rel?.displayName && rel?.value != null) {
                lines.push(`${rel.displayName}:${rel.value}`);
              }
            }
            relPanel.innerText = lines.join('\n');
          } catch (err) {
            relPanel.innerText = '❌ 获取人物关系失败';
          }
        }
        document.addEventListener('keydown', (e) => {
          if (e.key.toLowerCase() === 'l') {
            isVisible = !isVisible;
            relPanel.style.display = isVisible ? 'block' : 'none';
            if (isVisible) {
              updatePanel();
              intervalId = setInterval(updatePanel, 1000);
            } else {
              clearInterval(intervalId);
            }
          }
        });
      })();
      // 监听 K 键:预测人物关系变化
      (function () {
        let isKPanelEnabled = false;
        let kPanel = null;
        let updateTimer = null;
        function createKPanel() {
          if (kPanel) return;
          kPanel = document.createElement('div');
          Object.assign(kPanel.style, {
            position: 'fixed',
            bottom: '10px',
            left: '10px',
            background: 'rgba(0,0,0,0.85)',
            color: '#fff',
            padding: '10px 16px',
            borderRadius: '8px',
            fontSize: '14px',
            whiteSpace: 'pre-wrap',
            fontFamily: 'monospace',
            zIndex: '999999',
            maxWidth: '480px',
            maxHeight: '60vh',
            overflowY: 'auto',
            display: 'none'
          });
          document.body.appendChild(kPanel);
        }
        function updateKPanel() {
          try {
            if (!isKPanelEnabled || !gamePlay?.UIShow) {
              kPanel.style.display = 'none';
              return;
            }
            const chapter = gamePlay.getCurrentChapterInfo?.();
            const chapterId = chapter?.chapterId;
            const currentNode = gamePlay.archiveManager?.archive?.currentNode;
            const edges = gamePlay.archiveManager?.layout?.[chapterId]?.edges || [];
            const targets = edges.filter(edge => edge.source === currentNode).map(edge => edge.target);
            const lines = [];
            targets.forEach(target => {
              const nodeDetail = gamePlay.archiveManager?.nodeList?.[target];
              if (!nodeDetail) {
                lines.push(`${currentNode} → ${target}:未找到节点信息`);
                return;
              }
              const relChange = nodeDetail.relationship || {};
              const keys = Object.keys(relChange);
              if (keys.length === 0) {
                lines.push(`${currentNode} → ${target}:无影响`);
              } else {
                const parts = keys.map(k => {
                  const delta = relChange[k];
                  const name = gamePlay.relationshipManager?.relationship?.[k]?.displayName || k;
                  const sign = delta > 0 ? '+' : '';
                  return `${name} ${sign}${delta}`;
                });
                lines.push(`${currentNode} → ${target}:${parts.join(';')}`);
              }
            });
            kPanel.innerText = lines.join('\n');
            kPanel.style.display = 'block';
          } catch (err) {
            kPanel.innerText = '❌ 获取数据失败';
          }
        }
        document.addEventListener('keydown', (e) => {
          if (e.key.toLowerCase() === 'k') {
            isKPanelEnabled = !isKPanelEnabled;
            if (isKPanelEnabled) {
              createKPanel();
              updateKPanel();
              updateTimer = setInterval(updateKPanel, 1000);
              showToast('✅ 已开启人物关系预测面板');
            } else {
              clearInterval(updateTimer);
              updateTimer = null;
              if (kPanel) kPanel.style.display = 'none';
              showToast('❎ 已关闭人物关系预测面板');
            }
          }
        });
      })();
      // 捕捉日志输出中的关键词
      (function () {
        const rawLog = console.log;
        const toastContainer = document.createElement('div');
        Object.assign(toastContainer.style, {
          position: 'fixed',
          top: '10px',
          right: '10px',
          zIndex: '999999',
          display: 'flex',
          flexDirection: 'column',
          alignItems: 'flex-end'
        });
        document.body.appendChild(toastContainer);
        function showLogToast(message) {
          const toast = document.createElement('div');
          toast.innerText = message;
          Object.assign(toast.style, {
            background: 'rgba(50, 50, 50, 0.9)',
            color: '#fff',
            padding: '8px 14px',
            marginTop: '6px',
            borderRadius: '6px',
            fontSize: '14px',
            maxWidth: '400px',
            wordBreak: 'break-word',
            boxShadow: '0 2px 6px rgba(0,0,0,0.3)',
            opacity: '0',
            transition: 'opacity 0.3s ease'
          });
          toastContainer.appendChild(toast);
          requestAnimationFrame(() => {
            toast.style.opacity = '1';
          });
          setTimeout(() => {
            toast.style.opacity = '0';
            setTimeout(() => toast.remove(), 300);
          }, 10000);
        }
        console.log = function (...args) {
          try {
            const str = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : String(arg)).join(' ');
            if (str.includes('[conditionCheck]')) {
              showLogToast(str);
            }
          } catch {}
          rawLog.apply(console, args);
        };
      })();
    })();
    前言
    最近在Steam上有一款游戏小小的出了一下圈,叫“感情XX模拟器”,也叫“捞女游戏”。这种互动影游说白了就是播放视频,玩家选择故事走向,就当电视剧、短剧看了。
    现在大家看视频都倍速看了,所以这种游戏良心点的会提供倍速播放的按钮,差一点的只有解锁后的故事章节有倍速按钮,最差的不管故事章节是否解锁,都无法倍速播放。
    而这款游戏就属于中间那档,只有解锁的故事章节才能倍速播放,奈何剧情确实有些拖沓,实在不想浪费太多时间观看视频,就想着是否能有办法让未解锁的故事章节也能倍速播放视频。
    本人也是小白一个,也是一点点根据chatGPT的提示来完成的,所以在此跟大家分享一下过程。
    (PS.该游戏是跨平台的,以下的操作都是在MacOS中完成的,但和windows系统应该都是通用的)
    打开App包内容后发现,这个游戏是用electron框架编写的,那么应该就可以跟调试网页一样来进行调试。
    开启远程调试
    {
      "name": "RevengeOnGoldDiggers",
      "version": "1.1.3",
      "description": "RevengeOnGoldDiggers",
      "main": "src/main.loader.js",
      "author": "zuoqianfang",
      "license": "ISC",
      "dependencies": {
        "appdata-path": "1.0.0",
        "steamworks.js": "^0.3.2",
        "bytenode": "1.5.3",
        "electron-log": "5.1.5"
      }
    }
    找到package.json文件,找到了程序的入口文件。


    image-20250623174105147.png (213.09 KB, 下载次数: 0)
    下载附件
    2025-6-23 17:57 上传

    require('bytenode');
      const path = require('node:path');
      const arch = process.arch;
      require(path.join(__dirname, './bin/main-darwin-' + arch + '.jsc'));
    原来所有的逻辑都是在jsc文件中,那就不考虑了。但好在main.loader.js文件是可以修改的。
    尝试了各种各样的方法,都无法在游戏主窗口中打开DevTools,应该是开发者做了相关的屏蔽,那么就只能尝试开启远程调试了。
    直接找到程序的二进制文件,使用 --remote-debugging-port=9222 来开启远程调试。该方法会被检测到,并且几秒后游戏就会自动关闭。
    后来在chatGPT的帮助下,通过修改main.loader.js的方式,成功绕开了检测,并开启了远程调试。
    require('bytenode');
    const path = require('node:path');
    const arch = process.arch;
    const { app } = require('electron');
    app.commandLine.appendSwitch('remote-debugging-port', '9222');//开启远程调试
    app.commandLine.appendSwitch('remote-allow-origins', '*');//允许所有源访问
    require(path.join(__dirname, './bin/main-darwin-' + arch + '.jsc'));
    然后使用chrome浏览器直接访问 http://localhost:9222 按照提示就能开始远程调试。


    image-20250623174313283.png (1.26 MB, 下载次数: 0)
    下载附件
    2025-6-23 17:58 上传

    JS注入


    image-20250623174440070.png (300.8 KB, 下载次数: 0)
    下载附件
    2025-6-23 17:58 上传

    既然顺利开启了远程调试,那么一切都在掌握中了。
    页面也并不复杂,主要就是四层,分别是:视频层,互动层,UI层,语音层(应该是用来播放游戏里的微信语音)。
    我们就直奔主题,看看他的视频层吧。这里用的都是标签,那么就直接通过 document.querySelectorAll('.--player-video-root video') 遍历所有video标签,设置 playbackRate 属性就可以了。
    在控制台中尝试后,确实实现了视频倍速播放,但当更换视频的时候,倍速的效果就消失了。


    image-20250623174642759.png (807.42 KB, 下载次数: 0)
    下载附件
    2025-6-23 17:58 上传

    仔细观察一下就会发现,player-video-root 下面有15个video标签轮流播放视频,当轮到当前video标签播放视频时,style中的 opacity 会变为 1 ;z-index会变为-10000,当播放结束时,opacity 会变为 0 ;z-index会变为-10002。
    那么就简单设置一个定时器,不断地改吧。
    setInterval(() => {
        const videos = document.querySelectorAll('.--player-video-root video');
        videos.forEach(video => {
          const style = getComputedStyle(video);
          const isPlaying = style.opacity === '1' && style.zIndex === '-10000';
          if (isPlaying) {
            video.playbackRate = 2.0;
          }
        });
      }, 1000);
    确实奏效,接着用chatGPT完善下功能。
  • 左上角显示播放进度
  • R键切换播放速度,并有提示
  • 左右键分别可后退、快进5秒

    (function () {
      let rateList = [1.0, 1.5, 2.0];
      let currentRateIndex = 0;
      let currentRate = rateList[currentRateIndex];
      // 右上角 - 播放进度面板
      const infoPanel = document.createElement('div');
      infoPanel.style.position = 'fixed';
      infoPanel.style.top = '10px';
      infoPanel.style.left = '10px';
      infoPanel.style.background = 'rgba(0, 0, 0, 0.7)';
      infoPanel.style.color = 'white';
      infoPanel.style.padding = '6px 12px';
      infoPanel.style.borderRadius = '6px';
      infoPanel.style.fontSize = '14px';
      infoPanel.style.fontFamily = 'monospace';
      infoPanel.style.zIndex = 999999;
      document.body.appendChild(infoPanel);
      function formatTime(seconds) {
        if (isNaN(seconds)) return '--:--';
        const m = Math.floor(seconds / 60).toString().padStart(2, '0');
        const s = Math.floor(seconds % 60).toString().padStart(2, '0');
        return `${m}:${s}`;
      }
      // 中间提示用 Toast
      const toast = document.createElement('div');
      toast.style.position = 'fixed';
      toast.style.top = '50px';
      toast.style.left = '50%';
      toast.style.transform = 'translateX(-50%)';
      toast.style.background = 'rgba(0, 0, 0, 0.7)';
      toast.style.color = 'white';
      toast.style.padding = '8px 16px';
      toast.style.borderRadius = '8px';
      toast.style.fontSize = '16px';
      toast.style.zIndex = 999999;
      toast.style.transition = 'opacity 0.3s ease';
      toast.style.opacity = '0';
      toast.innerText = '';
      document.body.appendChild(toast);
      function showToast(message) {
        toast.innerText = message;
        toast.style.opacity = '1';
        clearTimeout(toast._timeout);
        toast._timeout = setTimeout(() => {
          toast.style.opacity = '0';
        }, 1500);
      }
      function getPlayingVideo() {
        const videos = document.querySelectorAll('.--player-video-root video');
        for (const video of videos) {
          const style = getComputedStyle(video);
          if (style.opacity === '1' && style.zIndex === '-10000') {
            return video;
          }
        }
        return null;
      }
      // 每秒更新播放信息 + 设置倍速
      setInterval(() => {
        const video = getPlayingVideo();
        if (video) {
          // 强制 playbackRate
          if (video.playbackRate !== currentRate) {
            video.playbackRate = currentRate;
          }
          // 更新 info 面板
          infoPanel.innerText = `播放进度:${formatTime(video.currentTime)} / ${formatTime(video.duration)}\n播放速度:${currentRate}x`;
        } else {
          infoPanel.innerText = `未检测到正在播放的视频`;
        }
      }, 1000);
      // 快捷键:R = 切换速度,←/→ = 快进/快退
      document.addEventListener('keydown', (e) => {
        const video = getPlayingVideo();
        if (!video) return;
        if (e.key === 'ArrowLeft') {
          video.currentTime = Math.max(0, video.currentTime - 5);
          showToast(`⏪ 后退 5 秒:${formatTime(video.currentTime)}`);
        } else if (e.key === 'ArrowRight') {
          video.currentTime = Math.min(video.duration, video.currentTime + 5);
          showToast(`⏩ 前进 5 秒:${formatTime(video.currentTime)}`);
        } else if (e.key.toLowerCase() === 'r') {
          currentRateIndex = (currentRateIndex + 1) % rateList.length;
          currentRate = rateList[currentRateIndex];
          showToast(`当前播放速度:${currentRate}x`);
        }
      });
    })();
    然后我们再将这些代码整合到main.loader.js中。
    require('bytenode');
    const path = require('node:path');
    const arch = process.arch;
    const { app } = require('electron');
    app.commandLine.appendSwitch('remote-debugging-port', '9222');
    app.commandLine.appendSwitch('remote-allow-origins', '*');
    const injectionScript = `(${function () {
      (function () {
        let rateList = [1.0, 1.5, 2.0, 3.0];
        let currentRateIndex = 0;
        let currentRate = rateList[currentRateIndex];
        // 右上角 - 播放进度面板
        const infoPanel = document.createElement('div');
        infoPanel.style.position = 'fixed';
        infoPanel.style.top = '10px';
        infoPanel.style.left = '10px';
        infoPanel.style.background = 'rgba(0, 0, 0, 0.7)';
        infoPanel.style.color = 'white';
        infoPanel.style.padding = '6px 12px';
        infoPanel.style.borderRadius = '6px';
        infoPanel.style.fontSize = '14px';
        infoPanel.style.fontFamily = 'monospace';
        infoPanel.style.zIndex = 999999;
        document.body.appendChild(infoPanel);
        function formatTime(seconds) {
          if (isNaN(seconds)) return '--:--';
          const m = Math.floor(seconds / 60).toString().padStart(2, '0');
          const s = Math.floor(seconds % 60).toString().padStart(2, '0');
          return `${m}:${s}`;
        }
        // 中间提示用 Toast
        const toast = document.createElement('div');
        toast.style.position = 'fixed';
        toast.style.top = '10px';
        toast.style.left = '50%';
        toast.style.transform = 'translateX(-50%)';
        toast.style.background = 'rgba(0, 0, 0, 0.7)';
        toast.style.color = 'white';
        toast.style.padding = '8px 16px';
        toast.style.borderRadius = '8px';
        toast.style.fontSize = '16px';
        toast.style.zIndex = 999999;
        toast.style.transition = 'opacity 0.3s ease';
        toast.style.opacity = '0';
        toast.innerText = '';
        document.body.appendChild(toast);
        function showToast(message) {
          toast.innerText = message;
          toast.style.opacity = '1';
          clearTimeout(toast._timeout);
          toast._timeout = setTimeout(() => {
            toast.style.opacity = '0';
          }, 1500);
        }
        function getPlayingVideo() {
          const videos = document.querySelectorAll('.--player-video-root video');
          for (const video of videos) {
            const style = getComputedStyle(video);
            if (style.opacity === '1' && style.zIndex === '-10000') {
              return video;
            }
          }
          return null;
        }
        // 每秒更新播放信息 + 设置倍速
        setInterval(() => {
          const video = getPlayingVideo();
          if (video) {
            // 强制 playbackRate
            if (video.playbackRate !== currentRate) {
              video.playbackRate = currentRate;
            }
            // 更新 info 面板
            infoPanel.innerText = `播放进度:${formatTime(video.currentTime)} / ${formatTime(video.duration)}\n播放速度:${currentRate}x`;
          } else {
            infoPanel.innerText = `未检测到正在播放的视频`;
          }
        }, 1000);
        // 快捷键:R = 切换速度,←/→ = 快进/快退
        document.addEventListener('keydown', (e) => {
          const video = getPlayingVideo();
          if (!video) return;
          if (e.key === 'ArrowLeft') {
            video.currentTime = Math.max(0, video.currentTime - 5);
            showToast(`⏪ 后退 5 秒:${formatTime(video.currentTime)}`);
          } else if (e.key === 'ArrowRight') {
            video.currentTime = Math.min(video.duration, video.currentTime + 5);
            showToast(`⏩ 前进 5 秒:${formatTime(video.currentTime)}`);
          } else if (e.key.toLowerCase() === 'r') {
            currentRateIndex = (currentRateIndex + 1) % rateList.length;
            currentRate = rateList[currentRateIndex];
            showToast(`当前播放速度:${currentRate}x`);
          }
        });
      })();  
    }})()`;
    app.on('web-contents-created', (event, contents) => {
      contents.on('did-finish-load', () => {
        contents.executeJavaScript(injectionScript)
          .then(() => console.log('[注入] 成功注入 video 控制脚本'))
          .catch(err => console.error('[注入失败]', err));
      });
    });
    require(path.join(__dirname, './bin/main-darwin-' + arch + '.jsc'));


    image-20250623174818378.png (539.38 KB, 下载次数: 0)
    下载附件
    2025-6-23 17:58 上传

    一切大功告成,直接使用steam打开游戏后,就会自动注入代码,可以随时倍速播放了!
    所有功能都正常,但有时候倍速播放可能会导致比较短的循环视频黑屏,但无所谓了,那些也不影响刷剧情~

    倍速, 视频

  • ltgb   

    哪些也不影响刷剧情~
    那些也不影响刷剧情~
    helory
    OP
      


    YIUA 发表于 2025-6-23 18:14
    大佬,这个还能开启远程调试吗,可以加个好友带带吗

    开启远程调试很简单呀,直接在 maiin.loader.js 文件中,加三行代码就行。[JavaScript] 纯文本查看 复制代码require('bytenode');
    const path = require('node:path');
    const arch = process.arch;
    const { app } = require('electron');
    app.commandLine.appendSwitch('remote-debugging-port', '9222');//开启远程调试
    app.commandLine.appendSwitch('remote-allow-origins', '*');//允许所有源访问
    require(path.join(__dirname, './bin/main-darwin-' + arch + '.jsc'));
    YIUA   

    大佬,这个还能开启远程调试吗,可以加个好友带带吗
    qiutieniu   

    第一步就难倒千万个小白
    cksuperxlh   

    为了游戏真是拼了.
    fgyu88   

    确实很有特点
    博士   

    🐂🍺 有点东西  思路新颖
    wuai_V   

    厉害啊,我也感觉剧情有些拖沓,原速度看有点无聊,搜搜看了,真的发现了有同感的大佬,佩服这行动力和动手能力,希望大佬多多分享
    NewhopeBCY   

    同求,我也需要这个,
    您需要登录后才可以回帖 登录 | 立即注册

    返回顶部