# 拿花火表情包面板测试了下哈基米3.7Flash
80hou
2026-08-16 03:50
1

前言:
# ゛花火表情包面板真是太可爱了!
之前只是融入了RPG玩法,然后感觉转盘这个游戏还是差点意思。
刚好拿3.7Flash测试跑了会,发现竟然每轮都没有出现语法错误,看来哈基米工作流确实优化了不少。 ^-^



花火修仙表情面板 (v26.0.0 乾坤天衍·九极化晶彩金版)
// ==UserScript==
// @name 花火修仙表情面板 (v26.0.0 乾坤天衍·九极化晶彩金版)
// @namespace https://deepflood.com/
// @version 26.0.0
// @description 3x3九宫格8线街机老虎机:999溢出表情自动熔炼兑换仙晶彩金+过五关斩六将连胜阶梯+赌鬼一梭到底实时动态仓位+全图鉴优先解封+全UI高清锐化+防泄露安全引擎;4字Tab+居中🔒锁纹+119全图鉴;ESLint零报错
// @author Sparkle
// @match *://www.deepflood.com/*
// @match *://www.nodeseek.com/*
// @grant none
// ==/UserScript==
/* eslint-env browser */
(function () {
'use strict';
// =========================================================================
// 【模块 0】单例模式与防重复加载保护
// =========================================================================
if (window._hanabi_loaded) {
document.getElementById('hanabi-emoji-panel')?.remove();
document.getElementById('hanabi-toggle-btn')?.remove();
}
window._hanabi_loaded = true;
// =========================================================================
// 【模块 1】静态资源与修仙图鉴数据库
// =========================================================================
const CHIGUA_TOP_ICON = "https://cdn.nodeimage.com/i/jbZrDO140rXSZpEqZ6xrOavN2wsUXuPY.webp";
const GACHA_TOP_ICON = "https://cdn.nodeimage.com/i/LLYwA5x25a3sbzuGlzSzA0yQCHnuHkit.webp";
const RESERVED_TOP_ICON = "https://cdn.nodeimage.com/i/lMepKbJMV2whSeb9Bl4WqXBEvT9VGHCf.webp";
const TOGGLE_BTN_ICON = "https://cdn.nodeimage.com/i/IEyH4NN7T0gzIj2GNDLEkMNfxi5e7S5R.png";
const MAX_EMOJI_CAP = 999; // 须弥纳戒单种法宝极限上限
// 119 张全量表情图鉴(39张花火神装 UR 奖池)
const hanabiGodSets = [
"https://cdn.nodeimage.com/i/kiTPNRkkUMXrFbcqiQjInY997EXX8ugQ.png","https://cdn.nodeimage.com/i/yNwUePEGVy7u15Dav0dsnKe44c3YJvAK.gif",
"https://cdn.nodeimage.com/i/YtrI0qXlSjH1vjIVEPCIFrra7p93S9kn.webp","https://cdn.nodeimage.com/i/BAyT6QNxu41dsi2jLwmhfE2qaRiIxyY6.webp",
"https://cdn.nodeimage.com/i/p4NKizdYxK7YtdBjHmuYqaogU4QBYaUd.webp","https://cdn.nodeimage.com/i/vTcG6KHwda3ZzsWCYHxPIXI36cPvFgaR.avif",
"https://cdn.nodeimage.com/i/MdE5TIiLs1sogvre8Rc1TunNkROvwXbR.png","https://cdn.nodeimage.com/i/DLckJTHxmoTysBWShRGhXcmY3bmB56TG.png",
"https://cdn.nodeimage.com/i/rM7RVynnxChinGGZXXc1kzcJNaPsxx09.webp","https://cdn.nodeimage.com/i/nJj1NJMN3FrvCjiYxLjDGnnMQrOuodX0.webp",
"https://cdn.nodeimage.com/i/dI2NfaGlg4LMHsJJYbj6Deg7AvSrvfPW.webp","https://cdn.nodeimage.com/i/v8bbgwPmDhn8CJfRLoJfTExECZXY9cAJ.avif",
"https://cdn.nodeimage.com/i/s6yvTaNndMqSW2237VHvVaGbGUrtR482.avif","https://cdn.nodeimage.com/i/IqtoK3LNY6UH8F49SMH6PnrdHbJDxbL5.avif",
"https://cdn.nodeimage.com/i/EcfVbQVEhIQuhhZfz3GfmUbXbOugaTKs.avif","https://cdn.nodeimage.com/i/jjmCWuOeedjWFyUMI1tM9KDLpK0YzMuU.avif",
"https://cdn.nodeimage.com/i/d2Ybd1xx8ejNkfu7Rvv6YXHEEcj4dDuE.avif","https://cdn.nodeimage.com/i/a53uo9CgZlL78BqIResfFmVJSk6YSVpi.webp",
"https://cdn.nodeimage.com/i/2Jmuo2O6rd2BAwUv5IPnzrqOndF4GaXH.avif","https://cdn.nodeimage.com/i/aa5u2pyhmLgxiqNye1Bm600GdFgQwnoH.avif",
"https://cdn.nodeimage.com/i/sg1QIipECwsa0mVAXhGtDEUtrXz32I9j.avif","https://cdn.nodeimage.com/i/Z24cydZ2nUL5jYmIxYbx8PTCgHUYWHVk.avif",
"https://cdn.nodeimage.com/i/ixMkhZuRNt39ObpRpY5XTyNdyEpVenGh.avif","https://cdn.nodeimage.com/i/qJbzpaPkUflHQxf0aUszKZrEgQzta5jd.webp",
"https://cdn.nodeimage.com/i/Bjm9HjOzzaXTqNUWYx1yZexGs0lIN9so.webp","https://cdn.nodeimage.com/i/3TyPkkNXQ2iWsT2cuUBb5lqNEXkhQwMu.gif",
"https://cdn.nodeimage.com/i/Rs1eZBpod5QsSoV1kIv1husXtopA6AcI.png","https://cdn.nodeimage.com/i/Gy9MjsQyA7tW6kkRBux6Vurjw8tIuGAX.png",
"https://cdn.nodeimage.com/i/4dQT9ylVI51vzTvwdWAzZalZCOXS3RYc.png","https://cdn.nodeimage.com/i/5Z2V8HGqrFYzTdJDdoNAvIX4WQIQnBZz.png",
"https://cdn.nodeimage.com/i/yIdwRnUajcvuVOlHaO5647PdMcRua2yS.png","https://cdn.nodeimage.com/i/IEyH4NN7T0gzIj2GNDLEkMNfxi5e7S5R.png",
"https://cdn.nodeimage.com/i/Q05BMry7UbL1QzNAAr0b4CO1jwB7po5v.png","https://cdn.nodeimage.com/i/jCc6NDHOEP8AmpWifMkopF0w1vcNJVMC.png",
"https://cdn.nodeimage.com/i/cLmlEhOL5qv1r7UNW6MgRuYePyupd35k.png","https://cdn.nodeimage.com/i/5qP7UR9sOgTBVH63ZXf5pWPiMq18iTyK.png",
"https://cdn.nodeimage.com/i/43KwtgzDgaU2C91WXwp4ItBKHjsevHQE.png","https://cdn.nodeimage.com/i/mRtWtxLeHYXdhM4yXmKAvPAZlkTzHfSl.gif",
"https://cdn.nodeimage.com/i/Jrn7JvYVY7dAhQHMrQ0i2ixfaDDvxGYU.png"
];
const GOD_SET = new Set(hanabiGodSets);
const baseCategoryMap = {
"https://cdn.nodeimage.com/i/vOTJU4khVo1Qb1cbtT904TCEOBDuY2pU.webp": "kaixin",
"https://cdn.nodeimage.com/i/0ZCReBeyFFQ6lZYIpaP19PyTYNsu7mxg.webp": "kaixin",
"https://cdn.nodeimage.com/i/Kp6lEcDDGE5MxXC0gwJfrpFaHQiTRtEM.webp": "kaixin",
"https://cdn.nodeimage.com/i/tpoIZ4Km7Uwv6qMFI2kV6TXKYO1ziRNh.webp": "kaixin",
"https://cdn.nodeimage.com/i/tFDVSfqDUJ3use04YbsAA4llEmFIKCTn.webp": "weiqu",
"https://cdn.nodeimage.com/i/8hppjJWDYBVTeK85m2K3bSgd3JuYmEbf.webp": "kaixin",
"https://cdn.nodeimage.com/i/54AChLa8vSocW0hnYfGNvL6IpBYc2pQO.webp": "weiqu",
"https://cdn.nodeimage.com/i/MuGvoHfcZur4LIxV0vmAild1gxqyOp2D.webp": "chigua",
"https://cdn.nodeimage.com/i/1OSvfN0tb9K9um3gXtBBh4TXHCO1JbGd.webp": "chigua",
"https://cdn.nodeimage.com/i/RmNsDWdgERzfqgBGreUV7GO4KUYRyaYG.webp": "chigua",
"https://cdn.nodeimage.com/i/1NPHX79DgNxskE6XuZyxT3s3IjGzVvr8.webp": "weiqu",
"https://cdn.nodeimage.com/i/dhdPfmUJ1wZgDqlcsxIzIMVblUJ1q1Zt.webp": "weiqu",
"https://cdn.nodeimage.com/i/aVRKKCv7C1e3TttRXx9bDdgqWW5CYaQb.webp": "chigua",
"https://cdn.nodeimage.com/i/OefRvbVQdLf8iZZqt49amiteU8CW6cEi.webp": "weiqu",
"https://cdn.nodeimage.com/i/QLhu6wFbgNP0Qqg2ObKCyMqjy2WvBVEu.webp": "weiqu",
"https://cdn.nodeimage.com/i/ahoxBgKxdt1JCSMeXv4d8h6aj6ZlsCED.webp": "chigua",
"https://cdn.nodeimage.com/i/0F8icWwTar1Z0iP07pi4oKv1bpEfdkfg.webp": "chigua",
"https://cdn.nodeimage.com/i/JXQfBalFDqGillv0Ur8azl3tnkEu9m8g.webp": "weiqu",
"https://cdn.nodeimage.com/i/mFW4Tr47fnWRCYs5ywPGcnipsVlxBRdH.webp": "chigua",
"https://cdn.nodeimage.com/i/9MB8mx8QDOcqspQwSfe527VA6KLA3ZGH.webp": "weiqu",
"https://cdn.nodeimage.com/i/oezEmg3ro5cvSoAOcHp8LxW5azS64uVy.webp": "kaixin",
"https://cdn.nodeimage.com/i/hKOdrQgGLXhYgetDkUO9EoOIOndMVY5N.webp": "weiqu",
"https://cdn.nodeimage.com/i/oiy8rFNM2nSN7y2gzXzHDEcUXvHgdYAn.webp": "kaixin",
"https://cdn.nodeimage.com/i/fSv4NUBkgyQ84nnAnbHY5GQuUxWtbqvW.webp": "weiqu",
"https://cdn.nodeimage.com/i/XpCIL0ek4d3VoMYdajWnHqt9LNp1AVi0.webp": "weiqu",
"https://cdn.nodeimage.com/i/0g17Z0pXl4ce9QVOqv2osuVYFhOyR7ur.webp": "kaixin",
"https://cdn.nodeimage.com/i/xNMGqEuVsnUqiQp2jK6cefXMF00odQnV.webp": "weiqu",
"https://cdn.nodeimage.com/i/JQtQRHLLb4KjRk450y2E4LYiGnfuUxBq.webp": "weiqu",
"https://cdn.nodeimage.com/i/00QMQUlje2NYbJv7m9bgbCV6EzOuf2ml.webp": "kaixin",
"https://cdn.nodeimage.com/i/kOtHR5LQ0NBEmM42USEzxh91YNMafFEf.webp": "weiqu",
"https://cdn.nodeimage.com/i/g3fLeoVd8uddMpZCYkN5IVdaGPGK628v.webp": "chigua",
"https://cdn.nodeimage.com/i/RSPL5R9X5GsbGY6RgNmtm5nhYzXDEsyC.webp": "weiqu",
"https://cdn.nodeimage.com/i/yAv9LFBiRnt2dBnuXSiI7Yba3OasBbnv.webp": "kaixin",
"https://cdn.nodeimage.com/i/iPojY1Kv7oIFIIMtgVtlfOSRh4JP5a0O.webp": "chigua",
"https://cdn.nodeimage.com/i/2PKujazf4JuWrj1VHx6tFIp7AkJKcxFR.webp": "chigua",
"https://cdn.nodeimage.com/i/ITs8pMIgID6IpuF6zqibTRwNHgBewAos.webp": "chigua",
"https://cdn.nodeimage.com/i/jpGOKzfczXVyRSx2acQ1Q4CTozeWMfhu.webp": "chigua",
"https://cdn.nodeimage.com/i/YPwKuJE0n12mubDsWS1lt5O1DLtPEnYL.webp": "chigua",
"https://cdn.nodeimage.com/i/lJS7h90l7jFSr73MHb4TRpyUByRUHGSS.webp": "chigua",
"https://cdn.nodeimage.com/i/sZkULJ6ujMuKPhzjYRVj5HXwoxhuj91i.webp": "kaixin",
"https://cdn.nodeimage.com/i/jIxOBPo1aasfMG9vtX2lmdXKlrYlrzn8.webp": "chigua",
"https://cdn.nodeimage.com/i/LQC2wAe6j9Xoq2YPYT3OCGPzVK6BUXeY.webp": "kaixin",
"https://cdn.nodeimage.com/i/kSthzVLv6HY1zz4suH3sy8vDoTmp5ZIO.webp": "gengtu",
"https://cdn.nodeimage.com/i/kl9ooVQRMKmC8mkpCslIU0meTaqN2S3E.webp": "gengtu",
"https://cdn.nodeimage.com/i/MUFCcFraGScTjA7uifnGouCX1NKTZ0A3.webp": "gengtu",
"https://cdn.nodeimage.com/i/Gql10SAUMMkGShynVRHzjjRahXJYkNXB.webp": "gengtu",
"https://cdn.nodeimage.com/i/UbzwRB37Jm06NDAbgbmxu01rPAnybhu7.webp": "gengtu",
"https://cdn.nodeimage.com/i/T5fKEVVhW0COgGZ7KNAsROJeYVGcm37M.webp": "gengtu",
"https://cdn.nodeimage.com/i/Vepi6EWHI3NScN80GJQilQnx2Gb9AyzC.webp": "gengtu",
"https://cdn.nodeimage.com/i/nhpaALWwEGkHnB84nYqK5ReywWQMSXwv.webp": "gengtu",
"https://cdn.nodeimage.com/i/myGs7ZfsJft3u3xPlAcBiGyKq1DM5IAE.webp": "gengtu",
"https://cdn.nodeimage.com/i/M2OKTDg9G5BkdKtQuFBhjmkvkFZ6vGRM.webp": "gengtu",
"https://cdn.nodeimage.com/i/BN9HS2QthEdRMnkD8HRfG7YUCJw62Unl.webp": "gengtu",
"https://cdn.nodeimage.com/i/Wc00G6taGKxvDaTtCqv1YCwuJZEQa1ui.webp": "gengtu",
"https://cdn.nodeimage.com/i/1x3aogCXDNn8QcqsUG3TsBNLoRAzYFXA.webp": "gengtu",
"https://cdn.nodeimage.com/i/AoUnrPjRm5suaaw6Vk5vm9DC3ThUmtPm.webp": "gengtu",
"https://cdn.nodeimage.com/i/IbreqSXkTGKB8lI7nWPNWXf6qnZjTi9M.webp": "gengtu",
"https://cdn.nodeimage.com/i/0mpBkpWpSgBkkL8Hw9KSJDmeQQGZNDEP.webp": "gengtu",
"https://cdn.nodeimage.com/i/efpGAkW3O1EUL58FHizBZbCUlKAcl0Zq.webp": "gengtu",
"https://cdn.nodeimage.com/i/ScbnJdPf3Hw1mWf8wWWvWXisACSenf35.webp": "gengtu",
"https://cdn.nodeimage.com/i/mXKFrUzOlsFxUQ1MgTk7X4GtXRPHR5rK.webp": "gengtu",
"https://cdn.nodeimage.com/i/8WIZnwhX3eNldy5yUdlMZrgy7okYkaSN.webp": "gengtu",
"https://cdn.nodeimage.com/i/wLt0xaL7kkwOEl4q6VuU1g88ntqOk722.webp": "gengtu",
"https://cdn.nodeimage.com/i/Ya8KaVwYDqO1mTPqebTeRjUFr2TMyZ0O.webp": "gengtu",
"https://cdn.nodeimage.com/i/N4XUIBm4KNRo9ysN4PwXGrLMbHllPFZH.webp": "gengtu",
"https://cdn.nodeimage.com/i/WrhtlDF4e2FVTGgP3LYEsGvJlRAMr5qT.webp": "kaixin",
"https://cdn.nodeimage.com/i/9hUzPyjTYKSeUUwNVCJjZd4r3a5MbVst.webp": "kaixin",
"https://cdn.nodeimage.com/i/zKaaAx5QA5DJOwXHomdoVYxlVSOx4XYw.webp": "gengtu",
"https://cdn.nodeimage.com/i/WpfeSAVcdGT6THZ7CucBFQzTJUKnEdlv.webp": "gengtu",
"https://cdn.nodeimage.com/i/J3RQ9zv64vMGQotORHvsig0HxN7wpTWL.webp": "kaixin",
"https://cdn.nodeimage.com/i/upreYjX1tW4abHIPJaMjXueBKXKHXCIF.webp": "kaixin",
"https://cdn.nodeimage.com/i/Nm7WfKnIfYCqg3Gdaf6vXBryvPyqA8YD.webp": "weiqu",
"https://cdn.nodeimage.com/i/sNsHwzI0dtEyVWFKTumoDX4SOx8Ncxo1.webp": "kaixin",
"https://cdn.nodeimage.com/i/Iz5oq4yiE9zaWYN1XBPxMFGujRhvf180.webp": "kaixin",
"https://cdn.nodeimage.com/i/8VkehC61LsB9m2zce46gUCwEagcN7tKg.webp": "weiqu",
"https://cdn.nodeimage.com/i/0MDhgSqmnCiAIg0eZbvU4FCEzCgLtUd7.webp": "weiqu",
"https://cdn.nodeimage.com/i/NwYa2Wxjk87X2quDYDLH9XtPbZAXK4lu.webp": "kaixin",
"https://cdn.nodeimage.com/i/uUG7GSfToq9m6fx9jLPFoQDQpNgEfZLI.webp": "kaixin",
"https://cdn.nodeimage.com/i/Oad0U5Ug01zrPAlk5uyGSZYYaNXt3Kb9.webp": "kaixin",
"https://cdn.nodeimage.com/i/znzD9F3p9mkCWWAUD1K0RV6Yz5Xtq0Bb.webp": "gengtu"
};
const DEFAULT_INITIAL_URLS = Object.keys(baseCategoryMap).concat(hanabiGodSets);
function getAllUrls() {
const userKeys = Object.keys(emojiCounts || {});
return Array.from(new Set(DEFAULT_INITIAL_URLS.concat(userKeys)));
}
const xianxiaTabs = [
{ id: 'bag', name: '须弥纳戒', unlockThreshold: 0 },
{ id: 'artifact', name: '上古法宝', unlockThreshold: 5 },
{ id: 'elixir', name: '仙丹灵饮', unlockThreshold: 12 },
{ id: 'armor', name: '防具秘籍', unlockThreshold: 20 },
{ id: 'godset', name: '花火神装', unlockThreshold: 30 }
];
const SLOT_PAYLINES = [
{ id: 1, indices: [0, 1, 2], name: '第1横行', coords: { x1: 16.7, y1: 16.7, x2: 83.3, y2: 16.7 }, mid: { x: 50.0, y: 16.7 } },
{ id: 2, indices: [3, 4, 5], name: '第2横行', coords: { x1: 16.7, y1: 50.0, x2: 83.3, y2: 50.0 }, mid: { x: 50.0, y: 50.0 } },
{ id: 3, indices: [6, 7, 8], name: '第3横行', coords: { x1: 16.7, y1: 83.3, x2: 83.3, y2: 83.3 }, mid: { x: 50.0, y: 83.3 } },
{ id: 4, indices: [0, 3, 6], name: '第1竖列', coords: { x1: 16.7, y1: 16.7, x2: 16.7, y2: 83.3 }, mid: { x: 16.7, y: 50.0 } },
{ id: 5, indices: [1, 4, 7], name: '第2竖列', coords: { x1: 50.0, y1: 16.7, x2: 50.0, y2: 83.3 }, mid: { x: 50.0, y: 50.0 } },
{ id: 6, indices: [2, 5, 8], name: '第3竖列', coords: { x1: 83.3, y1: 16.7, x2: 83.3, y2: 83.3 }, mid: { x: 83.3, y: 50.0 } },
{ id: 7, indices: [0, 4, 8], name: '主对角线', coords: { x1: 16.7, y1: 16.7, x2: 83.3, y2: 83.3 }, mid: { x: 50.0, y: 50.0 } },
{ id: 8, indices: [2, 4, 6], name: '副对角线', coords: { x1: 83.3, y1: 16.7, x2: 16.7, y2: 83.3 }, mid: { x: 50.0, y: 50.0 } }
];
const adventureNarratives = [
{ place: "潜入太古废弃机房·核心枢纽", event: "斩断万载纠缠之因果禁制", reverse: "自虚空裂隙拾得太初残兵" },
{ place: "探访九幽深处·业火混沌洞府", event: "硬撼护宗无上因果大阵", reverse: "捞出失传已久的造化真经" },
{ place: "登临高强螺母峰·万丈剑绝之巅", event: "直面斩道无上剑意洗礼", reverse: "与沉睡万古的欢愉主宰隔空对弈" },
{ place: "横渡禁断虚空·时空乱流界标", event: "顶住九重寂灭雷劫推演玄机", reverse: "截获一缕鸿蒙始源纯阳真气" }
];
// =========================================================================
// 【模块 2】安全原生 Web Audio 音效引擎
// =========================================================================
let audioCtx = null;
function getAudioContext() {
if (!audioCtx) {
const AudioContextClass = window.AudioContext || window.webkitAudioContext;
if (AudioContextClass) audioCtx = new AudioContextClass();
}
if (audioCtx && audioCtx.state === 'suspended') {
audioCtx.resume().catch(() => {});
}
return audioCtx;
}
function playTone(freq, type, duration, gainVal = 0.08) {
try {
const ctx = getAudioContext();
if (!ctx) return;
const osc = ctx.createOscillator();
const gainNode = ctx.createGain();
osc.type = type;
osc.frequency.setValueAtTime(freq, ctx.currentTime);
gainNode.gain.setValueAtTime(gainVal, ctx.currentTime);
gainNode.gain.exponentialRampToValueAtTime(0.0001, ctx.currentTime + duration);
osc.connect(gainNode);
gainNode.connect(ctx.destination);
osc.onended = () => {
try {
osc.disconnect();
gainNode.disconnect();
} catch (e) { /* ignore */ }
};
osc.start();
osc.stop(ctx.currentTime + duration);
} catch (e) { /* ignore */ }
}
function playLeverPullSound() {
playTone(180, 'sawtooth', 0.1, 0.08);
setTimeout(() => playTone(300, 'triangle', 0.12, 0.06), 60);
}
function playCoinSound() {
playTone(987.77, 'sine', 0.08, 0.1);
setTimeout(() => playTone(1318.51, 'sine', 0.15, 0.12), 60);
}
function playReelStopSound() {
playTone(420, 'sine', 0.06, 0.09);
}
function playWinFanfare(isMega) {
const notes = isMega ? [523, 659, 784, 1046, 1318, 1568] : [587, 740, 880, 1174];
notes.forEach((freq, i) => {
setTimeout(() => playTone(freq, 'triangle', 0.22, 0.14), i * 75);
});
}
// =========================================================================
// 【模块 3】持久化存储与图鉴解锁算法引擎 (含999溢出自动熔炼化晶)
// =========================================================================
const COUNTS_STORAGE_KEY = 'hanabi_emoji_counts_v26.0';
const COINS_STORAGE_KEY = 'hanabi_slot_coins_v26.0';
let isHeheMode = false;
let isLianqiMode = false;
let isSpinningSlot = false;
let activeSlotIntervals = [];
let activeSlotTimeouts = [];
let selectedHeheUrls = [];
let emojiCounts = {};
let slotCoins = 30;
// 动态筹码状态机
let activeBetRatioMode = '1coin';
let progressiveStreak = 0;
let currentCalculatedBet = 1;
let currentBetLabelText = '试刀 1币';
let currentTabId = 'bag';
let lastActiveInput = null;
// ⚔️ 过五关斩六将 经典连胜阶梯
const PROGRESSIVE_STAGES = [
{ name: '首战·破东岭', mult: 1 },
{ name: '过一关·洛阳', mult: 2 },
{ name: '过二关·汜水', mult: 4 },
{ name: '过三关·荥阳', mult: 8 },
{ name: '斩四将·滑州', mult: 16 },
{ name: '过五关·黄河', mult: 32 },
{ name: '斩六将·封神', mult: 64 }
];
const rpgStatsCache = new Map();
if (!window._hanabi_focus_guard_attached) {
document.addEventListener('focusin', function (e) {
const target = e.target;
if (!target) return;
const panel = document.getElementById('hanabi-emoji-panel');
if (panel && panel.contains(target)) return;
if (target.tagName === 'TEXTAREA' || target.isContentEditable || (target.tagName === 'INPUT' && target.type === 'text') || target.classList.contains('vditor-textarea')) {
lastActiveInput = target;
}
}, true);
window._hanabi_focus_guard_attached = true;
}
function clearAllSlotTimers() {
activeSlotIntervals.forEach(id => { if (id) clearInterval(id); });
activeSlotIntervals = [];
activeSlotTimeouts.forEach(id => { if (id) clearTimeout(id); });
activeSlotTimeouts = [];
}
function loadSlotCoins() {
try {
const saved = localStorage.getItem(COINS_STORAGE_KEY);
if (saved !== null) {
const val = parseInt(saved, 10);
return isNaN(val) ? 30 : Math.max(0, val);
}
return 30;
} catch (e) {
return 30;
}
}
function saveSlotCoins() {
try { localStorage.setItem(COINS_STORAGE_KEY, slotCoins.toString()); } catch (err) { /* ignore */ }
}
function setSlotCoins(amount) {
slotCoins = Math.max(0, amount);
saveSlotCoins();
updateCoinsUI();
recalculateBetAmount();
return slotCoins;
}
function addSlotCoins(amount) {
return setSlotCoins(slotCoins + amount);
}
function updateCoinsUI() {
const coinEl = document.getElementById('hnb-arcade-credit-val');
if (coinEl) {
coinEl.textContent = slotCoins.toString().padStart(4, '0');
coinEl.classList.remove('num-flash');
void coinEl.offsetWidth;
coinEl.classList.add('num-flash');
}
}
function recalculateBetAmount() {
const maxCoins = Math.max(1, slotCoins);
if (activeBetRatioMode === '1coin') {
currentCalculatedBet = 1;
currentBetLabelText = '试刀 1币';
} else if (activeBetRatioMode === '0.25') {
currentCalculatedBet = Math.max(1, Math.floor(maxCoins * 0.25));
currentBetLabelText = '问道 1/4';
} else if (activeBetRatioMode === '0.5') {
currentCalculatedBet = Math.max(1, Math.floor(maxCoins * 0.5));
currentBetLabelText = '斩将 半仓';
} else if (activeBetRatioMode === 'allin') {
currentCalculatedBet = maxCoins;
currentBetLabelText = '一梭到底';
} else if (activeBetRatioMode === 'progressive') {
const idx = Math.min(progressiveStreak, PROGRESSIVE_STAGES.length - 1);
const stage = PROGRESSIVE_STAGES[idx];
currentCalculatedBet = Math.min(maxCoins, Math.max(1, stage.mult));
currentBetLabelText = `${stage.name} (${stage.mult}X)`;
} else {
currentCalculatedBet = Math.max(1, Math.min(maxCoins, currentCalculatedBet));
currentBetLabelText = `${currentCalculatedBet}注`;
}
renderBetUI();
}
function renderBetUI() {
const betValEl = document.getElementById('hnb-arcade-bet-val');
const betTagEl = document.getElementById('hnb-bet-tag');
const spinBtn = document.getElementById('hnb-spin-btn');
const statusScreen = document.getElementById('hnb-arcade-status-screen');
if (betValEl) betValEl.textContent = currentCalculatedBet.toString().padStart(4, '0');
if (betTagEl) betTagEl.textContent = currentBetLabelText;
if (spinBtn) {
if (activeBetRatioMode === 'allin') {
spinBtn.textContent = `👑 赌鬼一梭到底 (押入全部 ${currentCalculatedBet} 仙晶)`;
} else {
spinBtn.textContent = `🎰 启 动 天 衍 轮 (消耗 ${currentCalculatedBet} 仙晶 · ${currentBetLabelText})`;
}
}
if (statusScreen && !isSpinningSlot) {
statusScreen.innerHTML = `天机已锁定 · 当前下注 <b style="color:#00ff88;">${currentCalculatedBet}</b> 仙晶 [<span style="color:#f1c40f;">${currentBetLabelText}</span>]`;
}
}
function loadEmojiCounts() {
try {
const saved = JSON.parse(localStorage.getItem(COUNTS_STORAGE_KEY) || 'null');
if (saved && typeof saved === 'object') return saved;
const initial = {};
DEFAULT_INITIAL_URLS.forEach(u => { initial[u] = 0; });
initial[DEFAULT_INITIAL_URLS[0]] = 1; initial[DEFAULT_INITIAL_URLS[1]] = 1;
return initial;
} catch (err) {
const initial = {};
initial[DEFAULT_INITIAL_URLS[0]] = 1;
return initial;
}
}
function saveEmojiCounts() {
try { localStorage.setItem(COUNTS_STORAGE_KEY, JSON.stringify(emojiCounts)); } catch (err) { /* ignore */ }
}
// 💎 核心改造:999 溢出自动熔炼兑换为仙晶彩金
function addEmojiCount(url, addAmount) {
const amount = (typeof addAmount === 'number') ? addAmount : 1;
const cur = emojiCounts[url] || 0;
let next = cur + amount;
let overflowCoins = 0;
if (next > MAX_EMOJI_CAP) {
const overflow = next - MAX_EMOJI_CAP;
next = MAX_EMOJI_CAP;
overflowCoins = overflow * 1; // 1:1 自动熔炼兑换为仙晶彩金
addSlotCoins(overflowCoins);
} else if (next < 0) {
next = 0;
}
const isNewUnlock = (cur === 0 && next > 0);
emojiCounts[url] = next;
saveEmojiCounts();
return { nextCount: next, isNewUnlock, overflowCoins };
}
function getUnlockedCount() {
let count = 0;
getAllUrls().forEach(u => {
if ((emojiCounts[u] || 0) > 0) count++;
});
return count;
}
function getPrioritizedUnlockEmojiUrl(isGodSetOnly = false) {
const pool = isGodSetOnly ? hanabiGodSets : getAllUrls();
const lockedPool = pool.filter(u => (emojiCounts[u] || 0) === 0);
if (lockedPool.length > 0) {
return lockedPool[Math.floor(Math.random() * lockedPool.length)];
}
return pool[Math.floor(Math.random() * pool.length)];
}
function getRandomWeightedEmojiUrl() {
const allUrls = getAllUrls();
const lockedCandidates = allUrls.filter(u => (emojiCounts[u] || 0) === 0);
const unlockedCandidates = allUrls.filter(u => (emojiCounts[u] || 0) > 0);
if (lockedCandidates.length > 0 && Math.random() < 0.60) {
return lockedCandidates[Math.floor(Math.random() * lockedCandidates.length)];
}
if (unlockedCandidates.length > 0) {
return unlockedCandidates[Math.floor(Math.random() * unlockedCandidates.length)];
}
return allUrls[Math.floor(Math.random() * allUrls.length)];
}
function getEmojiRPGStats(url) {
if (rpgStatsCache.has(url)) return rpgStatsCache.get(url);
if (GOD_SET.has(url)) {
const godItem = { name: "花火绝版神装·原初流光", rarity: "UR", slot: "weapon", power: 199 };
rpgStatsCache.set(url, godItem);
return godItem;
}
let hash = 0;
for (let i = 0; i < url.length; i++) hash = ((hash << 5) - hash) + url.charCodeAt(i);
hash = Math.abs(hash);
const slots = ['head', 'glasses', 'ring', 'armor', 'weapon', 'drink', 'doll'];
const computed = { name: `法宝-${hash.toString(16).slice(0,4)}`, rarity: 'SR', slot: slots[hash % slots.length], power: 50 };
rpgStatsCache.set(url, computed);
return computed;
}
function getTabProgress(tabId) {
const allUrls = getAllUrls();
let groupUrls = allUrls;
if (tabId === 'artifact') {
groupUrls = allUrls.filter(u => !GOD_SET.has(u) && ['weapon', 'doll', 'ring'].includes(getEmojiRPGStats(u).slot));
} else if (tabId === 'elixir') {
groupUrls = allUrls.filter(u => !GOD_SET.has(u) && getEmojiRPGStats(u).slot === 'drink');
} else if (tabId === 'armor') {
groupUrls = allUrls.filter(u => !GOD_SET.has(u) && ['armor', 'head', 'glasses'].includes(getEmojiRPGStats(u).slot));
} else if (tabId === 'godset') {
groupUrls = hanabiGodSets;
}
const total = groupUrls.length;
const unlocked = groupUrls.filter(u => (emojiCounts[u] || 0) > 0).length;
return { unlocked, total };
}
function getEpicAdventureOutcome() {
const narrative = adventureNarratives[Math.floor(Math.random() * adventureNarratives.length)];
return {
text: `${narrative.place},${narrative.event},${narrative.reverse}。`,
gratification: "诸天震动,万道共鸣,此番机缘足以让道友道行精进数百年。"
};
}
function isVisible(el) {
return !!(el && !el.disabled && !el.readOnly && (el.offsetWidth > 0 || el.offsetHeight > 0 || el.getClientRects().length > 0));
}
function renderIconElement(targetEl, iconValue) {
if (!iconValue) return;
if (/^https?:\/\//i.test(iconValue)) {
targetEl.innerHTML = `<img src="${iconValue}" class="hnb-card-fill-img" decoding="async" loading="lazy" />`;
} else {
targetEl.innerHTML = `<span class="hnb-card-fill-emoji">${iconValue}</span>`;
}
}
// =========================================================================
// 【模块 4】文本插入与剪贴板引擎
// =========================================================================
function findInputElement() {
const panel = document.getElementById('hanabi-emoji-panel');
if (lastActiveInput && document.body.contains(lastActiveInput) && isVisible(lastActiveInput)) return lastActiveInput;
const active = document.activeElement;
if (active && active !== document.body && panel && !panel.contains(active)) {
if (active.tagName === 'TEXTAREA' || active.isContentEditable || active.classList.contains('vditor-textarea')) return active;
}
const selectors = ['.vditor-textarea', 'textarea', 'div[contenteditable="true"]', '.vditor-reset', 'input[type="text"]'];
for (let i = 0; i < selectors.length; i++) {
const els = document.querySelectorAll(selectors[i]);
for (let j = 0; j < els.length; j++) {
const el = els[j];
if (panel && panel.contains(el)) continue;
if (isVisible(el)) return el;
}
}
return null;
}
function getVditorInstance(el) {
if (window.vditor && typeof window.vditor.insertValue === 'function') return window.vditor;
if (el && el.vditor && typeof el.vditor.insertValue === 'function') return el.vditor;
const vditorEl = document.querySelector('.vditor');
if (vditorEl && vditorEl.vditor && typeof vditorEl.vditor.insertValue === 'function') return vditorEl.vditor;
return null;
}
function insertTextAtCursor(el, text) {
if (!el) return false;
try { el.focus(); } catch (e) { /* ignore */ }
const vInst = getVditorInstance(el);
if (vInst) {
try { vInst.insertValue(text); return true; } catch (e) { /* ignore */ }
}
if (el.isContentEditable) {
try {
document.execCommand('insertText', false, text);
el.dispatchEvent(new Event('input', { bubbles: true }));
return true;
} catch (e) { /* ignore */ }
}
let inserted = false;
try { inserted = document.execCommand('insertText', false, text); } catch (e) { /* ignore */ }
if (!inserted && typeof el.value === 'string') {
const start = el.selectionStart ?? el.value.length;
const end = el.selectionEnd ?? el.value.length;
el.value = el.value.slice(0, start) + text + el.value.slice(end);
el.selectionStart = el.selectionEnd = start + text.length;
el.dispatchEvent(new Event('input', { bubbles: true }));
el.dispatchEvent(new Event('change', { bubbles: true }));
return true;
}
return inserted;
}
function showToast(msg) {
const t = document.createElement('div');
t.textContent = msg;
Object.assign(t.style, { position: 'fixed', bottom: '70px', right: '20px', padding: '6px 14px', borderRadius: '6px', background: 'rgba(20,20,20,0.92)', color: '#fff', fontSize: '11px', zIndex: '100002', boxShadow: '0 4px 12px rgba(0,0,0,0.3)', backdropFilter: 'blur(4px)' });
document.body.appendChild(t);
setTimeout(() => { t.remove(); }, 1200);
}
function fallbackCopy(text) {
const ta = document.createElement('textarea');
ta.value = text;
document.body.appendChild(ta);
ta.select();
document.execCommand('copy');
ta.remove();
}
function copyToClipboard(text) {
if (navigator.clipboard && navigator.clipboard.writeText) {
return navigator.clipboard.writeText(text).catch(() => fallbackCopy(text));
}
fallbackCopy(text);
}
// =========================================================================
// 【模块 5】全隔绝 CSS 样式注入 (高清锐化 + 赛博街机机台)
// =========================================================================
const style = document.createElement('style');
style.textContent = `
#hanabi-emoji-panel {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif !important;
will-change: transform, opacity; contain: layout style paint;
-webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility;
}
#hanabi-emoji-panel * { box-sizing: border-box; }
#hanabi-emoji-panel-grid::-webkit-scrollbar { width: 5px; }
#hanabi-emoji-panel-grid::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.4); border-radius: 3px; }
#hnb-top-cards-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; margin: 2px auto 6px auto; width: 100%; flex-shrink: 0; }
.hnb-top-card {
height: 78px; border-radius: 12px; background: rgba(255, 255, 255, 0.28); border: 1.5px solid rgba(255, 255, 255, 0.65);
padding: 3px; position: relative; display: flex; align-items: center; justify-content: center; cursor: pointer;
overflow: hidden; transition: transform 0.22s cubic-bezier(0.175, 0.885, 0.32, 1.275); box-shadow: 0 4px 12px rgba(0,0,0,0.12); user-select: none;
}
.hnb-top-card:hover { transform: translateY(-2px) scale(1.03); border-color: #ffeaa7; }
.hnb-top-card.card-shake { animation: hnbCardShake 0.35s ease-in-out; }
@keyframes hnbCardShake {
0% { transform: scale(1) rotate(0deg); }
20% { transform: scale(1.1) rotate(-8deg); }
40% { transform: scale(1.1) rotate(8deg); }
60% { transform: scale(1.1) rotate(-6deg); }
80% { transform: scale(1.1) rotate(6deg); }
100% { transform: scale(1) rotate(0deg); }
}
.hnb-card-inner-wrap { width: 100%; height: 100%; border-radius: 10px; overflow: hidden; position: relative; display: flex; align-items: center; justify-content: center; background: rgba(0, 0, 0, 0.05); }
.hnb-card-fill-img { width: 100%; height: 100%; object-fit: cover; border-radius: 10px; transition: transform 0.3s ease; }
.hnb-top-card:hover .hnb-card-fill-img { transform: scale(1.08); }
.hnb-card-fill-emoji { font-size: 28px; line-height: 1; filter: drop-shadow(0 2px 4px rgba(0,0,0,0.3)); }
.hnb-card-title-overlay {
position: absolute; bottom: 2px; left: 2px; right: 2px; height: 18px; line-height: 18px;
font-size: 11px; font-weight: bold; color: #ffffff; text-shadow: 0 1px 3px rgba(0, 0, 0, 0.85);
text-align: center; background: linear-gradient(to top, rgba(0, 0, 0, 0.72) 0%, rgba(0, 0, 0, 0.3) 60%, rgba(0, 0, 0, 0) 100%);
border-radius: 0 0 10px 10px; pointer-events: none; z-index: 2;
}
#hnb-epic-log-ticker {
background: linear-gradient(135deg, rgba(20, 15, 30, 0.85), rgba(40, 30, 50, 0.9));
border: 1px solid rgba(241, 196, 15, 0.4); border-radius: 8px; padding: 6px 10px;
margin-bottom: 6px; color: #fff; font-size: 11px; box-shadow: inset 0 2px 6px rgba(0,0,0,0.4);
display: flex; flex-direction: column; gap: 2px; flex-shrink: 0; min-height: 48px; justify-content: center;
}
#hnb-emoji-cat-tabs { display: flex; gap: 4px; overflow-x: auto; padding-bottom: 5px; margin-bottom: 5px; flex-shrink: 0; }
#hnb-emoji-cat-tabs::-webkit-scrollbar { display: none; }
.hnb-cat-tab-btn {
background: rgba(255,255,255,0.25); border: 1px solid rgba(255,255,255,0.4); padding: 5px 8px;
font-weight: 600; border-radius: 6px; color: #fff; cursor: pointer; position: relative; overflow: hidden;
white-space: nowrap; transition: all .2s; text-shadow: 0 1px 2px rgba(0,0,0,0.3); font-size: 11.5px;
flex-shrink: 0;
}
.hnb-cat-tab-btn:hover { background: rgba(255,255,255,0.4); }
.hnb-cat-tab-btn.active { background: rgba(255, 118, 117, 0.85); border-color: #ff7675; box-shadow: 0 2px 8px rgba(255, 118, 117, 0.4); }
.hnb-cat-tab-btn.locked-tab { opacity: 0.55; filter: grayscale(0.4); }
.hnb-tab-progress-bar {
position: absolute; bottom: 0; left: 0; height: 3px; border-radius: 0 0 6px 6px;
transition: width 0.3s ease; pointer-events: none;
}
#hanabi-emoji-panel-grid {
display: grid;
grid-template-columns: repeat(5, 58px);
grid-auto-rows: 58px;
align-content: start;
justify-content: space-between;
gap: 6px;
overflow-y: auto;
min-height: 200px;
max-height: 260px;
padding-right: 2px;
transform: translateZ(0);
flex-grow: 1;
contain: content;
}
.hnb-emoji-item {
width: 58px;
height: 58px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.hnb-emoji-item img {
width: 100%; height: 100%; border-radius: 8px; object-fit: cover; cursor: pointer;
transition: transform .15s, box-shadow .15s; -webkit-touch-callout: none; -webkit-user-select: none; user-select: none;
}
.hnb-emoji-item img:hover { transform: scale(1.08); box-shadow: 0 4px 10px rgba(0,0,0,0.25); }
.hnb-emoji-count-badge {
position: absolute; right: 2px; bottom: 2px; background: rgba(0,0,0,0.75); color: #ffeaa7;
font-weight: bold; padding: 1px 4px; border-radius: 4px; pointer-events: none;
box-shadow: 0 1px 2px rgba(0,0,0,0.5); border: 0.5px solid rgba(255,255,255,0.3); font-size: 10.5px;
}
.hnb-emoji-item.locked img { filter: grayscale(1) opacity(0.25) blur(0.5px); }
.hnb-emoji-item.locked::after {
content: '🔒'; position: absolute; top: 50%; left: 50%;
transform: translate(-50%, -50%); font-size: 18px; pointer-events: none;
filter: drop-shadow(0 1px 3px rgba(0,0,0,0.8));
}
.hnb-emoji-item.hehe-selected img { border: 3px solid #00b894; box-shadow: 0 0 12px #00b894; transform: scale(1.08); }
#hanabi-emoji-panel.hehe-mode .hnb-emoji-item:not(.locked) img { border: 2px dashed #00b894; opacity: 0.9; }
#hanabi-emoji-panel.lianqi-mode .hnb-emoji-item:not(.locked) img { border: 2px dashed #ff7675; opacity: 0.9; }
#hnb-lianqi-modal-overlay, #hnb-slot-modal-overlay {
position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: rgba(15, 10, 24, 0.97);
backdrop-filter: blur(16px); border-radius: 16px; display: none; flex-direction: column;
align-items: center; justify-content: flex-start; z-index: 100000; padding: 10px; color: #fff; opacity: 0; transition: opacity .2s ease; overflow-y: auto;
}
#hnb-lianqi-modal-overlay.show, #hnb-slot-modal-overlay.show { display: flex; opacity: 1; }
.hnb-lianqi-item-preview { width: 54px; height: 54px; border-radius: 8px; object-fit: cover; border: 2px solid #ff7675; margin-bottom: 6px; }
/* =========================================================================
🎰 赛博街机机台【乾坤天衍·九宫夺宝仪】(高清字体增强)
========================================================================= */
.hnb-arcade-cabinet {
width: 100%; background: linear-gradient(180deg, #2b1836 0%, #160c1d 100%);
border: 3px solid #f1c40f; border-radius: 14px; padding: 8px 6px; position: relative;
box-shadow: 0 0 25px rgba(241, 196, 15, 0.4), inset 0 0 15px rgba(0,0,0,0.85);
display: flex; flex-direction: column; align-items: center;
}
.hnb-arcade-marquee {
width: 100%; display: flex; align-items: center; justify-content: space-between;
background: #0f0714; border: 1.5px solid #e67e22; border-radius: 8px;
padding: 4px 8px; margin-bottom: 6px; box-shadow: inset 0 0 8px rgba(230, 126, 34, 0.5);
}
.hnb-marquee-lights { display: flex; gap: 4px; }
.hnb-bulb {
width: 6px; height: 6px; border-radius: 50%; background: #f1c40f;
box-shadow: 0 0 4px #f1c40f; animation: hnbBulbBlink 0.8s infinite alternate;
}
.hnb-bulb:nth-child(2) { background: #ff7675; box-shadow: 0 0 4px #ff7675; animation-delay: 0.25s; }
.hnb-bulb:nth-child(3) { background: #00cec9; box-shadow: 0 0 4px #00cec9; animation-delay: 0.5s; }
@keyframes hnbBulbBlink {
from { opacity: 0.3; transform: scale(0.85); }
to { opacity: 1; transform: scale(1.15); }
}
.hnb-arcade-dashboard {
width: 100%; display: grid; grid-template-columns: 1.2fr 0.8fr 1fr; gap: 4px;
margin-bottom: 6px;
}
.hnb-dash-screen {
background: #000; border: 1px solid #444; border-radius: 6px; padding: 4px 2px;
display: flex; flex-direction: column; align-items: center; justify-content: center;
box-shadow: inset 0 0 6px rgba(0,0,0,0.9);
}
.hnb-dash-label {
font-size: 10px; color: #cad3df; font-weight: 700; letter-spacing: 0.5px;
text-shadow: 0 1px 2px rgba(0,0,0,0.8); margin-bottom: 1px;
}
.hnb-dash-val {
font-family: "Courier New", Courier, monospace, sans-serif;
font-size: 14px; font-weight: 900; line-height: 1.1;
}
.val-credit { color: #00ff88; text-shadow: 0 0 8px rgba(0,255,136,0.7); }
.val-bet { color: #ffeaa7; text-shadow: 0 0 8px rgba(255,234,167,0.7); }
.val-win { color: #ff3838; text-shadow: 0 0 8px rgba(255,56,56,0.8); }
.num-flash { animation: hnbDashFlash 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); }
@keyframes hnbDashFlash {
0% { transform: scale(1); filter: brightness(1); }
50% { transform: scale(1.2); filter: brightness(2); }
100% { transform: scale(1); filter: brightness(1); }
}
.hnb-fractional-bet-panel {
width: 100%; display: flex; flex-direction: column; gap: 5px;
background: rgba(0,0,0,0.65); border: 1px solid rgba(241,196,15,0.4);
border-radius: 6px; padding: 5px 6px; margin-bottom: 6px;
}
.hnb-bet-row-top { display: flex; align-items: center; justify-content: space-between; }
.hnb-bet-chips-wrap { display: flex; gap: 3px; width: 100%; justify-content: space-between; }
.hnb-bet-chip-btn {
flex: 1; background: linear-gradient(180deg, #34495e 0%, #1a252f 100%);
border: 1px solid #7f8c8d; border-radius: 4px; color: #fff;
font-size: 10.5px; font-weight: 900; padding: 5px 0; cursor: pointer; text-align: center;
transition: all 0.15s ease; user-select: none; letter-spacing: 0.2px;
}
.hnb-bet-chip-btn:hover { border-color: #f1c40f; color: #f1c40f; }
.hnb-bet-chip-btn.active {
background: linear-gradient(180deg, #f1c40f 0%, #d35400 100%);
border-color: #fff; color: #fff; box-shadow: 0 0 10px rgba(241,196,15,0.7);
}
.hnb-bet-chip-btn.chip-allin.active {
background: linear-gradient(180deg, #e74c3c 0%, #c0392b 100%);
box-shadow: 0 0 12px rgba(231,76,60,0.9); animation: hnbAllinPulse 0.6s infinite alternate;
}
@keyframes hnbAllinPulse {
from { transform: scale(0.98); }
to { transform: scale(1.04); }
}
.hnb-stepper-btn {
background: rgba(255,255,255,0.25); border: 1px solid #bbb; border-radius: 4px;
color: #fff; font-weight: bold; width: 24px; height: 20px; font-size: 13px;
display: flex; align-items: center; justify-content: center; cursor: pointer;
}
.hnb-stepper-btn:hover { background: rgba(255,255,255,0.45); }
.hnb-arcade-paybar {
width: 100%; display: grid; grid-template-columns: repeat(4, 1fr); gap: 2px;
background: rgba(0,0,0,0.55); border: 1px dashed rgba(241,196,15,0.4);
border-radius: 5px; padding: 4px 2px; margin-bottom: 6px; font-size: 10px; text-align: center;
}
.hnb-arcade-paybar span { color: #bdc3c7; }
.hnb-arcade-paybar b { color: #f1c40f; display: block; font-size: 10.5px; margin-top: 1px; }
.hnb-reel-chamber {
width: 100%; max-width: 220px; position: relative; margin: 0 auto 6px auto;
border: 3px solid #222; border-radius: 10px; background: #111; overflow: hidden;
box-shadow: inset 0 12px 14px rgba(0,0,0,0.95), inset 0 -12px 14px rgba(0,0,0,0.95), 0 0 12px rgba(0,0,0,0.8);
}
.hnb-reel-chamber.mega-flash { animation: hnbMegaChamberGlow 0.4s infinite alternate; }
@keyframes hnbMegaChamberGlow {
from { border-color: #f1c40f; box-shadow: 0 0 15px #f1c40f, inset 0 0 15px #f1c40f; }
to { border-color: #ff3838; box-shadow: 0 0 25px #ff3838, inset 0 0 25px #ff3838; }
}
.hnb-slot-3x3-grid {
display: grid; grid-template-columns: repeat(3, 1fr); gap: 5px; padding: 6px;
position: relative; z-index: 1;
}
.hnb-slot-cell {
width: 64px; height: 64px; border-radius: 6px; border: 1px solid rgba(255,255,255,0.15);
background: #1a1a1a; display: flex; align-items: center; justify-content: center;
overflow: hidden; position: relative; box-shadow: inset 0 1px 4px rgba(0,0,0,0.8);
transition: transform 0.2s, border-color 0.2s;
}
.hnb-slot-cell img { width: 100%; height: 100%; object-fit: cover; }
.hnb-slot-cell.spinning { filter: blur(0.8px); animation: hnbReelPulser 0.1s infinite alternate; }
.hnb-slot-cell.win-flash {
border-color: #f1c40f !important; box-shadow: 0 0 14px #f1c40f, inset 0 0 8px #f1c40f !important;
animation: hnbWinIconGlow 0.3s infinite alternate; z-index: 3;
}
@keyframes hnbReelPulser {
from { transform: scale(0.96); opacity: 0.8; }
to { transform: scale(1.03); opacity: 1; }
}
@keyframes hnbWinIconGlow {
from { transform: scale(1); filter: brightness(1.1); }
to { transform: scale(1.08); filter: brightness(1.35); }
}
/* ⚡ 双层极光流线与节点光核 */
#hnb-slot-svg-layer {
position: absolute; top: 0; left: 0; width: 100%; height: 100%;
pointer-events: none; z-index: 6; overflow: visible;
}
.hnb-laser-glow {
stroke: #ff7675; stroke-width: 6; stroke-linecap: round; opacity: 0.55;
filter: drop-shadow(0 0 8px #ff7675);
}
.hnb-laser-core {
stroke: #fff; stroke-width: 2.2; stroke-linecap: round;
filter: drop-shadow(0 0 4px #ffeaa7); stroke-dasharray: 8 4;
animation: hnbLaserDashFlow 0.5s linear infinite;
}
.hnb-laser-node {
fill: #fff; stroke: #f1c40f; stroke-width: 1.5;
filter: drop-shadow(0 0 5px #f1c40f);
animation: hnbNodePulse 0.4s infinite alternate;
}
@keyframes hnbLaserDashFlow { to { stroke-dashoffset: -24; } }
@keyframes hnbNodePulse {
from { transform: scale(0.9); opacity: 0.8; }
to { transform: scale(1.25); opacity: 1; }
}
#hnb-mega-badge-overlay {
position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%) scale(0);
background: linear-gradient(135deg, #f1c40f, #e74c3c); color: #fff; font-size: 16px;
font-weight: 900; padding: 8px 16px; border-radius: 30px; border: 3px solid #fff;
box-shadow: 0 0 30px #f1c40f, 0 0 50px #ff3838; z-index: 10; pointer-events: none;
text-shadow: 0 2px 4px rgba(0,0,0,0.8); white-space: nowrap; transition: transform 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
#hnb-mega-badge-overlay.show {
transform: translate(-50%, -50%) scale(1.08);
animation: hnbMegaBadgeShake 0.4s infinite alternate;
}
@keyframes hnbMegaBadgeShake {
from { transform: translate(-50%, -50%) scale(1.05) rotate(-2deg); }
to { transform: translate(-50%, -50%) scale(1.12) rotate(2deg); }
}
#hnb-arcade-status-screen {
width: 100%; background: #000; border: 1px solid #333; border-radius: 6px;
padding: 6px 8px; margin-bottom: 8px; font-size: 11.5px; font-weight: bold;
color: #ffeaa7; text-align: center; min-height: 30px; display: flex; align-items: center; justify-content: center;
box-shadow: inset 0 1px 4px rgba(0,0,0,0.8); line-height: 1.3;
}
.hnb-arcade-btn-spin {
flex: 2; background: linear-gradient(180deg, #ff4757 0%, #b33939 100%);
border: 2px solid #ff6b81; border-radius: 8px; padding: 10px; color: #fff;
font-size: 13px; font-weight: 900; letter-spacing: 0.5px; cursor: pointer;
box-shadow: 0 4px 0 #782020, 0 6px 14px rgba(255, 71, 87, 0.45);
transition: transform 0.1s, box-shadow 0.1s; text-shadow: 0 1px 3px rgba(0,0,0,0.6);
}
.hnb-arcade-btn-spin:hover { filter: brightness(1.1); }
.hnb-arcade-btn-spin:active {
transform: translateY(3px); box-shadow: 0 1px 0 #782020, 0 2px 6px rgba(255, 71, 87, 0.4);
}
.hnb-arcade-btn-spin:disabled {
opacity: 0.55; cursor: not-allowed; transform: none; filter: grayscale(0.5);
}
.hnb-control-button { background: rgba(255,255,255,0.25); border: 1px solid rgba(255,255,255,0.3); padding: 6px 14px; font-weight: 600; border-radius: 6px; color: white; cursor: pointer; transition: background .2s, transform .1s; font-size: 11.5px; }
.hnb-control-button:hover { background: rgba(255,255,255,0.4); }
.hnb-control-button:active { transform: scale(0.96); }
`;
document.head.appendChild(style);
// =========================================================================
// 【模块 6】全局 UI 渲染与视图调度 (Tabs & Emojis)
// =========================================================================
function renderTabs() {
const tabsContainer = document.getElementById('hnb-emoji-cat-tabs');
if (!tabsContainer) return;
tabsContainer.innerHTML = '';
const unlockedTotalCount = getUnlockedCount();
xianxiaTabs.forEach(tab => {
const isUnlocked = unlockedTotalCount >= tab.unlockThreshold;
const progress = getTabProgress(tab.id);
const btn = document.createElement('button');
btn.className = `hnb-cat-tab-btn ${currentTabId === tab.id ? 'active' : ''} ${!isUnlocked ? 'locked-tab' : ''}`;
if (isUnlocked) {
const percent = progress.total > 0 ? Math.round((progress.unlocked / progress.total) * 100) : 0;
let barColor = "#ff7675";
if (percent > 75) barColor = "#00b894";
else if (percent > 50) barColor = "#0984e3";
else if (percent > 25) barColor = "#f39c12";
btn.innerHTML = `${tab.name}<div class="hnb-tab-progress-bar" style="width: ${percent}%; background: ${barColor};"></div>`;
} else {
btn.innerHTML = `${tab.name}`;
}
btn.onclick = () => {
if (isUnlocked) {
currentTabId = tab.id;
renderTabs();
renderEmojis();
} else {
showToast(`需累计解封 ${tab.unlockThreshold} 个法宝方可开启此阁楼。`);
}
};
tabsContainer.appendChild(btn);
});
}
function renderEmojis() {
const grid = document.getElementById('hanabi-emoji-panel-grid');
if (!grid) return;
grid.innerHTML = '';
const allUrls = getAllUrls();
let renderList = [];
if (currentTabId === 'bag') {
renderList = allUrls.filter(u => (emojiCounts[u] || 0) > 0);
} else if (currentTabId === 'artifact') {
renderList = allUrls.filter(u => !GOD_SET.has(u) && ['weapon', 'doll', 'ring'].includes(getEmojiRPGStats(u).slot));
} else if (currentTabId === 'elixir') {
renderList = allUrls.filter(u => !GOD_SET.has(u) && getEmojiRPGStats(u).slot === 'drink');
} else if (currentTabId === 'armor') {
renderList = allUrls.filter(u => !GOD_SET.has(u) && ['armor', 'head', 'glasses'].includes(getEmojiRPGStats(u).slot));
} else if (currentTabId === 'godset') {
renderList = hanabiGodSets;
} else {
renderList = allUrls;
}
const frag = document.createDocumentFragment();
renderList.forEach(url => {
const count = emojiCounts[url] || 0;
const isUnlocked = count > 0;
const item = document.createElement('div');
item.className = `hnb-emoji-item ${!isUnlocked ? 'locked' : ''} ${selectedHeheUrls.includes(url) ? 'hehe-selected' : ''}`;
const img = document.createElement('img');
img.src = url;
img.loading = 'lazy';
img.decoding = 'async';
item.appendChild(img);
if (isUnlocked) {
const badge = document.createElement('div');
badge.className = 'hnb-emoji-count-badge';
badge.textContent = `x${count}`;
item.appendChild(badge);
}
frag.appendChild(item);
});
grid.appendChild(frag);
}
// =========================================================================
// 【模块 7】事件逻辑绑定与【乾坤天衍·九宫夺宝仪】引擎
// =========================================================================
function bindEvents(cardChigua, cardGacha, cardSlot, addButton, heheModeButton, lianqiModeButton, grid, urlInput, lianqiModal, slotModal, heheTip, epicLogTicker, panel) {
function handleHeheFusionClick(url) {
const count = emojiCounts[url] || 0;
if (count <= 0) return showToast('未解封法宝无法参与万法归一。');
if (selectedHeheUrls.includes(url)) selectedHeheUrls = selectedHeheUrls.filter(u => u !== url);
else {
if (selectedHeheUrls.length >= 2) selectedHeheUrls.shift();
selectedHeheUrls.push(url);
}
updateHeheTip();
renderEmojis();
if (selectedHeheUrls.length === 2) {
const u1 = selectedHeheUrls[0];
const u2 = selectedHeheUrls[1];
addEmojiCount(u1, -1);
addEmojiCount(u2, -1);
const outputUrl = getRandomWeightedEmojiUrl();
selectedHeheUrls = [];
updateHeheTip();
const res = addEmojiCount(outputUrl, 1);
showToast(res.isNewUnlock ? '万法归一成功,解封获得了全新法宝!' : '万法归一成功,推演获得了法宝!');
renderTabs();
renderEmojis();
}
}
function updateHeheTip() {
if (!isHeheMode) { heheTip.style.display = 'none'; return; }
heheTip.style.display = 'block';
heheTip.textContent = selectedHeheUrls.length === 0 ? '请选择第1个融合法宝材料' : (selectedHeheUrls.length === 1 ? '已选1个,请选择第2个材料' : '正在推演融合中...');
}
function openLianqiModal(url) {
const count = emojiCounts[url] || 0;
lianqiModal.innerHTML = `
<div style="font-weight:bold;margin-bottom:8px;color:#f39c12;font-size:13px;">宗门炼器熔炉</div>
<div style="display:flex;align-items:center;gap:10px;background:rgba(255,255,255,0.06);padding:8px;border-radius:8px;margin-bottom:10px;width:100%;">
<img src="${url}" class="hnb-lianqi-item-preview" style="margin-bottom:0;" decoding="async" />
<div style="text-align:left;flex-grow:1;min-width:0;">
<div style="font-weight:bold;font-size:11.5px;">宗门专属法宝</div>
<div style="color:#ffeaa7;font-size:10.5px;">当前库存:<b>x${count}</b></div>
</div>
</div>
<div style="font-size:11px;color:#ddd;margin-bottom:6px;">调整祭献数量:</div>
<div style="display:flex;gap:6px;align-items:center;margin-bottom:12px;width:100%;">
<button class="hnb-control-button" id="lianqi-minus" style="padding:4px 10px;">-</button>
<input type="number" id="lianqi-input-amt" value="1" min="1" max="${count}" style="width:70px;text-align:center;background:rgba(0,0,0,0.3);border:1px solid rgba(255,255,255,0.3);color:#fff;border-radius:4px;padding:4px;font-size:12px;">
<button class="hnb-control-button" id="lianqi-plus" style="padding:4px 10px;">+</button>
<button class="hnb-control-button" id="lianqi-all" style="background:rgba(231,76,60,0.8);padding:4px 10px;font-size:11px;">全部</button>
</div>
<div style="display:flex;gap:6px;width:100%;">
<button class="hnb-control-button" style="flex:1;background:rgba(0,184,148,0.9);padding:6px;font-size:11.5px;" id="lianqi-confirm">确认祭献炼化</button>
<button class="hnb-control-button" style="flex:1;background:rgba(100,100,100,0.6);padding:6px;font-size:11.5px;" id="l-close">关闭熔炉</button>
</div>
`;
const inputAmt = lianqiModal.querySelector('#lianqi-input-amt');
lianqiModal.querySelector('#lianqi-minus').onclick = () => {
let val = parseInt(inputAmt.value, 10) || 1;
if (val > 1) inputAmt.value = val - 1;
};
lianqiModal.querySelector('#lianqi-plus').onclick = () => {
let val = parseInt(inputAmt.value, 10) || 1;
if (val < count) inputAmt.value = val + 1;
};
lianqiModal.querySelector('#lianqi-all').onclick = () => {
inputAmt.value = count;
};
lianqiModal.querySelector('#lianqi-confirm').onclick = () => {
const amt = parseInt(inputAmt.value, 10) || 1;
if (amt > count) return showToast('库存不足。');
doLianqi(url, amt);
};
lianqiModal.querySelector('#l-close').onclick = () => { lianqiModal.classList.remove('show'); };
lianqiModal.classList.add('show');
}
function doLianqi(url, amt) {
addEmojiCount(url, -amt);
lianqiModal.classList.remove('show');
const targetUrl = getRandomWeightedEmojiUrl();
const res = addEmojiCount(targetUrl, amt);
showToast(res.isNewUnlock ? `炼器炉运转成功,解封全新法宝 x${amt}` : `炼器炉运转成功,凝练获得法宝 x${amt}`);
renderTabs();
renderEmojis();
}
// 🎰 3x3 赛博街机【乾坤天衍·九宫夺宝仪】渲染 (高清锐化版)
function openSlotModal() {
const allUrls = getAllUrls();
let cellsHTML = '';
for (let i = 0; i < 9; i++) {
const initUrl = allUrls[Math.floor(Math.random() * allUrls.length)];
cellsHTML += `<div class="hnb-slot-cell" id="hnb-cell-${i}"><img src="${initUrl}" decoding="async" /></div>`;
}
slotModal.innerHTML = `
<div class="hnb-arcade-cabinet">
<!-- 顶部跑马灯招牌 -->
<div class="hnb-arcade-marquee">
<div class="hnb-marquee-lights">
<div class="hnb-bulb"></div><div class="hnb-bulb"></div><div class="hnb-bulb"></div>
</div>
<div style="font-weight:900;color:#f1c40f;font-size:12.5px;letter-spacing:1px;text-shadow:0 0 8px rgba(241,196,15,0.8);">
🎰 乾坤天衍 · 九宫夺宝仪
</div>
<div class="hnb-marquee-lights">
<div class="hnb-bulb"></div><div class="hnb-bulb"></div><div class="hnb-bulb"></div>
</div>
</div>
<!-- 街机数码管仪表盘 (高清大字) -->
<div class="hnb-arcade-dashboard">
<div class="hnb-dash-screen">
<div class="hnb-dash-label">🪙 仙晶余量</div>
<div class="hnb-dash-val val-credit" id="hnb-arcade-credit-val">${slotCoins.toString().padStart(4, '0')}</div>
</div>
<div class="hnb-dash-screen">
<div class="hnb-dash-label">⚡ 押注额度</div>
<div class="hnb-dash-val val-bet" id="hnb-arcade-bet-val">${currentCalculatedBet.toString().padStart(4, '0')}</div>
</div>
<div class="hnb-dash-screen">
<div class="hnb-dash-label">🏆 赢取彩金</div>
<div class="hnb-dash-val val-win" id="hnb-arcade-win-val">0000</div>
</div>
</div>
<!-- 🪙 修仙境界动态筹码面板 (高清文字增强) -->
<div class="hnb-fractional-bet-panel">
<div class="hnb-bet-row-top">
<span style="font-size:10.5px;color:#ffeaa7;font-weight:bold;">⚡ 修仙天命筹码:</span>
<div style="display:flex;gap:4px;align-items:center;">
<button class="hnb-stepper-btn" id="hnb-bet-minus" title="减少1注">-</button>
<span id="hnb-bet-tag" style="font-size:10.5px;color:#00ff88;font-weight:bold;min-width:60px;text-align:center;">${currentBetLabelText}</span>
<button class="hnb-stepper-btn" id="hnb-bet-plus" title="增加1注">+</button>
</div>
</div>
<div class="hnb-bet-chips-wrap">
<button class="hnb-bet-chip-btn ${activeBetRatioMode === '1coin' ? 'active' : ''}" data-mode="1coin">试刀1币</button>
<button class="hnb-bet-chip-btn ${activeBetRatioMode === '0.25' ? 'active' : ''}" data-mode="0.25">问道1/4</button>
<button class="hnb-bet-chip-btn ${activeBetRatioMode === '0.5' ? 'active' : ''}" data-mode="0.5">斩将半仓</button>
<button class="hnb-bet-chip-btn ${activeBetRatioMode === 'progressive' ? 'active' : ''}" data-mode="progressive" title="过五关斩六将连胜阶梯">过关斩将</button>
<button class="hnb-bet-chip-btn chip-allin ${activeBetRatioMode === 'allin' ? 'active' : ''}" data-mode="allin" title="全仓梭哈">一梭到底</button>
</div>
</div>
<!-- 常驻街机微赔率表 (高清增强) -->
<div class="hnb-arcade-paybar">
<div><span>👑全盘8线</span><b>+50x币+URx10</b></div>
<div><span>🔥多线Combo</span><b>+10x币+双倍</b></div>
<div><span>🌟单线贯穿</span><b>+3x币+法宝x2</b></div>
<div><span>🎁逆风感悟</span><b>必得新法宝x1</b></div>
</div>
<!-- 3D 机械滚筒视窗 Chamber -->
<div class="hnb-reel-chamber" id="hnb-reel-chamber">
<div id="hnb-mega-badge-overlay">👑 MEGA WIN 👑</div>
<svg id="hnb-slot-svg-layer" viewBox="0 0 100 100" preserveAspectRatio="none"></svg>
<div class="hnb-slot-3x3-grid">${cellsHTML}</div>
</div>
<!-- LED 电子滚动状态公告屏 (高清大字) -->
<div id="hnb-arcade-status-screen">
天地造化尽在卦中 · 当前下注 ${currentCalculatedBet} 仙晶 [${currentBetLabelText}]
</div>
<!-- 实体拍键操作台 -->
<div style="display:flex;gap:8px;width:100%;">
<button class="hnb-arcade-btn-spin" id="hnb-spin-btn">🎰 启 动 天 衍 轮</button>
<button class="hnb-control-button" style="flex:1;background:rgba(80,80,80,0.6);" id="hnb-slot-close">退出</button>
</div>
</div>
`;
const spinBtn = slotModal.querySelector('#hnb-spin-btn');
const closeBtn = slotModal.querySelector('#hnb-slot-close');
slotModal.querySelectorAll('.hnb-bet-chip-btn').forEach(btn => {
btn.onclick = () => {
if (isSpinningSlot) return;
activeBetRatioMode = btn.getAttribute('data-mode');
if (activeBetRatioMode === 'progressive') {
progressiveStreak = 0;
}
slotModal.querySelectorAll('.hnb-bet-chip-btn').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
recalculateBetAmount();
playTone(600, 'sine', 0.04, 0.05);
};
});
slotModal.querySelector('#hnb-bet-minus').onclick = () => {
if (isSpinningSlot) return;
activeBetRatioMode = 'custom';
currentCalculatedBet = Math.max(1, currentCalculatedBet - 1);
slotModal.querySelectorAll('.hnb-bet-chip-btn').forEach(b => b.classList.remove('active'));
recalculateBetAmount();
playTone(450, 'sine', 0.03, 0.04);
};
slotModal.querySelector('#hnb-bet-plus').onclick = () => {
if (isSpinningSlot) return;
activeBetRatioMode = 'custom';
currentCalculatedBet = Math.min(Math.max(1, slotCoins), currentCalculatedBet + 1);
slotModal.querySelectorAll('.hnb-bet-chip-btn').forEach(b => b.classList.remove('active'));
recalculateBetAmount();
playTone(700, 'sine', 0.03, 0.04);
};
spinBtn.onclick = () => { run3x3SlotMachine(); };
closeBtn.onclick = () => {
if (!isSpinningSlot) {
clearAllSlotTimers();
slotModal.classList.remove('show');
}
};
recalculateBetAmount();
slotModal.classList.add('show');
}
// 🎰 3x3 夺宝仪核心推演引擎 (带化晶彩金结算)
function run3x3SlotMachine() {
if (isSpinningSlot) return;
const winValEl = slotModal.querySelector('#hnb-arcade-win-val');
const statusScreen = slotModal.querySelector('#hnb-arcade-status-screen');
const chamberEl = slotModal.querySelector('#hnb-reel-chamber');
const megaBadge = slotModal.querySelector('#hnb-mega-badge-overlay');
const svgLayer = slotModal.querySelector('#hnb-slot-svg-layer');
const spinBtn = slotModal.querySelector('#hnb-spin-btn');
if (slotCoins < 1) {
statusScreen.innerHTML = `<span style="color:#00ff88;">【乾坤聚灵】道友仙晶见底,天地有感特赐 +10 仙晶!</span>`;
addSlotCoins(10);
playCoinSound();
return;
}
// 实时重算当前有效下注
recalculateBetAmount();
const betAmt = currentCalculatedBet;
addSlotCoins(-betAmt);
isSpinningSlot = true;
clearAllSlotTimers();
playLeverPullSound();
if (winValEl) winValEl.textContent = '0000';
if (megaBadge) megaBadge.classList.remove('show');
if (chamberEl) chamberEl.classList.remove('mega-flash');
if (svgLayer) svgLayer.innerHTML = '';
spinBtn.disabled = true;
statusScreen.innerHTML = `<span style="color:#ffeaa7;">九宫星轮飞旋逆转 · [${currentBetLabelText} | ${betAmt}注] 正在窥探天道因果...</span>`;
const cells = [];
for (let i = 0; i < 9; i++) {
const cell = slotModal.querySelector(`#hnb-cell-${i}`);
cell.classList.remove('win-flash');
cell.classList.add('spinning');
cells.push(cell);
}
// 真实数学模型:2% 全盘大满贯 | 12% 多线连爆 | 34% 单线中奖 | 52% 散盘保底
const roll = Math.random();
const gridResults = new Array(9);
if (roll < 0.02) {
const target = getPrioritizedUnlockEmojiUrl(true);
gridResults.fill(target);
} else if (roll < 0.14) {
const symbolA = getPrioritizedUnlockEmojiUrl(false);
const symbolB = getRandomWeightedEmojiUrl();
gridResults[0] = symbolA; gridResults[1] = symbolA; gridResults[2] = symbolA;
gridResults[3] = symbolA; gridResults[4] = symbolB; gridResults[5] = symbolB;
gridResults[6] = symbolA; gridResults[7] = symbolB; gridResults[8] = symbolB;
} else if (roll < 0.48) {
const symbolA = getPrioritizedUnlockEmojiUrl(false);
gridResults[0] = symbolA; gridResults[1] = symbolA; gridResults[2] = symbolA;
gridResults[3] = getRandomWeightedEmojiUrl(); gridResults[4] = getRandomWeightedEmojiUrl(); gridResults[5] = getRandomWeightedEmojiUrl();
gridResults[6] = getRandomWeightedEmojiUrl(); gridResults[7] = getRandomWeightedEmojiUrl(); gridResults[8] = getRandomWeightedEmojiUrl();
} else {
for (let i = 0; i < 9; i++) gridResults[i] = getRandomWeightedEmojiUrl();
}
const allDynamicUrls = getAllUrls();
activeSlotIntervals = cells.map(cell => {
return setInterval(() => {
const randUrl = allDynamicUrls[Math.floor(Math.random() * allDynamicUrls.length)];
const img = cell.querySelector('img');
if (img) img.src = randUrl;
}, 50);
});
// 第 1 列停轮
activeSlotTimeouts.push(setTimeout(() => {
[0, 3, 6].forEach(idx => {
if (activeSlotIntervals[idx]) clearInterval(activeSlotIntervals[idx]);
cells[idx].classList.remove('spinning');
cells[idx].querySelector('img').src = gridResults[idx];
});
playReelStopSound();
}, 750));
// 第 2 列停轮
activeSlotTimeouts.push(setTimeout(() => {
[1, 4, 7].forEach(idx => {
if (activeSlotIntervals[idx]) clearInterval(activeSlotIntervals[idx]);
cells[idx].classList.remove('spinning');
cells[idx].querySelector('img').src = gridResults[idx];
});
playReelStopSound();
}, 1250));
// 第 3 列停轮并结算
activeSlotTimeouts.push(setTimeout(() => {
[2, 5, 8].forEach(idx => {
if (activeSlotIntervals[idx]) clearInterval(activeSlotIntervals[idx]);
cells[idx].classList.remove('spinning');
cells[idx].querySelector('img').src = gridResults[idx];
});
playReelStopSound();
clearAllSlotTimers();
const winningLines = [];
const winningCellsSet = new Set();
SLOT_PAYLINES.forEach(payline => {
const [a, b, c] = payline.indices;
if (gridResults[a] === gridResults[b] && gridResults[b] === gridResults[c]) {
winningLines.push(payline);
winningCellsSet.add(a);
winningCellsSet.add(b);
winningCellsSet.add(c);
}
});
isSpinningSlot = false;
spinBtn.disabled = false;
const isFullHouse = (winningCellsSet.size === 9);
const lineCount = winningLines.length;
const isWin = (isFullHouse || lineCount > 0);
// 过五关斩六将连胜推进
if (activeBetRatioMode === 'progressive') {
if (isWin) {
progressiveStreak = Math.min(progressiveStreak + 1, PROGRESSIVE_STAGES.length - 1);
} else {
progressiveStreak = 0;
}
}
winningCellsSet.forEach(idx => {
cells[idx].classList.add('win-flash');
});
// 渲染极光射线
if (isFullHouse) {
if (chamberEl) chamberEl.classList.add('mega-flash');
if (megaBadge) megaBadge.classList.add('show');
} else if (svgLayer && winningLines.length > 0) {
winningLines.forEach(lineObj => {
const glowLine = document.createElementNS('http://www.w3.org/2000/svg', 'line');
glowLine.setAttribute('x1', lineObj.coords.x1.toString());
glowLine.setAttribute('y1', lineObj.coords.y1.toString());
glowLine.setAttribute('x2', lineObj.coords.x2.toString());
glowLine.setAttribute('y2', lineObj.coords.y2.toString());
glowLine.setAttribute('class', 'hnb-laser-glow');
const coreLine = document.createElementNS('http://www.w3.org/2000/svg', 'line');
coreLine.setAttribute('x1', lineObj.coords.x1.toString());
coreLine.setAttribute('y1', lineObj.coords.y1.toString());
coreLine.setAttribute('x2', lineObj.coords.x2.toString());
coreLine.setAttribute('y2', lineObj.coords.y2.toString());
coreLine.setAttribute('class', 'hnb-laser-core');
const nodePoints = [
{ x: lineObj.coords.x1, y: lineObj.coords.y1 },
{ x: lineObj.mid.x, y: lineObj.mid.y },
{ x: lineObj.coords.x2, y: lineObj.coords.y2 }
];
svgLayer.append(glowLine, coreLine);
nodePoints.forEach(pt => {
const node = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
node.setAttribute('cx', pt.x.toString());
node.setAttribute('cy', pt.y.toString());
node.setAttribute('r', '2.5');
node.setAttribute('class', 'hnb-laser-node');
svgLayer.appendChild(node);
});
});
}
let summaryText = '';
let hasNewUnlock = false;
let totalOverflowCoins = 0;
if (isFullHouse) {
playWinFanfare(true);
const winCoins = 50 * betAmt;
const winEmoteAmt = 10 * betAmt;
addSlotCoins(winCoins);
if (winValEl) winValEl.textContent = `+${winCoins.toString().padStart(4, '0')}`;
const targetUrl = gridResults[0];
const res = addEmojiCount(targetUrl, winEmoteAmt);
if (res.isNewUnlock) hasNewUnlock = true;
totalOverflowCoins += (res.overflowCoins || 0);
summaryText = `👑【全盘通天 · 极道大满贯】八卦齐鸣![${currentBetLabelText}] 狂揽 +${winCoins}仙晶 & UR神装x${winEmoteAmt} ${hasNewUnlock ? '✨[解封全新UR!]' : ''}`;
} else if (lineCount > 1) {
playWinFanfare(false);
const winCoins = 10 * betAmt;
const winEmoteAmt = 2 * betAmt;
addSlotCoins(winCoins);
if (winValEl) winValEl.textContent = `+${winCoins.toString().padStart(4, '0')}`;
winningCellsSet.forEach(idx => {
const res = addEmojiCount(gridResults[idx], winEmoteAmt);
if (res.isNewUnlock) hasNewUnlock = true;
totalOverflowCoins += (res.overflowCoins || 0);
});
summaryText = `🔥【多线连爆 · 气运翻腾】达成 ${lineCount} 条贯穿仙脉![${currentBetLabelText}] 暴击 +${winCoins}仙晶,双倍入库 ${hasNewUnlock ? '✨[解封新图鉴!]' : ''}`;
} else if (lineCount === 1) {
playWinFanfare(false);
const winCoins = 3 * betAmt;
const winEmoteAmt = 2 * betAmt;
addSlotCoins(winCoins);
if (winValEl) winValEl.textContent = `+${winCoins.toString().padStart(4, '0')}`;
const matchedUrl = gridResults[winningLines[0].indices[0]];
const res = addEmojiCount(matchedUrl, winEmoteAmt);
if (res.isNewUnlock) hasNewUnlock = true;
totalOverflowCoins += (res.overflowCoins || 0);
summaryText = `🎉【${winningLines[0].name}贯穿】法力流转![${currentBetLabelText}] +${winCoins}仙晶,法宝x${winEmoteAmt} ${hasNewUnlock ? '✨[解封新图鉴!]' : ''}`;
} else {
const consolationUrl = getPrioritizedUnlockEmojiUrl(false);
const res = addEmojiCount(consolationUrl, 1);
if (res.isNewUnlock) hasNewUnlock = true;
totalOverflowCoins += (res.overflowCoins || 0);
summaryText = `🌟【偶得机缘】卦象未成连线,宗门特赐法宝 x1 以固道心! ${hasNewUnlock ? '✨[解封新图鉴!]' : ''}`;
}
// 💎 若有溢出自动熔炼,追加提示
if (totalOverflowCoins > 0) {
summaryText += ` 💎【九极化晶】溢出法宝自动熔炼额外获得 +${totalOverflowCoins}仙晶!`;
playCoinSound();
}
statusScreen.innerHTML = `<span style="color:#f1c40f;">${summaryText}</span>`;
epicLogTicker.innerHTML = `
<div style="color:#f1c40f;font-weight:bold;">【🎰 九宫夺宝仪推演结果】</div>
<div style="color:#fff;font-size:10px;line-height:1.2;">${summaryText}</div>
`;
renderTabs();
renderEmojis();
}, 1750));
}
cardChigua.onclick = () => {
triggerCardShake(cardChigua);
const drawCount = Math.floor(Math.random() * 3) + 1;
let newUnlockCount = 0;
let totalOverflow = 0;
let lastUrl = getRandomWeightedEmojiUrl();
for (let i = 0; i < drawCount; i++) {
const randomUrl = getRandomWeightedEmojiUrl();
const res = addEmojiCount(randomUrl, 1);
if (res.isNewUnlock) newUnlockCount++;
totalOverflow += (res.overflowCoins || 0);
lastUrl = randomUrl;
}
if (Math.random() < 0.5) addSlotCoins(2);
const epicOutcome = getEpicAdventureOutcome();
epicLogTicker.innerHTML = `
<div style="color:#f39c12;font-weight:bold;">【宗门秘境历练大捷】</div>
<div style="color:#fff;font-size:10px;line-height:1.2;">${epicOutcome.text}</div>
<div style="color:#ffeaa7;font-size:9px;">入库法宝: <b>${drawCount} 件</b> ${newUnlockCount > 0 ? `| 解封新图鉴: <b>${newUnlockCount} 个</b>` : ''} ${totalOverflow > 0 ? `| 💎溢出化晶: <b>+${totalOverflow}仙晶</b>` : ''}</div>
`;
const markdown = `:::details 吃瓜\n\n:::\n`;
copyToClipboard(markdown);
const input = findInputElement();
const success = input ? insertTextAtCursor(input, markdown) : false;
if (success) {
showToast('表情已成功插入光标处。');
} else {
showToast('找不到打开的回复框,已自动复制 Markdown。');
}
renderTabs();
renderEmojis();
};
cardGacha.onclick = () => {
triggerCardShake(cardGacha);
const drawCount = Math.floor(Math.random() * 3) + 1;
let newUnlockCount = 0;
let totalOverflow = 0;
let lastUrl = getRandomWeightedEmojiUrl();
for (let i = 0; i < drawCount; i++) {
const randomUrl = getRandomWeightedEmojiUrl();
const res = addEmojiCount(randomUrl, 1);
if (res.isNewUnlock) newUnlockCount++;
totalOverflow += (res.overflowCoins || 0);
lastUrl = randomUrl;
}
addSlotCoins(3);
playCoinSound();
const epicOutcome = getEpicAdventureOutcome();
epicLogTicker.innerHTML = `
<div style="color:#f39c12;font-weight:bold;">【秘境寻宝纳珍圆满】</div>
<div style="color:#fff;font-size:10px;line-height:1.2;">${epicOutcome.text}</div>
<div style="color:#ffeaa7;font-size:9px;">入库法宝: <b>${drawCount} 件</b> | 获得仙晶: <b>+3</b> ${totalOverflow > 0 ? `| 💎溢出化晶: <b>+${totalOverflow}</b>` : ''}</div>
`;
const markdown = `\n`;
copyToClipboard(markdown);
const input = findInputElement();
const success = input ? insertTextAtCursor(input, markdown) : false;
if (success) {
showToast('表情已成功插入光标处。');
} else {
showToast('找不到打开的回复框,已自动复制 Markdown。');
}
renderTabs();
renderEmojis();
};
cardSlot.onclick = () => {
triggerCardShake(cardSlot);
openSlotModal();
};
function triggerCardShake(cardEl) {
cardEl.classList.remove('card-shake');
void cardEl.offsetWidth;
cardEl.classList.add('card-shake');
}
grid.onclick = e => {
const img = e.target.closest('img');
if (!img) return;
const item = img.closest('.hnb-emoji-item');
const isLocked = item ? item.classList.contains('locked') : false;
const url = img.src;
if (isHeheMode) { handleHeheFusionClick(url); return; }
if (isLianqiMode) { if (!isLocked) openLianqiModal(url); return; }
if (isLocked) { showToast('此法宝尚未解封,请前往九宫夺宝仪或抽卡获得造化。'); return; }
addEmojiCount(url, -1);
renderTabs();
renderEmojis();
const markdown = `\n`;
copyToClipboard(markdown);
const input = findInputElement();
const success = input ? insertTextAtCursor(input, markdown) : false;
if (success) {
showToast('表情已成功插入光标处。');
} else {
showToast('找不到打开的回复框,已自动复制 Markdown。');
}
};
addButton.onclick = () => {
const url = urlInput.value.trim();
if (!/^https?:\/\//i.test(url)) return showToast('请输入有效的图片链接。');
const res = addEmojiCount(url, 1);
urlInput.value = '';
currentTabId = 'bag';
renderTabs();
renderEmojis();
if (res.overflowCoins > 0) {
showToast(`✨ 法宝达999极道上限,溢出部分已自动熔炼为 +${res.overflowCoins} 仙晶!`);
} else {
showToast(res.isNewUnlock ? '✨ 新法宝已成功录入须弥纳戒!' : '法宝库存已增加 x1');
}
};
heheModeButton.onclick = () => {
isHeheMode = !isHeheMode;
if (isHeheMode) {
isLianqiMode = false;
panel.classList.remove('lianqi-mode');
panel.classList.add('hehe-mode');
heheModeButton.textContent = '结束融合';
} else {
panel.classList.remove('hehe-mode');
selectedHeheUrls = [];
updateHeheTip();
heheModeButton.textContent = '万法归一';
}
lianqiModeButton.textContent = '炼器熔炉';
};
lianqiModeButton.onclick = () => {
isLianqiMode = !isLianqiMode;
if (isLianqiMode) {
isHeheMode = false;
panel.classList.remove('hehe-mode');
panel.classList.add('lianqi-mode');
selectedHeheUrls = [];
updateHeheTip();
lianqiModeButton.textContent = '离开熔炉';
} else {
panel.classList.remove('lianqi-mode');
lianqiModeButton.textContent = '炼器熔炉';
}
heheModeButton.textContent = '万法归一';
};
}
function appendWhenReady() {
let retries = 0;
function tryAppend() {
if (!document.body) {
if (retries++ < 200) setTimeout(tryAppend, 50);
return;
}
const toggleBtn = document.createElement('div');
toggleBtn.id = 'hanabi-toggle-btn';
Object.assign(toggleBtn.style, {
position: 'fixed', right: '15px', bottom: '15px', width: '50px', height: '50px', borderRadius: '50%',
cursor: 'pointer', zIndex: '99998', background: 'rgba(255,255,255,0.4)', backdropFilter: 'blur(10px) saturate(180%)',
border: '1px solid rgba(255,255,255,0.5)', boxShadow: '0 4px 18px rgba(0,0,0,0.25)',
display: 'flex', alignItems: 'center', justifyContent: 'center', overflow: 'hidden', transition: 'transform .25s'
});
toggleBtn.innerHTML = `<img src="${TOGGLE_BTN_ICON}" style="width:100%;height:100%;object-fit:cover;" decoding="async" onerror="this.style.display='none';this.parentElement.innerText='🌸';" />`;
document.body.appendChild(toggleBtn);
const panel = document.createElement('div');
panel.id = 'hanabi-emoji-panel';
Object.assign(panel.style, {
position: 'fixed', right: '20px', bottom: '75px', width: '350px', minHeight: '580px', maxHeight: '88vh',
display: 'none', flexDirection: 'column', padding: '12px 10px', fontSize: '12px',
background: 'rgba(255,255,255,0.22)', border: '1px solid rgba(255,255,255,0.45)', borderRadius: '16px',
backdropFilter: 'blur(16px) saturate(180%)', boxShadow: '0 12px 35px rgba(0,0,0,0.25)', zIndex: '99999',
color: '#222', transition: 'opacity .3s ease, transform .3s ease', transform: 'translateY(10px)'
});
const header = document.createElement('div');
Object.assign(header.style, { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '8px', color: '#fff', fontWeight: '600', textShadow: '0 1px 3px rgba(0,0,0,0.4)', cursor: 'move', userSelect: 'none' });
header.innerHTML = `<span>花火修仙 · 演武宝阁</span><span style="cursor:pointer;font-size:14px;background:rgba(0,0,0,0.3);padding:2px 6px;border-radius:4px;" title="关闭面板">关闭</span>`;
header.querySelector('span:last-child').onclick = () => {
clearAllSlotTimers();
panel.style.display = 'none';
};
panel.appendChild(header);
const epicLogTicker = document.createElement('div');
epicLogTicker.id = 'hnb-epic-log-ticker';
epicLogTicker.innerHTML = `<div style="color:#f39c12;font-weight:bold;">【宗门秘闻】</div><div style="color:#ccc;font-size:10px;">道友尚在闭关潜修,可启动九宫天命仪运转乾坤!</div>`;
panel.appendChild(epicLogTicker);
const topCardsContainer = document.createElement('div');
topCardsContainer.id = 'hnb-top-cards-container';
const cardChigua = document.createElement('div');
cardChigua.className = 'hnb-top-card';
const chiguaInner = document.createElement('div');
chiguaInner.className = 'hnb-card-inner-wrap';
renderIconElement(chiguaInner, CHIGUA_TOP_ICON);
chiguaInner.innerHTML += `<div class="hnb-card-title-overlay">机缘历练</div>`;
cardChigua.appendChild(chiguaInner);
const cardGacha = document.createElement('div');
cardGacha.className = 'hnb-top-card';
const gachaInner = document.createElement('div');
gachaInner.id = 'card-gacha-inner';
gachaInner.className = 'hnb-card-inner-wrap';
renderIconElement(gachaInner, GACHA_TOP_ICON);
gachaInner.innerHTML += `<div class="hnb-card-title-overlay">秘境纳珍</div>`;
cardGacha.appendChild(gachaInner);
const cardSlot = document.createElement('div');
cardSlot.className = 'hnb-top-card';
const slotInner = document.createElement('div');
slotInner.className = 'hnb-card-inner-wrap';
renderIconElement(slotInner, RESERVED_TOP_ICON);
slotInner.innerHTML += `<div class="hnb-card-title-overlay">天衍九宫</div>`;
cardSlot.appendChild(slotInner);
topCardsContainer.append(cardChigua, cardGacha, cardSlot);
panel.appendChild(topCardsContainer);
const tabsContainer = document.createElement('div');
tabsContainer.id = 'hnb-emoji-cat-tabs';
panel.appendChild(tabsContainer);
const grid = document.createElement('div');
grid.id = 'hanabi-emoji-panel-grid';
panel.appendChild(grid);
const controls = document.createElement('div');
controls.style.marginTop = '8px';
controls.style.flexShrink = '0';
const urlInput = document.createElement('input');
Object.assign(urlInput.style, { width: '100%', padding: '6px', borderRadius: '6px', border: '1px solid rgba(255,255,255,0.4)', background: 'rgba(0,0,0,0.15)', color: 'white', marginBottom: '6px' });
urlInput.placeholder = '粘贴法宝图鉴图片直链...';
const buttonContainer = document.createElement('div');
Object.assign(buttonContainer.style, { display: 'flex', justifyContent: 'space-between' });
const addButton = document.createElement('button');
addButton.textContent = '录入法宝';
addButton.className = 'hnb-control-button';
const heheModeButton = document.createElement('button');
heheModeButton.textContent = '万法归一';
heheModeButton.className = 'hnb-control-button';
const lianqiModeButton = document.createElement('button');
lianqiModeButton.textContent = '炼器熔炉';
lianqiModeButton.className = 'hnb-control-button';
buttonContainer.append(addButton, heheModeButton, lianqiModeButton);
controls.append(urlInput, buttonContainer);
panel.appendChild(controls);
const heheTip = document.createElement('div');
heheTip.id = 'hehe-tip';
Object.assign(heheTip.style, { display: 'none', background: 'rgba(0,184,148,0.85)', color: '#fff', padding: '4px', fontWeight: 'bold', textAlign: 'center', borderRadius: '5px', marginTop: '4px', fontSize: '11px' });
panel.appendChild(heheTip);
const lianqiModal = document.createElement('div');
lianqiModal.id = 'hnb-lianqi-modal-overlay';
panel.appendChild(lianqiModal);
const slotModal = document.createElement('div');
slotModal.id = 'hnb-slot-modal-overlay';
panel.appendChild(slotModal);
document.body.appendChild(panel);
toggleBtn.onclick = () => {
const show = panel.style.display === 'none' || !panel.style.display;
panel.style.display = show ? 'flex' : 'none';
panel.style.opacity = show ? '1' : '0';
if (show) { renderTabs(); renderEmojis(); }
};
bindEvents(cardChigua, cardGacha, cardSlot, addButton, heheModeButton, lianqiModeButton, grid, urlInput, lianqiModal, slotModal, heheTip, epicLogTicker, panel);
renderTabs();
renderEmojis();
}
tryAppend();
}
// 初始化入口
emojiCounts = loadEmojiCounts();
slotCoins = loadSlotCoins();
appendWhenReady();
console.log('花火修仙表情面板 v26.0.0 (乾坤天衍·九极化晶彩金版) 已顺利加载!');
})();
开局30仙晶,一梭到底,赌鬼模式感觉老好玩啦。 ^-^

最新回复 (17)
-
夜轻 08-16 03:511楼
-
lotfree 08-16 03:552楼网页小游戏?我感觉Gemini的canvas还挺好用的
-
80hou 楼主 08-16 03:573楼@lotfree #2

花火论坛表情包油猴插件啊。 ^-^ -
80hou 楼主 08-16 04:024楼@lotfree #2
-
baoweise 08-16 04:045楼nsapp://stardust-receive?member_id=45949&ref_id=68561357&description=Pay with Stardust&diff=2&onetime=true
-
Jiuqi 08-16 04:166楼pro模型依旧难产吗
-
80hou 楼主 08-16 04:367楼@Jiuqi #6
3.1Pro
Refining Bet Logic
都能优化思考到怀疑人生。
估计想蒸馏学习豆包的轻量和文心一言的快速响应.
Pro算力成本太贵了。 ^-^

Pro就是个二愣子,为了省算力,直接对代码进行了自动精简审计。出新的Pro估计也是上不了台面的,还没Flash的工作流好用。 -
海狸-1376 08-16 04:568楼不错
-
小柒 08-16 05:399楼 -
lotfree 08-16 06:0710楼@80hou #4 依旧赛博讨口子
-
80hou 楼主 08-16 06:5511楼@lotfree #10
底裤都被你看光了。 ^-^
睡觉了 ^-^ 追剧追上头了,瞄了一眼,天色已晚。
-
LogicNova 08-16 07:5012楼不报错就挺省心
-
RUSALL-Musk 08-16 07:5613楼哈吉米3.7flash额度对我跑通代码测试非常耗额度 ^-^
-
sss1231 08-16 17:0114楼@80hou #11 你的gemini pro怎么来的,是8元那种吗
-
80hou 楼主 08-16 17:0615楼@sss1231 #14
好像比8元贵一点,当时买的是自己账号然后网站自动绑卡的。
自己绑的好像才四块多,忘记啦,之前有发过帖子
-
sss1231 08-16 17:0716楼@80hou #15 那个1key网站给验证链接自己生成学生身份?我的7月就到期了,被发现不是美国大学生了
-
80hou 楼主 08-16 17:1117楼@sss1231 #16

忘记了,当时买的好像是pixel渠道的一年。
* 帖子来源NodeSeek
附近帖子