您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Combines Cyclist alerts and difficulty color-coding for the pickpocketing crime. All features are toggleable.
当前为
// ==UserScript== // @name Torn Pickpocketing Helper // @namespace torn.pickpocketing.helper // @version 3.0 // @description Combines Cyclist alerts and difficulty color-coding for the pickpocketing crime. All features are toggleable. // @author Microbes & Korbrm (Merged & Rebuilt by eaksquad) // @match https://www.torn.com/loader.php?sid=crimes* // @icon https://www.google.com/s2/favicons?sz=64&domain=torn.com // @grant none // @license MIT // ==/UserScript== (function() { 'use strict'; // --- Configuration --- const SETTINGS = { cyclistAlerts: { enabled: true, soundUrl: 'https://audio.jukehost.co.uk/gxd2HB9RibSHhr13OiW6ROCaaRbD8103', highlightColor: '#00ff00', }, difficultyColors: { enabled: true, showCategoryText: true, } }; // --- Data Definitions --- const markGroups = { "Safe": ["Drunk man", "Drunk woman", "Homeless person", "Junkie", "Elderly man", "Elderly woman"], "Moderately Unsafe": ["Classy lady", "Laborer", "Postal worker", "Young man", "Young woman", "Student"], "Unsafe": ["Rich kid", "Sex worker", "Thug"], "Risky": ["Jogger", "Businessman", "Businesswoman", "Gang member", "Mobster"], "Dangerous": ["Cyclist"], "Very Dangerous": ["Police officer"], }; const categoryColorMap = { "Safe": "#37b24d", "Moderately Unsafe": "#74b816", "Unsafe": "#f59f00", "Risky": "#f76707", "Dangerous": "#f03e3e", "Very Dangerous": "#7048e8" }; const skillTiers = { tier1: { "Safe": "#37b24d", "Moderately Unsafe": "#f76707", "Unsafe": "#f03e3e", "Risky": "#f03e3e", "Dangerous": "#f03e3e", "Very Dangerous": "#7048e8" }, tier2: { "Safe": "#37b24d", "Moderately Unsafe": "#37b24d", "Unsafe": "#f76707", "Risky": "#f03e3e", "Dangerous": "#f03e3e", "Very Dangerous": "#7048e8" }, tier3: { "Safe": "#37b24d", "Moderately Unsafe": "#37b24d", "Unsafe": "#37b24d", "Risky": "#f76707", "Dangerous": "#f03e3e", "Very Dangerous": "#7048e8" }, tier4: { "Safe": "#37b24d", "Moderately Unsafe": "#37b24d", "Unsafe": "#37b24d", "Risky": "#37b24d", "Dangerous": "#f76707", "Very Dangerous": "#7048e8" }, tier5: { "Safe": "#37b24d", "Moderately Unsafe": "#37b24d", "Unsafe": "#37b24d", "Risky": "#37b24d", "Dangerous": "#37b24d", "Very Dangerous": "#7048e8" }, }; // --- State Management --- let isCyclistAlertsEnabled = SETTINGS.cyclistAlerts.enabled; let isDifficultyColorsEnabled = SETTINGS.difficultyColors.enabled; let isCyclistCurrentlyAvailable = false; // --- Core Logic --- /** * The master function to style all targets. It's called after the API confirms an update. * @param {number} skill - The user's current pickpocketing skill. */ function applyAllStyling(skill) { let activeTierColors; if (skill < 10) { activeTierColors = skillTiers.tier1; } else if (skill < 35) { activeTierColors = skillTiers.tier2; } else if (skill < 65) { activeTierColors = skillTiers.tier3; } else if (skill < 80) { activeTierColors = skillTiers.tier4; } else { activeTierColors = skillTiers.tier5; } const targetContainers = document.querySelectorAll('div[class*="crimes-pickpocketing-container"] div[class*="item-container_"]'); targetContainers.forEach(container => { const titleElement = container.querySelector('div[class*="title_"]'); if (!titleElement) return; // Reset styles and text before applying new ones container.style.backgroundColor = ''; container.style.borderLeft = ''; titleElement.style.color = ''; const originalText = titleElement.textContent.trim().split(' (')[0]; titleElement.textContent = originalText; // --- Difficulty Colors Logic (from original Colors script) --- if (isDifficultyColorsEnabled) { let category = ''; for (const cat in markGroups) { if (markGroups[cat].includes(originalText)) { category = cat; break; } } if (category) { titleElement.style.color = categoryColorMap[category]; container.style.borderLeft = `3px solid ${activeTierColors[category]}`; if (SETTINGS.difficultyColors.showCategoryText && window.innerWidth > 400) { titleElement.textContent = `${originalText} (${category})`; } } } // --- Cyclist Highlight Logic (from original Cyclist script) --- // This runs after and will override the difficulty colors if the cyclist is available. if (isCyclistAlertsEnabled && isCyclistCurrentlyAvailable) { const iconElement = container.querySelector('div[class*="icon_"]'); // This is the key: identify the cyclist by its unique icon style, not by name. if (iconElement && $(iconElement).css('background-position-y') === '0px') { container.style.backgroundColor = SETTINGS.cyclistAlerts.highlightColor; } } }); } /** * Sets up the main logic to intercept network requests. */ function initializeCrimeObserver() { interceptFetch("torn.com", "/page.php?sid=crimesData", (response) => { // Resilient API path check: works whether Torn uses "DB" or not. const crimesData = response.crimesByType ? response : response.DB; if (!crimesData || !crimesData.crimesByType || typeof crimesData.pickpocketing?.skill === 'undefined') { console.error("[PPHelper] Crime data or skill not found in API response.", response); return; } const crimes = crimesData.crimesByType; const skill = crimesData.pickpocketing.skill; isCyclistCurrentlyAvailable = crimes.some(c => c.title === "Cyclist" && c.available === true); if (isCyclistAlertsEnabled && isCyclistCurrentlyAvailable) { playAlertSound(); } // Use a timeout to ensure the DOM has rendered before we try to style it. setTimeout(() => applyAllStyling(skill), 150); }); } function setupInterface() { if (document.getElementById('pp-helper-controls')) return; const controlsContainer = `<div id="pp-helper-controls" style="margin-bottom: 10px; display: flex; gap: 10px; flex-wrap: wrap;"><a id="cyclist-toggle-btn" class="torn-btn"></a><a id="colors-toggle-btn" class="torn-btn"></a></div>`; $('.pickpocketing-root').prepend(controlsContainer); const cyclistBtn = $('#cyclist-toggle-btn'); const colorsBtn = $('#colors-toggle-btn'); function updateButtons() { cyclistBtn.text(`Cyclist Alerts: ${isCyclistAlertsEnabled ? 'ON' : 'OFF'}`).css(isCyclistAlertsEnabled ? { 'background': '#4CAF50', 'color': 'white' } : { 'background': '', 'color': '' }); colorsBtn.text(`Difficulty Colors: ${isDifficultyColorsEnabled ? 'ON' : 'OFF'}`).css(isDifficultyColorsEnabled ? { 'background': '#4CAF50', 'color': 'white' } : { 'background': '', 'color': '' }); } cyclistBtn.on('click', () => { isCyclistAlertsEnabled = !isCyclistAlertsEnabled; updateButtons(); if (isCyclistAlertsEnabled && isCyclistCurrentlyAvailable) playAlertSound(); // Trigger a re-style to apply/remove the highlight immediately document.querySelector('div[class*="crimes-pickpocketing-container"]').click(); }); colorsBtn.on('click', () => { isDifficultyColorsEnabled = !isDifficultyColorsEnabled; updateButtons(); // Trigger a re-style to apply/remove colors immediately document.querySelector('div[class*="crimes-pickpocketing-container"]').click(); }); updateButtons(); } // --- Utility Functions --- function playAlertSound() { const audio = new Audio(SETTINGS.cyclistAlerts.soundUrl); audio.play().catch(error => console.error("[PPHelper] Audio failed:", error)); } function waitForElementToExist(selector) { return new Promise(resolve => { if (document.querySelector(selector)) return resolve(document.querySelector(selector)); const observer = new MutationObserver(() => { if (document.querySelector(selector)) { resolve(document.querySelector(selector)); observer.disconnect(); } }); observer.observe(document.body, { subtree: true, childList: true }); }); } function interceptFetch(url, q, callback) { const originalFetch = window.fetch; window.fetch = function(...args) { return originalFetch.apply(this, args).then(response => { if (response.url.includes(url) && response.url.includes(q)) { response.clone().json().then(json => callback(json)).catch(error => console.error("[PPHelper] Intercept failed:", error)); } return response; }); }; } // --- Script Entry Point --- waitForElementToExist('.pickpocketing-root').then(() => { console.log("[PPHelper] Initializing Pickpocketing Helper v3.0"); setupInterface(); }); initializeCrimeObserver(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址