您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Enhanced pickpocketing with advanced risk assessment, color coding and auto-picker - Framework Module
// ==UserScript== // @name Torn Pickpocket Module Enhanced // @namespace http://tampermonkey.net/ // @version 1.2 // @description Enhanced pickpocketing with advanced risk assessment, color coding and auto-picker - Framework Module // @match https://www.torn.com/* // @grant GM_setValue // @grant GM_getValue // @grant unsafeWindow // @run-at document-end // @license MIT (With recognition) // ==/UserScript== (function() { 'use strict'; // Use unsafeWindow to match framework const globalWindow = (typeof unsafeWindow !== 'undefined') ? unsafeWindow : window; console.log('[PICKPOCKET] Enhanced Module starting...'); // ENHANCED RISK ASSESSMENT CONFIG const riskFactors = { targets: { // Very High Risk "Police officer": 100, // High Risk "Thug": 80, "Gang member": 85, "Mobster": 90, // Medium-High Risk "Laborer": 60, "Cyclist": 65, "Jogger": 55, // Medium Risk "Businessman": 45, "Businesswoman": 45, "Young man": 40, "Rich kid": 50, // Low-Medium Risk "Young woman": 30, "Student": 35, "Classy lady": 40, "Postal worker": 35, "Sex worker": 45, // Low Risk "Elderly man": 15, "Elderly woman": 10, "Drunk man": 5, "Drunk woman": 5, "Homeless person": 5, "Junkie": 8 }, activities: { // High Risk Activities "Running": 25, "Alert": 30, "Chasing": 35, // Medium Risk "Walking": 10, "Jogging": 15, "Cycling": 20, "On Phone": 5, // Low Risk "Stumbling": -15, "Begging": -10, "Distracted": -12, "Loitering": -8, "Listening to music": -5, "Soliciting": 0 }, builds: { "Muscular": 20, "Athletic": 15, "Average": 5, "Heavyset": 8, "Skinny": -5 } }; // Enhanced color coding based on total risk score const riskColorMap = { "Minimal": "#26de81", // Green - 0-20 "Low": "#51cf66", // Light Green - 21-40 "Moderate": "#74b816", // Yellow-Green - 41-60 "High": "#ffa502", // Orange - 61-80 "Dangerous": "#f76707", // Red-Orange - 81-100 "Extreme": "#f03e3e" // Red - 100+ }; // Legacy category mapping for backwards compatibility 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 activityTypes = ["Walking", "Stumbling", "Loitering", "Listening to music", "Distracted", "Soliciting", "Running", "Jogging"]; // Settings let ppSettings = { coloringEnabled: GM_getValue('ppColoringEnabled', true), enhancedRiskMode: GM_getValue('ppEnhancedRiskMode', true), showRiskScores: GM_getValue('ppShowRiskScores', true), autoPickerEnabled: GM_getValue('ppAutoPickerEnabled', false), targetCategories: GM_getValue('ppTargetCategories', ["Safe"]), targetActivities: GM_getValue('ppTargetActivities', ["Stumbling"]), maxRiskScore: GM_getValue('ppMaxRiskScore', 40), autoPickDelay: GM_getValue('ppAutoPickDelay', 3000), maxNerve: GM_getValue('ppMaxNerve', 5), randomDelay: GM_getValue('ppRandomDelay', true), maxActions: GM_getValue('ppMaxActions', 50), safetyMode: GM_getValue('ppSafetyMode', true), avoidHighRisk: GM_getValue('ppAvoidHighRisk', true) }; // State let processedTargets = new Set(); let autoPickerInterval = null; let actionCount = 0; let sessionStart = Date.now(); function saveSettings() { Object.keys(ppSettings).forEach(key => { GM_setValue(`pp${key.charAt(0).toUpperCase() + key.slice(1)}`, ppSettings[key]); }); } function log(msg, type = 'info') { if (globalWindow.TornFramework && globalWindow.TornFramework.log) { globalWindow.TornFramework.log(msg, type, 'PICKPOCKET'); } else { console.log(`[PICKPOCKET] ${msg}`); } } // Enhanced risk calculation function calculateRiskScore(targetName, activity, physical) { let score = 0; // Base target risk const targetRisk = riskFactors.targets[targetName] || 25; score += targetRisk; // Activity modifier const activityWords = Object.keys(riskFactors.activities); for (const activityWord of activityWords) { if (activity.toLowerCase().includes(activityWord.toLowerCase())) { score += riskFactors.activities[activityWord]; break; } } // Physical build modifier const buildWords = Object.keys(riskFactors.builds); for (const buildWord of buildWords) { if (physical.toLowerCase().includes(buildWord.toLowerCase())) { score += riskFactors.builds[buildWord]; break; } } return Math.max(0, score); } function getRiskCategory(score) { if (score <= 20) return "Minimal"; if (score <= 40) return "Low"; if (score <= 60) return "Moderate"; if (score <= 80) return "High"; if (score <= 100) return "Dangerous"; return "Extreme"; } function getLegacyCategory(targetName) { for (const category in markGroups) { if (markGroups[category].includes(targetName)) { return category; } } return "Unknown"; } function extractTargetInfo(crimeOption) { try { const titleElement = crimeOption.querySelector('.titleAndProps___DdeVu > div'); const activityElement = crimeOption.querySelector('.activity___e7mdA'); const physicalElement = crimeOption.querySelector('.physicalProps___E5YrR span[aria-hidden="true"]'); const name = titleElement ? titleElement.textContent.trim().split(' (')[0] : ''; let activity = ''; let physical = ''; if (activityElement) { const activityText = activityElement.childNodes[0]; activity = activityText ? activityText.textContent.trim() : ''; } if (physicalElement) { physical = physicalElement.textContent.trim(); } return { name, activity, physical }; } catch (error) { return { name: '', activity: '', physical: '' }; } } function addRandomDelay(baseDelay) { if (!ppSettings.randomDelay) return baseDelay; const variance = baseDelay * 0.3; return baseDelay + (Math.random() * variance * 2 - variance); } function isRateLimited() { if (!ppSettings.safetyMode) return false; if (actionCount >= ppSettings.maxActions) { return true; } return false; } function processCurrentTargets() { if (!ppSettings.coloringEnabled) return; try { const crimeOptions = document.querySelectorAll('.crime-option, .crimeOptionWrapper___IOnLO'); crimeOptions.forEach((option) => { const titleElement = option.querySelector('.titleAndProps___DdeVu > div'); if (!titleElement) return; const targetInfo = extractTargetInfo(option); if (!targetInfo.name) return; let displayText = targetInfo.name; let color = '#ffffff'; if (ppSettings.enhancedRiskMode && targetInfo.activity && targetInfo.physical) { // Enhanced risk assessment mode const riskScore = calculateRiskScore(targetInfo.name, targetInfo.activity, targetInfo.physical); const riskCategory = getRiskCategory(riskScore); color = riskColorMap[riskCategory]; if (ppSettings.showRiskScores) { displayText = `${targetInfo.name} (${riskCategory} - ${riskScore})`; } else { displayText = `${targetInfo.name} (${riskCategory})`; } // Add risk indicator dot const existing = option.querySelector('.risk-indicator'); if (existing) existing.remove(); const indicator = document.createElement('div'); indicator.className = 'risk-indicator'; indicator.style.cssText = ` position: absolute; top: 5px; right: 5px; width: 10px; height: 10px; border-radius: 50%; background: ${color}; border: 1px solid rgba(255,255,255,0.5); box-shadow: 0 0 4px rgba(0,0,0,0.3); z-index: 10; `; indicator.title = `Risk: ${riskCategory} (${riskScore})`; const wrapper = option.querySelector('.crimeOptionWrapper___IOnLO') || option; if (wrapper) { wrapper.style.position = 'relative'; wrapper.appendChild(indicator); } } else { // Legacy category mode const legacyCategory = getLegacyCategory(targetInfo.name); if (legacyCategory !== "Unknown") { color = riskColorMap.Moderate; // Default color for legacy mode displayText = `${targetInfo.name} (${legacyCategory})`; } } // Apply styling titleElement.style.color = color; titleElement.style.fontWeight = 'bold'; titleElement.style.textShadow = '0 1px 2px rgba(0,0,0,0.5)'; if (!titleElement.textContent.includes('(')) { titleElement.textContent = displayText; } }); } catch (error) { log(`Target processing failed: ${error.message}`, 'error'); } } function getCurrentNerve() { try { const nerveElement = document.querySelector('.bar-value___NTdce'); if (nerveElement) { const nerveText = nerveElement.textContent; const match = nerveText.match(/(\d+)/); return match ? parseInt(match[1]) : 0; } const altNerveElement = document.querySelector('[class*="nerve"] .bar-value, .nerve-bar .bar-value'); if (altNerveElement) { const match = altNerveElement.textContent.match(/(\d+)/); return match ? parseInt(match[1]) : 0; } return 100; } catch (error) { log(`Nerve reading failed: ${error.message}`, 'error'); return 0; } } function findBestTarget() { if (isRateLimited()) { log('Rate limited - skipping target search', 'warning'); return null; } try { const crimeOptions = document.querySelectorAll('.crime-option'); const currentNerve = getCurrentNerve(); if (currentNerve < 1) { log('Insufficient nerve for pickpocketing', 'warning'); return null; } const validTargets = []; for (const option of crimeOptions) { const titleElement = option.querySelector('.titleAndProps___DdeVu > div'); const buttonElement = option.querySelector('.commit-button'); if (!titleElement || !buttonElement) continue; const targetInfo = extractTargetInfo(option); if (!targetInfo.name) continue; const ariaLabel = buttonElement.getAttribute('aria-label') || ''; const nerveMatch = ariaLabel.match(/(\d+)\s*nerve/i); const nerveCost = nerveMatch ? parseInt(nerveMatch[1]) : 5; if (currentNerve < nerveCost || nerveCost > ppSettings.maxNerve) continue; if (buttonElement.getAttribute('aria-disabled') === 'true') continue; let riskScore = 50; // Default risk let targetCategory = "Unknown"; if (ppSettings.enhancedRiskMode && targetInfo.activity && targetInfo.physical) { riskScore = calculateRiskScore(targetInfo.name, targetInfo.activity, targetInfo.physical); targetCategory = getRiskCategory(riskScore); // Skip if risk too high if (ppSettings.avoidHighRisk && riskScore > ppSettings.maxRiskScore) { continue; } } else { // Legacy mode targetCategory = getLegacyCategory(targetInfo.name); if (!ppSettings.targetCategories.includes(targetCategory)) continue; } // Activity filter (still applies in enhanced mode) if (ppSettings.targetActivities.length > 0) { if (!ppSettings.targetActivities.some(activity => targetInfo.activity.toLowerCase().includes(activity.toLowerCase()))) { continue; } } validTargets.push({ element: buttonElement, title: targetInfo.name, activity: targetInfo.activity, category: targetCategory, nerve: nerveCost, riskScore: riskScore, priority: ppSettings.enhancedRiskMode ? riskScore : getCategoryPriority(targetCategory) }); } // Sort by risk score (lower is better) then by nerve cost validTargets.sort((a, b) => { if (a.riskScore !== b.riskScore) return a.riskScore - b.riskScore; return a.nerve - b.nerve; }); return validTargets[0] || null; } catch (error) { log(`Target search failed: ${error.message}`, 'error'); return null; } } function getCategoryPriority(category) { const priorities = { "Safe": 1, "Moderately Unsafe": 2, "Unsafe": 3, "Risky": 4, "Dangerous": 5, "Very Dangerous": 6 }; return priorities[category] || 999; } function performAutoPick(isTest = false) { try { const target = findBestTarget(); if (!target) { const msg = isTest ? 'No valid targets available for test' : 'No targets match current criteria'; log(msg, 'warning'); return false; } if (isTest) { const riskInfo = ppSettings.enhancedRiskMode ? ` - Risk: ${target.riskScore}` : ''; log(`Test successful: Would pick ${target.title} (${target.category})${riskInfo} - ${target.activity} [${target.nerve} nerve]`, 'success'); return true; } if (ppSettings.safetyMode && isRateLimited()) { log('Safety mode: Action blocked due to rate limiting', 'warning'); return false; } target.element.click(); actionCount++; const riskInfo = ppSettings.enhancedRiskMode ? ` - Risk: ${target.riskScore}` : ''; log(`Auto-picked: ${target.title} (${target.category})${riskInfo} [${target.nerve} nerve] - Activity: ${target.activity}`, 'success'); processedTargets.add(target.title + target.activity); setTimeout(() => { processedTargets.delete(target.title + target.activity); }, 30000); return true; } catch (error) { log(`Auto pick failed: ${error.message}`, 'error'); return false; } } function startAutoPicker() { if (autoPickerInterval) return; try { log('Auto picker starting...', 'success'); autoPickerInterval = setInterval(() => { if (ppSettings.autoPickerEnabled && isOnPickpocketPage()) { if (ppSettings.safetyMode && isRateLimited()) { log('Auto picker paused - rate limit reached', 'warning'); return; } performAutoPick(); } }, addRandomDelay(ppSettings.autoPickDelay)); } catch (error) { log(`Auto picker start failed: ${error.message}`, 'error'); } } function stopAutoPicker() { if (autoPickerInterval) { clearInterval(autoPickerInterval); autoPickerInterval = null; log('Auto picker stopped', 'warning'); } } function isOnPickpocketPage() { return window.location.href.includes('crimes') && (document.querySelector('.pickpocketing-root') !== null || document.querySelector('[class*="pickpocket"]') !== null || document.querySelector('.crime-option') !== null); } // Create enhanced menu section HTML const menuSection = ` <h4 style="margin: 0 0 12px 0; color: #37b24d;">👤 Enhanced Pickpocketing</h4> <div style="display: grid; grid-template-columns: 1fr auto; gap: 10px; align-items: center; margin-bottom: 12px;"> <label style="display: flex; align-items: center; cursor: pointer;"> <input type="checkbox" id="ppColoringEnabled" ${ppSettings.coloringEnabled ? 'checked' : ''}> <span style="margin-left: 8px;">Target Color Coding</span> </label> <div style="font-size: 10px; color: #999;">Visual aid</div> </div> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 12px;"> <label style="display: flex; align-items: center; cursor: pointer;"> <input type="checkbox" id="ppEnhancedRiskMode" ${ppSettings.enhancedRiskMode ? 'checked' : ''}> <span style="margin-left: 8px; font-size: 11px;">Enhanced Risk Mode</span> </label> <label style="display: flex; align-items: center; cursor: pointer;"> <input type="checkbox" id="ppShowRiskScores" ${ppSettings.showRiskScores ? 'checked' : ''}> <span style="margin-left: 8px; font-size: 11px;">Show Risk Scores</span> </label> </div> <div style="display: flex; align-items: center; margin-bottom: 12px; padding: 8px; background: rgba(55,178,77,0.1); border-radius: 6px;"> <label style="display: flex; align-items: center; cursor: pointer; flex-grow: 1;"> <input type="checkbox" id="ppAutoPickerEnabled" ${ppSettings.autoPickerEnabled ? 'checked' : ''}> <span style="margin-left: 8px; font-weight: bold; color: #37b24d;">Auto Picker</span> </label> <div id="ppAutoPickStatus" style="padding: 4px 8px; border-radius: 4px; font-size: 10px; font-weight: bold; background: ${ppSettings.autoPickerEnabled ? '#37b24d' : '#666'}; color: white;"> ${ppSettings.autoPickerEnabled ? 'ACTIVE' : 'DISABLED'} </div> </div> <div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; margin-bottom: 12px;"> <div> <label style="display: block; margin-bottom: 4px; font-size: 10px;">Delay (ms):</label> <input type="number" id="ppAutoPickDelay" value="${ppSettings.autoPickDelay}" min="1000" max="30000" step="500" style="width: 100%; padding: 6px; background: #333; color: white; border: 1px solid #555; border-radius: 4px; font-size: 11px;"> </div> <div> <label style="display: block; margin-bottom: 4px; font-size: 10px;">Max Nerve:</label> <input type="number" id="ppMaxNerve" value="${ppSettings.maxNerve}" min="1" max="50" style="width: 100%; padding: 6px; background: #333; color: white; border: 1px solid #555; border-radius: 4px; font-size: 11px;"> </div> <div> <label style="display: block; margin-bottom: 4px; font-size: 10px;">Max Risk:</label> <input type="number" id="ppMaxRiskScore" value="${ppSettings.maxRiskScore}" min="0" max="150" style="width: 100%; padding: 6px; background: #333; color: white; border: 1px solid #555; border-radius: 4px; font-size: 11px;"> </div> </div> <div style="display: grid; grid-template-columns: 1fr auto; gap: 8px; margin-bottom: 12px; align-items: center;"> <div> <label style="display: block; margin-bottom: 4px; font-size: 10px;">Max Actions/Hour:</label> <input type="number" id="ppMaxActions" value="${ppSettings.maxActions}" min="10" max="200" style="width: 100%; padding: 6px; background: #333; color: white; border: 1px solid #555; border-radius: 4px; font-size: 11px;"> </div> <div style="display: flex; flex-direction: column; gap: 4px;"> <label style="display: flex; align-items: center; cursor: pointer;"> <input type="checkbox" id="ppSafetyMode" ${ppSettings.safetyMode ? 'checked' : ''}> <span style="margin-left: 6px; font-size: 10px;">Safety Mode</span> </label> <label style="display: flex; align-items: center; cursor: pointer;"> <input type="checkbox" id="ppAvoidHighRisk" ${ppSettings.avoidHighRisk ? 'checked' : ''}> <span style="margin-left: 6px; font-size: 10px;">Avoid High Risk</span> </label> </div> </div> <div id="ppLegacyControls" style="display: ${ppSettings.enhancedRiskMode ? 'none' : 'block'};"> <div style="margin-bottom: 12px;"> <label style="display: block; margin-bottom: 6px; font-weight: bold; font-size: 11px;">Target Categories (Legacy Mode):</label> <div id="ppCategoryCheckboxes" style="max-height: 80px; overflow-y: auto; border: 1px solid #555; padding: 6px; border-radius: 4px; background: rgba(0,0,0,0.3);"> ${Object.keys(markGroups).map(category => ` <label style="display: block; margin-bottom: 2px; cursor: pointer; font-size: 10px;"> <input type="checkbox" class="ppCategoryCheck" value="${category}" ${ppSettings.targetCategories.includes(category) ? 'checked' : ''}> <span style="margin-left: 4px;">${category}</span> </label> `).join('')} </div> </div> </div> <div style="margin-bottom: 12px;"> <label style="display: block; margin-bottom: 6px; font-weight: bold; font-size: 11px;">Target Activities:</label> <div id="ppActivityCheckboxes" style="max-height: 80px; overflow-y: auto; border: 1px solid #555; padding: 6px; border-radius: 4px; background: rgba(0,0,0,0.3);"> ${activityTypes.map(activity => ` <label style="display: block; margin-bottom: 2px; cursor: pointer; font-size: 10px;"> <input type="checkbox" class="ppActivityCheck" value="${activity}" ${ppSettings.targetActivities.includes(activity) ? 'checked' : ''}> <span style="margin-left: 4px;">${activity}</span> </label> `).join('')} </div> </div> <button id="ppTestPick" style="width: 100%; padding: 8px; background: linear-gradient(45deg, #37b24d, #51cf66); border: none; color: white; border-radius: 6px; cursor: pointer; font-size: 11px; font-weight: bold; box-shadow: 0 2px 8px rgba(55,178,77,0.3); transition: all 0.2s;">Test Auto Pick</button> `; function setupEventHandlers() { // Coloring toggle const coloringToggle = document.getElementById('ppColoringEnabled'); if (coloringToggle) { coloringToggle.onchange = function() { ppSettings.coloringEnabled = this.checked; saveSettings(); setTimeout(processCurrentTargets, 100); log(`Color coding ${this.checked ? 'enabled' : 'disabled'}`, 'info'); }; } // Enhanced risk mode toggle const enhancedToggle = document.getElementById('ppEnhancedRiskMode'); if (enhancedToggle) { enhancedToggle.onchange = function() { ppSettings.enhancedRiskMode = this.checked; saveSettings(); // Toggle legacy controls visibility const legacyControls = document.getElementById('ppLegacyControls'); if (legacyControls) { legacyControls.style.display = this.checked ? 'none' : 'block'; } setTimeout(processCurrentTargets, 100); log(`Enhanced risk mode ${this.checked ? 'enabled' : 'disabled'}`, 'info'); }; } // Show risk scores toggle const scoresToggle = document.getElementById('ppShowRiskScores'); if (scoresToggle) { scoresToggle.onchange = function() { ppSettings.showRiskScores = this.checked; saveSettings(); setTimeout(processCurrentTargets, 100); log(`Risk scores ${this.checked ? 'shown' : 'hidden'}`, 'info'); }; } // Auto picker toggle const autoPickToggle = document.getElementById('ppAutoPickerEnabled'); if (autoPickToggle) { autoPickToggle.onchange = function() { ppSettings.autoPickerEnabled = this.checked; const status = document.getElementById('ppAutoPickStatus'); if (status) { status.textContent = ppSettings.autoPickerEnabled ? 'ACTIVE' : 'DISABLED'; status.style.background = ppSettings.autoPickerEnabled ? '#37b24d' : '#666'; } if (ppSettings.autoPickerEnabled && isOnPickpocketPage() && !isRateLimited()) { startAutoPicker(); } else { stopAutoPicker(); } saveSettings(); log(`Auto picker ${this.checked ? 'enabled' : 'disabled'}`, 'info'); }; } // Number inputs ['ppAutoPickDelay', 'ppMaxNerve', 'ppMaxActions', 'ppMaxRiskScore'].forEach(id => { const input = document.getElementById(id); if (input) { input.onchange = function() { const setting = id.replace('pp', '').charAt(0).toLowerCase() + id.replace('pp', '').slice(1); ppSettings[setting] = parseInt(this.value); saveSettings(); // Restart auto picker if running and delay changed if (id === 'ppAutoPickDelay' && autoPickerInterval) { stopAutoPicker(); startAutoPicker(); } }; } }); // Boolean toggles const booleanToggles = ['ppSafetyMode', 'ppAvoidHighRisk']; booleanToggles.forEach(id => { const toggle = document.getElementById(id); if (toggle) { toggle.onchange = function() { const setting = id.replace('pp', '').charAt(0).toLowerCase() + id.replace('pp', '').slice(1); ppSettings[setting] = this.checked; saveSettings(); log(`${setting} ${this.checked ? 'enabled' : 'disabled'}`, 'info'); }; } }); // Category checkboxes document.querySelectorAll('.ppCategoryCheck').forEach(checkbox => { checkbox.onchange = () => { ppSettings.targetCategories = Array.from(document.querySelectorAll('.ppCategoryCheck:checked')).map(cb => cb.value); saveSettings(); log(`Target categories updated: ${ppSettings.targetCategories.join(', ')}`, 'info'); }; }); // Activity checkboxes document.querySelectorAll('.ppActivityCheck').forEach(checkbox => { checkbox.onchange = () => { ppSettings.targetActivities = Array.from(document.querySelectorAll('.ppActivityCheck:checked')).map(cb => cb.value); saveSettings(); log(`Target activities updated: ${ppSettings.targetActivities.join(', ')}`, 'info'); }; }); // Test button const testBtn = document.getElementById('ppTestPick'); if (testBtn) { testBtn.onclick = () => { log('Testing auto pick functionality...', 'warning'); const result = performAutoPick(true); if (!result) { log('Test failed - check your target settings or visit crimes page', 'error'); } }; } } // Module configuration const moduleConfig = { name: 'Enhanced Pickpocket', version: '1.2', description: 'Enhanced pickpocketing with advanced risk assessment, color coding and auto-picker', menuSection: menuSection, initialize: function() { log('Enhanced Pickpocket module initializing...', 'info'); setupEventHandlers(); // Start observer for target processing const observer = new MutationObserver(() => { if (ppSettings.coloringEnabled) { clearTimeout(observer.debounceTimer); observer.debounceTimer = setTimeout(processCurrentTargets, 300); } }); observer.observe(document.body, { childList: true, subtree: true }); // Initial target processing setTimeout(processCurrentTargets, 1000); // Auto-start if enabled and on pickpocket page if (ppSettings.autoPickerEnabled && isOnPickpocketPage()) { setTimeout(startAutoPicker, 2000); log('Auto picker will start in 2 seconds (on pickpocket page)', 'info'); } log('Enhanced Pickpocket module initialized successfully', 'success'); }, cleanup: function() { stopAutoPicker(); log('Enhanced Pickpocket module cleaned up', 'info'); }, isActive: function() { return ppSettings.autoPickerEnabled && autoPickerInterval !== null && isOnPickpocketPage(); }, getStats: function() { const uptime = Math.floor((Date.now() - sessionStart) / 1000); return { 'Actions Performed': actionCount, 'Session Uptime': `${uptime}s`, 'Rate Limit Status': isRateLimited() ? 'ACTIVE' : 'OK', 'Risk Mode': ppSettings.enhancedRiskMode ? 'Enhanced' : 'Legacy', 'Max Risk Score': ppSettings.maxRiskScore }; } }; function initializePickpocketModule() { log('Attempting to register enhanced pickpocket module with framework...', 'info'); // Register with framework if (globalWindow.TornFramework && globalWindow.TornFramework.registerModule(moduleConfig)) { log('Enhanced Pickpocket module registered successfully', 'success'); // Page change detection let currentUrl = window.location.href; const urlObserver = new MutationObserver(() => { if (window.location.href !== currentUrl) { currentUrl = window.location.href; if (!isOnPickpocketPage() && autoPickerInterval) { stopAutoPicker(); log('Left pickpocket page - auto picker stopped', 'info'); } else if (isOnPickpocketPage() && ppSettings.autoPickerEnabled && !autoPickerInterval) { setTimeout(startAutoPicker, 1000); log('Entered pickpocket page - auto picker starting', 'info'); } } }); urlObserver.observe(document.body, { childList: true, subtree: true }); } else { log('Failed to register enhanced pickpocket module - framework not available', 'error'); } } // Wait for framework function waitForFramework() { console.log('[PICKPOCKET] Checking for framework...'); if (globalWindow.TornFramework && globalWindow.TornFramework.initialized) { console.log('[PICKPOCKET] Framework found, initializing enhanced module'); initializePickpocketModule(); } else { console.log('[PICKPOCKET] Framework not ready, waiting...'); setTimeout(waitForFramework, 500); } } // Start initialization waitForFramework(); })();