[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]
боссфайт2
Сообщений 31 страница 60 из 74
Поделиться312026-01-10 22:38:31
Поделиться322026-01-10 22:41:02
[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]
Поделиться332026-01-10 22:41:13
[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]
Поделиться342026-01-14 18:01:00
[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]
Поделиться352026-01-14 18:01: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;">⚔️ АТАКА: 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]
Поделиться362026-01-14 18:02:14
[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]
Поделиться372026-01-14 18:02: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;">⚔️ АТАКА: 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]
Поделиться382026-01-14 18:19:34
[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]
Поделиться392026-01-14 19:36: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;">⚔️ АТАКА: 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]
Поделиться402026-01-14 19:36: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;">⚔️ АТАКА: 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]
Поделиться412026-01-14 19:41:06
[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]
Поделиться422026-01-14 19:42: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;">⚔️ АТАКА: 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]
Поделиться432026-01-20 17:31:35
[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)
Поделиться442026-01-20 17:34:07
[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)
Поделиться452026-01-20 17:34:14
[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]
Поделиться462026-01-20 17:34:19
[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)
Поделиться472026-01-20 17:34:29
[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]
Поделиться482026-01-20 17:34: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;">⚔️ АТАКА: 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]
Поделиться492026-01-20 17:34: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;">⚔️ АТАКА: 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]
Поделиться502026-01-20 17:35:17
[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)
Поделиться512026-01-20 17:35:25
[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]
Поделиться522026-01-20 17:35:30
[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]
Поделиться532026-01-20 17:36:12
[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]
Поделиться542026-01-20 17:36:20
[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]
Поделиться552026-01-20 17:36:26
[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]
Поделиться562026-01-20 17:36: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;">⚔️ АТАКА: 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]
Поделиться572026-01-20 17:36: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;">⚔️ АТАКА: 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]
Поделиться582026-01-20 17:36: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;">⚔️ АТАКА: 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]
Поделиться592026-01-20 17:36: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;">⚔️ АТАКА: 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]
Поделиться602026-01-20 17:37:02
[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]