@dx2727 #22 发布于2026/8/10 06:27:27 @80hou #21 哇 你好可爱呀 我可以跟你做朋友么 我买辣条你吃 nsapp://stardust-receive?member_id=39375&ref_id=76959271&description=不好意思%2C我只吃星辰.辣条太辣了%2C吃不了一点儿.&diff=1&onetime=false
@selkk #27 发布于2026/8/10 08:00:16 @80hou #19 这是什么插件啊大佬 @DeepDiveX #28 发布于2026/8/10 08:06:40 @80hou #19 这是啥软件 好看 @小赤佬 #54 发布于2026/8/10 12:33:59 @80hou #19 这是啥插件我去 背景和封边用的论坛扩展的,表情用的花火表情包魔改的. 论坛扩展css自定义可爱封边 花火修仙表情面板 (v15.0.0 终极全功能无错版) // ==UserScript== // @name 花火修仙表情面板 (v15.0.0 终极全功能无错版) // @namespace https://deepflood.com/ // @version 15.0.0 // @description 彻底修复no-undef报错;100%还原8槽位RPG修仙档案与AI提示词;4字Tab+居中🔒锁纹+119全图鉴;ESLint零报错 // @author Sparkle // @match *://www.deepflood.com/* // @match *://www.nodeseek.com/* // @grant none // ==/UserScript== /* eslint-env browser */ (function () { 'use strict'; // 防重复加载 if (window._hanabi_loaded) { document.getElementById('hanabi-panel')?.remove(); document.getElementById('hanabi-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 PLUGIN_SHARE_URL = "https://github.com/your-username/hanabi-emoji-xianxia"; // 119 张全量表情图鉴(80张基础 + 39张花火神装) 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 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 defaultInitialCategoryMap = {}; Object.keys(baseCategoryMap).forEach(function (u) { defaultInitialCategoryMap[u] = baseCategoryMap[u]; }); hanabiGodSets.forEach(function (u) { defaultInitialCategoryMap[u] = "godset"; }); const BASE_URLS = Object.keys(baseCategoryMap); const ALL_URLS = Object.keys(defaultInitialCategoryMap); // 严格控制 Tab 名字为 4 个汉字 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_NAMES = { storage: '储物装置', head: '头部防具', glasses: '面饰墨镜', ring: '戒指手饰', armor: '护体战袍', weapon: '护体神兵', drink: '仙丹灵饮', doll: '灵宠法宝' }; const emojiRPGDB = { "https://cdn.nodeimage.com/i/uUG7GSfToq9m6fx9jLPFoQDQpNgEfZLI.webp": { name: "软萌治愈兔子玩偶", rarity: "SSR", slot: "doll", power: 88, desc: "治愈力爆表", icon: "兔" }, "https://cdn.nodeimage.com/i/aVRKKCv7C1e3TttRXx9bDdgqWW5CYaQb.webp": { name: "大佬战术黑墨镜", rarity: "SSR", slot: "glasses", power: 95, desc: "气场极强", icon: "镜" }, "https://cdn.nodeimage.com/i/jbZrDO140rXSZpEqZ6xrOavN2wsUXuPY.webp": { name: "加厚军绿大棉袄", rarity: "SR", slot: "armor", power: 45, desc: "防寒保暖", icon: "衣" }, "https://cdn.nodeimage.com/i/jpGOKzfczXVyRSx2acQ1Q4CTozeWMfhu.webp": { name: "M8镀锌高强螺母", rarity: "SR", slot: "ring", power: 50, desc: "工业风戒指", icon: "环" }, "https://cdn.nodeimage.com/i/znzD9F3p9mkCWWAUD1K0RV6Yz5Xtq0Bb.webp": { name: "马戏团七彩神装头饰", rarity: "UR", slot: "head", power: 150, desc: "神级隐藏款", icon: "冠" }, "https://cdn.nodeimage.com/i/kSthzVLv6HY1zz4suH3sy8vDoTmp5ZIO.webp": { name: "二冲程汽油电锯", rarity: "UR", slot: "weapon", power: 145, desc: "火力压制", icon: "锯" } }; const titleMods = ["太初", "无量", "混沌", "九幽", "两仪", "虚空", "灭世", "不朽", "太上", "造化"]; const bodyTraits = ["独眼", "盲瞳", "断臂", "缺牙", "无名", "负伤", "隐世", "道心种魔", "疯魔", "斩道"]; const contrastProfessions = ["破阵", "观星", "斩龙", "驭兽", "搬砖", "推演", "观棋", "补天", "炼心", "横渡"]; const titleSuffixes = ["真君", "大圣", "天尊", "老祖", "剑仙", "魔尊", "道主", "圣人", "谪仙"]; const itemPrefixes = ["太上玄铁", "混沌淬炼", "九天星辰", "不朽造化", "两仪微尘", "岁月斑驳", "因果缠绕", "大罗金精", "寂灭雷霆", "远古遗落"]; const itemCores = { ring: ["M8六角螺母", "弹簧垫圈", "生料带戒指", "不锈钢平垫", "活塞卡环", "虚空指环"], armor: ["军绿防寒大棉袄", "快递纸箱战甲", "高压防爆重铠", "羽绒服道袍", "塑料雨衣玄甲"], weapon: ["二冲程汽油电锯", "战术高压马桶吸", "M12钛合金扳手", "裂天重型加特林", "折叠工兵铲"], glasses: ["大佬战术黑墨镜", "破妄透视圆镜", "焊接防光面罩", "太虚观星镜"], drink: ["核动力特浓美式", "九转大肠仙丹", "特调星空冰摇茶", "万古不化冰沙", "极道珍珠奶茶"], head: ["马戏团七彩神冠", "太上无极睡帽", "高压工业安全帽", "混沌斗笠"], doll: ["软萌治愈兔偶", "焦糖爆米花炉", "岁月西瓜切片", "大荒傀儡娃娃"] }; const itemSuffixes = ["(带散热片)", "[质保纪元]", "(+10大圣加厚)", "[超大号因果律]", "(高压防爆免责)", "(已证道+9)"]; const adventureNarratives = [ { place: "于太古废弃机房无名核心深处", event: "剥离万载禁制微尘", reverse: "虚空坠落沾血残兵" }, { place: "在九幽之下混沌业火垃圾桶洞府", event: "硬撼因果律护宗大阵", reverse: "捞出失传无上造化经文" }, { place: "在M8高强螺母谷底绝壁之上", event: "直面斩道剑意洗礼", reverse: "与沉睡万古巨擘隔空交错" }, { place: "于403禁忌领域空间裂缝边缘", event: "顶住寂灭雷劫推演天机", reverse: "截取一缕太初之气" } ]; // ========================================================================= // 【模块 2】持久化存储与算法引擎 // ========================================================================= const COUNTS_STORAGE_KEY = 'hanabi_emoji_counts_v15.0'; const EQUIP_STORAGE_KEY = 'hanabi_equipped_inventory_v15.0'; let isHeheMode = false; let isLianqiMode = false; let selectedHeheUrls = []; let emojiCounts = {}; let equippedInventory = { ring: [], armor: [], head: null, glasses: null, drink: null, doll: null, weapon: null }; let currentTabId = 'bag'; let lastActiveInput = null; // 避免高频哈希运算的内存缓存 Map 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 loadEmojiCounts() { try { const saved = JSON.parse(localStorage.getItem(COUNTS_STORAGE_KEY) || 'null'); if (saved) return saved; const initial = {}; ALL_URLS.forEach(function (u) { initial[u] = 0; }); initial[BASE_URLS[0]] = 1; initial[BASE_URLS[1]] = 1; return initial; } catch (err) { const initial = {}; initial[BASE_URLS[0]] = 1; return initial; } } function saveEmojiCounts() { try { localStorage.setItem(COUNTS_STORAGE_KEY, JSON.stringify(emojiCounts)); } catch (err) {} } function addEmojiCount(url, addAmount) { const amount = (typeof addAmount === 'number') ? addAmount : 1; const cur = emojiCounts[url] || 0; const next = Math.min(99, Math.max(0, cur + amount)); emojiCounts[url] = next; saveEmojiCounts(); return next; } function loadEquippedInventory() { try { return JSON.parse(localStorage.getItem(EQUIP_STORAGE_KEY) || '{}'); } catch (err) { return { ring: [], armor: [], head: null, glasses: null, drink: null, doll: null, weapon: null }; } } function saveEquippedInventory() { try { localStorage.setItem(EQUIP_STORAGE_KEY, JSON.stringify(equippedInventory)); } catch (err) {} } function getUnlockedCount() { let count = 0; ALL_URLS.forEach(function (u) { if ((emojiCounts[u] || 0) > 0) count++; }); return count; } // 1-3 连抽:88% 高重复率拦截 + 3% 极稀有花火神装 UR function getRandomWeightedEmojiUrl() { const unlockedSet = new Set(ALL_URLS.filter(function (u) { return (emojiCounts[u] || 0) > 0; })); let candidatePool = (Math.random() < 0.03) ? hanabiGodSets : BASE_URLS; const unlockedCandidates = candidatePool.filter(function (u) { return unlockedSet.has(u); }); const lockedCandidates = candidatePool.filter(function (u) { return !unlockedSet.has(u); }); if (lockedCandidates.length > 0 && unlockedCandidates.length > 0) { if (Math.random() < 0.88) { return unlockedCandidates[Math.floor(Math.random() * unlockedCandidates.length)]; } return lockedCandidates[Math.floor(Math.random() * lockedCandidates.length)]; } return candidatePool[Math.floor(Math.random() * candidatePool.length)]; } function getTabProgress(tabId) { let groupUrls = ALL_URLS; if (tabId === 'artifact') { groupUrls = ALL_URLS.filter(function (u) { return !hanabiGodSets.includes(u) && ['weapon', 'doll', 'ring'].includes(getEmojiRPGStats(u).slot); }); } else if (tabId === 'elixir') { groupUrls = ALL_URLS.filter(function (u) { return !hanabiGodSets.includes(u) && getEmojiRPGStats(u).slot === 'drink'; }); } else if (tabId === 'armor') { groupUrls = ALL_URLS.filter(function (u) { return !hanabiGodSets.includes(u) && ['armor', 'head', 'glasses'].includes(getEmojiRPGStats(u).slot); }); } else if (tabId === 'godset') { groupUrls = hanabiGodSets; } const total = groupUrls.length; const unlocked = groupUrls.filter(function (u) { return (emojiCounts[u] || 0) > 0; }).length; return { unlocked: unlocked, total: total }; } function getEmojiRPGStats(url) { if (rpgStatsCache.has(url)) return rpgStatsCache.get(url); const dbItem = emojiRPGDB[url]; if (dbItem) { rpgStatsCache.set(url, dbItem); return dbItem; } if (hanabiGodSets.includes(url)) { const godItem = { name: "花火绝版神装·原初流光", rarity: "UR", slot: "weapon", power: 199, desc: "花火系列至高神装", icon: "光" }; 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 slot = slots[hash % slots.length]; const prefix = itemPrefixes[hash % itemPrefixes.length]; const coreList = itemCores[slot] || itemCores.doll; const core = coreList[hash % coreList.length]; const suffix = itemSuffixes[hash % itemSuffixes.length]; const rarities = [ { rarity: 'UR', power: 130 + (hash % 20), icon: '极' }, { rarity: 'SSR', power: 80 + (hash % 19), icon: '绝' }, { rarity: 'SR', power: 45 + (hash % 24), icon: '珍' }, { rarity: 'R', power: 15 + (hash % 24), icon: '凡' } ]; const rolled = (hash % 100) / 100; let selected = rarities[3]; if (rolled < 0.05) selected = rarities[0]; else if (rolled < 0.25) selected = rarities[1]; else if (rolled < 0.60) selected = rarities[2]; const computed = { name: `${prefix}${core}${suffix}`, rarity: selected.rarity, slot: slot, power: selected.power, desc: "工业废土法宝", icon: selected.icon }; rpgStatsCache.set(url, computed); return computed; } function addEquipToInventory(url) { const stats = getEmojiRPGStats(url); if (stats.slot === 'ring' || stats.slot === 'armor') { if (!equippedInventory[stats.slot]) equippedInventory[stats.slot] = []; equippedInventory[stats.slot].push(url); saveEquippedInventory(); return true; } const currentUrl = equippedInventory[stats.slot]; if (!currentUrl) { equippedInventory[stats.slot] = url; saveEquippedInventory(); return true; } const currentStats = getEmojiRPGStats(currentUrl); if (stats.power > currentStats.power) { equippedInventory[stats.slot] = url; saveEquippedInventory(); return true; } return false; } function getDynamicPlayerTitle() { const rings = equippedInventory.ring || []; const armors = equippedInventory.armor || []; const ringCount = rings.length; let totalPower = 0; Object.keys(equippedInventory).forEach(function (k) { const val = equippedInventory[k]; if (Array.isArray(val)) { val.forEach(function (u) { totalPower += getEmojiRPGStats(u).power; }); } else if (val) { totalPower += getEmojiRPGStats(val).power; } }); let realm = "凡胎肉眼·炼气筑基"; if (totalPower >= 1200) realm = "寂灭天尊·超脱因果"; else if (totalPower >= 800) realm = "诸圣黄昏·镇压万古"; else if (totalPower >= 500) realm = "大罗金仙·万劫不侵"; else if (totalPower >= 300) realm = "两仪微尘·洞虚归一"; else if (totalPower >= 120) realm = "虚空生电·元婴化神"; const p = titleMods[totalPower % titleMods.length]; const body = bodyTraits[(totalPower + ringCount) % bodyTraits.length]; const prof = contrastProfessions[(totalPower + 7) % contrastProfessions.length]; const suf = titleSuffixes[(totalPower + ringCount * 3) % titleSuffixes.length]; let coreItem = "吃瓜"; if (ringCount >= 6) coreItem = `螺母x${ringCount}`; else if (armors.length >= 5) coreItem = `棉袄x${armors.length}`; else if (equippedInventory.weapon) coreItem = "电锯"; const title = `【${p}·${body}${prof}·${coreItem}${suf}】`; const unlockedCount = getUnlockedCount(); let storageName = "破旧塑料垃圾袋"; if (unlockedCount >= 30) storageName = "装满废铁的二手帆布包"; else if (unlockedCount >= 15) storageName = "写满化肥的尿素袋"; else if (unlockedCount >= 5) storageName = "村头集市蛇皮编织袋"; return { totalPower: totalPower, realm: realm, title: title, storageName: storageName, unlockedCount: unlockedCount }; } 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="card-fill-img" decoding="async" loading="lazy" />`; } else { targetEl.innerHTML = `<span class="card-fill-emoji">${iconValue}</span>`; } } // ========================================================================= // 【模块 3】文本插入与提示引擎 // ========================================================================= 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) {} const vInst = getVditorInstance(el); if (vInst) { try { vInst.insertValue(text); return true; } catch (e) {} } if (el.isContentEditable) { try { document.execCommand('insertText', false, text); el.dispatchEvent(new Event('input', { bubbles: true })); return true; } catch (e) {} } let inserted = false; try { inserted = document.execCommand('insertText', false, text); } catch (e) {} 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.9)', color: '#fff', fontSize: '11px', zIndex: '100002', boxShadow: '0 4px 12px rgba(0,0,0,0.3)' }); document.body.appendChild(t); setTimeout(function () { t.remove(); }, 1200); } function copyToClipboard(text) { if (navigator.clipboard && navigator.clipboard.writeText) return navigator.clipboard.writeText(text); const ta = document.createElement('textarea'); ta.value = text; document.body.appendChild(ta); ta.select(); document.execCommand('copy'); ta.remove(); } // ========================================================================= // 【模块 4】CSS 样式注入 (居中🔒图标 + 3px四色微型进度条) // ========================================================================= const style = document.createElement('style'); style.textContent = ` #hanabi-emoji-panel { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important; will-change: transform, opacity; contain: layout style paint; } #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; } #top-cards-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; margin: 2px auto 6px auto; width: 100%; flex-shrink: 0; } .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; } .top-card:hover { transform: translateY(-2px) scale(1.03); border-color: #ffeaa7; } .top-card.card-shake { animation: cardShake 0.35s ease-in-out; } @keyframes cardShake { 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); } } .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); } .card-fill-img { width: 100%; height: 100%; object-fit: cover; border-radius: 10px; transition: transform 0.3s ease; } .top-card:hover .card-fill-img { transform: scale(1.08); } .card-fill-emoji { font-size: 28px; line-height: 1; filter: drop-shadow(0 2px 4px rgba(0,0,0,0.3)); } .card-title-overlay { position: absolute; bottom: 2px; left: 2px; right: 2px; height: 18px; line-height: 18px; font-size: 10px; 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; } #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; } /* 4字Tab规范排版,不占高度的 3px 微型进度条 */ #emoji-cat-tabs { display: flex; gap: 4px; overflow-x: auto; padding-bottom: 5px; margin-bottom: 5px; flex-shrink: 0; } #emoji-cat-tabs::-webkit-scrollbar { display: none; } .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: 11px; flex-shrink: 0; } .cat-tab-btn:hover { background: rgba(255,255,255,0.4); } .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); } .cat-tab-btn.locked-tab { opacity: 0.55; filter: grayscale(0.4); } .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, 1fr); gap: 6px; overflow-y: auto; max-height: 180px; min-height: 140px; padding-right: 2px; transform: translateZ(0); flex-grow: 1; contain: content; } .emoji-item { width: 100%; aspect-ratio: 1; display: flex; align-items: center; justify-content: center; position: relative; } .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; } .emoji-item img:hover { transform: scale(1.08); box-shadow: 0 4px 10px rgba(0,0,0,0.25); } .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: 10px; } /* 核心精修:未解锁表情正中间展示 🔒 锁纹 */ .emoji-item.locked img { filter: grayscale(1) opacity(0.25) blur(0.5px); } .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)); } .emoji-item.hehe-selected img { border: 3px solid #00b894; box-shadow: 0 0 12px #00b894; transform: scale(1.08); } #hanabi-emoji-panel.hehe-mode .emoji-item:not(.locked) img { border: 2px dashed #00b894; opacity: 0.9; } #hanabi-emoji-panel.lianqi-mode .emoji-item:not(.locked) img { border: 2px dashed #ff7675; opacity: 0.9; } #lianqi-modal-overlay, #hehe-modal-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: rgba(20, 10, 20, 0.92); backdrop-filter: blur(12px); border-radius: 16px; display: none; flex-direction: column; align-items: center; justify-content: center; z-index: 100000; padding: 14px; color: #fff; opacity: 0; transition: opacity .2s ease; } #lianqi-modal-overlay.show, #hehe-modal-overlay.show { display: flex; opacity: 1; } .lianqi-item-preview { width: 54px; height: 54px; border-radius: 8px; object-fit: cover; border: 2px solid #ff7675; margin-bottom: 6px; } #xianxia-profile-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: rgba(15, 15, 25, 0.97); backdrop-filter: blur(14px); border-radius: 16px; display: none; flex-direction: column; z-index: 100000; padding: 12px; color: #fff; overflow-y: auto; opacity: 0; transition: opacity .2s ease; } #xianxia-profile-overlay.show { display: flex; opacity: 1; } .profile-header-card { background: linear-gradient(135deg, rgba(45, 52, 54, 0.8), rgba(27, 20, 35, 0.9)); border: 1.5px solid rgba(255, 215, 0, 0.3); border-radius: 10px; padding: 8px 10px; margin-bottom: 8px; box-shadow: 0 4px 15px rgba(0,0,0,0.3); } .profile-title-tag { background: linear-gradient(135deg, #f1c40f, #e67e22); padding: 2px 8px; border-radius: 5px; font-weight: bold; display: inline-block; font-size: 11px; color: #fff; text-shadow: 0 1px 2px rgba(0,0,0,0.4); margin-top: 3px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .profile-slots-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 5px; margin-bottom: 8px; } .equip-slot-card { background: rgba(255, 255, 255, 0.05); border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 7px; padding: 5px 8px; display: flex; align-items: center; gap: 7px; height: 42px; overflow: hidden; } .equip-slot-img { width: 30px; height: 30px; border-radius: 5px; object-fit: cover; background: rgba(0,0,0,0.3); flex-shrink: 0; } .control-button { background: rgba(255,255,255,0.3); border: none; padding: 6px 14px; font-weight: 500; border-radius: 6px; color: white; cursor: pointer; transition: background .2s; font-size: 11px; } .control-button:hover { background: rgba(255,255,255,0.5); } `; document.head.appendChild(style); // ========================================================================= // 【模块 5】全局 UI 渲染函数 (Tabs & Emojis) // ========================================================================= function renderTabs() { const tabsContainer = document.getElementById('emoji-cat-tabs'); if (!tabsContainer) return; tabsContainer.innerHTML = ''; const unlockedTotalCount = getUnlockedCount(); xianxiaTabs.forEach(function (tab) { const isUnlocked = unlockedTotalCount >= tab.unlockThreshold; const progress = getTabProgress(tab.id); const btn = document.createElement('button'); btn.className = `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="tab-progress-bar" style="width: ${percent}%; background: ${barColor};"></div>`; } else { // 锁定状态依然严格保持 4 个汉字名字,精爽好看 btn.innerHTML = `${tab.name}`; } btn.onclick = function () { 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 = ''; let renderList = []; if (currentTabId === 'bag') { renderList = ALL_URLS.filter(function (u) { return (emojiCounts[u] || 0) > 0; }); } else if (currentTabId === 'artifact') { renderList = ALL_URLS.filter(function (u) { return !hanabiGodSets.includes(u) && ['weapon', 'doll', 'ring'].includes(getEmojiRPGStats(u).slot); }); } else if (currentTabId === 'elixir') { renderList = ALL_URLS.filter(function (u) { return !hanabiGodSets.includes(u) && getEmojiRPGStats(u).slot === 'drink'; }); } else if (currentTabId === 'armor') { renderList = ALL_URLS.filter(function (u) { return !hanabiGodSets.includes(u) && ['armor', 'head', 'glasses'].includes(getEmojiRPGStats(u).slot); }); } else if (currentTabId === 'godset') { renderList = hanabiGodSets; } else { renderList = ALL_URLS; } const frag = document.createDocumentFragment(); renderList.forEach(function (url) { const count = emojiCounts[url] || 0; const isUnlocked = count > 0; const item = document.createElement('div'); item.className = `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 = 'emoji-count-badge'; badge.textContent = `x${count}`; item.appendChild(badge); } frag.appendChild(item); }); grid.appendChild(frag); } // ========================================================================= // 【模块 6】事件逻辑绑定与完整 RPG 档案 Modal 渲染 // ========================================================================= function bindEvents(cardChigua, cardGacha, cardReserved, addButton, heheModeButton, lianqiModeButton, grid, urlInput, lianqiModal, profileModal, heheTip, epicLogTicker, panel) { function handleHeheFusionClick(url) { const count = emojiCounts[url] || 0; if (count <= 0) return showToast('未解封法宝无法参与万法归一。'); if (selectedHeheUrls.includes(url)) selectedHeheUrls = selectedHeheUrls.filter(function (u) { return 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(); const stats = getEmojiRPGStats(outputUrl); selectedHeheUrls = []; updateHeheTip(); addEmojiCount(outputUrl, 1); addEquipToInventory(outputUrl); showToast(`万法归一成功,推演获得:[${stats.rarity}] ${stats.name}`); 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; const stats = getEmojiRPGStats(url); 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="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:11px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">[${stats.rarity}] ${stats.name}</div> <div style="color:#ffeaa7;font-size:10px;">当前库存:<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="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="control-button" id="lianqi-plus" style="padding:4px 10px;">+</button> <button class="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="control-button" style="flex:1;background:rgba(0,184,148,0.9);padding:6px;font-size:11px;" id="lianqi-confirm">确认祭献炼化</button> <button class="control-button" style="flex:1;background:rgba(100,100,100,0.6);padding:6px;font-size:11px;" id="l-close">关闭熔炉</button> </div> `; const inputAmt = document.getElementById('lianqi-input-amt'); document.getElementById('lianqi-minus').onclick = function () { let val = parseInt(inputAmt.value, 10) || 1; if (val > 1) inputAmt.value = val - 1; }; document.getElementById('lianqi-plus').onclick = function () { let val = parseInt(inputAmt.value, 10) || 1; if (val < count) inputAmt.value = val + 1; }; document.getElementById('lianqi-all').onclick = function () { inputAmt.value = count; }; document.getElementById('lianqi-confirm').onclick = function () { const amt = parseInt(inputAmt.value, 10) || 1; if (amt > count) return showToast('库存不足。'); doLianqi(url, amt); }; document.getElementById('l-close').onclick = function () { lianqiModal.classList.remove('show'); }; lianqiModal.classList.add('show'); } function doLianqi(url, amt) { addEmojiCount(url, -amt); lianqiModal.classList.remove('show'); const targetUrl = getRandomWeightedEmojiUrl(); const stats = getEmojiRPGStats(targetUrl); addEmojiCount(targetUrl, amt); addEquipToInventory(targetUrl); showToast(`炼器炉运转成功,凝练获得:[${stats.rarity}] ${stats.name} x${amt}`); renderTabs(); renderEmojis(); } // 100% 完整复原的 8 槽位 RPG 修仙档案(含 AI Prompt 生成) function renderProfileModal() { const data = getDynamicPlayerTitle(); let slotsHTML = ` <div class="equip-slot-card"> <div class="equip-slot-img" style="display:flex;align-items:center;justify-content:center;font-size:14px;">仓</div> <div style="flex-grow:1;min-width:0;"> <div style="font-size:9px;font-weight:bold;color:#aaa;">${SLOT_NAMES.storage}</div> <div style="font-size:10px;color:#ffeaa7;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;"><b>${data.storageName}</b></div> </div> </div> `; Object.keys(SLOT_NAMES).forEach(function (slotKey) { if (slotKey === 'storage') return; const val = equippedInventory[slotKey]; const slotName = SLOT_NAMES[slotKey]; if (Array.isArray(val) && val.length > 0) { const lastUrl = val[val.length - 1]; slotsHTML += ` <div class="equip-slot-card"> <img src="${lastUrl}" class="equip-slot-img" decoding="async" /> <div style="flex-grow:1;min-width:0;"> <div style="font-size:10px;font-weight:bold;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">${slotName}</div> <div style="font-size:9px;color:#ffeaa7;">已叠加 x${val.length} 层</div> </div> </div> `; } else if (typeof val === 'string' && val) { const stats = getEmojiRPGStats(val); slotsHTML += ` <div class="equip-slot-card"> <img src="${val}" class="equip-slot-img" decoding="async" /> <div style="flex-grow:1;min-width:0;"> <div style="font-size:10px;font-weight:bold;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">[${stats.rarity}] ${stats.name}</div> <div style="font-size:9px;color:#ffeaa7;">战力加成 +${stats.power}</div> </div> </div> `; } else { slotsHTML += ` <div class="equip-slot-card" style="opacity:0.4;"> <div class="equip-slot-img" style="display:flex;align-items:center;justify-content:center;font-size:12px;">空</div> <div style="flex-grow:1;min-width:0;"> <div style="font-size:10px;font-weight:bold;">${slotName}</div> <div style="font-size:9px;color:#ccc;">暂未穿戴</div> </div> </div> `; } }); profileModal.innerHTML = ` <div class="profile-header-card"> <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:3px;"> <span style="font-size:11px;font-weight:bold;color:#f39c12;">宗门真传道友档案</span> <span style="background:linear-gradient(135deg,#fd79a8,#a29bfe);padding:2px 8px;border-radius:10px;font-weight:bold;font-size:10px;color:#fff;">${data.realm}</span> </div> <div class="profile-title-tag">${data.title}</div> </div> <div style="font-size:11px;font-weight:bold;margin-bottom:6px;color:#ffeaa7;">当前总战力:${data.totalPower} | 解封图鉴:<b>${data.unlockedCount}/${ALL_URLS.length}</b></div> <div class="profile-slots-grid">${slotsHTML}</div> <button class="control-button" style="width:100%;padding:6px;background:rgba(0,184,148,0.85);margin-bottom:4px;font-size:11px;" id="copy-ai">复制 AI 修仙自画像提示词</button> <button class="control-button" style="width:100%;padding:6px;background:rgba(255,118,117,0.8);margin-bottom:4px;font-size:11px;" id="share-card">复制宗门真传名片(含传送阵)</button> <button class="control-button" style="width:100%;padding:6px;font-size:11px;" id="close-prof">关闭修仙档案</button> `; document.getElementById('copy-ai').onclick = function () { const rings = equippedInventory.ring || []; const armors = equippedInventory.armor || []; const promptMarkdown = `AI 修仙自画像提示词:\n\`\`\`text\nChibi anime style, cute abstract cyber xianxia character, ${data.title}, carrying a ${data.storageName}, wearing ${armors.length} layers of padded jackets, ${rings.length} industrial nuts as rings, holding tactical chainsaw, funny meme expression, pastel color palette, high detail, 2D vector art --ar 1:1\n\`\`\`\n`; copyToClipboard(promptMarkdown); const input = findInputElement(); if (input) insertTextAtCursor(input, promptMarkdown); showToast('AI 自画像提示词已复制到剪贴板。'); }; document.getElementById('share-card').onclick = function () { const shareMarkdown = `修仙名片:境界 [${data.realm}] | 尊号 ${data.title}\n总战力:${data.totalPower} | 储物装置:${data.storageName}\n韩道友给你赠送了功法秘籍:[点击进入传送阵](${PLUGIN_SHARE_URL})\n`; copyToClipboard(shareMarkdown); const input = findInputElement(); if (input) insertTextAtCursor(input, shareMarkdown); showToast('宗门名片已复制并成功插入编辑器。'); }; document.getElementById('close-prof').onclick = function () { profileModal.classList.remove('show'); }; } cardChigua.onclick = function () { triggerCardShake(cardChigua); const drawCount = Math.floor(Math.random() * 3) + 1; let newUnlockCount = 0; let lastUrl = getRandomWeightedEmojiUrl(); for (let i = 0; i < drawCount; i++) { const randomUrl = getRandomWeightedEmojiUrl(); const curCount = addEmojiCount(randomUrl, 1); if (curCount === 1) newUnlockCount++; addEquipToInventory(randomUrl); lastUrl = randomUrl; } 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>` : ''}</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 = function () { triggerCardShake(cardGacha); const drawCount = Math.floor(Math.random() * 3) + 1; let newUnlockCount = 0; let lastUrl = getRandomWeightedEmojiUrl(); for (let i = 0; i < drawCount; i++) { const randomUrl = getRandomWeightedEmojiUrl(); const curCount = addEmojiCount(randomUrl, 1); if (curCount === 1) newUnlockCount++; addEquipToInventory(randomUrl); lastUrl = randomUrl; } 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>` : ''}</div> `; const markdown = `\n`; copyToClipboard(markdown); const input = findInputElement(); const success = input ? insertTextAtCursor(input, markdown) : false; if (success) { showToast('表情已成功插入光标处。'); } else { showToast('找不到打开的回复框,已自动复制 Markdown。'); } renderTabs(); renderEmojis(); }; cardReserved.onclick = function () { triggerCardShake(cardReserved); renderProfileModal(); profileModal.classList.add('show'); }; function triggerCardShake(cardEl) { cardEl.classList.remove('card-shake'); void cardEl.offsetWidth; cardEl.classList.add('card-shake'); } grid.onclick = function (e) { const img = e.target.closest('img'); if (!img) return; const item = img.closest('.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 = function () { const url = urlInput.value.trim(); if (!/^https?:\/\//i.test(url)) return showToast('请输入有效的图片链接。'); addEmojiCount(url, 1); renderTabs(); renderEmojis(); urlInput.value = ''; showToast('自定义法宝已成功录入布袋。'); }; heheModeButton.onclick = function () { 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 = function () { 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() { if (!document.body) { setTimeout(appendWhenReady, 50); return; } // 1. 创建悬浮按钮 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); // 2. 创建主面板 const panel = document.createElement('div'); panel.id = 'hanabi-emoji-panel'; Object.assign(panel.style, { position: 'fixed', right: '20px', bottom: '75px', width: '340px', maxHeight: '82vh', display: 'none', flexDirection: 'column', padding: '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: '6px', 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 = function () { panel.style.display = 'none'; }; panel.appendChild(header); // 3. 顶部沉浸式宗门奇遇日志栏 const epicLogTicker = document.createElement('div'); epicLogTicker.id = '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 = 'top-cards-container'; const cardChigua = document.createElement('div'); cardChigua.className = 'top-card'; const chiguaInner = document.createElement('div'); chiguaInner.className = 'card-inner-wrap'; renderIconElement(chiguaInner, CHIGUA_TOP_ICON); chiguaInner.innerHTML += `<div class="card-title-overlay">探险历练</div>`; cardChigua.appendChild(chiguaInner); const cardGacha = document.createElement('div'); cardGacha.className = 'top-card'; const gachaInner = document.createElement('div'); gachaInner.id = 'card-gacha-inner'; gachaInner.className = 'card-inner-wrap'; renderIconElement(gachaInner, GACHA_TOP_ICON); gachaInner.innerHTML += `<div class="card-title-overlay">寻宝抽卡</div>`; cardGacha.appendChild(gachaInner); const cardReserved = document.createElement('div'); cardReserved.className = 'top-card'; const reservedInner = document.createElement('div'); reservedInner.className = 'card-inner-wrap'; renderIconElement(reservedInner, RESERVED_TOP_ICON); reservedInner.innerHTML += `<div class="card-title-overlay">人物修仙</div>`; cardReserved.appendChild(reservedInner); topCardsContainer.append(cardChigua, cardGacha, cardReserved); panel.appendChild(topCardsContainer); const tabsContainer = document.createElement('div'); tabsContainer.id = '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 = '6px'; controls.style.flexShrink = '0'; const urlInput = document.createElement('input'); Object.assign(urlInput.style, { width: '100%', padding: '5px', borderRadius: '6px', border: '1px solid rgba(255,255,255,0.4)', background: 'rgba(0,0,0,0.1)', color: 'white', marginBottom: '5px' }); 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 = 'control-button'; const heheModeButton = document.createElement('button'); heheModeButton.textContent = '万法归一'; heheModeButton.className = 'control-button'; const lianqiModeButton = document.createElement('button'); lianqiModeButton.textContent = '炼器熔炉'; lianqiModeButton.className = '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 = 'lianqi-modal-overlay'; panel.appendChild(lianqiModal); const profileModal = document.createElement('div'); profileModal.id = 'xianxia-profile-overlay'; panel.appendChild(profileModal); document.body.appendChild(panel); toggleBtn.onclick = function () { 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, cardReserved, addButton, heheModeButton, lianqiModeButton, grid, urlInput, lianqiModal, profileModal, heheTip, epicLogTicker, panel); renderTabs(); renderEmojis(); } // 初始化入口 emojiCounts = loadEmojiCounts(); equippedInventory = loadEquippedInventory(); appendWhenReady(); console.log('花火修仙表情面板 v15.0.0 已加载:完整全功能复原引擎启动。'); })();
nsapp://stardust-receive?member_id=39375&ref_id=76959271&description=不好意思%2C我只吃星辰.辣条太辣了%2C吃不了一点儿.&diff=1&onetime=false
@80hou #61 哇 好可爱呀
背景和封边用的论坛扩展的,表情用的花火表情包魔改的.
论坛扩展css自定义可爱封边