// ==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();
})();