您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds subtraction buttons for quick money adjustments within trades on Torn.
// ==UserScript== // @name Ghost Trade Helper // @namespace GreasyDiddy // @version 1.1 // @description Adds subtraction buttons for quick money adjustments within trades on Torn. // @license MIT // @author GreasyDiddy[3455236] // @match https://www.torn.com/trade.php* // @grant none // ==/UserScript== (() => { 'use strict'; const normalizeInput = (str) => { let cleaned = str.toLowerCase().replace(/,/g, '').trim(); const units = { k: 1e3, m: 1e6, b: 1e9 }; const unit = cleaned.slice(-1); const multiplier = units[unit] || 1; if (units[unit]) cleaned = cleaned.slice(0, -1); const num = parseFloat(cleaned); return isNaN(num) || num <= 0 ? null : Math.floor(num * multiplier); }; const locateMoneyFields = () => { const inputs = document.querySelectorAll(".user-id.input-money"); return inputs.length === 2 ? [...inputs] : [null, null]; }; const updateMoney = (diff, isSet = false) => { const [visible, hidden] = locateMoneyFields(); if (!visible || !hidden) return; const current = parseInt(hidden.value) || 0; const result = Math.max(0, isSet ? diff : current + diff); visible.value = result; visible.dispatchEvent(new Event("input", { bubbles: true })); }; const fabricateButton = (label, action) => { const btn = document.createElement("input"); btn.type = "button"; btn.value = label; btn.className = "torn-btn"; btn.addEventListener("click", action); return btn; }; const buildPresetButtons = (container) => { container.appendChild(fabricateButton("-1m", () => updateMoney(-1000000))); container.appendChild(fabricateButton("-5m", () => updateMoney(-5000000))); container.appendChild(fabricateButton("-10m", () => updateMoney(-10000000))); }; const buildCustomButton = (container) => { const customBtn = fabricateButton("Custom", () => { const userVal = prompt("Enter amount to subtract:"); const parsed = normalizeInput(userVal || ""); parsed !== null ? updateMoney(-parsed) : alert("Invalid amount."); }); container.appendChild(customBtn); }; const buildPasteButton = (container) => { const pasteBtn = fabricateButton("Paste", async () => { try { const raw = await navigator.clipboard.readText(); const clean = raw.replace(/[, $]/g, ""); const parsed = normalizeInput(clean); parsed !== null ? updateMoney(-parsed) : alert("Clipboard doesn't contain a valid amount."); } catch (e) { console.error("Clipboard error:", e); alert("Clipboard access failed. Paste manually."); } }); container.appendChild(pasteBtn); }; const injectControls = () => { const inputGroup = document.querySelector("div.input-money-group"); if (!inputGroup) return; const refButton = document.querySelector("span.btn-wrap.silver"); if (!refButton) return; const btnWrapper = document.createElement("div"); const clonedSpacer = refButton.previousElementSibling?.cloneNode(); if (clonedSpacer) btnWrapper.appendChild(clonedSpacer); buildPresetButtons(btnWrapper); buildCustomButton(btnWrapper); buildPasteButton(btnWrapper); inputGroup.parentNode.insertBefore(btnWrapper, inputGroup.nextSibling); }; const watchTradePage = () => { if (!window.location.href.includes("trade.php#step=addmoney")) return; clearInterval(window.GhostTradeWatch); window.GhostTradeWatch = setInterval(() => { const moneyFieldExists = document.querySelector(".user-id.input-money"); const tooFewInputs = document.querySelectorAll("ul.inputs > li > div").length < 3; if (moneyFieldExists && tooFewInputs) { clearInterval(window.GhostTradeWatch); injectControls(); } }, 100); }; window.addEventListener("hashchange", watchTradePage); watchTradePage(); })();