- 楼主
最近看到好几个饼友都出了水果机满徽章,感觉爆率还挺高的,于是我也忍不住去试了试。
玩了两个小时,成功出了两个!不过徽章是出了,手也快点废了…… 整整两个小时都在不停地点 “开始”,属实给我点麻了。😂
为了造福后面想刷水果机满徽章的饼友们,我就顺手写了一个油猴脚本,可以自动点击 “开始”,彻底解放双手,再也不用一直手动狂点了!
废话不多说,直接上脚本!
最后,祝各位饼友都能出,早日拿下水果机的满勋章!🎰
// ==UserScript== // @name 烧饼水果机自动开奖助手 // @namespace sb-fruit-auto-spin // @version 2.1.0 // @description 等待游戏加载,沿用下注,无下注时尝试苹果10,自动续开 // @match https://sb.sb/games/fruit* // @grant none // @run-at document-idle // ==/UserScript== (() => { 'use strict'; if (window.__SB_FRUIT_AUTO_210__) return; window.__SB_FRUIT_AUTO_210__ = true; const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); const $ = (selector, root = document) => root.querySelector(selector); let running = false; let paused = false; let rounds = 0; let loopToken = 0; const PANEL_ID = 'sb-fruit-auto-panel'; function getSpin() { return $('#spin'); } function getLabel() { return $('.spin-label')?.textContent.trim() || ''; } function getBets() { return [...document.querySelectorAll( '#bet-grid output[data-amount]' )].map(el => Number(el.textContent.trim()) || 0); } function getTotalBet() { return getBets().reduce((sum, value) => sum + value, 0); } function gameReady() { return !!( getSpin() && $('#bet-grid') && document.querySelector('canvas') ); } function setStatus(message) { const el = $('#sb-fa-status'); if (el) el.textContent = message; } function addLog(message) { const el = $('#sb-fa-log'); const time = new Date().toLocaleTimeString(); if (el) { el.textContent = `${time} ${message}`; } console.log('[水果机助手]', message); } function updateButtons() { const start = $('#sb-fa-start'); const pause = $('#sb-fa-pause'); if (!start || !pause) return; start.disabled = running; pause.disabled = !running; pause.textContent = paused ? '继续' : '暂停'; } // 查找显示为10的下注档位 function findTenUnit() { const candidates = [ ...document.querySelectorAll( 'button, [role="button"]' ) ]; return candidates.find(el => { if (el.closest('#bet-grid')) return false; const text = (el.innerText || el.textContent || '') .replace(/\s+/g, ' ') .trim(); return /^10(?:\s*游戏币)?$/.test(text); }); } // 无下注时才尝试设置苹果10 async function ensureBet() { const current = getBets(); if (current.some(value => value > 0)) { addLog('检测到已有下注,沿用原下注'); return true; } setStatus('没有下注,正在查找10游戏币档位…'); const unit = findTenUnit(); const apple = $('#bet-grid [data-add="3"]'); if (!unit || !apple) { setStatus('找不到下注档位,请手动设置苹果10'); addLog('没有找到可靠的10游戏币按钮,未自动下注'); return false; } unit.click(); await sleep(500); apple.click(); await sleep(700); const after = getBets(); if (after[3] === 10 && after.reduce((a, b) => a + b, 0) === 10) { addLog('已成功设置苹果10'); return true; } setStatus('下注验证不通过,请手动检查'); addLog('实际下注:' + JSON.stringify(after)); return false; } async function waitForGame(token) { setStatus('等待你进入水果机…'); while (running && token === loopToken) { if (gameReady()) { setStatus('游戏已加载,可以开始'); return true; } await sleep(500); } return false; } async function waitForIdle(token) { let busyDetected = false; let idleSince = 0; const started = Date.now(); while (running && token === loopToken) { if (paused) { await sleep(300); continue; } const spin = getSpin(); if (!spin) { setStatus('游戏按钮消失,等待恢复'); await sleep(500); continue; } const busy = spin.disabled || getLabel() !== '开始开奖'; if (busy) { busyDetected = true; idleSince = 0; } else if (busyDetected) { if (!idleSince) idleSince = Date.now(); // 按钮恢复空闲并稳定一段时间 if (Date.now() - idleSince >= 1800) { return true; } } if (Date.now() - started > 120000) { setStatus('等待开奖超时,停止自动续开'); return false; } await sleep(300); } return false; } async function run(token) { if (!await waitForGame(token)) return; const maxRounds = Math.min( 999, Math.max(1, Number($('#sb-fa-limit').value) || 10) ); const stopBalance = Math.max( 0, Number($('#sb-fa-balance').value) || 0 ); while (running && token === loopToken) { if (paused) { await sleep(300); continue; } if (document.hidden) { setStatus('页面在后台,等待切回'); await sleep(1000); continue; } if (!gameReady()) { setStatus('等待游戏重新加载'); await sleep(1000); continue; } if (rounds >= maxRounds) { setStatus('达到最大局数,停止'); break; } const spin = getSpin(); if (spin.disabled || getLabel() !== '开始开奖') { setStatus('等待游戏进入空闲状态'); await sleep(500); continue; } if (!await ensureBet()) break; if (stopBalance > 0) { const balanceElement = $('#balance') || $('[data-balance]'); if (!balanceElement) { setStatus('无法读取余额,停止运行'); break; } const currentBalance = Number( balanceElement.textContent.replace(/[^\d.-]/g, '') ); if (!Number.isFinite(currentBalance) || currentBalance <= stopBalance) { setStatus('余额达到停止线'); break; } } if (!getSpin() || getSpin().disabled || getLabel() !== '开始开奖') { await sleep(500); continue; } setStatus('正在启动下一局…'); getSpin().click(); // 必须检测到游戏真正进入运行状态 let started = false; for (let i = 0; i < 40; i++) { await sleep(250); if ( !getSpin() || getSpin().disabled || getLabel() !== '开始开奖' ) { started = true; break; } } if (!started) { setStatus('没有检测到开始状态,已停止'); addLog('开始状态检测失败'); break; } rounds++; setStatus(`第 ${rounds} 局正在进行`); addLog(`第 ${rounds} 局开始`); const completed = await waitForIdle(token); if (!completed) break; addLog(`第 ${rounds} 局完成`); setStatus(`第 ${rounds} 局结束,准备下一局`); await sleep(1500); } if (token === loopToken) { running = false; paused = false; updateButtons(); setStatus(`自动运行结束,启动 ${rounds} 局`); } } function start() { if (running) return; running = true; paused = false; rounds = 0; const token = ++loopToken; updateButtons(); addLog('自动运行启动'); run(token).catch(error => { console.error('[水果机助手]', error); running = false; paused = false; updateButtons(); setStatus('脚本错误:' + error.message); }); } function togglePause() { if (!running) return; paused = !paused; updateButtons(); setStatus(paused ? '已暂停' : '继续运行'); addLog(paused ? '暂停' : '恢复'); } function stop() { running = false; paused = false; loopToken++; updateButtons(); setStatus('已停止,不再自动开始下一局'); addLog('手动停止'); } function createPanel() { if ($('#' + PANEL_ID)) return; const panel = document.createElement('div'); panel.id = PANEL_ID; panel.innerHTML = ` <div style="font-size:16px;font-weight:bold;margin-bottom:12px"> 🍎 水果机自动开奖 2.1 </div> <div id="sb-fa-status" style=" font-size:13px; color:#a7e9b6; margin-bottom:12px; ">等待进入游戏…</div> <label style="font-size:12px"> 最大连续局数 <input id="sb-fa-limit" type="number" min="1" max="999" value="10"> </label> <label style="font-size:12px"> 余额停止线(0为关闭) <input id="sb-fa-balance" type="number" min="0" value="0"> </label> <div style="display:flex;gap:6px;margin-top:12px"> <button id="sb-fa-start">开始</button> <button id="sb-fa-pause" disabled>暂停</button> <button id="sb-fa-stop">停止</button> </div> <div id="sb-fa-log" style=" font-size:11px; color:#ccc; margin-top:12px; word-break:break-word; ">等待操作</div> `; Object.assign(panel.style, { position: 'fixed', right: '16px', top: '100px', width: '250px', padding: '15px', boxSizing: 'border-box', background: 'rgba(25,30,35,.97)', color: '#fff', zIndex: '2147483647', border: '1px solid #777', borderRadius: '10px', boxShadow: '0 4px 20px #0008', fontFamily: 'Arial,sans-serif' }); const style = document.createElement('style'); style.textContent = ` #${PANEL_ID} input { display:block; box-sizing:border-box; width:100%; padding:7px; margin:5px 0 10px; border-radius:5px; border:1px solid #888; } #${PANEL_ID} button { flex:1; padding:9px 4px; border:0; border-radius:5px; background:#268b48; color:white; cursor:pointer; } #${PANEL_ID} button:disabled { opacity:.4; cursor:not-allowed; } #sb-fa-pause { background:#b17b20; } #sb-fa-stop { background:#bd3333; } `; document.head.appendChild(style); document.body.appendChild(panel); $('#sb-fa-start').addEventListener('click', start); $('#sb-fa-pause').addEventListener('click', togglePause); $('#sb-fa-stop').addEventListener('click', stop); updateButtons(); } function init() { if (!document.body) { setTimeout(init, 300); return; } // 不在游戏启动页创建面板 if (gameReady()) { createPanel(); setStatus('游戏已加载,可以开始'); addLog('游戏初始化完成'); return; } setTimeout(() => { const observer = new MutationObserver(() => { if (gameReady()) { observer.disconnect(); // 只有真正进入游戏后才创建面板 createPanel(); setStatus('游戏已加载,可以开始'); addLog('已检测到游戏场景'); } }); observer.observe(document.body, { childList: true, subtree: true }); // 防止游戏在监听器建立前刚好加载完成 if (gameReady()) { observer.disconnect(); createPanel(); setStatus('游戏已加载,可以开始'); } }, 500); } init(); })();收藏支持 1反对打赏 1个性签名学习的能力和方法比知识本身更重要
支持,我先试试
好东西 可惜我是手机玩