Mizzuho / SMMO - Mizzuho V2 Full Auto (Kiwi Fix)

// ==UserScript==
// @name         SMMO - Mizzuho V2 Full Auto (Kiwi Fix)
// @namespace    http://tampermonkey.net/
// @version      2.1
// @description  Full Auto V32 Core - Refactored & Clean Code Edition (Kiwi Browser Compatible)
// @author       Mizzuho
// @match        https://web.simple-mmo.com/*
// @match        https://simple-mmo.com/*
// @match        https://*.simple-mmo.com/*
// @run-at       document-end
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // ==========================================
    // 1. CONFIGURATION (Pusat Pengaturan)
    // ==========================================
    const CONFIG = {
        keywords: {
            resource: ["salvage", "mine", "chop", "catch", "gather"],
            combat: ["attack", "attack again", "leave", "close"],
            step: ["take a step"]
        },
        delays: {
            securityRest: 20000,   // Istirahat saat kena Captcha
            stepRest: 20000,       // Istirahat kelipatan 50 langkah
            stepCooldown: 2600,
            combatCooldown: 1200,
            modalCooldown: 2000,
            triggerCooldown: 2500,
            idleScan: 500
        },
        thresholds: {
            restStepCount: 50
        }
    };

    // ==========================================
    // 2. STATE MANAGEMENT (Memori Bot)
    // ==========================================
    const STATE = {
        stepCount: 0,
        isLocked: false,
        isRunning: false
    };

    // ==========================================
    // 3. UTILITIES & INPUT (Fungsi Bantuan)
    // ==========================================
    const Utils = {
        log: (msg, color = '#3b82f6') => {
            console.log(`%c[MZH-CORE] ${msg}`, `color: ${color}; font-weight: bold; background: #0f172a; padding: 2px 6px; border-radius: 4px;`);
        },
        random: (min, max) => Math.floor(Math.random() * (max - min + 1)) + min,
        isReady: (el) => {
            if (!el || el.offsetParent === null) return false;
            const style = window.getComputedStyle(el);
            return !el.disabled && !el.classList.contains('disabled') && parseFloat(style.opacity) > 0.8;
        },
        findBtn: (buttons, keywords) => {
            return buttons.find(el => {
                const txt = el.innerText.toLowerCase();
                return keywords.some(kw => txt.includes(kw)) && Utils.isReady(el);
            });
        }
    };

    const Input = {
        smartClick: (el, label) => {
            if (!el || STATE.isLocked) return;
            STATE.isLocked = true;
            el.focus();

            const rect = el.getBoundingClientRect();
            const x = rect.left + (Math.random() * rect.width);
            const y = rect.top + (Math.random() * rect.height);
            const opts = { bubbles: true, cancelable: true, view: window, isTrusted: true, clientX: x, clientY: y };

            el.dispatchEvent(new MouseEvent('mousedown', opts));

            setTimeout(() => {
                el.dispatchEvent(new MouseEvent('mouseup', opts));
                el.dispatchEvent(new MouseEvent('click', opts));
                Utils.log(`[${label}] Executed`, '#10b981');

                setTimeout(() => { STATE.isLocked = false; }, 400);
            }, 40);
        }
    };

    // ==========================================
    // 4. CORE ENGINE (Logika Utama)
    // ==========================================
    function engineLoop() {
        if (STATE.isLocked) {
            setTimeout(engineLoop, 200);
            return;
        }

        const text = document.body.innerText || "";
        const domButtons = Array.from(document.querySelectorAll('button, a.btn, .btn-primary, .btn-danger, .btn-success'));

        // --- A. SECURITY CHECK ---
        if (text.includes("I'm a person") || text.includes("Hold up there") || text.includes("Please slow down")) {
            Utils.log("ALERT: Captcha Terdeteksi! Istirahat 20 detik...", "#ef4444");
            try { if (navigator.vibrate) navigator.vibrate([500, 200, 500]); } catch(e){}
            setTimeout(engineLoop, CONFIG.delays.securityRest);
            return;
        }

        const isSkillLocked = text.includes("Your skill level isn't high enough") || text.includes("You cannot gather right now");

        // --- B. MODAL STATE (Pop-up) ---
        const isModalActive = text.includes("Remaining Material") || document.querySelector('.swal2-shown');
        if (isModalActive) {
            if (isSkillLocked) {
                const closeBtn = document.querySelector('.swal2-close');
                if (closeBtn) {
                    setTimeout(() => {
                        Input.smartClick(closeBtn, "CLOSE_BLOCKED_MODAL");
                        setTimeout(engineLoop, 1000);
                    }, 800);
                    return;
                }
            } else {
                const modalBtn = Utils.findBtn(domButtons.reverse(), CONFIG.keywords.resource);
                if (modalBtn) {
                    const delay = Utils.random(1500, 3000);
                    setTimeout(() => {
                        Input.smartClick(modalBtn, "GATHERING_MODAL");
                        setTimeout(engineLoop, CONFIG.delays.modalCooldown);
                    }, delay);
                    return;
                }
            }
            setTimeout(engineLoop, 500);
            return;
        }

        const mainBtns = domButtons.filter(b => b.offsetParent !== null && !b.closest('.sidebar'));

        // --- C. TRIGGER RESOURCE ---
        if (!isSkillLocked) {
            const triggerBtn = Utils.findBtn(mainBtns, CONFIG.keywords.resource);
            if (triggerBtn) {
                const delay = Utils.random(2000, 4000);
                setTimeout(() => {
                    Input.smartClick(triggerBtn, "OPEN_RESOURCE");
                    setTimeout(engineLoop, CONFIG.delays.triggerCooldown);
                }, delay);
                return;
            }
        }

        // --- D. COMBAT ---
        const combatBtn = Utils.findBtn(mainBtns, CONFIG.keywords.combat);
        if (combatBtn) {
            const delay = Utils.random(400, 1200);
            setTimeout(() => {
                Input.smartClick(combatBtn, "COMBAT");
                setTimeout(engineLoop, CONFIG.delays.combatCooldown);
            }, delay);
            return;
        }

        // --- E. STEPPING ---
        const stepBtn = Utils.findBtn(mainBtns, CONFIG.keywords.step);
        if (stepBtn) {
            STATE.stepCount++;

            if (STATE.stepCount % CONFIG.thresholds.restStepCount === 0) {
                Utils.log("REST: Istirahat 20 detik...", "#fbbf24");
                setTimeout(engineLoop, CONFIG.delays.stepRest);
                return;
            }

            const delay = Utils.random(1000, 2500);
            setTimeout(() => {
                const modalCheck = document.body.innerText.includes("Remaining Material") || document.querySelector('.swal2-shown');
                if (!modalCheck) {
                    Input.smartClick(stepBtn, "STEP");
                    setTimeout(engineLoop, CONFIG.delays.stepCooldown);
                } else {
                    engineLoop();
                }
            }, delay);
            return;
        }

        setTimeout(engineLoop, CONFIG.delays.idleScan);
    }

    // ==========================================
    // 5. BOOTSTRAP (Kiwi Safe Auto Start)
    // ==========================================
    function init() {
        if (STATE.isRunning) return;
        STATE.isRunning = true;
        
        Utils.log("Mizzuho V2 Full Auto Active (Kiwi Edition)", "#34d399");
        if (typeof Notification !== 'undefined' && Notification.permission !== "granted") {
            Notification.requestPermission();
        }
        setTimeout(engineLoop, 2000);
    }

    // Pemicu ganda supaya dipastikan jalan di Android
    if (document.readyState === "complete" || document.readyState === "interactive") {
        init();
    } else {
        window.addEventListener('DOMContentLoaded', init);
        window.addEventListener('load', init);
    }

})();