返回列表 发布新帖

【油猴脚本】404那只猫定制多种玩法助手(直播必备小游戏)

2374 1
小K网牛逼 发表于 昨天 00:00 | 查看全部 阅读模式 <

马上注册,结交更多好友,享用更多功能,让你轻松玩转小K网。

您需要 登录 才可以下载或查看,没有账号?立即注册 微信登录

×
相信经常逛的朋友对论坛那个 404 页面的“围住小猫”游戏都不陌生。本来只是个打发时间的小游戏,但我总觉得玩法单一了点。于是利用一下时间,撸了一个“定制助手”脚本。不仅能改游戏规则(多步连走),还能拉上好基友开启本地双人甚至四人乱斗模式!目前已经是某音直播娱乐必备的非常有节目效果的多人小游戏!!!
还有贪吃蛇版在下面!!!一、 脚本亮点
  • 界面美化:将404改成了帅哥标题和头像。
  • 单人定制:支持设置“玩家连续放墙次数”(1次、2次、3次甚至无限),还独家新增了“1-2-1-2 循环步数”玩法。
  • 双人模式:伙伴不再是观众!你可以放墙,伙伴可以手动控猫逃跑,开启真正的博弈。
  • 四人模式(双猫乱斗):屏幕左侧会空降第二只紫猫。支持 2 名玩家 + 2 只猫交替行动,场面一度非常混乱又充满趣味!
  • 智能逻辑:四人模式下,如果其中一只猫被围死,脚本会自动跳过它的回合,直到所有猫都被围住才判定胜利。
  • 极简 UI:右上角悬浮窗,支持一键收起/展开,收起后就是一个精致的小头像,完全不遮挡视线。
  • 按需开启:脚本非常聪明,只有在检测到是论坛 404 页面时才会加载,不占用其他页面的内存。
二、 玩法说明
  • 基础玩法: 安装脚本后,进入 404 页面,点击右上角“猫猫助手”的“应用修改并重置”即可生效。
  • 四人模式: 流程为:玩家 1 放墙 -\> 猫 1(中间)行动 -\> 玩家 2 放墙 -\> 猫 2(左侧,紧邻中间猫)行动。
  • 1-2-1-2 序列: 这是单人模式下的进阶玩法。第一回合你只能放 1 堵墙,第二回合可以放 2 堵,第三回合又变回 1 堵,以此循环。这非常考验你的长远布局能力!
    (贪吃蛇版)鼠标在贪吃蛇前面悬浮移动则贪吃蛇跟着你走,先吃掉所有黑点,最后吃猫,成功后进入下一关

油猴脚本】404那只猫定制多种玩法助手(直播必备小游戏)

【油猴脚本】404那只猫定制多种玩法助手(直播必备小游戏)

  1. <blockquote>// ==UserScript==
复制代码

油猴脚本】404那只猫定制多种玩法助手(直播必备小游戏)

【油猴脚本】404那只猫定制多种玩法助手(直播必备小游戏)

  1. // ==UserScript==
  2. // @name         Hmily的猫猫:贪吃蛇自动版
  3. // @namespace    http://tampermonkey.net/
  4. // @version      2.1
  5. // @description  【单人闯关版】
  6. // @author       52pojie
  7. // @match        https://www.xkwo.com/*
  8. // @grant        GM_addStyle
  9. // @run-at       document-end
  10. // ==/UserScript==
  11. (function() {
  12.     'use strict';
  13.     const win = (typeof unsafeWindow !== 'undefined') ? unsafeWindow : window;
  14.     // --- 0. 页面判定与内容修改 ---
  15.     const is404Page = () => {
  16.         const h1 = document.querySelector('.container h1');
  17.         const h2 = document.querySelector('.container h2');
  18.         const gameContainer = document.getElementById('catch-the-cat');
  19.         if (h1 && h1.innerText.includes('404') && gameContainer) {
  20.             h1.innerText = 'Hmily的猫猫:贪吃蛇闯关';
  21.             if (h2) h2.innerText = '吾爱破解祝你:喵运当头,锦鲤附体!🐾';
  22.             return true;
  23.         }
  24.         return false;
  25.     };
  26.     if (!is404Page()) return;
  27.     // --- 1. 样式定义 ---
  28.     GM_addStyle(`
  29.         #snake-mod-panel {
  30.             position: fixed; top: 20px; right: 20px; width: 260px;
  31.             background: #fff; border-radius: 12px; box-shadow: 0 10px 25px rgba(0,0,0,0.3);
  32.             z-index: 10000; padding: 15px; font-family: sans-serif; border: 2px solid #28a745;
  33.             transition: all 0.3s ease; overflow: hidden; display: flex; flex-direction: column;
  34.         }
  35.         #snake-mod-panel.minimized {
  36.             width: 44px; height: 44px; padding: 0; cursor: pointer; border-radius: 50%;
  37.             border: none; box-shadow: 0 4px 12px rgba(40,167,69,0.4);
  38.         }
  39.         .panel-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; border-bottom: 1px solid #eee; padding-bottom: 8px; }
  40.         #snake-mod-panel.minimized .panel-header { border: none; margin: 0; padding: 0; width: 100%; height: 100%; justify-content: center; }
  41.         .header-left { display: flex; align-items: center; }
  42.         .panel-icon { width: 28px; height: 28px; border-radius: 50%; border: 1px solid #28a745; transition: all 0.3s ease; object-fit: cover; }
  43.         #snake-mod-panel.minimized .panel-icon { width: 44px; height: 44px; border: none; }
  44.         .level-tag { background: #28a745; color: #fff; padding: 2px 6px; border-radius: 6px; font-size: 11px; margin-left: 8px; white-space: nowrap; }
  45.         .toggle-btn { background: none; border: none; color: #28a745; cursor: pointer; font-size: 12px; padding: 2px 5px; }
  46.         #snake-mod-panel.minimized h3,
  47.         #snake-mod-panel.minimized .level-tag,
  48.         #snake-mod-panel.minimized .info-box,
  49.         #snake-mod-panel.minimized .timer-box,
  50.         #snake-mod-panel.minimized .restart-btn,
  51.         #snake-mod-panel.minimized .status-msg,
  52.         #snake-mod-panel.minimized .toggle-btn,
  53.         #snake-mod-panel.minimized .reset-data,
  54.         #snake-mod-panel.minimized .hint { display: none; }
  55.         .info-box { padding: 8px; border-radius: 6px; text-align: center; margin-bottom: 10px; border: 1px solid #eee; background: #f8f9fa; font-size: 13px; line-height: 1.6; }
  56.         .timer-box { font-size: 20px; text-align: center; color: #d9534f; font-weight: bold; margin: 5px 0 10px 0; display: none; }
  57.         .restart-btn { background: #28a745; color: #fff; border: none; padding: 10px; width: 100%; border-radius: 5px; cursor: pointer; font-weight: bold; margin-bottom: 5px; }
  58.         .reset-data { font-size: 10px; color: #999; text-align: center; cursor: pointer; text-decoration: underline; margin-top: 5px; }
  59.         .status-msg { font-size: 12px; color: #666; margin-top: 8px; font-family: monospace; border-top: 1px solid #eee; padding-top: 5px; }
  60.         .hint { font-size: 11px; color: #999; text-align: center; margin-bottom: 8px; line-height: 1.4; }
  61.         #cat-god-overlay {
  62.             position: fixed; top: 0; left: 0; width: 100vw; height: 100vh;
  63.             background: rgba(0,0,0,0.7); display: flex; flex-direction: column;
  64.             justify-content: center; align-items: center; z-index: 20000;
  65.             pointer-events: none; opacity: 0; transition: opacity 1s;
  66.         }
  67.         #cat-god-text {
  68.             font-size: 120px; font-weight: 900; color: #ffcc00;
  69.             text-shadow: 0 0 20px #ff6600, 0 0 40px #ffcc00;
  70.             transform: scale(0.5); transition: transform 0.8s cubic-bezier(0.175, 0.885, 0.32, 1.275);
  71.             font-family: "Microsoft YaHei", sans-serif;
  72.         }
  73.         .confetti {
  74.             position: absolute; width: 10px; height: 10px; border-radius: 2px;
  75.             animation: confetti-fall 3s linear forwards;
  76.         }
  77.         @keyframes confetti-fall {
  78.             0% { transform: translateY(-10vh) rotate(0deg); opacity: 1; }
  79.             100% { transform: translateY(110vh) rotate(720deg); opacity: 0; }
  80.         }
  81.     `);
  82.     // --- 2. 游戏状态 ---
  83.     let gameState = {
  84.         level: 1,
  85.         snake: [],
  86.         foodCount: 0,
  87.         direction: 1,
  88.         gameTimerId: null,
  89.         catTimerId: null,
  90.         huntTimerId: null,
  91.         timeLeft: 30,
  92.         isHunting: false,
  93.         isGameOver: false,
  94.         isHooked: false
  95.     };
  96.     const saveLevel = (lvl) => localStorage.setItem('hmily_cat_snake_lvl', lvl);
  97.     const getLevel = () => {
  98.         let lvl = parseInt(localStorage.getItem('hmily_cat_snake_lvl')) || 1;
  99.         return Math.min(lvl, 15);
  100.     };
  101.     function getLevelName(lvl) {
  102.         return lvl >= 15 ? "最终关" : `第 ${lvl} 关`;
  103.     }
  104.     // --- 3. UI 构建 ---
  105.     function createUI() {
  106.         const panel = document.createElement('div');
  107.         panel.id = 'snake-mod-panel';
  108.         gameState.level = getLevel();
  109.         document.body.appendChild(panel);
  110.         const overlay = document.createElement('div');
  111.         overlay.id = 'cat-god-overlay';
  112.         overlay.innerHTML = `<div id="cat-god-text">你是猫神</div>`;
  113.         document.body.appendChild(overlay);
  114.         updatePanelHTML();
  115.     }
  116.     function updatePanelHTML() {
  117.         const panel = document.getElementById('snake-mod-panel');
  118.         if (!panel) return;
  119.         const foodGoal = calculateFoodLimit();
  120.         const timeGoal = calculateCatchTime();
  121.         panel.innerHTML = `
  122.             <div class="panel-header" id="panel-header">
  123.                 <div class="header-left">
  124.                     <img src="https://avatar.52pojie.cn/data/avatar/000/00/00/01_avatar_middle.jpg" class="panel-icon" id="panel-logo">
  125.                     <h3 style="margin:0 0 0 8px; font-size:15px; color:#28a745;">贪吃蛇闯关</h3>
  126.                     <span class="level-tag">${getLevelName(gameState.level)}</span>
  127.                 </div>
  128.                 <button class="toggle-btn" id="btn-minimize">收起</button>
  129.             </div>
  130.             <div class="hint">悬停蛇头相邻格转向</div>
  131.             <div id="target-info" class="info-box">
  132.                 <b>本关目标</b><br>
  133.                 吃掉 <span style="color:#d9534f">${foodGoal}</span> 个黑点<br>
  134.                 抓捕限时 <span style="color:#d9534f">${timeGoal}</span> 秒
  135.             </div>
  136.             <div id="status-display" class="info-box" style="color:#28a745; display:none;">剩余黑点:--</div>
  137.             <div class="timer-box" id="game-timer">倒计时:${timeGoal}s</div>
  138.             <button class="restart-btn" id="btn-start-snake">开始挑战</button>
  139.             <div class="reset-data" id="btn-reset-data">重置进度</div>
  140.             <div class="status-msg" id="snake-log">> 准备就绪</div>
  141.         `;
  142.         const minimizeBtn = document.getElementById('btn-minimize');
  143.         const togglePanel = () => {
  144.             panel.classList.toggle('minimized');
  145.             minimizeBtn.innerText = panel.classList.contains('minimized') ? "" : "收起";
  146.         };
  147.         minimizeBtn.onclick = (e) => { e.stopPropagation(); togglePanel(); };
  148.         panel.onclick = () => { if(panel.classList.contains('minimized')) togglePanel(); };
  149.         document.getElementById('btn-start-snake').onclick = initSnakeGame;
  150.         document.getElementById('btn-reset-data').onclick = () => {
  151.             if(confirm("确定要重置进度到第一关吗?")) {
  152.                 saveLevel(1);
  153.                 location.reload();
  154.             }
  155.         };
  156.     }
  157.     function calculateCatchTime() {
  158.         if (gameState.level >= 15) return 10;
  159.         return (gameState.level % 2 === 0) ? 20 : 30;
  160.     }
  161.     function calculateFoodLimit() {
  162.         if (gameState.level >= 15) return 2;
  163.         return Math.max(2, 8 - Math.floor((gameState.level - 1) / 2));
  164.     }
  165.     function addLog(msg) {
  166.         const log = document.getElementById('snake-log');
  167.         if (log) log.innerText = "> " + msg;
  168.     }
  169.     // --- 4. 特效逻辑 ---
  170.     function handleWinEffect(scene) {
  171.         if (gameState.level >= 15) {
  172.             showCatGodEffect();
  173.         }
  174.         scene.setStatusText(`恭喜通过 ${getLevelName(gameState.level)}!`);
  175.         scene.state = "win";
  176.         if (gameState.level < 15) {
  177.             gameState.level++;
  178.             saveLevel(gameState.level);
  179.         }
  180.         updatePanelHTML();
  181.         addLog("成功猎杀!");
  182.     }
  183.     function showCatGodEffect() {
  184.         const overlay = document.getElementById('cat-god-overlay');
  185.         const text = document.getElementById('cat-god-text');
  186.         overlay.style.opacity = "1";
  187.         text.style.transform = "scale(1)";
  188.         for (let i = 0; i < 100; i++) {
  189.             setTimeout(() => {
  190.                 const confetti = document.createElement('div');
  191.                 confetti.className = 'confetti';
  192.                 confetti.style.left = Math.random() * 100 + 'vw';
  193.                 confetti.style.backgroundColor = ['#ff0', '#f0f', '#0ff', '#f00', '#0f0'][Math.floor(Math.random() * 5)];
  194.                 overlay.appendChild(confetti);
  195.                 setTimeout(() => confetti.remove(), 3000);
  196.             }, i * 20);
  197.         }
  198.         setTimeout(() => {
  199.             overlay.style.opacity = "0";
  200.             text.style.transform = "scale(0.5)";
  201.         }, 5000);
  202.     }
  203.     // --- 5. 核心逻辑 ---
  204.     function initSnakeGame() {
  205.         if (!win.game || !win.game.mainScene) return;
  206.         const scene = win.game.mainScene;
  207.         scene.reset();
  208.         stopAllTimers();
  209.         gameState.level = getLevel();
  210.         const foodGoal = calculateFoodLimit();
  211.         gameState.timeLeft = calculateCatchTime();
  212.         scene.cat.isEscaped = function() { return false; };
  213.         scene.checkWin = function() { return false; };
  214.         scene.lose = function() { return gameState.isGameOver ? true : false; };
  215.         scene.win = function() { return false; };
  216.         gameState.snake = [{i: 5, j: 4}];
  217.         gameState.direction = 1;
  218.         gameState.isHunting = false;
  219.         gameState.isGameOver = false;
  220.         document.getElementById('game-timer').style.display = 'none';
  221.         document.getElementById('status-display').style.display = 'block';
  222.         document.getElementById('status-display').innerText = `剩余黑点:${foodGoal}`;
  223.         setupMapFood(scene, foodGoal);
  224.         updateVisuals();
  225.         if (!gameState.isHooked) hookEvents();
  226.         const snakeSpeed = Math.max(200, 400 - (gameState.level * 10));
  227.         const catSpeed = Math.max(250, 400 - (gameState.level * 9));
  228.         gameState.gameTimerId = setInterval(() => {
  229.             if (!gameState.isGameOver) autoMoveStep();
  230.         }, snakeSpeed);
  231.         gameState.catTimerId = setInterval(() => {
  232.             if (!gameState.isGameOver) moveCatAI(scene);
  233.         }, catSpeed);
  234.         addLog(`${getLevelName(gameState.level)} 已启动!`);
  235.     }
  236.     function setupMapFood(scene, limit) {
  237.         scene.blocks.forEach(row => row.forEach(b => b.isWall = false));
  238.         let placed = 0;
  239.         while (placed < limit) {
  240.             let ri = Math.floor(Math.random() * 11);
  241.             let rj = Math.floor(Math.random() * 11);
  242.             let b = scene.getBlock(ri, rj);
  243.             if (b && !b.isWall && (ri !== 5 || rj !== 5) && (ri !== 5 || rj !== 4)) {
  244.                 b.isWall = true;
  245.                 placed++;
  246.             }
  247.         }
  248.         gameState.foodCount = placed;
  249.     }
  250.     function updateVisuals() {
  251.         const scene = win.game.mainScene;
  252.         scene.blocks.forEach(row => row.forEach(b => {
  253.             b.fillColor = b.isWall ? 0x333333 : 0xb3ffbf00;
  254.             gameState.snake.forEach((part, index) => {
  255.                 if (b.i === part.i && b.j === part.j) {
  256.                     b.fillColor = (index === 0) ? 0x28a745 : 0x71d581;
  257.                 }
  258.             });
  259.         }));
  260.     }
  261.     function hookEvents() {
  262.         const scene = win.game.mainScene;
  263.         const handleHover = function(block) {
  264.             if (gameState.isGameOver || !gameState.snake.length) return;
  265.             const head = gameState.snake[0];
  266.             const neighbors = scene.constructor.getNeighbours(head.i, head.j);
  267.             const dirIndex = neighbors.findIndex(n => n.i === block.i && n.j === block.j);
  268.             if (dirIndex !== -1) gameState.direction = dirIndex;
  269.         };
  270.         scene.blocks.forEach(row => row.forEach(b => {
  271.             b.off('player_click');
  272.             b.on('pointerover', () => handleHover(b));
  273.             b.on('player_click', () => handleHover(b));
  274.         }));
  275.         gameState.isHooked = true;
  276.     }
  277.     function stopAllTimers() {
  278.         if (gameState.gameTimerId) clearInterval(gameState.gameTimerId);
  279.         if (gameState.catTimerId) clearInterval(gameState.catTimerId);
  280.         if (gameState.huntTimerId) clearInterval(gameState.huntTimerId);
  281.         gameState.gameTimerId = null;
  282.         gameState.catTimerId = null;
  283.         gameState.huntTimerId = null;
  284.     }
  285.     function autoMoveStep() {
  286.         const scene = win.game.mainScene;
  287.         const head = gameState.snake[0];
  288.         const neighbors = scene.constructor.getNeighbours(head.i, head.j);
  289.         const next = neighbors[gameState.direction];
  290.         const targetBlock = scene.getBlock(next.i, next.j);
  291.         if (!targetBlock || gameState.snake.some(p => p.i === next.i && p.j === next.j)) {
  292.             gameState.isGameOver = true;
  293.             stopAllTimers();
  294.             scene.setStatusText("失败!按开始重试");
  295.             addLog("失败:发生撞击");
  296.             return;
  297.         }
  298.         if (scene.cat.i === next.i && scene.cat.j === next.j) {
  299.             if (gameState.isHunting) {
  300.                 gameState.isGameOver = true;
  301.                 stopAllTimers();
  302.                 handleWinEffect(scene);
  303.                 return;
  304.             }
  305.         }
  306.         const newHead = {i: next.i, j: next.j};
  307.         if (targetBlock.isWall) {
  308.             targetBlock.isWall = false;
  309.             gameState.snake.unshift(newHead);
  310.             gameState.foodCount--;
  311.             document.getElementById('status-display').innerText = `剩余黑点:${gameState.foodCount}`;
  312.             if (gameState.foodCount <= 0 && !gameState.isHunting) startHuntingPhase();
  313.         } else {
  314.             gameState.snake.unshift(newHead);
  315.             gameState.snake.pop();
  316.         }
  317.         updateVisuals();
  318.     }
  319.     function startHuntingPhase() {
  320.         gameState.isHunting = true;
  321.         const scene = win.game.mainScene;
  322.         document.getElementById('game-timer').style.display = 'block';
  323.         document.getElementById('status-display').style.display = 'none';
  324.         scene.setStatusText(`猎杀时刻:${gameState.timeLeft}s`);
  325.         gameState.huntTimerId = setInterval(() => {
  326.             if (gameState.isGameOver) return;
  327.             gameState.timeLeft--;
  328.             document.getElementById('game-timer').innerText = `倒计时:${gameState.timeLeft}s`;
  329.             scene.setStatusText(`猎杀时刻:${gameState.timeLeft}s`);
  330.             if (gameState.timeLeft <= 0) {
  331.                 stopAllTimers();
  332.                 gameState.isGameOver = true;
  333.                 scene.setStatusText("时间到,猎杀失败!");
  334.                 scene.state = "lose";
  335.                 addLog("失败:倒计时结束");
  336.             }
  337.         }, 1000);
  338.     }
  339.     function moveCatAI(scene) {
  340.         if (gameState.isGameOver) return;
  341.         const cat = scene.cat;
  342.         const head = gameState.snake[0];
  343.         const neighbors = scene.constructor.getNeighbours(cat.i, cat.j);
  344.         let validMoves = neighbors.filter(n => {
  345.             if (n.i < 0 || n.i > 10 || n.j < 0 || n.j > 10) return false;
  346.             const b = scene.getBlock(n.i, n.j);
  347.             return b && !b.isWall && !gameState.snake.some(p => p.i === n.i && p.j === n.j);
  348.         });
  349.         if (validMoves.length > 0) {
  350.             validMoves.sort((a, b) => {
  351.                 const distA = Math.hypot(a.i - head.i, a.j - head.j);
  352.                 const distB = Math.hypot(b.i - head.i, b.j - head.j);
  353.                 if (Math.abs(distA - distB) < 0.5) {
  354.                     return Math.hypot(a.i - 5, a.j - 5) - Math.hypot(b.i - 5, b.j - 5);
  355.                 }
  356.                 return distB - distA;
  357.             });
  358.             const best = validMoves[0];
  359.             const dir = neighbors.findIndex(n => n.i === best.i && n.j === best.j);
  360.             cat.stepDirection(dir);
  361.             cat.i = Math.max(0, Math.min(10, cat.i));
  362.             cat.j = Math.max(0, Math.min(10, cat.j));
  363.         }
  364.     }
  365.     createUI();
  366. })();
复制代码


评论1

手机用户QK80992Lv.1 发表于 昨天 17:32 | 查看全部 <
🆕占个楼, 不过分吧!
回复

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 立即注册 微信登录

本版积分规则

您需要 登录 后才可以回复,轻松玩转社区,没有帐号?立即注册
快速回复
关灯 在本版发帖
扫一扫添加微信客服
QQ客服返回顶部
快速回复 返回顶部 返回列表