Zed.City Raid Monitor

Monitor raids and alert when they need more members (only when you're eligible)

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Zed.City Raid Monitor
// @namespace    https://swervelord.dev/
// @version      1.0
// @description  Monitor raids and alert when they need more members (only when you're eligible)
// @author       swervelord
// @match        https://www.zed.city/*
// @match        https://zed.city/*
// @grant        none
// @run-at       document-end
// ==/UserScript==

(function() {
    'use strict';

    const RAIDS_API_URL = 'https://api.zed.city/getRaids';
    const STATS_API_URL = 'https://api.zed.city/getStats';
    const CHECK_INTERVAL = 60000; // 60 seconds

    // Create GUI container
    function createGUI() {
        const container = document.createElement('div');
        container.id = 'raid-monitor-gui';
        container.style.cssText = `
            position: fixed;
            top: 140px;
            right: 20px;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 20px;
            border-radius: 12px;
            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
            z-index: 10000;
            min-width: 280px;
            max-width: 350px;
            font-family: Arial, sans-serif;
            animation: slideIn 0.3s ease-out;
        `;
        document.body.appendChild(container);
        return container;
    }

    // Add CSS animation
    const style = document.createElement('style');
    style.textContent = `
        @keyframes slideIn {
            from {
                transform: translateX(400px);
                opacity: 0;
            }
            to {
                transform: translateX(0);
                opacity: 1;
            }
        }
        #raid-monitor-gui .raid-item {
            background: rgba(255, 255, 255, 0.1);
            padding: 12px;
            margin-bottom: 10px;
            border-radius: 8px;
            border: 1px solid rgba(255, 255, 255, 0.2);
        }
        #raid-monitor-gui .raid-title {
            font-size: 16px;
            font-weight: bold;
            margin-bottom: 8px;
        }
        #raid-monitor-gui .raid-info {
            font-size: 13px;
            margin-bottom: 5px;
            opacity: 0.9;
        }
        #raid-monitor-gui .join-btn {
            background: #48bb78;
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 6px;
            cursor: pointer;
            font-size: 14px;
            font-weight: bold;
            width: 100%;
            margin-top: 10px;
            transition: background 0.2s;
        }
        #raid-monitor-gui .join-btn:hover {
            background: #38a169;
        }
        #raid-monitor-gui .header {
            font-size: 18px;
            font-weight: bold;
            margin-bottom: 15px;
            text-align: center;
            border-bottom: 2px solid rgba(255, 255, 255, 0.3);
            padding-bottom: 10px;
        }
        #raid-monitor-gui .worker-list {
            font-size: 12px;
            margin-top: 5px;
            opacity: 0.8;
        }
        #raid-monitor-gui .status-badge {
            display: inline-block;
            background: rgba(72, 187, 120, 0.3);
            padding: 4px 8px;
            border-radius: 4px;
            font-size: 11px;
            margin-top: 8px;
        }
    `;
    document.head.appendChild(style);

    // Check if user is eligible (not on cooldown)
    async function checkEligibility() {
        try {
            const response = await fetch(STATS_API_URL);
            const data = await response.json();

            // User is eligible if raid_cooldown is 0 or less
            return data.raid_cooldown <= 0;
        } catch (error) {
            console.error('Raid Monitor - Stats Check Error:', error);
            return false; // Assume not eligible if error
        }
    }

    // Check raids and update GUI
    async function checkRaids() {
        try {
            // First check if user is eligible
            const isEligible = await checkEligibility();

            if (!isEligible) {
                // Remove GUI if user is on cooldown
                const existingGUI = document.getElementById('raid-monitor-gui');
                if (existingGUI) {
                    existingGUI.remove();
                }
                console.log('Raid Monitor: On cooldown, not eligible for raids');
                return;
            }

            // User is eligible, now check for raids needing members
            const response = await fetch(RAIDS_API_URL);
            const data = await response.json();

            // Find raids that need more members
            const raidsNeedingMembers = [];

            if (data.activeRaids) {
                for (const [raidId, raid] of Object.entries(data.activeRaids)) {
                    const maxWorkers = raid.vars.max_workers;
                    const currentWorkers = raid.workers ? raid.workers.length : 0;

                    // Check if raid has workers and needs more
                    if (currentWorkers > 0 && currentWorkers < maxWorkers) {
                        raidsNeedingMembers.push({
                            id: raidId,
                            name: raid.name,
                            currentWorkers: currentWorkers,
                            maxWorkers: maxWorkers,
                            workers: raid.workers
                        });
                    }
                }
            }

            // Update or remove GUI based on raids
            const existingGUI = document.getElementById('raid-monitor-gui');

            if (raidsNeedingMembers.length > 0) {
                let container = existingGUI || createGUI();

                let html = '<div class="header">🚨 Raids Need Members!</div>';

                raidsNeedingMembers.forEach(raid => {
                    const workerNames = raid.workers.map(w => w.username).join(', ');
                    html += `
                        <div class="raid-item">
                            <div class="raid-title">${raid.name}</div>
                            <div class="raid-info">👥 ${raid.currentWorkers}/${raid.maxWorkers} members</div>
                            <div class="worker-list">Current: ${workerNames}</div>
                        </div>
                    `;
                });

                html += '<div class="status-badge">✓ You are eligible to join</div>';
                html += '<button class="join-btn" onclick="window.location.href=\'https://www.zed.city/raids\'">Join Raid</button>';

                container.innerHTML = html;
                console.log(`Raid Monitor: ${raidsNeedingMembers.length} raid(s) need members and you're eligible!`);
            } else if (existingGUI) {
                // Remove GUI if no raids need members
                existingGUI.remove();
                console.log('Raid Monitor: No raids currently need members');
            }

        } catch (error) {
            console.error('Raid Monitor Error:', error);
        }
    }

    // Initial check
    checkRaids();

    // Check every minute
    setInterval(checkRaids, CHECK_INTERVAL);

    console.log('Zed.City Raid Monitor Active - Checking every 60 seconds');
    console.log('Monitoring both raid availability and your eligibility status');
})();