Ortenskung Script Script / Hack 2.0.3

Automates crimes (neighborhood + car robbery) with a cleaner GUI + live stats bar

目前為 2025-09-20 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Ortenskung Script Script / Hack 2.0.3
// @namespace    http://tampermonkey.net/
// @version      2.0.3
// @description  Automates crimes (neighborhood + car robbery) with a cleaner GUI + live stats bar
// @match        https://www.ortenskung.com/en/*
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

// ======= Important state variables =======
let running = false;
let loopTimer = null;
let selectedCrimeId = 1;
let autoClose = true;

// Create panel
const panel = document.createElement('div');
panel.id = '__ortens_crime_bot_panel';
Object.assign(panel.style, {
  position: 'fixed',
  top: '5px',
  right: '5px',
  left: 'auto',
  width: '260px',
  background: '#111',
  color: '#eee',
  borderRadius: '8px',
  border: '1px solid rgba(255,255,255,0.05)',
  boxShadow: '0 4px 16px rgba(0,0,0,0.5)',
  fontFamily: 'Inter, Roboto, sans-serif',
  fontSize: '13px',
  zIndex: 999999,
  userSelect: 'none',
  overflow: 'hidden'
});

panel.innerHTML = `
    <div id="__header" style="display:flex;align-items:center;justify-content:space-between;padding:6px 10px;background:#0c0c0c;border-bottom:1px solid rgba(255,255,255,0.05);cursor:move;font-weight:600;font-size:13px">
        <div>Crime Bot</div>
        <div style="display:flex;gap:6px;align-items:center">
            <button id="__minBtn" title="Minimize" style="background:transparent;border:none;color:#aaa;cursor:pointer;font-size:14px">—</button>
            <button id="__closeBtn" title="Close" style="background:transparent;border:none;color:#aaa;cursor:pointer;font-size:14px">✕</button>
        </div>
    </div>
    <div id="__body" style="padding:8px;display:block">
        <div style="display:flex;gap:6px;margin-bottom:6px">
            <button class="__tab" data-tab="main" style="flex:1;padding:4px;border-radius:4px;border:0;background:#1b1b1b;color:#fff;cursor:pointer">Main</button>
            <button class="__tab" data-tab="settings" style="flex:1;padding:4px;border-radius:4px;border:0;background:#121212;color:#888;cursor:pointer">Settings</button>
        </div>

        <div id="__tab_main" class="__tabpanel">
            <label style="font-size:12px">Crime Type</label>
            <select id="__crimeType" style="width:100%;padding:4px;margin:4px 0 8px;border-radius:4px;border:1px solid rgba(255,255,255,0.06);background:#0b0b0b;color:#fff;font-size:12px">
                <option value="neighborhood">Neighborhood</option>
                <option value="car">Car Robbery</option>
            </select>

            <label style="font-size:12px">Crime ID</label>
            <select id="__crimeId" style="width:100%;padding:4px;margin:4px 0 8px;border-radius:4px;border:1px solid rgba(255,255,255,0.06);background:#0b0b0b;color:#fff;font-size:12px">
                ${Array.from({length:30}, (_,i)=>i+1).map(n=>`<option value="${n}">${n}</option>`).join('')}
            </select>

            <div style="display:flex;align-items:center;gap:6px;margin-bottom:8px">
                <label style="font-size:12px;display:flex;align-items:center;gap:4px">
                    <input type="checkbox" id="__autoClose" checked /> <span>Close dialogs</span>
                </label>
            </div>

            <button id="__startBtn" style="width:100%;padding:6px;border-radius:6px;border:0;background:linear-gradient(180deg,#2fa84f,#208f3a);color:#fff;font-weight:600;cursor:pointer;font-size:13px">Start</button>
        </div>

        <div id="__tab_settings" class="__tabpanel" style="display:none">
            <p style="font-size:12px;color:#bbb;margin:0 0 6px">Settings</p>
            <p style="font-size:11px;color:#999;margin:0 0 6px">Loop delay (ms)</p>
            <input id="__loopDelay" type="number" value="4000" style="width:100%;padding:4px;border-radius:4px;border:1px solid rgba(255,255,255,0.06);background:#0b0b0b;color:#fff;font-size:12px" />
            <p style="font-size:11px;color:#999;margin:6px 0 0">If something breaks, stop and inspect selectors.</p>
        </div>
    </div>
    <div id="__statsBar" style="display:flex;justify-content:space-around;align-items:center;padding:6px 8px;background:#181818;border-top:1px solid rgba(255,255,255,0.05);border-bottom:1px solid rgba(255,255,255,0.05);font-size:12px;color:#eaeaea">
      <span id="__diamonds">💎 0</span>
      <span id="__cash">💵 0</span>
      <span id="__bullets">🔫 0</span>
    </div>
    <div id="__footer" style="font-size:11px;padding:5px 8px;background:#0f0f0f;border-top:1px solid rgba(255,255,255,0.03);color:#9a9a9a">
        Status: <span id="__status">Idle</span>
    </div>
`;
document.body.appendChild(panel);

const header = panel.querySelector('#__header');
const body = panel.querySelector('#__body');
const footer = panel.querySelector('#__footer');
const closeBtn = panel.querySelector('#__closeBtn');
const minBtn = panel.querySelector('#__minBtn');
const tabs = panel.querySelectorAll('.__tab');
const tabMain = panel.querySelector('#__tab_main');
const tabSettings = panel.querySelector('#__tab_settings');
const startBtn = panel.querySelector('#__startBtn');
const crimeIdEl = panel.querySelector('#__crimeId');
const crimeTypeEl = panel.querySelector('#__crimeType');
const autoCloseEl = panel.querySelector('#__autoClose');
const statusEl = panel.querySelector('#__status');
const loopDelayEl = panel.querySelector('#__loopDelay');

// Tabs
tabs.forEach(t => t.addEventListener('click', () => {
  tabs.forEach(x => x.style.background = '#121212');
  t.style.background = '#1b1b1b';
  tabMain.style.display = t.dataset.tab === 'main' ? 'block' : 'none';
  tabSettings.style.display = t.dataset.tab === 'settings' ? 'block' : 'none';
}));

// ---------------- Draggable ----------------
let dragging = false;
let activePointerId = null;
let startX = 0, startY = 0, origLeft = 0, origTop = 0;

// Ensure numeric left/top exist so dragging works (computed from bounding rect)
(function ensurePositionValues() {
  const rect = panel.getBoundingClientRect();
  if (!panel.style.left || panel.style.left === 'auto') panel.style.left = rect.left + 'px';
  if (!panel.style.top || panel.style.top === 'auto') panel.style.top = rect.top + 'px';
  panel.style.right = 'auto';
})();

header.addEventListener('pointerdown', (ev) => {
    // only start drag when clicking header itself (not interactive children)
    if (ev.target !== header) return;
    ev.preventDefault();
    dragging = true;
    activePointerId = ev.pointerId;
    startX = ev.clientX;
    startY = ev.clientY;
    const rect = panel.getBoundingClientRect();
    origLeft = rect.left;
    origTop = rect.top;
    try { header.setPointerCapture(ev.pointerId); } catch (e) {}
});

document.addEventListener('pointermove', (ev) => {
    if (!dragging || ev.pointerId !== activePointerId) return;
    const dx = ev.clientX - startX;
    const dy = ev.clientY - startY;
    panel.style.left = (origLeft + dx) + 'px';
    panel.style.top = (origTop + dy) + 'px';
    panel.style.position = 'fixed';
    panel.style.right = 'auto';
});

document.addEventListener('pointerup', (ev) => {
    if (dragging && ev.pointerId === activePointerId) {
        try { header.releasePointerCapture(ev.pointerId); } catch (e) {}
        dragging = false;
        activePointerId = null;
    }
});

// Prevent interactive elements from starting drag
panel.querySelectorAll('button, input, select, a, textarea, label').forEach(node => {
    node.addEventListener('pointerdown', (e) => { e.stopPropagation(); });
});

// ---------------- Minimize / Close ----------------
let minimized = false;
minBtn.addEventListener('click', () => {
    minimized = !minimized;
    if (minimized) {
        body.style.display = 'none';
        footer.style.display = 'none';
        panel.querySelector('#__statsBar').style.display = 'none';
        panel.style.width = '140px';
        minBtn.textContent = '▢';
        minBtn.title = 'Restore';
    } else {
        body.style.display = 'block';
        footer.style.display = 'block';
        panel.querySelector('#__statsBar').style.display = 'flex';
        panel.style.width = '260px';
        minBtn.textContent = '—';
        minBtn.title = 'Minimize';
    }
});

closeBtn.addEventListener('click', () => {
    try { stopLoop(); } catch (e) {}
    panel.remove();
});

// ---------------- Stats ----------------
function updateStats() {
  const diamondEl = document.querySelector('.val[data-tip*="diamond"], .val[data-tip*="diamonds"], .val[data-tip*="diamanter"]');
  const cashEl    = document.querySelector('.val[data-tip*="cash"], .val[data-tip*="money"], .val[data-tip*="kontanter"]');
  const bulletEl  = document.querySelector('.val[data-tip*="ammunition"], .val[data-tip*="bullets"], .val[data-tip*="ammunitioner"]');

  function formatWithSpaces(raw) {
    if (raw == null) return '';
    // prefer numeric digits from data-number or strip non-digits from text
    const s = String(raw).replace(/[^\d.-]/g, '');
    if (s === '') return '';
    const parts = s.split('.');
    let int = parts[0];
    const sign = int.startsWith('-') ? '-' : '';
    if (sign) int = int.slice(1);
    int = int.replace(/\B(?=(\d{3})+(?!\d))/g, ' ');
    return sign + int + (parts[1] ? '.' + parts[1] : '');
  }

  function getText(el) {
    if (!el) return '';
    // use data-number when present (clean integer), otherwise use textContent
    const raw = el.getAttribute('data-number') ?? el.textContent ?? '';
    return formatWithSpaces(raw);
  }

  const diamonds = getText(diamondEl);
  const cash = getText(cashEl);
  const bullets = getText(bulletEl);

  const dNode = panel.querySelector('#__diamonds');
  const cNode = panel.querySelector('#__cash');
  const bNode = panel.querySelector('#__bullets');

  if (dNode && diamonds) dNode.textContent = '💎 ' + diamonds;
  if (cNode && cash)    cNode.textContent = '💵 ' + cash;
  if (bNode && bullets) bNode.textContent = '🔫 ' + bullets;
}

updateStats();
setInterval(updateStats, 2000);

function setStatus(text) {
    statusEl.textContent = text;
}

function stopLoop() {
    running = false;
    if (loopTimer) {
        clearTimeout(loopTimer);
        loopTimer = null;
    }
    startBtn.textContent = 'Start';
    setStatus('Stopped');
}

async function startLoop() {
    if (running) return;
    running = true;
    startBtn.textContent = 'Stop';
    setStatus('Running');
    // sync UI values
    selectedCrimeId = parseInt(crimeIdEl.value, 10) || selectedCrimeId;
    autoClose = !!autoCloseEl.checked;
    await performCrime(); // start immediately
}

startBtn.addEventListener('click', () => {
    if (!running) startLoop();
    else stopLoop();

function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }

// ---------------- Placeholder performCrime ----------------
// Keep your real performCrime implementation below or replace this stub.
// The GUI earlier expects functions: performCrime(), stopLoop(), setStatus()
async function performCrime() {
    if (!running) return;

    try {
        const delay = Math.max(50, parseInt(loopDelayEl.value, 10) || 4000);

        const timerEl = document.querySelector('#my_timers > div.val') || document.querySelector('.timers .val') || document.querySelector('.timer .val');
        if (timerEl) {
            const txt = timerEl.textContent.trim();
            const m = txt.match(/(\d+)\s*\/\s*(\d+)/);
            if (m) {
                const used = parseInt(m[1], 10), total = parseInt(m[2], 10);
                const avail = total - used;
                if (avail <= 0) {
                    setStatus('No timers left — waiting');
                    loopTimer = setTimeout(performCrime, 5000);
                    return;
                }
            }
        }

        // Example action cycle (replace with your real automation steps)
        setStatus('Performing crime id ' + (selectedCrimeId || crimeIdEl.value));
        await sleep(delay);

        // schedule next iteration
        if (running) loopTimer = setTimeout(performCrime, delay);
    } catch (err) {
        console.error('performCrime error', err);
        setStatus('Error — stopped');
        stopLoop();
    }
}

// Expose panel utilities if needed
window.__ortensPanel = { panel, setStatus, stopLoop };

    });
//OR maybe here it starts
    function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }

    async function performCrime() {
        if (!running) return;

        try {
            const delay = Math.max(50, parseInt(loopDelayEl.value, 10) || 4000);

            const timerEl = document.querySelector('#my_timers > div.val') || document.querySelector('.timers .val') || document.querySelector('.timer .val');
            if (timerEl) {
                const txt = timerEl.textContent.trim();
                const m = txt.match(/(\d+)\s*\/\s*(\d+)/);
                if (m) {
                    const used = parseInt(m[1], 10), total = parseInt(m[2], 10);
                    const avail = total - used;
                    if (avail <= 0) {
                        setStatus('No timers left — waiting');
                        loopTimer = setTimeout(performCrime, 5000);
                        return;
                    }
                }
            }
// somehwere here main loop starts
            const mode = (crimeTypeEl.value || 'neighborhood');

            if (mode === 'neighborhood') {
                if (!document.querySelector('#go_crimes_dialog') && document.querySelector('#go_crimes')) {
                    try { document.querySelector('#go_crimes').click(); } catch {}
                    await sleep(300);
                }
                const nbBtn = Array.from(document.querySelectorAll('.crimes_button, .crimes_button_small, .crimes-tab, .crimes_button'))
                    .find(el => /neighborhood/i.test(el.textContent || el.innerText || ''));
                if (nbBtn && !document.querySelector('#neighborhood_crimes')) {
                    try { nbBtn.click(); } catch (e) {}
                    await sleep(250);
                }
            } else if (mode === 'car') {
                if (!document.querySelector('#dialog_cars') && document.querySelector('#go_cars')) {
                    try { document.querySelector('#go_cars').click(); } catch {}
                    await sleep(300);
                } else {
                    const carOpener = Array.from(document.querySelectorAll('a,button')).find(el =>
    /(car|cars|vehicle|rob)/i.test((el.textContent || '') + ' ' + (el.getAttribute('title') || ''))
);


                    if (carOpener && !document.querySelector('#dialog_cars')) {
                        try { carOpener.click(); } catch (e) {}
                        await sleep(300);
                    }
                }
            }

            let commitBtn = null;

            if (mode === 'neighborhood') {
                const btns = Array.from(document.querySelectorAll('.crime_button_small, .crime_button, a, button'))
                    .filter(el => el.getAttribute && (el.getAttribute('onclick') || '').toString().length > 0);
                commitBtn = btns.find(el => {
                    const on = (el.getAttribute('onclick') || '');
                    return new RegExp(`['"]?id['"]?\\s*[:=]\\s*['"]?${selectedCrimeId}['"]?`).test(on);
                }) || btns.find(el => (el.getAttribute('onclick') || '').includes(`'id':'${selectedCrimeId}'`));
                if (!commitBtn) {
                    const byText = Array.from(document.querySelectorAll('.crime_button_small, .crime_button, a, button'))
                        .find(el => (el.textContent || '').includes(String(selectedCrimeId)));
                    if (byText) commitBtn = byText;
                }
                if (!commitBtn) {
                    commitBtn = document.querySelector('.crime_button_small, .crime_button, a, button');
                }
            } else if (mode === 'car') {
                commitBtn = Array.from(document.querySelectorAll('#dialog_cars .crime_button_small, #dialog_cars a, #dialog_cars button, .car_list a, .car_list button'))
                    .find(el => {
                        const on = el.getAttribute('onclick') || '';
                        return /robbing:perform|robbing|robb|rob|car|vehicle/i.test(on + ' ' + (el.textContent || ''));
                    });
                if (!commitBtn) {
                    // broader search
                    commitBtn = Array.from(document.querySelectorAll('a,button'))
                        .find(el => {
                            const on = (el.getAttribute('onclick') || '') + ' ' + (el.textContent || '');
                            return /robbing:perform|rob car|rob car|car robbery|rob car|rob/i.test(on);
                        });
                }
                if (!commitBtn) {
                    commitBtn = document.querySelector('#dialog_cars .crime_button_small') || document.querySelector('#dialog_cars a') || document.querySelector('#dialog_cars button');
                }
            }

            if (!commitBtn) {
                setStatus('No crime button found — retrying');
                loopTimer = setTimeout(performCrime, 5000);
                return;
            }

            try {
                commitBtn.scrollIntoView({block:'center', behavior:'auto'});
            } catch (e) {}
            try {
                commitBtn.click();
                setStatus(`Clicked ${mode} button`);
            } catch (e) {
                try { commitBtn.dispatchEvent(new MouseEvent('click', {bubbles:true,cancelable:true})); setStatus('Dispatched click'); }
                catch (err) { console.error('click failed', err); setStatus('Click failed'); }
            }

            setTimeout(() => {
                try {
                    if (typeof close_dialog === 'function') {
                        try { close_dialog('social'); } catch {}
                        try { close_dialog('levelup'); } catch {}
                        if (autoClose) try { close_dialog('crimes'); } catch {}
                        if (autoClose) try { close_dialog('cars'); } catch {}
                    }
                } catch (err) { /* ignore */ }

                const notif = document.querySelector('.button.first, .ui-button.primary, .ui-dialog .button, .ui-dialog .ui-button');
                if (notif) {
                    try { notif.click(); } catch (e) {}
                }
            }, 800);

            // 4) Schedule next run
            loopTimer = setTimeout(performCrime, Math.max(500, delay));
        } catch (err) {
            console.error('performCrime error', err);
            setStatus('Error — retrying');
            loopTimer = setTimeout(performCrime, 5000);
        }
    }

    // expose a small API
    window.__ortensCrimeBot = {
        stop: stopLoop,
        start: startLoop,
        status: () => ({ running, selectedCrimeId, autoClose })
    };

    // initialize selectedCrimeId from UI
    selectedCrimeId = parseInt(crimeIdEl.value, 10) || selectedCrimeId;

})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址