您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Blocks travel to destinations where the return time would overlap with OC initiation. Includes responsive toggle switch for manual control.
当前为
// ==UserScript== // @name OC Timing: Travel Blocker // @namespace zonure.scripts // @version 1.0 // @description Blocks travel to destinations where the return time would overlap with OC initiation. Includes responsive toggle switch for manual control. // @author Zonure [3787510] // @match https://www.torn.com/page.php?sid=travel // @grant none // @license MIT // ==/UserScript== (function () { 'use strict'; const STORAGE_KEY = 'oc_travel_block_enabled'; const style = document.createElement('style'); style.textContent = ` .script-disabled-button { background-color: #a00 !important; color: crimson !important; font-weight: bold; text-transform: uppercase; } #oc-toggle-container { margin: 10px 0; padding: 6px 10px; background: #222; color: #fff; border-radius: 5px; font-size: 13px; display: inline-flex; align-items: center; gap: 8px; } .switch { position: relative; display: inline-block; width: 38px; height: 20px; flex-shrink: 0; } .switch input { opacity: 0; width: 0; height: 0; } .slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; transition: 0.3s; border-radius: 34px; } .slider:before { position: absolute; content: ""; height: 14px; width: 14px; left: 3px; bottom: 3px; background-color: white; transition: 0.3s; border-radius: 50%; } input:checked + .slider { background-color: #4caf50; } input:checked + .slider:before { transform: translateX(18px); } @media (max-width: 600px) { #oc-toggle-container { font-size: 12px; padding: 4px 8px; gap: 6px; } .switch { width: 32px; height: 16px; } .slider:before { height: 10px; width: 10px; left: 3px; bottom: 3px; } input:checked + .slider:before { transform: translateX(14px); } } `; document.head.appendChild(style); let isEnabled = localStorage.getItem(STORAGE_KEY); if (isEnabled === null) { isEnabled = 'true'; localStorage.setItem(STORAGE_KEY, isEnabled); } isEnabled = isEnabled === 'true'; const injectToggle = () => { const wrapper = document.querySelector('div.content-wrapper.summer'); if (!wrapper || wrapper.querySelector('#oc-toggle-container')) return; const container = document.createElement('div'); container.id = 'oc-toggle-container'; container.innerHTML = ` <span>Travel Blocker:</span> <label class="switch"> <input type="checkbox" id="oc-toggle" ${isEnabled ? 'checked' : ''}> <span class="slider"></span> </label> <span id="oc-status">${isEnabled ? 'Enabled' : 'Disabled'}</span> `; const input = container.querySelector('#oc-toggle'); const status = container.querySelector('#oc-status'); input.addEventListener('change', () => { isEnabled = input.checked; localStorage.setItem(STORAGE_KEY, isEnabled); status.textContent = isEnabled ? 'Enabled' : 'Disabled'; disableButtonIfNeeded(); }); wrapper.prepend(container); }; const disableButtonIfNeeded = () => { const travelRoot = document.getElementById('travel-root'); if (!travelRoot || !isEnabled) return; const modelDataRaw = travelRoot.getAttribute('data-model'); if (!modelDataRaw) return; let parsed; try { parsed = JSON.parse(modelDataRaw); } catch (e) { return; } const destinations = parsed?.destinations; let shouldDisable = false; if (Array.isArray(destinations)) { for (const dest of destinations) { for (const key of ['standard', 'airstrip', 'private', 'business']) { if (dest[key]?.ocReadyBeforeBack === true) { shouldDisable = true; break; } } if (shouldDisable) break; } } const buttons = document.querySelectorAll("a.torn-btn.btn-dark-bg, button.torn-btn.btn-dark-bg"); buttons.forEach((btn) => { const alreadyBlocked = btn.classList.contains("script-disabled-button"); if (btn.textContent.trim() === "Continue") { if (shouldDisable && !alreadyBlocked) { btn.disabled = true; btn.textContent = "DISABLED"; btn.title = "Disabled: OC not ready yet."; btn.classList.add("script-disabled-button"); btn.onclick = (e) => { e.preventDefault(); e.stopImmediatePropagation(); console.log("Blocked: OC not ready."); }; } else if (!shouldDisable && alreadyBlocked) { btn.disabled = false; btn.textContent = "Continue"; btn.title = ""; btn.classList.remove("script-disabled-button"); btn.onclick = null; } } }); }; const init = () => { injectToggle(); disableButtonIfNeeded(); }; const observer = new MutationObserver(() => { injectToggle(); disableButtonIfNeeded(); }); observer.observe(document.body, { childList: true, subtree: true }); init(); })();