Drawaria.online RPG Mode🗡️

Pixel companions with player selector, very optimized, monster enemies, and DOM-based image mode

// ==UserScript==
// @name         Drawaria.online RPG Mode🗡️
// @namespace    http://tampermonkey.net/
// @version      3.9
// @description  Pixel companions with player selector, very optimized, monster enemies, and DOM-based image mode
// @author       YouTubeDrawaria
// @match        https://drawaria.online/*
// @match        https://*.drawaria.online/*
// @grant        none
// @license      MIT
// @icon         https://www.google.com/s2/favicons?sz=64&domain=drawaria.online
// ==/UserScript==

(function() {
    'use strict';

    /* ----------  SISTEMA BASE OPTIMIZADO  ---------- */
    let drawariaSocket = null;
    let drawariaCanvas = null;
    let drawariaCtx = null;

    // Queue optimizado para comandos con batching inteligente
    const commandQueue = [];
    let batchProcessor = null;
    const BATCH_SIZE = 8;
    const BATCH_INTERVAL = 60;

    // Variables de control del sistema
    let systemActive = false;
    let selectedPlayerId = null;
    let selectedPlayerName = null;
    let renderMode = 'drawings'; // 'drawings' o 'images'
    let activeComponents = {
        hearts: true,
        sword: true,
        shield: true,
        monsters: true
    };

    // Función auxiliar para delays
    function sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    // Intercept WebSocket optimizado
    const originalWebSocketSend = WebSocket.prototype.send;
    WebSocket.prototype.send = function (...args) {
        if (!drawariaSocket && this.url && this.url.includes('drawaria')) {
            drawariaSocket = this;
            console.log('🔗 [PIXEL COMPANIONS] Socket capturado para Pixel Companions');
            startBatchProcessor();
        }
        return originalWebSocketSend.apply(this, args);
    };

    function startBatchProcessor() {
        if (batchProcessor) return;
        batchProcessor = setInterval(() => {
            if (!drawariaSocket || drawariaSocket.readyState !== WebSocket.OPEN || commandQueue.length === 0) {
                return;
            }
            const batch = commandQueue.splice(0, BATCH_SIZE);
            batch.forEach(cmd => {
                try {
                    drawariaSocket.send(cmd);
                } catch (e) {
                    console.warn('⚠️ [PIXEL COMPANIONS] Error enviando comando:', e);
                }
            });
        }, BATCH_INTERVAL);
    }

    /* ----------  SISTEMA DE IMÁGENES  ---------- */
    class ImageAssetManager {
        constructor() {
            this.loadedImages = new Map();
            this.imageUrls = {
                sword: 'https://i.ibb.co/KpD33DZV/espada.png',
                shield: 'https://i.ibb.co/XxbQXt5g/escudo.png',
                hearts: 'https://i.ibb.co/b5HT0JDQ/hearts-fw.png',
                monster: 'https://media.tenor.com/dPsOXgYjb30AAAAj/pixel-pixelart.gif'
            };
            this.loadingPromises = new Map();
            this.preloadImages();
        }

        preloadImages() {
            console.log('🖼️ [IMAGE MODE] Precargando imágenes...');

            Object.entries(this.imageUrls).forEach(([key, url]) => {
                this.loadImage(key, url);
            });
        }

        loadImage(key, url) {
            if (this.loadingPromises.has(key)) {
                return this.loadingPromises.get(key);
            }

            const promise = new Promise((resolve, reject) => {
                const img = new Image();
                img.crossOrigin = 'anonymous';

                img.onload = () => {
                    this.loadedImages.set(key, img);
                    console.log(`✅ [IMAGE MODE] Imagen cargada: ${key} (${img.width}x${img.height})`);
                    resolve(img);
                };

                img.onerror = (error) => {
                    console.error(`❌ [IMAGE MODE] Error cargando imagen ${key}:`, error);
                    reject(error);
                };

                img.src = url;
            });

            this.loadingPromises.set(key, promise);
            return promise;
        }

        getImage(key) {
            return this.loadedImages.get(key) || null;
        }

        isImageLoaded(key) {
            return this.loadedImages.has(key);
        }

        async waitForImage(key) {
            if (this.isImageLoaded(key)) {
                return this.getImage(key);
            }

            if (this.loadingPromises.has(key)) {
                return await this.loadingPromises.get(key);
            }

            return null;
        }

        getLoadedImagesCount() {
            return this.loadedImages.size;
        }
    }

    /* ----------  PATRONES PIXEL ART OPTIMIZADOS + MONSTER  ---------- */
    const pixelPatterns = {
        'heart': [
            " RR   RR ",
            "RRRR RRRR",
            "RRRRRRRRR",
            " RRRRRRR ",
            "  RRRRR  ",
            "   RRR   ",
            "    R    "
        ],
        'sword': [
            "    W    ",
            "    W    ",
            "    W    ",
            "    W    ",
            "    W    ",
            "    W    ",
            "    W    ",
            "  BBBBB  ",
            "    B    ",
            "    B    "
        ],
        'shield': [
            "  BBBBB  ",
            " BWWWWWB ",
            "BWWWWWWB",
            "BWWWWWWB",
            "BWWWWWWB",
            "BWWWWWWB",
            " BWWWWB ",
            "  BWWB  ",
            "   BB   "
        ],
        'monster': [
            "  RRRRR  ",
            " RRRRRRR ",
            "RRR G RRR",
            "RRR   RRR",
            "RRR G RRR",
            "RRRRRRRRR",
            "RRR RRR RR",
            "RR  R  RR",
            " R     R ",
            "RR     RR"
        ]
    };

    const specificColorSchemes = {
        heart: {
            classic: { 'R': '#FF0000', 'W': '#FFFFFF', 'B': '#000000', ' ': null },
            dark: { 'R': '#330000', 'W': '#333333', 'B': '#111111', ' ': null }
        },
        sword: {
            classic: { 'W': '#00FFFF', 'B': '#0000FF', ' ': null },
            dark: { 'W': '#006666', 'B': '#000066', ' ': null }
        },
        shield: {
            classic: { 'W': '#FFFF00', 'B': '#000000', ' ': null },
            dark: { 'W': '#666600', 'B': '#111111', ' ': null }
        },
        monster: {
            classic: { 'R': '#CC0000', 'G': '#00FF00', ' ': null },
            angry: { 'R': '#FF0000', 'G': '#FFFF00', ' ': null }
        }
    };

    /* ----------  SISTEMA DE MONSTRUOS  ---------- */
    class MonsterSystem {
        constructor(companionSystem) {
            this.monsters = [];
            this.companionSystem = companionSystem;
            this.spawnTimer = 0;
            this.SPAWN_INTERVAL = 8000;
            this.MONSTER_SPEED = 0.8;
            this.COLLISION_DISTANCE = 25;
            this.MAX_MONSTERS = 3;
            this.lastSpawnTime = 0;
        }

        getRandomSpawnPosition() {
            if (!drawariaCanvas) return null;

            const margin = 50;
            const sides = ['top', 'bottom', 'left', 'right'];
            const side = sides[Math.floor(Math.random() * sides.length)];

            let x, y;

            switch(side) {
                case 'top':
                    x = Math.random() * (drawariaCanvas.width - 2 * margin) + margin;
                    y = margin;
                    break;
                case 'bottom':
                    x = Math.random() * (drawariaCanvas.width - 2 * margin) + margin;
                    y = drawariaCanvas.height - margin;
                    break;
                case 'left':
                    x = margin;
                    y = Math.random() * (drawariaCanvas.height - 2 * margin) + margin;
                    break;
                case 'right':
                    x = drawariaCanvas.width - margin;
                    y = Math.random() * (drawariaCanvas.height - 2 * margin) + margin;
                    break;
            }

            return { x, y, side };
        }

        spawnMonster() {
            if (this.monsters.length >= this.MAX_MONSTERS) return;

            const position = this.getRandomSpawnPosition();
            if (!position) return;

            const monster = {
                id: `monster_${Date.now()}_${Math.random()}`,
                x: position.x,
                y: position.y,
                spawnSide: position.side,
                lastX: -9999,
                lastY: -9999,
                targetX: position.x,
                targetY: position.y,
                speed: this.MONSTER_SPEED,
                active: true,
                chaseMode: false,
                needsRedraw: true,
                colorScheme: 'classic',
                domElement: null // Para modo images
            };

            this.monsters.push(monster);

            // Crear elemento DOM si estamos en modo images
            if (renderMode === 'images') {
                this.createMonsterDOMElement(monster);
            }

            console.log(`👹 [MONSTERS] Nuevo monstruo spawneado en ${position.side}: ${monster.id}`);
        }

        createMonsterDOMElement(monster) {
            const element = document.createElement('div');
            element.style.cssText = `
                position: fixed;
                width: 120px;
                height: 120px;
                background-image: url('${this.companionSystem.imageAssetManager.imageUrls.monster}');
                background-size: contain;
                background-repeat: no-repeat;
                background-position: center;
                pointer-events: none;
                z-index: 1001;
                display: block;
                will-change: transform, left, top;
            `;

            monster.domElement = element;
            document.body.appendChild(element);
        }

        updateMonsters() {
            if (!activeComponents.monsters || !systemActive) return;

            const now = Date.now();

            if (now - this.lastSpawnTime > this.SPAWN_INTERVAL) {
                this.spawnMonster();
                this.lastSpawnTime = now;
            }

            this.monsters.forEach(monster => {
                this.updateSingleMonster(monster);
            });

            this.monsters = this.monsters.filter(monster => monster.active);
        }

        updateSingleMonster(monster) {
            if (!monster.active) return;

            const targetPlayers = this.companionSystem.getTargetPlayerCoords(selectedPlayerId);
            if (!targetPlayers || targetPlayers.length === 0) return;

            let closestPlayer = targetPlayers;
            let minDistance = Infinity;

            targetPlayers.forEach(player => {
                const distance = Math.sqrt(
                    Math.pow(player.x - monster.x, 2) +
                    Math.pow(player.y - monster.y, 2)
                );
                if (distance < minDistance) {
                    minDistance = distance;
                    closestPlayer = player;
                }
            });

            if (minDistance < this.COLLISION_DISTANCE) {
                console.log(`💥 [MONSTERS] ¡Monstruo ${monster.id} colisionó con jugador!`);

                // Limpiar según el modo
                if (renderMode === 'drawings' && monster.lastX !== -9999) {
                    this.companionSystem.drawOptimizedPixelArt('monster', 'classic', 4,
                        monster.lastX, monster.lastY, 0, true);
                } else if (renderMode === 'images' && monster.domElement) {
                    if (monster.domElement.parentNode) {
                        monster.domElement.parentNode.removeChild(monster.domElement);
                    }
                }

                monster.active = false;

                if (!this.companionSystem.animationState.damageSequence) {
                    this.companionSystem.executeDamageSequence();
                    this.companionSystem.executeSwordAttack();
                }

                return;
            }

            const deltaX = closestPlayer.x - monster.x;
            const deltaY = closestPlayer.y - monster.y;
            const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);

            if (distance > 0) {
                const moveX = (deltaX / distance) * monster.speed;
                const moveY = (deltaY / distance) * monster.speed;

                monster.targetX = monster.x + moveX;
                monster.targetY = monster.y + moveY;

                monster.x = monster.targetX;
                monster.y = monster.targetY;

                monster.chaseMode = distance < 150;
                monster.colorScheme = monster.chaseMode ? 'angry' : 'classic';
            }

            this.drawMonster(monster);
        }

        drawMonster(monster) {
            const newX = Math.round(monster.x);
            const newY = Math.round(monster.y);

            const deltaX = Math.abs(newX - monster.lastX);
            const deltaY = Math.abs(newY - monster.lastY);

            if (deltaX > 2 || deltaY > 2 || monster.needsRedraw) {
                if (renderMode === 'drawings') {
                    if (monster.lastX !== -9999) {
                        this.companionSystem.drawOptimizedPixelArt('monster', 'classic', 4,
                            monster.lastX, monster.lastY, 0, true);
                    }
                    this.companionSystem.drawOptimizedPixelArt('monster', monster.colorScheme, 4,
                        newX, newY, 0, false);
                } else if (renderMode === 'images' && monster.domElement) {
                    // Obtener canvas para posición relativa
                    const canvas = document.getElementById('canvas');
                    if (canvas) {
                        const canvasRect = canvas.getBoundingClientRect();
                        const finalX = canvasRect.left + newX - 30;
                        const finalY = canvasRect.top + newY - 30;

                        monster.domElement.style.left = `${finalX}px`;
                        monster.domElement.style.top = `${finalY}px`;
                    }
                }

                monster.lastX = newX;
                monster.lastY = newY;
                monster.needsRedraw = false;
            }
        }

        clearAllMonsters() {
            console.log('🧹 [MONSTERS] Limpiando todos los monstruos...');

            this.monsters.forEach(monster => {
                if (renderMode === 'drawings' && monster.lastX !== -9999) {
                    this.companionSystem.drawOptimizedPixelArt('monster', 'classic', 4,
                        monster.lastX, monster.lastY, 0, true);
                } else if (renderMode === 'images' && monster.domElement) {
                    if (monster.domElement.parentNode) {
                        monster.domElement.parentNode.removeChild(monster.domElement);
                    }
                }
            });

            this.monsters = [];
            this.lastSpawnTime = 0;
            console.log('🧹 [MONSTERS] Todos los monstruos eliminados');
        }

        getStats() {
            return {
                active: this.monsters.length,
                chasing: this.monsters.filter(m => m.chaseMode).length
            };
        }
    }

    /* ----------  GESTIÓN DE JUGADORES SIMPLIFICADA  ---------- */
    class PlayerManager {
        constructor() {
            this.validPlayers = [];
            this.updateInterval = null;
        }

        updatePlayerOptions() {
            const playerSelect = document.getElementById('player-selector');
            if (!playerSelect) return;

            const currentSelection = playerSelect.value;
            playerSelect.innerHTML = '';

            const playerElements = document.querySelectorAll('.spawnedavatar[data-playerid], .playerlist-row[data-playerid]');
            const validPlayers = [];

            playerElements.forEach(el => {
                const playerId = el.dataset.playerid;

                if (!playerId || playerId === '0' || el.dataset.self === 'true') {
                    return;
                }

                let playerName = '';

                const nicknameEl = el.querySelector('.nickname, .playerlist-name a, .player-name');
                if (nicknameEl) {
                    playerName = nicknameEl.textContent.trim();
                }

                if (!playerName) {
                    const parentRow = el.closest('.playerlist-row');
                    if (parentRow) {
                        const nameEl = parentRow.querySelector('.playerlist-name a, .player-name');
                        if (nameEl) {
                            playerName = nameEl.textContent.trim();
                        }
                    }
                }

                if (!playerName) {
                    playerName = `Player ${playerId}`;
                }

                if (!validPlayers.some(p => p.id === playerId)) {
                    validPlayers.push({
                        id: playerId,
                        name: playerName
                    });
                }
            });

            this.validPlayers = validPlayers;

            if (validPlayers.length === 0) {
                const opt = document.createElement('option');
                opt.value = '';
                opt.textContent = '❌ No players available';
                opt.disabled = true;
                playerSelect.appendChild(opt);

                const startBtn = document.getElementById('start-system-btn');
                if (startBtn) startBtn.disabled = true;
            } else {
                const allOpt = document.createElement('option');
                allOpt.value = 'all';
                allOpt.textContent = `🌍 All Players (${validPlayers.length})`;
                playerSelect.appendChild(allOpt);

                validPlayers.forEach(player => {
                    const opt = document.createElement('option');
                    opt.value = player.id;
                    opt.textContent = `🎯 ${player.name}`;
                    opt.dataset.playerName = player.name;
                    playerSelect.appendChild(opt);
                });

                const stillExists = currentSelection === 'all' || validPlayers.some(p => p.id === currentSelection);

                if (currentSelection && stillExists) {
                    playerSelect.value = currentSelection;
                    if (currentSelection === 'all') {
                        selectedPlayerName = 'Todos los jugadores';
                    } else {
                        const selectedPlayer = validPlayers.find(p => p.id === currentSelection);
                        selectedPlayerName = selectedPlayer ? selectedPlayer.name : null;
                    }
                } else if (currentSelection && !stillExists) {
                    playerSelect.value = 'all';
                    selectedPlayerId = 'all';
                    selectedPlayerName = 'Todos los jugadores';
                } else {
                    playerSelect.value = 'all';
                    selectedPlayerId = 'all';
                    selectedPlayerName = 'Todos los jugadores';
                }

                const startBtn = document.getElementById('start-system-btn');
                if (startBtn) startBtn.disabled = false;
            }

            selectedPlayerId = playerSelect.value;
        }

        startAutoUpdate() {
            if (this.updateInterval) return;

            this.updateInterval = setInterval(() => {
                this.updatePlayerOptions();
            }, 2000);

            this.updatePlayerOptions();
        }

        stopAutoUpdate() {
            if (this.updateInterval) {
                clearInterval(this.updateInterval);
                this.updateInterval = null;
            }
        }
    }

    /* ----------  SISTEMA DE DIBUJO OPTIMIZADO  ---------- */
    function enqueueDrawCommand(x1, y1, x2, y2, color, thickness) {
        if (!drawariaCanvas || !drawariaSocket || !systemActive) return;

        const normX1 = (x1 / drawariaCanvas.width).toFixed(4);
        const normY1 = (y1 / drawariaCanvas.height).toFixed(4);
        const normX2 = (x2 / drawariaCanvas.width).toFixed(4);
        const normY2 = (y2 / drawariaCanvas.height).toFixed(4);

        const cmd = `42["drawcmd",0,[${normX1},${normY1},${normX2},${normY2},false,${-Math.abs(thickness)},"${color}",0,0,{}]]`;
        commandQueue.push(cmd);

        if (drawariaCtx) {
            drawariaCtx.strokeStyle = color;
            drawariaCtx.lineWidth = thickness;
            drawariaCtx.lineCap = 'round';
            drawariaCtx.beginPath();
            drawariaCtx.moveTo(x1, y1);
            drawariaCtx.lineTo(x2, y2);
            drawariaCtx.stroke();
        }
    }

    /* ----------  SISTEMA PRINCIPAL MEJORADO  ---------- */
    class EnhancedPixelCompanionSystem {
        constructor() {
            this.initialized = false;
            this.lives = 3;
            this.lastPlayerPositions = new Map();
            this.playerManager = new PlayerManager();
            this.imageAssetManager = new ImageAssetManager();
            this.monsterSystem = new MonsterSystem(this);

            // Elementos DOM para modo images
            this.imageElements = null;

            this.MOVEMENT_THRESHOLD = 4;
            this.UPDATE_INTERVAL = 80;
            this.lastUpdateTime = 0;
            this.COLLISION_COOLDOWN = 3000;
            this.lastCollisionTime = 0;

            this.companionStates = new Map();
            this.animationState = {
                damageSequence: false,
                swordAttack: false,
                shieldDefend: false
            };

            this.cachedPatterns = this.preOptimizePatterns();
            this.init();
        }

        init() {
            const checkGameReady = () => {
                const gameCanvas = document.getElementById('canvas');
                if (gameCanvas) {
                    this.canvasElement = gameCanvas;
                    drawariaCanvas = gameCanvas;
                    this.canvasContext = gameCanvas.getContext('2d');
                    drawariaCtx = gameCanvas.getContext('2d');

                    this.initialized = true;
                    this.createControlInterface();
                    console.log('✅ [PIXEL COMPANIONS] Sistema inicializado correctamente');
                } else {
                    setTimeout(checkGameReady, 100);
                }
            };
            checkGameReady();
        }

        preOptimizePatterns() {
            const optimized = {};
            Object.keys(pixelPatterns).forEach(patternName => {
                optimized[patternName] = this.optimizePatternToLines(pixelPatterns[patternName]);
            });
            return optimized;
        }

        optimizePatternToLines(pattern) {
            const lines = [];
            for (let row = 0; row < pattern.length; row++) {
                let currentLine = null;
                for (let col = 0; col < pattern[row].length; col++) {
                    const char = pattern[row][col];
                    if (char !== ' ') {
                        if (!currentLine || currentLine.char !== char) {
                            if (currentLine) lines.push(currentLine);
                            currentLine = { char, startCol: col, endCol: col, row };
                        } else {
                            currentLine.endCol = col;
                        }
                    } else {
                        if (currentLine) {
                            lines.push(currentLine);
                            currentLine = null;
                        }
                    }
                }
                if (currentLine) lines.push(currentLine);
            }
            return lines;
        }

        createImageElements() {
            console.log('🖼️ [DOM SIMPLE] Creando elementos DOM para companions...');

            // Limpiar elementos previos
            if (this.imageElements) {
                Object.values(this.imageElements).forEach(element => {
                    if (element && element.parentNode) {
                        element.parentNode.removeChild(element);
                    }
                });
            }

            this.imageElements = {};

            const configs = {
                hearts: { width: '80px', height: '30px', url: this.imageAssetManager.imageUrls.hearts },
                sword: { width: '50px', height: '50px', url: this.imageAssetManager.imageUrls.sword },
                shield: { width: '50px', height: '50px', url: this.imageAssetManager.imageUrls.shield }
            };

            // Usar exactamente el mismo método que los monstruos
            Object.entries(configs).forEach(([type, config]) => {
                const element = document.createElement('div');
                element.id = `companion-${type}`;

                element.style.cssText = `
                    position: fixed;
                    width: ${config.width};
                    height: ${config.height};
                    background-image: url('${config.url}');
                    background-size: contain;
                    background-repeat: no-repeat;
                    background-position: center;
                    pointer-events: none;
                    z-index: 1001;
                    display: block;
                    will-change: transform, left, top;
                    left: 200px;
                    top: 200px;
                `;

                this.imageElements[type] = element;
                document.body.appendChild(element);

                console.log(`✅ [DOM SIMPLE] ${type} creado exitosamente`);
            });
        }

        getTargetPlayerCoords(playerId = null) {
            if (!playerId || playerId === 'all') {
                const allPlayers = [];
                const avatars = document.querySelectorAll('.spawnedavatar[data-playerid]:not([data-playerid="0"]):not(.self)');

                avatars.forEach(avatar => {
                    if (!this.canvasElement) return;

                    const cRect = this.canvasElement.getBoundingClientRect();
                    const aRect = avatar.getBoundingClientRect();

                    if (aRect.width > 0 && aRect.height > 0) {
                        allPlayers.push({
                            id: avatar.dataset.playerid || `player_${allPlayers.length}`,
                            x: Math.round((aRect.left - cRect.left) + (aRect.width / 2)),
                            y: Math.round((aRect.top - cRect.top) + (aRect.height / 2)),
                            width: aRect.width,
                            height: aRect.height
                        });
                    }
                });

                return allPlayers.length > 0 ? allPlayers : null;
            }

            const targetPlayers = [];
            const avatars = document.querySelectorAll(`.spawnedavatar[data-playerid="${playerId}"]`);

            avatars.forEach(avatar => {
                if (!this.canvasElement) return;

                const cRect = this.canvasElement.getBoundingClientRect();
                const aRect = avatar.getBoundingClientRect();

                if (aRect.width > 0 && aRect.height > 0) {
                    targetPlayers.push({
                        id: playerId,
                        x: Math.round((aRect.left - cRect.left) + (aRect.width / 2)),
                        y: Math.round((aRect.top - cRect.top) + (aRect.height / 2)),
                        width: aRect.width,
                        height: aRect.height
                    });
                }
            });

            return targetPlayers.length > 0 ? targetPlayers : null;
        }

        detectCollisionWithOtherPlayers() {
            if (selectedPlayerId === 'all') return false;

            const myPos = this.getTargetPlayerCoords(selectedPlayerId);
            if (!myPos || myPos.length === 0) return false;

            const now = Date.now();
            if (now - this.lastCollisionTime < this.COLLISION_COOLDOWN) {
                return false;
            }

            const otherPlayers = document.querySelectorAll('.spawnedavatar.spawnedavatar-otherplayer');
            const collisionDistance = 45;

            for (let otherPlayer of otherPlayers) {
                if (!this.canvasElement) continue;

                const cRect = this.canvasElement.getBoundingClientRect();
                const otherRect = otherPlayer.getBoundingClientRect();

                const otherX = (otherRect.left - cRect.left) + (otherRect.width / 2);
                const otherY = (otherRect.top - cRect.top) + (otherRect.height / 2);

                const distance = Math.sqrt(
                    Math.pow(myPos.x - otherX, 2) + Math.pow(myPos.y - otherY, 2)
                );

                if (distance < collisionDistance) {
                    this.lastCollisionTime = now;
                    return true;
                }
            }
            return false;
        }

        drawOptimizedPixelArt(patternName, colorScheme, pixelSize, centerX, centerY, rotation = 0, eraseMode = false) {
            const lines = this.cachedPatterns[patternName];
            if (!lines) return;

            let colors;
            if (eraseMode) {
                colors = Object.keys(specificColorSchemes[patternName][colorScheme] || {})
                    .reduce((acc, key) => {
                        acc[key] = key === ' ' ? null : '#FFFFFF';
                        return acc;
                    }, {});
            } else {
                colors = specificColorSchemes[patternName] ?
                         specificColorSchemes[patternName][colorScheme] :
                         specificColorSchemes.heart[colorScheme];
            }

            const patternCenter = Math.floor(pixelPatterns[patternName].length / 2);

            lines.forEach(line => {
                if (!colors[line.char]) return;

                const startX = centerX + (line.startCol - patternCenter) * pixelSize;
                const endX = centerX + (line.endCol - patternCenter) * pixelSize + pixelSize;
                const y = centerY + (line.row - patternCenter) * pixelSize;

                enqueueDrawCommand(startX, y, endX, y, colors[line.char], pixelSize * 1.2);
            });
        }

        async executeDamageSequence() {
            if (this.animationState.damageSequence || this.lives <= 0) return;

            this.animationState.damageSequence = true;
            console.log(`💔 [PIXEL COMPANIONS] ¡Daño recibido! Vidas restantes: ${this.lives - 1}`);

            this.lives--;

            if (this.lives <= 0) {
                console.log('💀 [PIXEL COMPANIONS] ¡Sin vidas! Reiniciando sistema...');
                await new Promise(r => setTimeout(r, 2000));
                this.lives = 3;
                console.log('🔄 [PIXEL COMPANIONS] Sistema reiniciado con 3 vidas');
            }

            this.animationState.damageSequence = false;
        }

        async executeSwordAttack() {
            if (this.animationState.swordAttack) return;

            this.animationState.swordAttack = true;
            console.log('⚔️ [PIXEL COMPANIONS] ¡Ejecutando ataque con espada!');

            await new Promise(r => setTimeout(r, 1000));

            this.animationState.swordAttack = false;
        }

        async executeShieldDefense() {
            if (this.animationState.shieldDefend) return;

            this.animationState.shieldDefend = true;
            console.log('🛡️ [PIXEL COMPANIONS] ¡Activando defensa con escudo!');

            await new Promise(r => setTimeout(r, 800));

            this.animationState.shieldDefend = false;
        }

        async cleanCanvas() {
            if (!drawariaCanvas) return;

            console.log('🧹 [PIXEL COMPANIONS] Limpiando canvas...');

            const canvasWidth = drawariaCanvas.width;
            const canvasHeight = drawariaCanvas.height;

            for (let y = 0; y < canvasHeight; y += 100) {
                for (let x = 0; x < canvasWidth; x += 100) {
                    const width = Math.min(100, canvasWidth - x);
                    const height = Math.min(100, canvasHeight - y);
                    enqueueDrawCommand(x, y, x + width, y + height, '#FFFFFF', Math.max(width, height));
                    await sleep(5);
                }
            }

            if (drawariaCtx) {
                drawariaCtx.clearRect(0, 0, canvasWidth, canvasHeight);
            }

            console.log('🧹 [PIXEL COMPANIONS] Canvas limpiado completamente!');
        }

        updateCompanions() {
            if (!systemActive || !this.initialized) return;

            const now = Date.now();
            if (now - this.lastUpdateTime < this.UPDATE_INTERVAL) return;

            const targetPlayers = this.getTargetPlayerCoords(selectedPlayerId);
            if (!targetPlayers) return;

            this.monsterSystem.updateMonsters();

            if (selectedPlayerId !== 'all') {
                const collision = this.detectCollisionWithOtherPlayers();
                if (collision && !this.animationState.damageSequence) {
                    this.executeDamageSequence();
                    this.executeSwordAttack();
                    this.executeShieldDefense();
                }
            }

            targetPlayers.forEach(player => {
                this.updateCompanionForPlayer(player);
            });

            this.lastUpdateTime = now;
        }

        updateCompanionForPlayer(player) {
            const playerId = player.id;

            if (!this.companionStates.has(playerId)) {
                this.companionStates.set(playerId, {
                    hearts: Array(3).fill().map(() => ({ active: true, lastX: -9999, lastY: -9999, needsRedraw: true })),
                    sword: { rotation: 0, lastX: -9999, lastY: -9999, needsRedraw: true },
                    shield: { rotation: 0, lastX: -9999, lastY: -9999, needsRedraw: true }
                });
            }

            const state = this.companionStates.get(playerId);
            const lastPos = this.lastPlayerPositions.get(playerId) || { x: 0, y: 0 };

            const deltaX = Math.abs(player.x - lastPos.x);
            const deltaY = Math.abs(player.y - lastPos.y);
            const significantMovement = deltaX > this.MOVEMENT_THRESHOLD || deltaY > this.MOVEMENT_THRESHOLD;

            // Renderizado según el modo
            if (renderMode === 'drawings') {
                this.updateCompanionDrawings(player, state, significantMovement);
            } else if (renderMode === 'images') {
                this.updateCompanionImages(player, state, significantMovement);
            }

            if (significantMovement) {
                this.lastPlayerPositions.set(playerId, { x: player.x, y: player.y });
            }
        }

        updateCompanionDrawings(player, state, significantMovement) {
            if (activeComponents.hearts) {
                for (let i = 0; i < 3; i++) {
                    const heartX = player.x + (i - 1) * 32;
                    const heartY = player.y - player.height / 2 - 25;

                    if (significantMovement || state.hearts[i].needsRedraw) {
                        if (state.hearts[i].lastX !== -9999) {
                            this.drawOptimizedPixelArt('heart', 'classic', 3,
                                state.hearts[i].lastX, state.hearts[i].lastY, 0, true);
                        }

                        const scheme = state.hearts[i].active ? 'classic' : 'dark';
                        this.drawOptimizedPixelArt('heart', scheme, 3, heartX, heartY, 0, false);

                        state.hearts[i].lastX = heartX;
                        state.hearts[i].lastY = heartY;
                        state.hearts[i].needsRedraw = false;
                    }
                }
            }

            if (activeComponents.sword) {
                const swordX = player.x + player.width / 2 + 30;
                const swordY = player.y;

                if (significantMovement || state.sword.needsRedraw) {
                    if (state.sword.lastX !== -9999) {
                        this.drawOptimizedPixelArt('sword', 'classic', 5,
                            state.sword.lastX, state.sword.lastY, 0, true);
                    }

                    this.drawOptimizedPixelArt('sword', 'classic', 5, swordX, swordY, state.sword.rotation, false);

                    state.sword.lastX = swordX;
                    state.sword.lastY = swordY;
                    state.sword.needsRedraw = false;
                }
            }

            if (activeComponents.shield) {
                const shieldX = player.x - player.width / 2 - 30;
                const shieldY = player.y;

                if (significantMovement || state.shield.needsRedraw) {
                    if (state.shield.lastX !== -9999) {
                        this.drawOptimizedPixelArt('shield', 'classic', 5,
                            state.shield.lastX, state.shield.lastY, 0, true);
                    }

                    this.drawOptimizedPixelArt('shield', 'classic', 5, shieldX, shieldY, 0, false);

                    state.shield.lastX = shieldX;
                    state.shield.lastY = shieldY;
                    state.shield.needsRedraw = false;
                }
            }
        }

        // ✅ FUNCIÓN COMPLETA: updateCompanionImages
        updateCompanionImages(player, state, significantMovement) {
            // Crear elementos si no existen
            if (!this.imageElements) {
                this.createImageElements();
                return;
            }

            // Obtener canvas para posición relativa (igual que los monstruos)
            const canvas = document.getElementById('canvas');
            if (!canvas) return;

            const canvasRect = canvas.getBoundingClientRect();

            // ✅ ACTUALIZAR HEARTS (usando método exacto de monstruos)
            if (activeComponents.hearts && this.imageElements.hearts) {
                const heartsElement = this.imageElements.hearts;
                // Posicionar arriba del jugador, centrado
                const heartsX = canvasRect.left + player.x - 40; // Centrar (80px width / 2)
                const heartsY = canvasRect.top + player.y - player.height / 2 - 40;

                heartsElement.style.left = `${heartsX}px`;
                heartsElement.style.top = `${heartsY}px`;
                heartsElement.style.display = 'block';
            } else if (this.imageElements?.hearts) {
                this.imageElements.hearts.style.display = 'none';
            }

            // ✅ ACTUALIZAR SWORD (usando método exacto de monstruos)
            if (activeComponents.sword && this.imageElements.sword) {
                const swordElement = this.imageElements.sword;
                // Posicionar a la derecha del jugador
                const swordX = canvasRect.left + player.x + player.width / 2 + 30 - 25; // 30 offset - 25 center
                const swordY = canvasRect.top + player.y - 25; // Centrar verticalmente

                swordElement.style.left = `${swordX}px`;
                swordElement.style.top = `${swordY}px`;
                swordElement.style.display = 'block';
            } else if (this.imageElements?.sword) {
                this.imageElements.sword.style.display = 'none';
            }

            // ✅ ACTUALIZAR SHIELD (usando método exacto de monstruos)
            if (activeComponents.shield && this.imageElements.shield) {
                const shieldElement = this.imageElements.shield;
                // Posicionar a la izquierda del jugador
                const shieldX = canvasRect.left + player.x - player.width / 2 - 30 - 25; // 30 offset - 25 center
                const shieldY = canvasRect.top + player.y - 25; // Centrar verticalmente

                shieldElement.style.left = `${shieldX}px`;
                shieldElement.style.top = `${shieldY}px`;
                shieldElement.style.display = 'block';
            } else if (this.imageElements?.shield) {
                this.imageElements.shield.style.display = 'none';
            }
        }

        // ✅ FUNCIÓN COMPLETA: debugCompanionSystem
        debugCompanionSystem() {
            console.log('🐛 [SYSTEM DEBUG] === ESTADO DEL SISTEMA ===');
            console.log('System active:', systemActive);
            console.log('Render mode:', renderMode);
            console.log('Selected player:', selectedPlayerId);
            console.log('Active components:', activeComponents);
            console.log('Image elements exists:', !!this.imageElements);
            console.log('Canvas element:', !!this.canvasElement);

            // Debug de jugadores target
            const targetPlayers = this.getTargetPlayerCoords(selectedPlayerId);
            console.log('Target players found:', targetPlayers?.length || 0);
            if (targetPlayers && targetPlayers.length > 0) {
                console.log('First player coords:', targetPlayers);
            }

            if (this.imageElements) {
                Object.keys(this.imageElements).forEach(type => {
                    const element = this.imageElements[type];
                    console.log(`${type}:`, {
                        exists: !!element,
                        display: element?.style.display,
                        left: element?.style.left,
                        top: element?.style.top,
                        inDOM: document.body.contains(element)
                    });
                });
            }

            console.log('🐛 [SYSTEM DEBUG] === FIN DEBUG ===');
        }

        // ✅ FUNCIÓN COMPLETA: verifyElementsInDOM
        verifyElementsInDOM() {
            console.log('🔍 [DOM VERIFY] === VERIFICANDO ELEMENTOS ===');

            if (!this.imageElements) {
                console.error('❌ [DOM VERIFY] imageElements no existe');
                return;
            }

            Object.keys(this.imageElements).forEach(type => {
                const element = document.getElementById(`companion-${type}`);
                const inMemory = this.imageElements[type];
                const inDOM = document.body.contains(inMemory);

                console.log(`${type}:`, {
                    'En DOM por ID': !!element,
                    'En memoria': !!inMemory,
                    'Conectado al DOM': inDOM,
                    'Style ready': !!(inMemory && inMemory.style),
                    'Background set': !!(inMemory && inMemory.style.backgroundImage),
                                        'Position set': !!(inMemory && inMemory.style.left && inMemory.style.top)
                });

                if (inMemory && inDOM) {
                    const rect = inMemory.getBoundingClientRect();
                    console.log(`${type} rect:`, rect);
                }
            });

            console.log('🔍 [DOM VERIFY] === FIN VERIFICACIÓN ===');
        }

        startSystem() {
            if (!this.initialized) {
                console.log('❌ [PIXEL COMPANIONS] Sistema no inicializado. Esperando canvas...');
                return;
            }

            if (!selectedPlayerId) {
                console.log('❌ [PIXEL COMPANIONS] No hay jugador seleccionado');
                return;
            }

            systemActive = true;
            this.playerManager.startAutoUpdate();

            this.companions = {
                hearts: Array(3).fill().map(() => ({ active: true, lastX: -9999, lastY: -9999, needsRedraw: true })),
                sword: { rotation: 0, lastX: -9999, lastY: -9999, needsRedraw: true },
                shield: { rotation: 0, lastX: -9999, lastY: -9999, needsRedraw: true }
            };

            // Crear elementos DOM para modo imágenes
            if (renderMode === 'images') {
                this.createImageElements();
            }

            const updateLoop = () => {
                if (systemActive && this.initialized) {
                    this.updateCompanions();
                    this.updateStatusDisplay();
                }
                if (systemActive) {
                    requestAnimationFrame(updateLoop);
                }
            };
            updateLoop();

            console.log('🎮 [PIXEL COMPANIONS] Sistema iniciado exitosamente');
            console.log(`🎯 [PIXEL COMPANIONS] Target: ${selectedPlayerName || 'Jugador desconocido'}`);
            console.log(`📱 [PIXEL COMPANIONS] Modo de renderizado: ${renderMode}`);
            console.log(`⚙️ [PIXEL COMPANIONS] Componentes activos: ${Object.entries(activeComponents).filter(([,v]) => v).map(([k]) => k).join(', ')}`);

            if (renderMode === 'images') {
                console.log(`🖼️ [IMAGE MODE] Imágenes cargadas: ${this.imageAssetManager.getLoadedImagesCount()}/4`);
                console.log(`🖼️ [IMAGE MODE] Usando elementos DOM como monstruos - Sin rastros!`);
            }
        }

        async stopSystem() {
            console.log('⏹️ [PIXEL COMPANIONS] Deteniendo sistema...');

            systemActive = false;
            this.playerManager.stopAutoUpdate();

            this.monsterSystem.clearAllMonsters();

            // Limpiar elementos DOM individuales (no container)
            if (this.imageElements) {
                Object.values(this.imageElements).forEach(element => {
                    if (element && element.parentNode) {
                        element.parentNode.removeChild(element);
                    }
                });
                this.imageElements = null;
                console.log('🖼️ [IMAGE MODE] Elementos DOM eliminados');
            }

            // Solo limpiar canvas en modo drawings
            if (renderMode === 'drawings') {
                await this.cleanCanvas();
            }

            commandQueue.length = 0;
            this.companionStates.clear();
            this.lastPlayerPositions.clear();

            this.animationState = {
                damageSequence: false,
                swordAttack: false,
                shieldDefend: false
            };

            this.lives = 3;

            console.log('⏹️ [PIXEL COMPANIONS] Sistema detenido completamente');
        }

        createControlInterface() {
            const existingPanel = document.getElementById('pixel-companions-control');
            if (existingPanel) existingPanel.remove();

            const controlPanel = document.createElement('div');
            controlPanel.id = 'pixel-companions-control';
            controlPanel.style.cssText = `
                position: fixed; top: 20px; right: 20px; z-index: 9999;
                background: linear-gradient(135deg, #1a1a2e, #16213e);
                color: white; padding: 20px; border-radius: 15px;
                font-family: 'Segoe UI', Arial, sans-serif;
                border: 2px solid #4fd1c7; min-width: 320px;
                box-shadow: 0 0 30px rgba(79,209,199,0.4);
                font-size: 14px;
            `;

            controlPanel.innerHTML = `
                <div style="text-align: center; font-weight: bold; color: #4fd1c7; margin-bottom: 15px;">
                    🎮 DRAWARIA RPG Mode🗡️
                </div>

                <div style="margin-bottom: 15px;">
                    <label style="display: block; margin-bottom: 8px; color: #FFD700;">🎨 Render Mode:</label>
                    <div style="display: flex; gap: 10px;">
                        <label style="display: flex; align-items: center; gap: 5px; cursor: pointer;">
                            <input type="radio" name="render-mode" value="drawings" checked style="accent-color: #4fd1c7;">
                            <span>🖌️ Drawings</span>
                        </label>
                        <label style="display: flex; align-items: center; gap: 5px; cursor: pointer;">
                            <input type="radio" name="render-mode" value="images" style="accent-color: #4fd1c7;">
                            <span>🖼️ Images (DOM)</span>
                        </label>
                    </div>
                </div>

                <div style="margin-bottom: 15px;">
                    <label style="display: block; margin-bottom: 5px; color: #FFD700;">🎯 Target Player:</label>
                    <select id="player-selector" style="width: 100%; padding: 8px; border-radius: 5px; background: #2d2d2d; color: white; border: 1px solid #4fd1c7;">
                        <option value="">🔍 Scanning players...</option>
                    </select>
                </div>

                <div style="margin-bottom: 15px;">
                    <label style="display: block; margin-bottom: 8px; color: #FFD700;">⚙️ Active Components:</label>
                    <div style="display: flex; gap: 10px; flex-wrap: wrap;">
                        <label style="display: flex; align-items: center; gap: 5px; cursor: pointer;">
                            <input type="checkbox" id="hearts-toggle" checked style="accent-color: #FF0000;">
                            <span>💖 Hearts</span>
                        </label>
                        <label style="display: flex; align-items: center; gap: 5px; cursor: pointer;">
                            <input type="checkbox" id="sword-toggle" checked style="accent-color: #00FFFF;">
                            <span>⚔️ Sword</span>
                        </label>
                        <label style="display: flex; align-items: center; gap: 5px; cursor: pointer;">
                            <input type="checkbox" id="shield-toggle" checked style="accent-color: #FFFF00;">
                            <span>🛡️ Shield</span>
                        </label>
                        <label style="display: flex; align-items: center; gap: 5px; cursor: pointer;">
                            <input type="checkbox" id="monsters-toggle" checked style="accent-color: #CC0000;">
                            <span>👹 Monsters</span>
                        </label>
                    </div>
                </div>

                <div style="display: flex; gap: 10px; margin-bottom: 15px;">
                    <button id="start-system-btn" style="flex: 1; padding: 10px; background: linear-gradient(135deg, #00FF00, #32CD32); color: white; border: none; border-radius: 8px; font-weight: bold; cursor: pointer;" disabled>
                        ▶️ START
                    </button>
                    <button id="stop-system-btn" style="flex: 1; padding: 10px; background: linear-gradient(135deg, #FF4444, #CC0000); color: white; border: none; border-radius: 8px; font-weight: bold; cursor: pointer;" disabled>
                        ⏹️ STOP
                    </button>
                </div>

                <div style="display: flex; gap: 10px; margin-bottom: 15px;">
                    <button id="debug-system-btn" style="flex: 1; padding: 8px; background: linear-gradient(135deg, #FF8C00, #FF6347); color: white; border: none; border-radius: 6px; font-size: 12px; cursor: pointer;">
                        🐛 DEBUG
                    </button>
                    <button id="verify-dom-btn" style="flex: 1; padding: 8px; background: linear-gradient(135deg, #9370DB, #8A2BE2); color: white; border: none; border-radius: 6px; font-size: 12px; cursor: pointer;">
                        🔍 VERIFY DOM
                    </button>
                </div>

                <div id="system-status" style="text-align: center; padding: 10px; background: #333; border-radius: 5px; margin-bottom: 10px;">
                    ⏸️ System: <span style="color: #FF6B6B;">STOPPED</span> | Ready to start
                </div>

                <div id="companion-stats" style="font-size: 12px; color: #888;">
                    📊 Players: 0 | Images: 0/4 | Monsters: 0/0 chasing
                </div>

                <div style="font-size: 11px; color: #666; margin-top: 10px; text-align: center;">
                    🖼️ DOM Mode: Images without trails using monster method!
                </div>
            `;

            document.body.appendChild(controlPanel);
            this.setupEventListeners();
        }

        setupEventListeners() {
            const playerSelect = document.getElementById('player-selector');
            const heartsToggle = document.getElementById('hearts-toggle');
            const swordToggle = document.getElementById('sword-toggle');
            const shieldToggle = document.getElementById('shield-toggle');
            const monstersToggle = document.getElementById('monsters-toggle');
            const startBtn = document.getElementById('start-system-btn');
            const stopBtn = document.getElementById('stop-system-btn');
            const debugBtn = document.getElementById('debug-system-btn');
            const verifyBtn = document.getElementById('verify-dom-btn');
            const renderModeRadios = document.querySelectorAll('input[name="render-mode"]');

            // Guardar referencia a 'this'
            const self = this;

            // Event listener para modo de renderizado
            renderModeRadios.forEach(radio => {
                radio.addEventListener('change', (e) => {
                    const oldMode = renderMode;
                    renderMode = e.target.value;
                    console.log(`🎨 [PIXEL COMPANIONS] Modo de renderizado cambiado a: ${renderMode}`);

                    if (renderMode === 'images') {
                        console.log(`🖼️ [IMAGE MODE] Usando elementos DOM como monstruos - Sin rastros!`);
                    }

                    // Si el sistema está activo y cambiamos el modo, reiniciar companions
                    if (systemActive && oldMode !== renderMode) {
                        console.log('🔄 [PIXEL COMPANIONS] Reiniciando por cambio de modo...');

                        if (oldMode === 'images' && self.imageElements) {
                            Object.values(self.imageElements).forEach(element => {
                                if (element && element.parentNode) {
                                    element.parentNode.removeChild(element);
                                }
                            });
                            self.imageElements = null;
                        }

                        if (self.companionStates) {
                            self.companionStates.forEach(state => {
                                state.hearts.forEach(heart => heart.needsRedraw = true);
                                state.sword.needsRedraw = true;
                                state.shield.needsRedraw = true;
                            });
                        }
                    }
                });
            });

            // Event listeners para botones de debug
            debugBtn?.addEventListener('click', () => {
                self.debugCompanionSystem();
            });

            verifyBtn?.addEventListener('click', () => {
                self.verifyElementsInDOM();
            });

            playerSelect?.addEventListener('change', (e) => {
                selectedPlayerId = e.target.value;

                if (selectedPlayerId === 'all') {
                    selectedPlayerName = 'Todos los jugadores';
                } else if (selectedPlayerId) {
                    const selectedOption = e.target.options[e.target.selectedIndex];
                    selectedPlayerName = selectedOption.dataset.playerName ||
                                       selectedOption.textContent.replace('🎯 ', '') ||
                                       `Jugador ${selectedPlayerId}`;
                } else {
                    selectedPlayerName = null;
                }

                if (startBtn) startBtn.disabled = !selectedPlayerId;
            });

            heartsToggle?.addEventListener('change', (e) => {
                activeComponents.hearts = e.target.checked;
                console.log(`💖 [PIXEL COMPANIONS] Corazones: ${e.target.checked ? 'Activados' : 'Desactivados'}`);
            });

            swordToggle?.addEventListener('change', (e) => {
                activeComponents.sword = e.target.checked;
                console.log(`⚔️ [PIXEL COMPANIONS] Espada: ${e.target.checked ? 'Activada' : 'Desactivada'}`);
            });

            shieldToggle?.addEventListener('change', (e) => {
                activeComponents.shield = e.target.checked;
                console.log(`🛡️ [PIXEL COMPANIONS] Escudo: ${e.target.checked ? 'Activado' : 'Desactivado'}`);
            });

            monstersToggle?.addEventListener('change', (e) => {
                activeComponents.monsters = e.target.checked;
                console.log(`👹 [MONSTERS] Monstruos: ${e.target.checked ? 'Activados' : 'Desactivados'}`);

                if (!e.target.checked && self.monsterSystem) {
                    self.monsterSystem.clearAllMonsters();
                }
            });

            startBtn?.addEventListener('click', () => {
                if (!selectedPlayerId) {
                    console.log('🚫 [PIXEL COMPANIONS] Error: No hay jugador seleccionado');
                    return;
                }

                self.startSystem();
                startBtn.disabled = true;
                if (stopBtn) stopBtn.disabled = false;
            });

            stopBtn?.addEventListener('click', async () => {
                stopBtn.disabled = true;
                stopBtn.textContent = '🧹 CLEANING...';

                await self.stopSystem();

                stopBtn.textContent = '⏹️ STOP';
                if (startBtn) startBtn.disabled = false;
                stopBtn.disabled = true;
            });

            setTimeout(() => {
                self.playerManager.startAutoUpdate();
            }, 1000);
        }

        updateStatusDisplay() {
            const statusDiv = document.getElementById('system-status');
            const statsDiv = document.getElementById('companion-stats');

            if (statusDiv) {
                const status = systemActive ?
                    `▶️ System: <span style="color: #00FF00;">ACTIVE</span> | Mode: ${renderMode} | Target: ${selectedPlayerName || 'Unknown'}` :
                    `⏸️ System: <span style="color: #FF6B6B;">STOPPED</span> | Mode: ${renderMode} | Ready to start`;
                statusDiv.innerHTML = status;
            }

            if (statsDiv) {
                const monsterStats = this.monsterSystem.getStats();
                const imagesLoaded = this.imageAssetManager.getLoadedImagesCount();

                statsDiv.textContent = `📊 Players: ${this.playerManager.validPlayers.length} | Images: ${imagesLoaded}/4 | Monsters: ${monsterStats.active}/${monsterStats.chasing} chasing`;
            }
        }
    }

    /* ----------  INICIALIZACIÓN  ---------- */
    let enhancedCompanionSystem = null;

    const initEnhancedSystem = () => {
        if (!enhancedCompanionSystem) {
            console.log('🚀 [PIXEL COMPANIONS] Inicializando Enhanced Pixel Companions System v3.9 DOM MODE...');
            enhancedCompanionSystem = new EnhancedPixelCompanionSystem();

            setTimeout(() => {
                console.log('');
                console.log('✅ [PIXEL COMPANIONS] ENHANCED PIXEL COMPANIONS v3.9 LOADED! (DOM MODE)');
                console.log('🖼️ [DOM MODE] NEW: Images using DOM elements like monsters!');
                console.log('🚫 [DOM MODE] NO TRAILS: Elements move cleanly without canvas interference');
                console.log('📱 [DOM MODE] position: fixed + background-image like monster system');
                console.log('🎨 [RENDER MODE] Toggle: Drawings (canvas) vs Images (DOM)');
                console.log('👹 [MONSTERS] Compatible with both render modes');
                console.log('🧹 [CLEANUP] Smart cleanup: Canvas for drawings, DOM removal for images');
                console.log('⚡ [PERFORMANCE] Smooth following without rastros/estelas');
                console.log('🐛 [DEBUG] Added debug buttons for troubleshooting');
                console.log('');
                console.log('🖼️ [IMAGES] Hearts, Sword, Shield, Monster GIF as DOM elements');
                console.log('🎯 [USAGE] Select "Images (DOM)" mode for clean sprite following!');
                console.log('🔧 [MONSTER METHOD] Using exact same technique as monsters for companions');
                console.log('');
            }, 1000);
        }
    };

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initEnhancedSystem);
    } else {
        setTimeout(initEnhancedSystem, 500);
    }

    setTimeout(initEnhancedSystem, 2000);

    console.log('🌟 [PIXEL COMPANIONS] Enhanced Drawaria Pixel Companions v3.9 DOM MODE loaded! 🌟');
    console.log('🖼️ [DOM MODE] Images follow using monster method - Clean and smooth, no trails!');

})();