Здесь делается вжух 🪄

test

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

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


Вы здесь » test » Тестовый форум » боссфайт2


боссфайт2

Сообщений 31 страница 60 из 74

31

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 76 УРОНА!</h2>
        <p style="margin:10px 0;">admin ударил 🔥 собака сутулая</p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 0 / 500</p>
    </div>[/html]

0

32

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 42 УРОНА!</h2>
        <p style="margin:10px 0;">admin ударил 🔥 собака сутулая</p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 458 / 500</p>
    </div>[/html]

0

33

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 85 УРОНА!</h2>
        <p style="margin:10px 0;">desp ударил 🔥 собака сутулая</p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 373 / 500</p>
    </div>[/html]

0

34

[html]<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="UTF-8">
  <style>
    @import url('https://fonts.googleapis.com/css2?family=Oswald:wght@400;700&family=Roboto+Condensed:wght@400;700&display=swap');
    *{margin:0;padding:0;box-sizing:border-box}
    body{background:#0a0a0c;background-image:radial-gradient(circle at center,#1a1a2e 0%,#0a0a0c 100%);color:#e0e0e0;font-family:'Roboto Condensed',sans-serif;min-height:100vh;display:flex;align-items:center;justify-content:center;padding:20px}
    .game-container{display:grid;grid-template-columns:300px 1fr;gap:25px;max-width:1100px;width:100%;background:rgba(0,0,0,0.6);padding:30px;border-radius:20px;border:1px solid rgba(255,255,255,0.05);box-shadow:0 20px 50px rgba(0,0,0,0.5);backdrop-filter:blur(10px)}
    .sidebar{display:flex;flex-direction:column;gap:20px}
    .panel{background:rgba(255,255,255,0.03);border-left:3px solid #ff4655;padding:15px;border-radius:4px}
    .panel-h{font-family:'Oswald',sans-serif;font-size:14px;letter-spacing:2px;color:#ff4655;margin-bottom:12px;text-transform:uppercase}
    .stat-row{display:flex;justify-content:space-between;padding:6px 0;border-bottom:1px solid rgba(255,255,255,0.05);font-size:14px;gap:10px}
    .record-info{display:flex;flex-direction:column;gap:4px;text-align:right}
    .record-player{
      color:#aaa;
      font-size:12px;
      max-width:180px;
      white-space:normal;
      overflow:visible;
      text-overflow:clip;
      word-break:break-word;
      line-height:1.2;
    }
    .record-player .p{display:block}
    .log-container{font-size:13px;height:200px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:#ff4655 transparent}
    .log-entry{padding:4px 0;color:#aaa;border-bottom:1px solid rgba(255,255,255,0.02)}
    .log-entry b{color:#ff4655}
    .main-content{display:flex;flex-direction:column;gap:20px}
    .boss-frame{position:relative;border-radius:12px;overflow:hidden;box-shadow:0 0 30px rgba(255,70,85,0.2);border:1px solid rgba(255,70,85,0.3);transition:transform 0.1s}
    .boss-img{width:100%;height:450px;object-fit:cover;display:block}
    .boss-overlay{position:absolute;bottom:0;left:0;right:0;padding:40px 20px 20px;background:linear-gradient(to top,rgba(0,0,0,0.9) 0%,transparent 100%)}
    .boss-info{display:flex;justify-content:space-between;align-items:flex-end;margin-bottom:8px;gap:10px}
    .boss-name{font-family:'Oswald',sans-serif;font-size:32px;font-weight:700;color:#fff}
    .hp-text{font-family:'Oswald',sans-serif;color:#ff4655;font-size:18px}
    .hp-bar-bg{height:12px;background:rgba(255,255,255,0.1);border-radius:6px;overflow:hidden}
    .hp-bar-fill{height:100%;background:linear-gradient(90deg,#ff4655,#ff8a71);box-shadow:0 0 15px #ff4655;width:100%;transition:width 0.4s ease-out}
    .controls{display:grid;grid-template-columns:1fr 200px;gap:15px}
    .game-input{width:100%;height:60px;background:rgba(255,255,255,0.05);border:1px solid rgba(255,255,255,0.1);border-radius:8px;padding:0 20px;color:#fff;font-size:16px;outline:none}
    .btn-attack{height:60px;background:#ff4655;color:#fff;border:none;border-radius:8px;font-family:'Oswald',sans-serif;font-size:20px;font-weight:700;cursor:pointer;text-transform:uppercase;transition:0.2s}
    .btn-attack:hover:not(:disabled){background:#ff5e6a;transform:translateY(-2px)}
    .btn-attack:disabled{background:#333;cursor:not-allowed}
    .damage-popup{text-align:center;font-family:'Oswald',sans-serif;font-size:24px;color:#ff4655;height:30px;margin-top:10px}
  </style>
</head>
<body>
  <div class="game-container">
    <aside class="sidebar">
      <div class="panel">
        <div class="panel-h">Лидеры</div>
        <div id="topList"></div>
      </div>

      <div class="panel">
        <div class="panel-h">Рекорды</div>
        <div class="stat-row">
          <span>Макс. урон</span>
          <div class="record-info">
            <b id="maxDmg" style="color:#ff4655">-</b>
            <div id="maxPlayer" class="record-player">-</div>
          </div>
        </div>
        <div class="stat-row">
          <span>Мин. урон</span>
          <div class="record-info">
            <b id="minDmg" style="color:#fff">-</b>
            <div id="minPlayer" class="record-player">-</div>
          </div>
        </div>
      </div>

      <div class="panel" style="flex-grow:1;">
        <div class="panel-h">Журнал боя</div>
        <div id="logs" class="log-container"></div>
      </div>
    </aside>

    <main class="main-content">
      <div class="boss-frame" id="bossFrame">
        <img src="https://upforme.ru/uploads/001c/84/76/2/433839.jpg" class="boss-img" alt="Boss">
        <div class="boss-overlay">
          <div class="boss-info">
            <div class="boss-name">собака сутулая</div>
            <div id="hpText" class="hp-text">... / ...</div>
          </div>
          <div class="hp-bar-bg">
            <div id="hpBar" class="hp-bar-fill"></div>
          </div>
        </div>
      </div>

      <div class="controls">
        <input type="text" id="msg" class="game-input" placeholder="Введите боевой клич...">
        <button id="atkBtn" class="btn-attack">АТАКОВАТЬ</button>
      </div>
      <div id="dmgRes" class="damage-popup"></div>
    </main>
  </div>

  <script>
    const send = (action, data = {}) => {
      const requestId = Math.random().toString(16).slice(2);
      window.parent.postMessage({ _monsterGame: true, type: "gameRequest", requestId, action, ...data }, "*");
      return new Promise(resolve => {
        const handler = (e) => {
          if (e.data?._monsterGame && e.data.type === "gameResponse" && e.data.requestId === requestId) {
            window.removeEventListener("message", handler);
            resolve(e.data.data);
          }
        };
        window.addEventListener("message", handler);
      });
    };

    // ✅ кэш снапшота в текущей вкладке (ускоряет первый рендер)
    const SNAP_CACHE_KEY = "monster_snapshot_cache_v1";

    // ✅ локальная "память" рекордов (для совпадений макс/мин), но будет сбрасываться при resetId
    const REC_CACHE_KEY = "monster_records_ui_cache_v1";

    // ✅ ключ "увиденного" сброса (при изменении — очищаем UI+кэши)
    const RESET_ID_KEY = "monster_reset_id_seen_v1";

    function loadRecCache() {
      try {
        return JSON.parse(sessionStorage.getItem(REC_CACHE_KEY)) || {
          maxVal: null, maxPlayers: [],
          minVal: null, minPlayers: []
        };
      } catch (e) {
        return { maxVal:null, maxPlayers:[], minVal:null, minPlayers:[] };
      }
    }

    function saveRecCache(cache) {
      try { sessionStorage.setItem(REC_CACHE_KEY, JSON.stringify(cache)); } catch (e) {}
    }

    function mergeNames(oldArr, newArr) {
      const out = Array.isArray(oldArr) ? oldArr.slice() : [];
      (Array.isArray(newArr) ? newArr : []).forEach(n => {
        if (typeof n !== "string") return;
        const name = n.trim();
        if (!name) return;
        if (!out.includes(name)) out.push(name);
      });
      return out;
    }

    function clearAllUIAndCache() {
      try { sessionStorage.removeItem(SNAP_CACHE_KEY); } catch(e) {}
      try { sessionStorage.removeItem(REC_CACHE_KEY); } catch(e) {}

      // UI reset
      document.getElementById('hpBar').style.width = '100%';
      document.getElementById('hpText').textContent = `... / ...`;

      document.getElementById('topList').innerHTML = 'Нет данных';
      document.getElementById('logs').innerHTML = '';

      document.getElementById('maxDmg').textContent = '-';
      document.getElementById('maxPlayer').textContent = '-';
      document.getElementById('minDmg').textContent = '-';
      document.getElementById('minPlayer').textContent = '-';

      document.getElementById('dmgRes').textContent = '';

      const btn = document.getElementById('atkBtn');
      btn.disabled = false;
      btn.textContent = 'АТАКОВАТЬ';
    }

    function applySnapshotToUI(snap) {
      if (!snap || !snap.game || !snap.game.boss) return;

      const game = snap.game;
      const top = snap.top || [];
      const logs = snap.logs || [];
      const rec = snap.records || { maxVal:null, maxPlayers:[], minVal:null, minPlayers:[] };

      const currentHp = game.boss.currentHealth;
      const maxHp = game.boss.maxHealth;
      const hpPct = Math.max(0, (currentHp / maxHp) * 100);

      document.getElementById('hpBar').style.width = hpPct + '%';
      document.getElementById('hpText').textContent = `${currentHp} / ${maxHp}`;

      const isOver = (currentHp <= 0) || !!game.boss.isDefeated;

      const cd = snap.cooldownLeft || 0;
      const btn = document.getElementById('atkBtn');

      btn.disabled = isOver || cd > 0;

      if (!isOver && cd > 0) {
        const mins = Math.ceil(cd / 60000);
        btn.textContent = `ЖДАТЬ ${mins} МИН`;
      } else {
        btn.textContent = 'АТАКОВАТЬ';
      }

      document.getElementById('topList').innerHTML =
        top.slice(0,5).map(p => `<div class="stat-row"><span>${p.nickname}</span><b>${p.totalDamage}</b></div>`).join('')
        || 'Нет данных';

      document.getElementById('logs').innerHTML = logs.slice(-20).reverse().map(l => {
        const m = l.match(/^(.+?) нанес (\d+) урона$/);
        if (m) return `<div class="log-entry"><b>${m[1]}</b> нанес ${m[2]} урона</div>`;
        return `<div class="log-entry">${l}</div>`;
      }).join('');

      // ✅ рекорды: накапливаем имена при равных значениях (в рамках одного resetId)
      const recCache = loadRecCache();

      // MAX
      if (rec.maxVal != null) {
        if (recCache.maxVal == null || rec.maxVal > recCache.maxVal) {
          recCache.maxVal = rec.maxVal;
          recCache.maxPlayers = mergeNames([], rec.maxPlayers);
        } else if (recCache.maxVal === rec.maxVal) {
          recCache.maxPlayers = mergeNames(recCache.maxPlayers, rec.maxPlayers);
        }
      }

      // MIN
      if (rec.minVal != null) {
        if (recCache.minVal == null || rec.minVal < recCache.minVal) {
          recCache.minVal = rec.minVal;
          recCache.minPlayers = mergeNames([], rec.minPlayers);
        } else if (recCache.minVal === rec.minVal) {
          recCache.minPlayers = mergeNames(recCache.minPlayers, rec.minPlayers);
        }
      }

      saveRecCache(recCache);

      document.getElementById('maxDmg').textContent = (recCache.maxVal != null) ? String(recCache.maxVal) : '-';
      document.getElementById('maxPlayer').innerHTML =
        (recCache.maxPlayers && recCache.maxPlayers.length)
          ? recCache.maxPlayers.map(n => `<span class="p">${n}</span>`).join('')
          : '-';

      document.getElementById('minDmg').textContent = (recCache.minVal != null) ? String(recCache.minVal) : '-';
      document.getElementById('minPlayer').innerHTML =
        (recCache.minPlayers && recCache.minPlayers.length)
          ? recCache.minPlayers.map(n => `<span class="p">${n}</span>`).join('')
          : '-';
    }

    // ✅ получаем снапшот, сохраняем в кэш и рисуем
    async function updateUI() {
      try {
        const snap = await send("getSnapshot");

        // ✅ сброс по resetId из родительского скрипта:
        // ВАЖНО: чтобы работало, родитель должен отдавать snap.game.boss.resetId
        const newResetId = snap?.game?.boss?.resetId;
        if (newResetId != null) {
          const prevResetId = sessionStorage.getItem(RESET_ID_KEY);
          if (String(prevResetId) !== String(newResetId)) {
            sessionStorage.setItem(RESET_ID_KEY, String(newResetId));
            clearAllUIAndCache();
          }
        }

        sessionStorage.setItem(SNAP_CACHE_KEY, JSON.stringify(snap));
        applySnapshotToUI(snap);
      } catch (e) {
        console.error("UI Update Error:", e);
      }
    }

    document.getElementById('atkBtn').onclick = async () => {
      const msgInput = document.getElementById('msg');
      const btn = document.getElementById('atkBtn');
      btn.disabled = true;

      const res = await send("processAttack", { attackData: { message: msgInput.value } });

      if (res && res.cooldown) {
        const mins = Math.ceil(res.cooldownLeft / 60000);
        document.getElementById('dmgRes').textContent = `Повторная атака через ${mins} мин.`;
        setTimeout(() => document.getElementById('dmgRes').textContent = '', 3000);
        await updateUI();
        return;
      }

      if (res && res.gameOver) {
        document.getElementById('dmgRes').textContent = 'БОЙ ЗАВЕРШЕН!';
        await updateUI();
        return;
      }

      if (res && res.success) {
        document.getElementById('dmgRes').textContent = `УДАР: -${res.damage} HP!`;
        msgInput.value = '';

        const frame = document.getElementById('bossFrame');
        frame.style.transform = 'translate(4px, 4px) rotate(1deg)';
        setTimeout(() => frame.style.transform = 'none', 100);

        setTimeout(updateUI, 250);
      }
    };

    // ✅ мгновенная отрисовка из кэша (если он есть), потом подтягиваем актуальное
    try {
      const cached = sessionStorage.getItem(SNAP_CACHE_KEY);
      if (cached) applySnapshotToUI(JSON.parse(cached));
    } catch(e) {}

    updateUI();
    setInterval(updateUI, 15000);
  </script>
</body>
</html>[/html]

[hideprofile]

0

35

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 44 УРОНА!</h2>
        <p style="margin:10px 0;">admin ударил 🔥 собака сутулая</p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 329 / 500</p>
    </div>[/html]

0

36

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 1 УРОНА!</h2>
        <p style="margin:10px 0;">desp ударил 🔥 собака сутулая</p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 328 / 500</p>
    </div>[/html]

0

37

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 1 УРОНА!</h2>
        <p style="margin:10px 0;">admin ударил 🔥 собака сутулая</p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 327 / 500</p>
    </div>[/html]

0

38

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 1 УРОНА!</h2>
        <p style="margin:10px 0;">admin ударил 🔥 собака сутулая</p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 499 / 500</p>
    </div>[/html]

0

39

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 1 УРОНА!</h2>
        <p style="margin:10px 0;">desp ударил 🔥 собака сутулая</p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 499 / 500</p>
    </div>[/html]

0

40

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 1 УРОНА!</h2>
        <p style="margin:10px 0;">admin ударил 🔥 собака сутулая</p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 498 / 500</p>
    </div>[/html]

0

41

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 1 УРОНА!</h2>
        <p style="margin:10px 0;">desp ударил 🔥 собака сутулая</p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 497 / 500</p>
    </div>[/html]

0

42

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 1 УРОНА!</h2>
        <p style="margin:10px 0;">desp ударил 🔥 собака сутулая</p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 496 / 500</p>
    </div>[/html]

0

43

[html]<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="UTF-8">
  <style>
    @import url('https://fonts.googleapis.com/css2?family=Oswald:wght@400;700&family=Roboto+Condensed:wght@400;700&display=swap');
    *{margin:0;padding:0;box-sizing:border-box}
    body{background:#0a0a0c;background-image:radial-gradient(circle at center,#1a1a2e 0%,#0a0a0c 100%);color:#e0e0e0;font-family:'Roboto Condensed',sans-serif;min-height:100vh;display:flex;align-items:center;justify-content:center;padding:20px}
    .game-container{display:grid;grid-template-columns:300px 1fr;gap:25px;max-width:1100px;width:100%;background:rgba(0,0,0,0.6);padding:30px;border-radius:20px;border:1px solid rgba(255,255,255,0.05);box-shadow:0 20px 50px rgba(0,0,0,0.5);backdrop-filter:blur(10px)}
    .sidebar{display:flex;flex-direction:column;gap:20px}
    .panel{background:rgba(255,255,255,0.03);border-left:3px solid #ff4655;padding:15px;border-radius:4px}
    .panel-h{font-family:'Oswald',sans-serif;font-size:14px;letter-spacing:2px;color:#ff4655;margin-bottom:12px;text-transform:uppercase}
    .stat-row{display:flex;justify-content:space-between;padding:6px 0;border-bottom:1px solid rgba(255,255,255,0.05);font-size:14px;gap:10px}
    .record-info{display:flex;flex-direction:column;gap:4px;text-align:right}
    .record-player{
      color:#aaa;
      font-size:12px;
      max-width:180px;
      white-space:normal;
      overflow:visible;
      text-overflow:clip;
      word-break:break-word;
      line-height:1.2;
    }
    .record-player .p{display:block}
    .log-container{font-size:13px;height:200px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:#ff4655 transparent}
    .log-entry{padding:4px 0;color:#aaa;border-bottom:1px solid rgba(255,255,255,0.02)}
    .log-entry b{color:#ff4655}
    .main-content{display:flex;flex-direction:column;gap:20px}
    .boss-frame{position:relative;border-radius:12px;overflow:hidden;box-shadow:0 0 30px rgba(255,70,85,0.2);border:1px solid rgba(255,70,85,0.3);transition:transform 0.1s}
    .boss-img{width:100%;height:450px;object-fit:cover;display:block}
    .boss-overlay{position:absolute;bottom:0;left:0;right:0;padding:40px 20px 20px;background:linear-gradient(to top,rgba(0,0,0,0.9) 0%,transparent 100%)}
    .boss-info{display:flex;justify-content:space-between;align-items:flex-end;margin-bottom:8px;gap:10px}
    .boss-name{font-family:'Oswald',sans-serif;font-size:32px;font-weight:700;color:#fff}
    .hp-text{font-family:'Oswald',sans-serif;color:#ff4655;font-size:18px}
    .hp-bar-bg{height:12px;background:rgba(255,255,255,0.1);border-radius:6px;overflow:hidden}
    .hp-bar-fill{height:100%;background:linear-gradient(90deg,#ff4655,#ff8a71);box-shadow:0 0 15px #ff4655;width:100%;transition:width 0.4s ease-out}
    .controls{display:grid;grid-template-columns:1fr 200px;gap:15px}
    .game-input{width:100%;height:60px;background:rgba(255,255,255,0.05);border:1px solid rgba(255,255,255,0.1);border-radius:8px;padding:0 20px;color:#fff;font-size:16px;outline:none}
    .btn-attack{height:60px;background:#ff4655;color:#fff;border:none;border-radius:8px;font-family:'Oswald',sans-serif;font-size:20px;font-weight:700;cursor:pointer;text-transform:uppercase;transition:0.2s}
    .btn-attack:hover:not(:disabled){background:#ff5e6a;transform:translateY(-2px)}
    .btn-attack:disabled{background:#333;cursor:not-allowed}
    .damage-popup{text-align:center;font-family:'Oswald',sans-serif;font-size:24px;color:#ff4655;height:30px;margin-top:10px}
  </style>
</head>
<body>
  <div class="game-container">
    <aside class="sidebar">
      <div class="panel">
        <div class="panel-h">Лидеры</div>
        <div id="topList"></div>
      </div>

      <div class="panel">
        <div class="panel-h">Рекорды</div>
        <div class="stat-row">
          <span>Макс. урон</span>
          <div class="record-info">
            <b id="maxDmg" style="color:#ff4655">-</b>
            <div id="maxPlayer" class="record-player">-</div>
          </div>
        </div>
        <div class="stat-row">
          <span>Мин. урон</span>
          <div class="record-info">
            <b id="minDmg" style="color:#fff">-</b>
            <div id="minPlayer" class="record-player">-</div>
          </div>
        </div>
      </div>

      <div class="panel" style="flex-grow:1;">
        <div class="panel-h">Журнал боя</div>
        <div id="logs" class="log-container"></div>
      </div>
    </aside>

    <main class="main-content">
      <div class="boss-frame" id="bossFrame">
        <img src="https://upforme.ru/uploads/001c/84/76/2/433839.jpg" class="boss-img" alt="Boss">
        <div class="boss-overlay">
          <div class="boss-info">
            <div class="boss-name">ECS #1 «Фенрир» </div>
            <div id="hpText" class="hp-text">... / ...</div>
          </div>
          <div class="hp-bar-bg">
            <div id="hpBar" class="hp-bar-fill"></div>
          </div>
        </div>
      </div>

      <div class="controls">
        <input type="text" id="msg" class="game-input" placeholder="Введите боевой клич...">
        <button id="atkBtn" class="btn-attack">АТАКОВАТЬ</button>
      </div>
      <div id="dmgRes" class="damage-popup"></div>
    </main>
  </div>

  <script>
    const send = (action, data = {}) => {
      const requestId = Math.random().toString(16).slice(2);
      window.parent.postMessage({ _monsterGame: true, type: "gameRequest", requestId, action, ...data }, "*");
      return new Promise(resolve => {
        const handler = (e) => {
          if (e.data?._monsterGame && e.data.type === "gameResponse" && e.data.requestId === requestId) {
            window.removeEventListener("message", handler);
            resolve(e.data.data);
          }
        };
        window.addEventListener("message", handler);
      });
    };

    // ✅ кэш снапшота в текущей вкладке (ускоряет первый рендер)
    const SNAP_CACHE_KEY = "monster_snapshot_cache_v1";

    // ✅ локальная "память" рекордов (для совпадений макс/мин), но будет сбрасываться при resetId
    const REC_CACHE_KEY = "monster_records_ui_cache_v1";

    // ✅ ключ "увиденного" сброса (при изменении — очищаем UI+кэши)
    const RESET_ID_KEY = "monster_reset_id_seen_v1";

    function loadRecCache() {
      try {
        return JSON.parse(sessionStorage.getItem(REC_CACHE_KEY)) || {
          maxVal: null, maxPlayers: [],
          minVal: null, minPlayers: []
        };
      } catch (e) {
        return { maxVal:null, maxPlayers:[], minVal:null, minPlayers:[] };
      }
    }

    function saveRecCache(cache) {
      try { sessionStorage.setItem(REC_CACHE_KEY, JSON.stringify(cache)); } catch (e) {}
    }

    function mergeNames(oldArr, newArr) {
      const out = Array.isArray(oldArr) ? oldArr.slice() : [];
      (Array.isArray(newArr) ? newArr : []).forEach(n => {
        if (typeof n !== "string") return;
        const name = n.trim();
        if (!name) return;
        if (!out.includes(name)) out.push(name);
      });
      return out;
    }

    function clearAllUIAndCache() {
      try { sessionStorage.removeItem(SNAP_CACHE_KEY); } catch(e) {}
      try { sessionStorage.removeItem(REC_CACHE_KEY); } catch(e) {}

      // UI reset
      document.getElementById('hpBar').style.width = '100%';
      document.getElementById('hpText').textContent = `... / ...`;

      document.getElementById('topList').innerHTML = 'Нет данных';
      document.getElementById('logs').innerHTML = '';

      document.getElementById('maxDmg').textContent = '-';
      document.getElementById('maxPlayer').textContent = '-';
      document.getElementById('minDmg').textContent = '-';
      document.getElementById('minPlayer').textContent = '-';

      document.getElementById('dmgRes').textContent = '';

      const btn = document.getElementById('atkBtn');
      btn.disabled = false;
      btn.textContent = 'АТАКОВАТЬ';
    }

    function applySnapshotToUI(snap) {
      if (!snap || !snap.game || !snap.game.boss) return;

      const game = snap.game;
      const top = snap.top || [];
      const logs = snap.logs || [];
      const rec = snap.records || { maxVal:null, maxPlayers:[], minVal:null, minPlayers:[] };

      const currentHp = game.boss.currentHealth;
      const maxHp = game.boss.maxHealth;
      const hpPct = Math.max(0, (currentHp / maxHp) * 100);

      document.getElementById('hpBar').style.width = hpPct + '%';
      document.getElementById('hpText').textContent = `${currentHp} / ${maxHp}`;

      const isOver = (currentHp <= 0) || !!game.boss.isDefeated;

      const cd = snap.cooldownLeft || 0;
      const btn = document.getElementById('atkBtn');

      btn.disabled = isOver || cd > 0;

      if (!isOver && cd > 0) {
        const mins = Math.ceil(cd / 60000);
        btn.textContent = `ЖДАТЬ ${mins} МИН`;
      } else {
        btn.textContent = 'АТАКОВАТЬ';
      }

      document.getElementById('topList').innerHTML =
        top.slice(0,5).map(p => `<div class="stat-row"><span>${p.nickname}</span><b>${p.totalDamage}</b></div>`).join('')
        || 'Нет данных';

document.getElementById('logs').innerHTML = logs.slice().reverse().map(l => {
  const m = l.match(/^(.+?) нанес (\d+) урона$/);
  if (m) return `<div class="log-entry"><b>${m[1]}</b> нанес ${m[2]} урона</div>`;
  return `<div class="log-entry">${l}</div>`;
}).join('');

      // ✅ рекорды: накапливаем имена при равных значениях (в рамках одного resetId)
      const recCache = loadRecCache();

      // MAX
      if (rec.maxVal != null) {
        if (recCache.maxVal == null || rec.maxVal > recCache.maxVal) {
          recCache.maxVal = rec.maxVal;
          recCache.maxPlayers = mergeNames([], rec.maxPlayers);
        } else if (recCache.maxVal === rec.maxVal) {
          recCache.maxPlayers = mergeNames(recCache.maxPlayers, rec.maxPlayers);
        }
      }

      // MIN
      if (rec.minVal != null) {
        if (recCache.minVal == null || rec.minVal < recCache.minVal) {
          recCache.minVal = rec.minVal;
          recCache.minPlayers = mergeNames([], rec.minPlayers);
        } else if (recCache.minVal === rec.minVal) {
          recCache.minPlayers = mergeNames(recCache.minPlayers, rec.minPlayers);
        }
      }

      saveRecCache(recCache);

      document.getElementById('maxDmg').textContent = (recCache.maxVal != null) ? String(recCache.maxVal) : '-';
      document.getElementById('maxPlayer').innerHTML =
        (recCache.maxPlayers && recCache.maxPlayers.length)
          ? recCache.maxPlayers.map(n => `<span class="p">${n}</span>`).join('')
          : '-';

      document.getElementById('minDmg').textContent = (recCache.minVal != null) ? String(recCache.minVal) : '-';
      document.getElementById('minPlayer').innerHTML =
        (recCache.minPlayers && recCache.minPlayers.length)
          ? recCache.minPlayers.map(n => `<span class="p">${n}</span>`).join('')
          : '-';
    }

    // ✅ получаем снапшот, сохраняем в кэш и рисуем
    async function updateUI() {
      try {
        const snap = await send("getSnapshot");

        // ✅ сброс по resetId из родительского скрипта:
        // ВАЖНО: чтобы работало, родитель должен отдавать snap.game.boss.resetId
        const newResetId = snap?.game?.boss?.resetId;
        if (newResetId != null) {
          const prevResetId = sessionStorage.getItem(RESET_ID_KEY);
          if (String(prevResetId) !== String(newResetId)) {
            sessionStorage.setItem(RESET_ID_KEY, String(newResetId));
            clearAllUIAndCache();
          }
        }

        sessionStorage.setItem(SNAP_CACHE_KEY, JSON.stringify(snap));
        applySnapshotToUI(snap);
      } catch (e) {
        console.error("UI Update Error:", e);
      }
    }

    document.getElementById('atkBtn').onclick = async () => {
      const msgInput = document.getElementById('msg');
      const btn = document.getElementById('atkBtn');
      btn.disabled = true;

      const res = await send("processAttack", { attackData: { message: msgInput.value } });

      if (res && res.cooldown) {
        const mins = Math.ceil(res.cooldownLeft / 60000);
        document.getElementById('dmgRes').textContent = `Повторная атака через ${mins} мин.`;
        setTimeout(() => document.getElementById('dmgRes').textContent = '', 3000);
        await updateUI();
        return;
      }

      if (res && res.gameOver) {
        document.getElementById('dmgRes').textContent = 'БОЙ ЗАВЕРШЕН!';
        await updateUI();
        return;
      }

      if (res && res.success) {
        document.getElementById('dmgRes').textContent = `УДАР: -${res.damage} HP!`;
        msgInput.value = '';

        const frame = document.getElementById('bossFrame');
        frame.style.transform = 'translate(4px, 4px) rotate(1deg)';
        setTimeout(() => frame.style.transform = 'none', 100);

        setTimeout(updateUI, 250);
      }
    };

    // ✅ мгновенная отрисовка из кэша (если он есть), потом подтягиваем актуальное
    try {
      const cached = sessionStorage.getItem(SNAP_CACHE_KEY);
      if (cached) applySnapshotToUI(JSON.parse(cached));
    } catch(e) {}

    updateUI();
    setInterval(updateUI, 15000);
  </script>
</body>
</html>[/html]

[hideprofile]

Отредактировано desp (2026-01-20 17:31:38)

0

44

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 22 УРОНА!</h2>
        <p style="margin:10px 0;">desp ударил 🔥 собака сутулая</p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 472 / 12000</p>
    </div>[/html]

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 4 УРОНА!</h2>
        <p style="margin:10px 0;">desp ударил 🔥 собака сутулая</p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 468 / 12000</p>
    </div>[/html]

Отредактировано desp (2026-01-20 17:34:11)

0

45

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 50 УРОНА!</h2>
        <p style="margin:10px 0;">desp ударил 🔥 собака сутулая</p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 418 / 12000</p>
    </div>[/html]

0

46

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 10 УРОНА!</h2>
        <p style="margin:10px 0;">desp ударил 🔥 собака сутулая</p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 408 / 12000</p>
    </div>[/html]

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 76 УРОНА!</h2>
        <p style="margin:10px 0;">desp ударил 🔥 собака сутулая</p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 332 / 12000</p>
    </div>[/html]

Отредактировано desp (2026-01-20 17:34:22)

0

47

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 30 УРОНА!</h2>
        <p style="margin:10px 0;">desp ударил 🔥 собака сутулая</p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 302 / 12000</p>
    </div>[/html]

0

48

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 53 УРОНА!</h2>
        <p style="margin:10px 0;">desp ударил 🔥 собака сутулая</p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 249 / 12000</p>
    </div>[/html]

0

49

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 97 УРОНА!</h2>
        <p style="margin:10px 0;">desp ударил 🔥 собака сутулая</p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 152 / 12000</p>
    </div>[/html]

0

50

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 56 УРОНА!</h2>
        <p style="margin:10px 0;">desp ударил 🔥 собака сутулая</p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 96 / 12000</p>
    </div>[/html]

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 26 УРОНА!</h2>
        <p style="margin:10px 0;">desp ударил 🔥 собака сутулая</p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 70 / 12000</p>
    </div>[/html]

Отредактировано desp (2026-01-20 17:35:21)

0

51

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 48 УРОНА!</h2>
        <p style="margin:10px 0;">desp ударил 🔥 собака сутулая</p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 22 / 12000</p>
    </div>[/html]

0

52

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 26 УРОНА!</h2>
        <p style="margin:10px 0;">desp ударил 🔥 собака сутулая</p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 0 / 12000</p>
    </div>[/html]

0

53

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 94 УРОНА!</h2>
        <p style="margin:10px 0;">desp ударил 🐺 ECS #1 «Фенрир» </p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 11906 / 12000</p>
    </div>[/html]

0

54

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 50 УРОНА!</h2>
        <p style="margin:10px 0;">desp ударил 🐺 ECS #1 «Фенрир» </p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 11856 / 12000</p>
    </div>[/html]

0

55

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 39 УРОНА!</h2>
        <p style="margin:10px 0;">desp ударил 🐺 ECS #1 «Фенрир» </p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 11817 / 12000</p>
    </div>[/html]

0

56

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 19 УРОНА!</h2>
        <p style="margin:10px 0;">desp ударил 🐺 ECS #1 «Фенрир» </p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 11798 / 12000</p>
    </div>[/html]

0

57

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 100 УРОНА!</h2>
        <p style="margin:10px 0;">desp ударил 🐺 ECS #1 «Фенрир» </p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 11698 / 12000</p>
    </div>[/html]

0

58

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 96 УРОНА!</h2>
        <p style="margin:10px 0;">desp ударил 🐺 ECS #1 «Фенрир» </p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 11602 / 12000</p>
    </div>[/html]

0

59

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 84 УРОНА!</h2>
        <p style="margin:10px 0;">desp ударил 🐺 ECS #1 «Фенрир» </p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 11518 / 12000</p>
    </div>[/html]

0

60

[html]<div style="border:3px solid #ff6b6b;border-radius:15px;padding:20px;background:#494a4c;color:white;text-align:center;font-family:sans-serif;">
        <h2 style="color:#ff6b6b; margin:0; font-size:20px;">⚔️ АТАКА: 12 УРОНА!</h2>
        <p style="margin:10px 0;">desp ударил 🐺 ECS #1 «Фенрир» </p>
       
        <p style="font-size:13px; color:#aaa; margin-top:10px;">Осталось HP: 11506 / 12000</p>
    </div>[/html]

0


Вы здесь » test » Тестовый форум » боссфайт2


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