Альт

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Альт » Альт » ...


...

Сообщений 1 страница 4 из 4

Перевести1

https://i.pinimg.com/736x/ba/57/35/ba573584511eb97051f65c07d857e8b7.jpg

Перевести2

[Intervention] Slow network is detected. See https://www.chromestatus.com/feature/5636954674692096 for more details. Fallback font will be used while loading: chrome-extension://njgcanhfjdabfmnlmpmdedalocpafnhl/fonts/mplus-1m-regular.woff
rmmz_managers.js:824 [Intervention] Slow network is detected. See https://www.chromestatus.com/feature/5636954674692096 for more details. Fallback font will be used while loading: chrome-extension://njgcanhfjdabfmnlmpmdedalocpafnhl/fonts/mplus-2p-bold-sub.woff
0.peerjs.com/peerjs/id?ts=17796117758130.4098274064605709&version=1.5.2:1 Failed to load resource: the server responded with a status of 403 ()
peerjs.min.js:7 ERROR PeerJS:  Error retrieving ID (Error) Error. Status:403
_print @ peerjs.min.js:7
peerjs.min.js:7 ERROR PeerJS:  Aborting!
_print @ peerjs.min.js:7
peerjs.min.js:7 ERROR PeerJS:  Error: (Error) Could not get an ID from the server.
_print @ peerjs.min.js:7
NetworkCoop_P2P.js:104 PEER ERROR (Client): Error
    at e1.emitError (peerjs.min.js:7)
    at e1._abort (peerjs.min.js:7)
    at peerjs.min.js:7
(anonymous) @ NetworkCoop_P2P.js:104
DevTools failed to load SourceMap: Could not load content for chrome-extension://njgcanhfjdabfmnlmpmdedalocpafnhl/js/libs/peerjs.min.js.map: System error: net::ERR_FILE_NOT_FOUND
DevTools failed to load SourceMap: Could not load content for chrome-extension://njgcanhfjdabfmnlmpmdedalocpafnhl/js/libs/pixi.js.map: System error: net::ERR_FILE_NOT_FOUND

Перевести3

:flirt:

4

//=============================================================================
// NetworkCoop_P2P.js - Версия 15.0: Фикс ИИ (State Machine) и Фикс HP
//=============================================================================

(() => {
    const NETWORK_EVENT_ID = 1;
   
    const CHAR_LIST = [
        { name: "People2", index: 0, label: "1. Дед (Воин)", playerId: 1, actorId: 1,
          vars: { hp: 22, luck: 23, speed: 24, baseStat: 25, weaponId: 26, resource: 27, agility: 35 } },
        { name: "People2", index: 1, label: "2. Кабачок (Маг)", playerId: 1, actorId: 2,
          vars: { hp: 29, luck: 30, speed: 31, baseStat: 32, weaponId: 33, resource: 34, agility: 36 } },
        { name: "People2", index: 4, label: "3. Богач (Воин)", playerId: 2, actorId: 3,
          vars: { hp: 42, luck: 43, speed: 44, baseStat: 45, weaponId: 46, resource: 47, agility: 37 } },
        { name: "People2", index: 5, label: "4. Монашка (Маг)", playerId: 2, actorId: 4,
          vars: { hp: 49, luck: 50, speed: 51, baseStat: 52, weaponId: 53, resource: 54, agility: 38 } }
    ];

    let peer = null;
    let conn = null;
    let lastSentX = -1;
    let lastSentY = -1;
    let lastSentDir = -1;
    let networkActive = false;
    let isHost = false;

    let remoteTargetX = 0;
    let remoteTargetY = 0;
let lastSentEventPos = {};

    let currentTargetId = 0;
    let currentTargetVarId = 0;
    let currentTargetDeathSwitch = 0;
    let autoAttackTimer = 0;
    const ATTACK_RANGE = 2;
    const BASE_COOLDOWN = 90;
   
    let myStats = null;
    let remotePlayerStats = null;
    let myActorId = 1;
   
    let targetNameCache = "";
    let targetMaxHpCache = 100;

    // ИИ ВРАГОВ (State Machine)
    // Состояния: 0 = Спокойствие, 1 = Тревога, 2 = Бой
    let enemyAI = {};

    Input.keyMapper[82] = 'targetKey'; // R

    // ==========================================================
    // HTML UI
    // ==========================================================
    let targetFrame = null;
    let hpBarInner = null;
    let targetNameEl = null;
    let targetHpTextEl = null;
    let damageNumberEl = null;

    let playerFrame = null;
    let playerHpBarInner = null;
    let playerNameEl = null;
    let playerHpTextEl = null;
    let playerAvatarEl = null;

    function createHTMLUI() {
        if (document.getElementById('mmo-target-frame')) return;
       
        // --- ФРЕЙМ ВРАГА ---
        targetFrame = document.createElement('div');
        targetFrame.id = 'mmo-target-frame';
        targetFrame.style.cssText = `position: fixed; top: 20px; left: 50%; transform: translateX(-50%); width: 300px; height: 50px; background: rgba(0, 0, 0, 0.8); border: 2px solid #c9a034; border-radius: 8px; padding: 10px; display: none; z-index: 9999; font-family: Arial, sans-serif; color: white; pointer-events: none;`;
        targetNameEl = document.createElement('div');
        targetNameEl.style.cssText = `font-size: 16px; font-weight: bold; margin-bottom: 5px; text-align: center; color: #ffcc00;`;
        targetFrame.appendChild(targetNameEl);
        let hpBarOuter = document.createElement('div');
        hpBarOuter.style.cssText = `width: 100%; height: 15px; background: #333; border-radius: 3px; border: 1px solid #000;`;
        hpBarInner = document.createElement('div');
        hpBarInner.style.cssText = `width: 100%; height: 100%; background: linear-gradient(to bottom, #ff4444, #cc0000); border-radius: 3px; transition: width 0.2s;`;
        hpBarOuter.appendChild(hpBarInner);
        targetFrame.appendChild(hpBarOuter);
        targetHpTextEl = document.createElement('div');
        targetHpTextEl.style.cssText = `font-size: 12px; text-align: center; margin-top: 2px;`;
        targetFrame.appendChild(targetHpTextEl);

        // --- ФРЕЙМ ИГРОКА ---
        playerFrame = document.createElement('div');
        playerFrame.id = 'mmo-player-frame';
        playerFrame.style.cssText = `position: fixed; bottom: 20px; right: 20px; width: 250px; height: 60px; background: rgba(0, 0, 0, 0.8); border: 2px solid #1e3a5f; border-radius: 8px; padding: 10px; display: flex; align-items: center; z-index: 9999; font-family: Arial, sans-serif; color: white; pointer-events: none;`;
       
        playerAvatarEl = document.createElement('div');
        playerAvatarEl.style.cssText = `width: 40px; height: 40px; background: #555; border: 2px solid #fff; border-radius: 5px; margin-right: 10px; display: flex; justify-content: center; align-items: center; font-weight: bold;`;
        playerFrame.appendChild(playerAvatarEl);

        let playerInfoDiv = document.createElement('div');
        playerInfoDiv.style.cssText = `flex-grow: 1;`;
        playerNameEl = document.createElement('div');
        playerNameEl.style.cssText = `font-size: 14px; font-weight: bold; margin-bottom: 5px;`;
        playerInfoDiv.appendChild(playerNameEl);
       
        let pHpBarOuter = document.createElement('div');
        pHpBarOuter.style.cssText = `width: 100%; height: 10px; background: #333; border-radius: 3px; border: 1px solid #000;`;
        playerHpBarInner = document.createElement('div');
        playerHpBarInner.style.cssText = `width: 100%; height: 100%; background: linear-gradient(to bottom, #2ecc71, #27ae60); border-radius: 3px; transition: width 0.2s;`;
        pHpBarOuter.appendChild(playerHpBarInner);
        playerInfoDiv.appendChild(pHpBarOuter);
       
        playerHpTextEl = document.createElement('div');
        playerHpTextEl.style.cssText = `font-size: 10px; text-align: right; margin-top: 2px;`;
        playerInfoDiv.appendChild(playerHpTextEl);

        playerFrame.appendChild(playerInfoDiv);

        // --- ВСПЛЫВАЮЩИЙ УРОН ---
        damageNumberEl = document.createElement('div');
        damageNumberEl.id = 'mmo-damage-number';
        damageNumberEl.style.cssText = `position: fixed; top: 35%; left: 50%; transform: translateX(-50%); font-size: 40px; font-weight: bold; color: white; text-shadow: 2px 2px 0 #000; z-index: 10000; pointer-events: none; display: none; opacity: 0; transition: all 0.5s ease-out;`;

        document.body.appendChild(targetFrame);
        document.body.appendChild(playerFrame);
        document.body.appendChild(damageNumberEl);
    }

    function showDamageNumber(text, isCrit, isDodge) {
        if (!damageNumberEl) return;
        damageNumberEl.textContent = text;
        if (isDodge) { damageNumberEl.style.color = "#ffff00"; damageNumberEl.style.fontSize = "45px"; }
        else { damageNumberEl.style.color = isCrit ? "#ffaa00" : "#ffffff"; damageNumberEl.style.fontSize = isCrit ? "55px" : "40px"; }
        damageNumberEl.style.transition = 'none'; damageNumberEl.style.display = 'block'; damageNumberEl.style.opacity = 1; damageNumberEl.style.top = '35%';
        setTimeout(() => { damageNumberEl.style.transition = 'all 0.5s ease-out'; damageNumberEl.style.opacity = 0; damageNumberEl.style.top = '25%'; }, 50);
    }

    function updateUI() {
        if (!targetFrame) return;
        // Враг
        if (currentTargetId > 0 && currentTargetDeathSwitch > 0 && !$gameSwitches.value(currentTargetDeathSwitch)) {
            targetFrame.style.display = 'block';
            let currentHp = $gameVariables.value(currentTargetVarId);
            targetNameEl.textContent = targetNameCache; targetHpTextEl.textContent = `${currentHp} / ${targetMaxHpCache}`;
            hpBarInner.style.width = Math.max(0, (currentHp / targetMaxHpCache) * 100) + '%';
        } else { targetFrame.style.display = 'none'; }

        // Игрок (БЕЗ БАЗЫ ДАННЫХ!)
        if (myStats && $gameActors && $gameActors.actor(myActorId)) {
            let actor = $gameActors.actor(myActorId);
            let currentHp = $gameVariables.value(myStats.hp);
           
            playerNameEl.textContent = actor.name();
            playerHpTextEl.textContent = `HP: ${currentHp}`; // Только текущее HP из переменной
           
            // Полоска будет просто показывать текущее значение. Так как мы не знаем макс,
            // сделаем так: если HP > 20, считаем что максимум = текущее. Иначе 20.
            // Позже ты добавишь переменную Max HP и мы сделаем идеально!
            let maxHp = Math.max(currentHp, 20);
            playerHpBarInner.style.width = Math.max(0, (currentHp / maxHp) * 100) + '%';
           
            playerAvatarEl.textContent = actor.name().charAt(0);
            playerAvatarEl.style.backgroundColor = myStats.agility === 35 ? "#c0392b" : "#2980b9";
        }
    }

    // ==========================================================
    // ИНИЦИАЛИЗАЦИЯ И СЕТЬ
    // ==========================================================
    window.InitializeEnemyHP = function(varId, enemyId) {
        if ($gameVariables.value(varId) === 0) {
            let enemyData = $dataEnemies[enemyId];
            if (enemyData) { let maxHp = enemyData.params[0]; $gameVariables.setValue(varId, maxHp); if (isHost && networkActive) NetworkSendVariable(varId, maxHp); }
        }
    };
    window.NetworkSendSwitch = function(switchId, value) { if (networkActive && conn && conn.open) conn.send({ type: 'switch', switchId: switchId, value: value }); };
    window.NetworkSendVariable = function(varId, value) { if (networkActive && conn && conn.open) conn.send({ type: 'variable', varId: varId, value: value }); };

    function sendFullSync() {
    if (!networkActive || !conn || !conn.open || !$gameSwitches || !$gameVariables) return;
    let swData = []; let varData = [];
    for (let i = 1; i < $gameSwitches._data.length; i++) { if ($gameSwitches._data[i]) swData.push({ id: i, val: true }); }
    for (let i = 1; i < $gameVariables._data.length; i++) { if ($gameVariables._data[i] !== 0) varData.push({ id: i, val: $gameVariables._data[i] }); }
    conn.send({ type: 'full_sync', switches: swData, variables: varData });
   
    // Добавляем синхронизацию позиций врагов при подключении
    if ($gameMap) {
        $gameMap.events().forEach(event => {
        if (event.event().meta && event.event().meta.enemy) {
            conn.send({ type: 'event_move', eventId: event.eventId(), x: event.x, y: event.y, dir: event.direction() });
        }
        });
    }
    }

        function setupConnection(connection) {
        conn = connection;
        conn.on('open', function() {
            networkActive = true;
            if ($gamePlayer) {
                conn.send({ type: 'init_graphic', graphicName: $gamePlayer.characterName(), graphicIndex: $gamePlayer.characterIndex() });
                conn.send({ type: 'init_stats', stats: myStats });
            }
            if (isHost) setTimeout(sendFullSync, 1000);
        });
       
        conn.on('data', function(data) { // <--- ОШИБКА БЫЛА ЗДЕСЬ: обязательно должно быть (data)
            if (!$gameMap) return;
           
            // Движение второго игрока
            if (data.type === 'move') { remoteTargetX = data.x; remoteTargetY = data.y; }
           
            // Инициализация графики и статов
            if (data.type === 'init_graphic') { const event = $gameMap.event(NETWORK_EVENT_ID); if (event) event.setImage(data.graphicName, data.graphicIndex); }
            if (data.type === 'init_stats') { remotePlayerStats = data.stats; }
           
            // Синхронизация переключателей и переменных
            if (data.type === 'switch' && $gameSwitches) $gameSwitches.setValue(data.switchId, data.value);
            if (data.type === 'variable' && $gameVariables) $gameVariables.setValue(data.varId, data.value);
           
            // Полная синхронизация
            if (data.type === 'full_sync') {
                if ($gameSwitches) data.switches.forEach(sw => $gameSwitches.setValue(sw.id, sw.val));
                if ($gameVariables) data.variables.forEach(vr => $gameVariables.setValue(vr.id, vr.val));
                if ($gameMap) $gameMap.refresh();
            }
           
            // Анимации атак
            if (data.type === 'attack_anim') { let targetEvent = $gameMap.event(data.targetId); if (targetEvent) $gameTemp.requestAnimation([targetEvent], 1); }
                        if (data.type === 'player_hit_anim') {
                // Если хост говорит, что ударили его — на экране клиента анимация на модельке хоста (Event)
                // Если хост говорит, что ударили клиента — на экране клиента анимация на $gamePlayer (Игрок)
                let target = data.targetNetworkId === "host" ? $gameMap.event(NETWORK_EVENT_ID) : $gamePlayer;
               
                // Проигрываем анимацию удара (если не уворот)
                if (target && data.animId > 0) $gameTemp.requestAnimation([target], data.animId);
               
                // Если ударили тебя (клиента), показываем всплывающий урон и звуки
                if (data.targetNetworkId === "client") {
                    if (data.isDodge) {
                        showDamageNumber("DODGE!", false, true);
                        AudioManager.playSe({name: "Cancel2", volume: 90, pitch: 150, pan: 0});
                    } else {
                        showDamageNumber("-" + data.damage, false, false);
                        AudioManager.playSe({name: "Damage1", volume: 90, pitch: 100, pan: 0});
                    }
                }
            }
           
            // НОВОЕ: Синхронизация движения врагов/событий
            if (data.type === 'event_move') {
                let event = $gameMap.event(data.eventId);
                if (event) {
                    if (!event.isMoving()) {
                        let dx = data.x - event.x;
                        let dy = data.y - event.y;
                        // Если враг слишком далеко (рассинхрон), телепортируем
                        if (Math.abs(dx) > 1 || Math.abs(dy) > 1) {
                            event.setPosition(data.x, data.y);
                        } else if (dx !== 0 || dy !== 0) {
                            // Иначе плавно двигаем
                            event.setDirection(data.dir);
                            event.moveStraight(data.dir);
                        } else {
                            // Если координаты совпадают, просто обновляем направление взгляда
                            event.setDirection(data.dir);
                        }
                    } else if (Math.abs(data.x - event.x) > 2 || Math.abs(data.y - event.y) > 2) {
                        // Жесткий фикс: если враг застрял в анимации ходьбы, но сильно отстал — телепортируем
                        event.setPosition(data.x, data.y);
                    }
                }
            }
        });
       
        conn.on('close', function() { networkActive = false; });
        conn.on('error', function(err) { console.error("P2P Ошибка:", err); });
    }

    const _Scene_Map_start = Scene_Map.prototype.start;
    Scene_Map.prototype.start = function() {
        _Scene_Map_start.call(this);
        createHTMLUI();
        if (!peer) {
            let promptText = "CHOOSE YOUR CLASS:\n\n";
            for (let i = 0; i < CHAR_LIST.length; i++) promptText += CHAR_LIST[i].label + "\n";
            promptText += "\n(Type a number)";
            const charChoice = prompt(promptText, "1");
            let charIndex = parseInt(charChoice) - 1;
            if (charIndex < 0 || charIndex >= CHAR_LIST.length) charIndex = 0;
           
            let chosenChar = CHAR_LIST[charIndex];
            $gamePlayer.setImage(chosenChar.name, chosenChar.index);
            myStats = chosenChar.vars;
            myActorId = chosenChar.actorId;

            const choice = prompt("CO-OP MULTIPLAYER\n\n1. Type 'host' to CREATE room\n2. Type 'join' to CONNECT", "host");
            if (choice === 'host') {
                isHost = true;
                const roomCode = Math.floor(1000 + Math.random() * 9000);
                peer = new Peer('rpg' + roomCode, { secure: true, debug: 1 });
                peer.on('open', id => alert("YOUR ROOM CODE:\n\n" + roomCode));
                peer.on('connection', conn => { setupConnection(conn); alert("FRIEND CONNECTED!"); });
                peer.on('error', err => alert("Error: " + err.type));
            } else if (choice === 'join') {
                isHost = false;
                const inputCode = prompt("ENTER HOST'S 4-DIGIT CODE:");
                if (inputCode) {
                    peer = new Peer({ secure: true, debug: 1 });
                    peer.on('open', () => { setupConnection(peer.connect('rpg' + inputCode, { reliable: true })); setTimeout(() => alert(networkActive ? "CONNECTED!" : "Failed."), 3000); });
                    peer.on('error', err => alert("Error: " + err.type));
                }
            }
        }
    };

    // ==========================================================
    // ОБНОВЛЕНИЕ КАРТЫ
    // ==========================================================
    const _Scene_Map_update = Scene_Map.prototype.update;
    Scene_Map.prototype.update = function() {
        _Scene_Map_update.call(this);
        if (!$gameMap || !$gamePlayer || !myStats) return;

        // --- СЕТЬ ДВИЖЕНИЯ ---
        if (networkActive && conn && conn.open) {
            const x = $gamePlayer.x; const y = $gamePlayer.y; const dir = $gamePlayer.direction();
            if (x !== lastSentX || y !== lastSentY || dir !== lastSentDir) {
                try { conn.send({ type: 'move', x: x, y: y, dir: dir }); } catch(e) {}
                lastSentX = x; lastSentY = y; lastSentDir = dir;
            }
            const friendEvent = $gameMap.event(NETWORK_EVENT_ID);
            if (friendEvent && !friendEvent.isMoving()) {
                let dx = remoteTargetX - friendEvent.x; let dy = remoteTargetY - friendEvent.y;
                if (Math.abs(dx) > 1 || Math.abs(dy) > 1) friendEvent.setPosition(remoteTargetX, remoteTargetY);
                else if (dx !== 0 || dy !== 0) { let dir = Math.abs(dx) > Math.abs(dy) ? (dx > 0 ? 6 : 4) : (dy > 0 ? 2 : 8); friendEvent.setDirection(dir); friendEvent.moveStraight(dir); }
            }
        }

        // --- ТАГРЕТИНГ (R) ---
        if (Input.isTriggered('targetKey')) {
            AudioManager.playSe({name: "Cursor1", volume: 90, pitch: 100, pan: 0});
            let closestDist = 999; let closestId = 0; let closestVar = 0; let closestDeathSw = 0;
            $gameMap.events().forEach(event => {
                if (event.event().meta && event.event().meta.enemy) {
                    let varId = parseInt(event.event().meta.enemy);
                    let deathSw = parseInt(event.event().meta.deathSwitch || 0);
                    let isDead = deathSw > 0 ? $gameSwitches.value(deathSw) : false;
                    if ($gameVariables.value(varId) > 0 && !isDead) {
                        let dist = Math.abs($gamePlayer.x - event.x) + Math.abs($gamePlayer.y - event.y);
                        if (dist < closestDist) { closestDist = dist; closestId = event.eventId(); closestVar = varId; closestDeathSw = deathSw; }
                    }
                }
            });
            if (closestId > 0) {
                currentTargetId = closestId; currentTargetVarId = closestVar; currentTargetDeathSwitch = closestDeathSw;
                let event = $gameMap.event(closestId); targetNameCache = event.event().name;
                let enemyDbId = parseInt(event.event().meta.enemyId || 1);
                targetMaxHpCache = $dataEnemies[enemyDbId] ? $dataEnemies[enemyDbId].params[0] : 100;
                AudioManager.playSe({name: "Decision1", volume: 90, pitch: 150, pan: 0});
            } else { currentTargetId = 0; currentTargetVarId = 0; currentTargetDeathSwitch = 0; targetNameCache = ""; AudioManager.playSe({name: "Buzzer1", volume: 90, pitch: 100, pan: 0}); }
        }

        // --- АВТОАТАКА ИГРОКА ---
        if (currentTargetId > 0 && autoAttackTimer <= 0) {
            let targetEvent = $gameMap.event(currentTargetId);
            let isDead = currentTargetDeathSwitch > 0 ? $gameSwitches.value(currentTargetDeathSwitch) : false;
            if (targetEvent && $gameVariables.value(currentTargetVarId) > 0 && !isDead) {
                let dist = Math.abs($gamePlayer.x - targetEvent.x) + Math.abs($gamePlayer.y - targetEvent.y);
                if (dist <= ATTACK_RANGE) {
                    if (isHost || !networkActive) {
                        let baseStatVal = $gameVariables.value(myStats.baseStat);
                        let weaponIdVal = $gameVariables.value(myStats.weaponId);
                        let luckVal = $gameVariables.value(myStats.luck);         
                        let weaponDmg = (weaponIdVal > 0 && $dataWeapons[weaponIdVal]) ? $dataWeapons[weaponIdVal].params[3] : 0;
                        let totalDamage = baseStatVal + weaponDmg;
                        let isCrit = false;
                        if (Math.randomInt(100) + 1 <= luckVal) { totalDamage *= 2; isCrit = true; AudioManager.playSe({name: "Crossbow", volume: 90, pitch: 150, pan: 0}); }
                        totalDamage = Math.max(1, totalDamage);
                        let newHp = Math.max(0, $gameVariables.value(currentTargetVarId) - totalDamage);
                        $gameVariables.setValue(currentTargetVarId, newHp);
                        showDamageNumber("-" + totalDamage, isCrit, false);
                        if (newHp <= 0 && currentTargetDeathSwitch > 0) { $gameSwitches.setValue(currentTargetDeathSwitch, true); if (networkActive) NetworkSendSwitch(currentTargetDeathSwitch, true); }
                        if (networkActive) { NetworkSendVariable(currentTargetVarId, newHp); conn.send({ type: 'attack_anim', targetId: currentTargetId }); }
                        $gameTemp.requestAnimation([targetEvent], 1);
                    }
                    autoAttackTimer = Math.max(20, BASE_COOLDOWN - ($gameVariables.value(myStats.speed) * 5));
                }
            } else { currentTargetId = 0; currentTargetVarId = 0; currentTargetDeathSwitch = 0; }
        }
        if (autoAttackTimer > 0) autoAttackTimer--;

        // --- УМНЫЙ ИИ ВРАГОВ (State Machine) ---
        if (isHost || !networkActive) {
            const AGGRO_RANGE = 4;
            const DEAGGRO_RANGE = 6;
            const ENEMY_ATK_RANGE = 1;
            const ENEMY_COOLDOWN = 120;
            const AGGRO_DELAY = 90;

            $gameMap.events().forEach(event => {
                if (!event.event().meta || !event.event().meta.enemy) return;
                let varId = parseInt(event.event().meta.enemy);
                let deathSw = parseInt(event.event().meta.deathSwitch || 0);
                if ($gameVariables.value(varId) <= 0 || (deathSw > 0 && $gameSwitches.value(deathSw))) return;

                let eId = event.eventId();
                if (!enemyAI[eId]) enemyAI[eId] = { state: 0, timer: 0, cooldown: 0 };
                let ai = enemyAI[eId];

                let p1Dist = Math.abs($gamePlayer.x - event.x) + Math.abs($gamePlayer.y - event.y);
                let p2Dist = 999;
                if (networkActive && remotePlayerStats) {
                    let p2Event = $gameMap.event(NETWORK_EVENT_ID);
                    p2Dist = Math.abs(p2Event.x - event.x) + Math.abs(p2Event.y - event.y);
                }

                let targetIsP1 = (p1Dist <= p2Dist);
                let targetDist = targetIsP1 ? p1Dist : p2Dist;

                // Деагро (Сброс состояния)
                if (targetDist > DEAGGRO_RANGE) {
                    ai.state = 0; ai.timer = 0;
                    return;
                }

                // Игрок в радиусе агро
                if (targetDist <= AGGRO_RANGE) {
                    // СОСТОЯНИЕ 0: СПОКОЙСТВИЕ -> ТРЕВОГА
                    if (ai.state === 0) {
                        ai.state = 1;
                        ai.timer = AGGRO_DELAY;
                        AudioManager.playSe({name: "Skill3", volume: 90, pitch: 100, pan: 0}); // Звук 1 раз!
                    }
                   
                    // СОСТОЯНИЕ 1: ТРЕВОГА (Ждет)
                    if (ai.state === 1) {
                        ai.timer--;
                        if (ai.timer <= 0) ai.state = 2; // Переходим к бою
                        return; // Стоим на месте
                    }

                    // СОСТОЯНИЕ 2: БОЙ (Гоняется и бьет)
                    if (ai.state === 2) {
                        if (ai.cooldown > 0) { ai.cooldown--; return; }

                                                if (targetDist <= ENEMY_ATK_RANGE) {
                            // АТАКА
                            let targetAgilityVar = targetIsP1 ? myStats.agility : (remotePlayerStats ? remotePlayerStats.agility : 0);
                            let targetHpVar = targetIsP1 ? myStats.hp : (remotePlayerStats ? remotePlayerStats.hp : 0);
                            let targetEntity = targetIsP1 ? $gamePlayer : $gameMap.event(NETWORK_EVENT_ID);
                            let agility = $gameVariables.value(targetAgilityVar);
                           
                            if (Math.randomInt(100) + 1 <= agility) {
                                // УВОРОТ
                                if (targetIsP1) {
                                    showDamageNumber("DODGE!", false, true);
                                    AudioManager.playSe({name: "Cancel2", volume: 90, pitch: 150, pan: 0});
                                }
                                if (networkActive) {
                                    let hitTarget = targetIsP1 ? "host" : "client";
                                    conn.send({ type: 'player_hit_anim', targetNetworkId: hitTarget, animId: 0, isDodge: true });
                                }
                            } else {
                                // ПОПАДАНИЕ
                                let enemyAtk = parseInt(event.event().meta.atk || 3);
                                let currentHp = $gameVariables.value(targetHpVar);
                                let newHp = Math.max(0, currentHp - enemyAtk);
                                $gameVariables.setValue(targetHpVar, newHp);
                                $gameTemp.requestAnimation([targetEntity], 1);
                               
                                if (targetIsP1) {
                                    showDamageNumber("-" + enemyAtk, false, false);
                                    AudioManager.playSe({name: "Damage1", volume: 90, pitch: 100, pan: 0});
                                }
                               
                                if (networkActive) {
                                    NetworkSendVariable(targetHpVar, newHp);
                                    let hitTarget = targetIsP1 ? "host" : "client";
                                    conn.send({ type: 'player_hit_anim', targetNetworkId: hitTarget, animId: 1, damage: enemyAtk, isDodge: false });
                                }
                            }
                            ai.cooldown = ENEMY_COOLDOWN;
                        } else {
                            // ПРЕСЛЕДОВАНИЕ
                            if (!event.isMoving()) {
                                if (targetIsP1) { event.moveTowardPlayer(); }
                                else {
                                    let p2Event = $gameMap.event(NETWORK_EVENT_ID);
                                    let dx = p2Event.x - event.x; let dy = p2Event.y - event.y;
                                    let dir = Math.abs(dx) > Math.abs(dy) ? (dx > 0 ? 6 : 4) : (dy > 0 ? 2 : 8);
                                    event.setDirection(dir); event.moveStraight(dir);
                                }
                            }
                        }
                    }
                }
            });
        }
   
    // --- СИНХРОНИЗАЦИЯ ПОЗИЦИЙ ВРАГОВ ---
if (isHost && networkActive && conn && conn.open) {
    $gameMap.events().forEach(event => {
        // Синхронизируем только врагов (можно убрать проверку meta.enemy, если нужны все NPC)
        if (event.event().meta && event.event().meta.enemy) {
            let eId = event.eventId();
            let eX = event.x;
            let eY = event.y;
            let eDir = event.direction();
           
            // Отправляем только если позиция или направление изменились
            if (!lastSentEventPos[eId] || lastSentEventPos[eId].x !== eX || lastSentEventPos[eId].y !== eY || lastSentEventPos[eId].dir !== eDir) {
                try {
                    conn.send({ type: 'event_move', eventId: eId, x: eX, y: eY, dir: eDir });
                } catch(e) {}
                lastSentEventPos[eId] = { x: eX, y: eY, dir: eDir };
            }
        }
    });
}

        updateUI();
    };
})();


Вы здесь » Альт » Альт » ...


Рейтинг форумов | Создать форум бесплатно