From ca903adb18a7da698a162c85ceea86632b30b961 Mon Sep 17 00:00:00 2001 From: strawberry42271 <2806566736@qq.com> Date: Sat, 8 Mar 2025 16:59:40 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A3=85=E5=A4=87=E6=A0=8F/=E7=AE=80=E6=98=93u?= =?UTF-8?q?i/=E6=88=98=E6=96=97=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- project/data.js | 6 +- project/floors/xiaoxiang01.js | 4 +- project/floors/yiqu1.js | 4 +- project/functions.js | 53 +- project/plugins.js | 22242 +++++++++++++++++--------------- 5 files changed, 11837 insertions(+), 10472 deletions(-) diff --git a/project/data.js b/project/data.js index f8a11c5..9fd4a58 100644 --- a/project/data.js +++ b/project/data.js @@ -1529,7 +1529,7 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = "hp": 1000, "manamax": -1, "mana": 0, - "atk": 60, + "atk": 10, "def": 10, "mdef": 100, "speed": 10, @@ -1555,9 +1555,9 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = "followers": [], "steps": 0, "matk": 0, - "spell": 100, + "spell": 0, "spelldef": 0, - "mhp": 42 + "mhp": 0 }, "startCanvas": [ { diff --git a/project/floors/xiaoxiang01.js b/project/floors/xiaoxiang01.js index 2e55dad..85f6bd0 100644 --- a/project/floors/xiaoxiang01.js +++ b/project/floors/xiaoxiang01.js @@ -55,9 +55,9 @@ main.floors.xiaoxiang01= [120147, 0, 32, 0,200199, 0,201029,225,110132,224, 0, 0,90675], [120164,225,200998,200999,201037, 81,201029, 0, 0, 0,110116, 0, 94], [120172, 0,222, 0,221, 0,201029, 81,110116,225,110137,110138,90650], - [120180,201037,201037, 81,201037,201037,201037, 0,110124, 0, 81, 31,90658], + [120180,201037,201037, 81,201037,201037,201037,246,110124, 0, 81, 31,90658], [ 92, 32, 32, 22, 21,80089, 31, 0,110132, 0,110122,110122,110197], - [140,110191, 21, 21, 21,80089, 0, 0, 81, 0,222, 29,110197], + [140,110191, 21, 21, 21,80089, 0,246, 81, 0,222, 29,110197], [140,140,140,110191,80083,80097, 93,110138,110138,140189,140,140,140] ], "areas": "牢狱", diff --git a/project/floors/yiqu1.js b/project/floors/yiqu1.js index c7c3f66..ec80832 100644 --- a/project/floors/yiqu1.js +++ b/project/floors/yiqu1.js @@ -48,8 +48,8 @@ main.floors.yiqu1= [140142, 0,120015,120028,201037, 0,201029, 0, 0, 0, 0, 0,110197], [140150, 0, 0,120019, 0, 0,201029, 0,110189,140,110191, 0,110205], [ 92, 0, 0,120019,201037,201037,201037, 0,110197,140,110199, 81,110224], - [ 0, 0, 0,120027, 37, 37, 0, 0,110197,140,110199, 0,110232], - [110191, 0, 0, 0, 36, 35,110189,140,140,140,110199, 0, 94], + [ 0, 0, 0,120027, 0, 0, 0, 0,110197,140,110199, 0,110232], + [110191, 0, 0, 0, 0, 0,110189,140,140,140,110199, 0, 94], [110199,140,140,110191, 0, 0,110197,140,140,110204,110207, 0, 0], [140,140,140,110199,90684,90684,110197,140,140,110199,110234, 0, 0], [140,140,140,110199,100307,100308,110197,140,140,110199, 0, 0, 0] diff --git a/project/functions.js b/project/functions.js index fc5b908..a9a00a6 100644 --- a/project/functions.js +++ b/project/functions.js @@ -928,6 +928,17 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = origin_hero_atk = core.getStatusOrDefault(hero, "atk"), origin_hero_def = core.getStatusOrDefault(hero, "def"); + //编辑器特判 + if (main.mode == "editor") { + hero_hp = hero?.hp ?? core.status.hero.hp, + hero_atk = hero?.atk ?? core.status.hero.atk, + hero_def = hero?.def ?? core.status.hero.def, + hero_matk = hero?.matk ?? core.status.hero.matk, + hero_mdef = hero?.mdef ?? core.status.hero.mdef, + hero_mhp = hero?.mhp ?? core.status.hero.mhp, + hero_speed = hero?.speed ?? core.status.hero.speed, + hero_spell = hero?.spell ?? core.status.hero.spell; + } // 怪物的各项数据 // 对坚固模仿等处理扔到了脚本编辑-getEnemyInfo之中 var enemyInfo = core.enemys.getEnemyInfo(enemy, hero, x, y, floorId); @@ -1017,7 +1028,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = //需要变更 const onegcd = gcd(...oneTurn) //最大公约数 - oneTurn = lcm(...oneTurn) / onegcd //单次回合长度 + oneTurn = lcm(...oneTurn) //单次回合长度 //在这里处理equip的初始位置now equipInfo.forEach(v => { switch (v.id) { @@ -1029,7 +1040,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = v.onAttack = false if (v.now === oneTurn) v.onAttack = true //增加正在攻击的标志 }) - const heroinfo = { hp: hero_hp, atk: hero_atk, def: hero_def, mdef: hero_mdef, spell: hero_spell, mhp: Math.floor(hero_spell * hero_mhp / 100), matk: Math.floor(hero_spell * hero_matk / 100), speed: hero_speed, now: 0, isAttack: false } //勇士属性 + const heroinfo = { hp: hero_hp, atk: hero_atk, def: hero_def, mdef: (!hero?.mdef || hero?.mdef === 100) ? hero_mdef : hero.mdef, spell: hero_spell, mhp: Math.floor(hero_spell * hero_mhp / 100), matk: Math.floor(hero_spell * hero_matk / 100), speed: hero_speed, now: 0, isAttack: false } //勇士属性 const enemyinfo = { hp: mon_hp, atk: mon_atk, def: mon_def, mdef: mon_mdef, spell: mon_spell, speed: mon_speed, special: mon_special, now: 0, onAttack: false, isAttack: false } //怪物属性 //先攻,先攻为怪物和勇士勇士行动前怪物出第一刀 if (core.hasSpecial(mon_special, 1)) { @@ -1194,27 +1205,27 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = }) - if (onattack) { //处理完毕后的数据处理 - heroDiffList.push(hero_diff) - enemyDiffList.push(enemy_diff) - heroanimateList.push(hero_animate) - enemyanimateList.push(enemy_animate) - //处理属性变化 - for (let v in hero_diff) { - heroinfo[v] += hero_diff[v] - } - for (let v in enemy_diff) { - enemyinfo[v] += enemy_diff[v] - } - let a = hero_turn % 50 //出手50回合怪物生命未降低直接判负,避免死循环 - if (a === 0) { - if (enemyinfo.hp >= beforehp) { - return null - } else { - beforehp = enemyinfo.hp - } + //处理完毕后的数据处理 + heroDiffList.push(hero_diff) + enemyDiffList.push(enemy_diff) + heroanimateList.push(hero_animate) + enemyanimateList.push(enemy_animate) + //处理属性变化 + for (let v in hero_diff) { + heroinfo[v] += hero_diff[v] + } + for (let v in enemy_diff) { + enemyinfo[v] += enemy_diff[v] + } + + //出手50回合怪物生命未降低直接判负,避免死循环 + if (hero_turn === 50) { + + if (enemyinfo.hp >= beforehp) { + return null } } + } //下面这些还没修改,原有技能除先攻、连击外暂时全部移除,所有技能需要在上方的模拟循环中做修正 diff --git a/project/plugins.js b/project/plugins.js index 823da2a..71ba899 100644 --- a/project/plugins.js +++ b/project/plugins.js @@ -1,266 +1,268 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = { "init": function () { - this._afterLoadResources = function () { - // 本函数将在所有资源加载完毕后,游戏开启前被执行 - core.ui.statusBar.init(); - core.dom.playGame.style.fontFamily = "pala"; - core.dom.loadGame.style.fontFamily = "pala"; - core.dom.CGMode.style.fontFamily = "pala"; - core.dom.musicMode.style.fontFamily = "pala"; - core.dom.replayGame.style.fontFamily = "pala"; - core.registerEvent("changeMouse", function (data) { - if (!main.replayChecking && !core.isReplaying()) - core.changeMouse( - data.icon, - data.div, - data.translate[0], - data.translate[1], - data.scale[0], - data.scale[1], - data.angel, - data.px, - data.py - ); - core.doAction(); - }); - core.registerEvent("removeMouse", function (data) { - if (!main.replayChecking && !core.isReplaying()) - core.removeMouse(data.div); - core.doAction(); - }); - core.registerEvent("addPop", function (data) { - if (!main.replayChecking && !core.isReplaying()) { - data.value = core.replaceText(data.value); - core.addPop( - data.value, - data.px, - data.py, - data.color, - data.boldColor, - data.left, - data.jump, - data.time, - data.show, - data.font, - data.speed - ); - } - core.doAction(); - }); - core.registerEvent("drawWarning", function (data) { - if (!main.replayChecking && !core.isReplaying()) { - data.text = core.replaceText(data.text); - data.text2 = core.replaceText(data.text2); - core.drawWarning( - data.x, - data.y, - data?.text, - data?.text2, - data?.warning, - data.large, - data.size - ); + this._afterLoadResources = function () { + // 本函数将在所有资源加载完毕后,游戏开启前被执行 + core.ui.statusBar.init(); + core.dom.playGame.style.fontFamily = "pala"; + core.dom.loadGame.style.fontFamily = "pala"; + core.dom.CGMode.style.fontFamily = "pala"; + core.dom.musicMode.style.fontFamily = "pala"; + core.dom.replayGame.style.fontFamily = "pala"; + core.registerEvent("changeMouse", function (data) { + if (!main.replayChecking && !core.isReplaying()) + core.changeMouse( + data.icon, + data.div, + data.translate[0], + data.translate[1], + data.scale[0], + data.scale[1], + data.angel, + data.px, + data.py + ); + core.doAction(); + }); + core.registerEvent("removeMouse", function (data) { + if (!main.replayChecking && !core.isReplaying()) + core.removeMouse(data.div); + core.doAction(); + }); + core.registerEvent("addPop", function (data) { + if (!main.replayChecking && !core.isReplaying()) { + data.value = core.replaceText(data.value); + core.addPop( + data.value, + data.px, + data.py, + data.color, + data.boldColor, + data.left, + data.jump, + data.time, + data.show, + data.font, + data.speed + ); + } + core.doAction(); + }); + core.registerEvent("drawWarning", function (data) { + if (!main.replayChecking && !core.isReplaying()) { + data.text = core.replaceText(data.text); + data.text2 = core.replaceText(data.text2); + core.drawWarning( + data.x, + data.y, + data?.text, + data?.text2, + data?.warning, + data.large, + data.size + ); - setTimeout(() => core.doAction(), 3100); - } else { - core.doAction(); - } - }); + setTimeout(() => core.doAction(), 3100); + } else { + core.doAction(); + } + }); - core.registerEvent("over", function (data) { - let image = data.image ?? ""; - let time = data.time ?? 3000; - let sound = data.sound ?? ""; - let textColor = data.textColor ?? "#FFFFFF"; - let boldColor = data.boldColor ?? "#000000"; - let font = data.font ?? "bold 48px Verdana"; - let text = data.text ?? ""; - let hidetime = data.hidetime ?? 100; - if (!main.replayChecking && !core.isReplaying()) { - core.over( - image, - data.memory, - time, - hidetime, - sound, - textColor, - boldColor, - font, - text - ); - } else { - core.doAction(); - } - }); - core.registerEvent("changebg", function (data) { - if (!main.replayChecking && !core.isReplaying()) { - core.changebg( - data.img1, - data.memory1, - data.img2, - data.memory2, - data.time, - data.style - ); - } else { - core.doAction(); - } - }); - core.registerEvent("overlist", function (data) { - if (!main.replayChecking && !core.isReplaying()) { - core.overlist( - data.image, - data.memory, - data.hidetime || 30, - data.list || [{ - text: "", - sound: "", - time: 50, - textColor: "#FFFFFF", - boldColor: "#000000", - font: "bold 48px Verdana", - frame: 0, - }, ] - ); - } else { - core.doAction(); - } - }); - core.registerEvent("op", function (data) { - if (!main.replayChecking && !core.isReplaying()) { - core.openvideo(); - } else { - core.doAction(); - } - }); - core.registerEvent("animationDrawable", function (data) { - if (!main.replayChecking && !core.isReplaying()) { - core.animationDrawable( - data.allFarme, - data.color, - data.globalAlpha, - data.imageList, - data.soundList - ); - } else { - core.doAction(); - } - }); - core.registerEvent("setanimate", function (data) { - data.px = data.px ?? 0; - data.py = data.py ?? 0; - core.setanimate( - data.name, - data.px, - data.py, - data.width, - data.height, - data.allFarme, - data.imageList, - data.soundList - ); - core.doAction(); - }); - core.registerEvent("clearanimate", function (data) { - core.plugin.playing.clear(); + core.registerEvent("over", function (data) { + let image = data.image ?? ""; + let time = data.time ?? 3000; + let sound = data.sound ?? ""; + let textColor = data.textColor ?? "#FFFFFF"; + let boldColor = data.boldColor ?? "#000000"; + let font = data.font ?? "bold 48px Verdana"; + let text = data.text ?? ""; + let hidetime = data.hidetime ?? 100; + if (!main.replayChecking && !core.isReplaying()) { + core.over( + image, + data.memory, + time, + hidetime, + sound, + textColor, + boldColor, + font, + text + ); + } else { + core.doAction(); + } + }); + core.registerEvent("changebg", function (data) { + if (!main.replayChecking && !core.isReplaying()) { + core.changebg( + data.img1, + data.memory1, + data.img2, + data.memory2, + data.time, + data.style + ); + } else { + core.doAction(); + } + }); + core.registerEvent("overlist", function (data) { + if (!main.replayChecking && !core.isReplaying()) { + core.overlist( + data.image, + data.memory, + data.hidetime || 30, + data.list || [ + { + text: "", + sound: "", + time: 50, + textColor: "#FFFFFF", + boldColor: "#000000", + font: "bold 48px Verdana", + frame: 0, + }, + ] + ); + } else { + core.doAction(); + } + }); + core.registerEvent("op", function (data) { + if (!main.replayChecking && !core.isReplaying()) { + core.openvideo(); + } else { + core.doAction(); + } + }); + core.registerEvent("animationDrawable", function (data) { + if (!main.replayChecking && !core.isReplaying()) { + core.animationDrawable( + data.allFarme, + data.color, + data.globalAlpha, + data.imageList, + data.soundList + ); + } else { + core.doAction(); + } + }); + core.registerEvent("setanimate", function (data) { + data.px = data.px ?? 0; + data.py = data.py ?? 0; + core.setanimate( + data.name, + data.px, + data.py, + data.width, + data.height, + data.allFarme, + data.imageList, + data.soundList + ); + core.doAction(); + }); + core.registerEvent("clearanimate", function (data) { + core.plugin.playing.clear(); - core.doAction(); - }); - core.registerEvent("deleteanimate", function (data) { - core.deleteanimate(data.name); - core.doAction(); - }); - core.registerEvent("playanimate", function (data) { - if (!main.replayChecking && !core.isReplaying()) { - data.x = data.x ?? 0; - data.y = data.y ?? 0; - data.scalex = data.scalex ?? 1; - data.scaley = data.scaley ?? 1; - core.playanimate( - data.name, - data.x, - data.y, - data.hero, - data.scalex, - data.scaley - ); - core.doAction(); - } else { - core.doAction(); - } - }); - core.registerEvent("cgtextList", function (data) { - core.ui.cgText.textList = core.plugin[data.textList]; - core.doAction(); - }); - core.registerEvent("cgtext", function (data) { - if (!main.replayChecking && !core.isReplaying()) { - core.ui.cgText.image = data.bg; - core.ui.cgText.nobg = data.nobg ?? false; - core.ui.cgText.memory = data.memory; - core.ui.cgText.head = core.clone(data.head); - core.ui.cgText.index = data.index; - core.ui.cgText.name = core.ui.cgText.textList[data.index][0]; - core.ui.cgText.text = data.text ? - data.text : - core.ui.cgText.textList[data.index][1]; - core.ui.cgText.time = data.time; - core.ui.cgText.wait = data.wait; - core.ui.cgText.WindowSkin = data.WindowSkin; - core.ui.cgText.sound = - data.sound === "" ? - data.sound : - core.ui.cgText.textList[data.index][2] || ""; - core.ui.cgText.bodyList = core.clone(data.bodyList); - main.dom.cgText.style.display = "block"; - core.ui.cgText.update(); - } else { - core.doAction(); - } - }); - core.registerEvent("introAndLoop", function (data) { - if (!main.replayChecking && !core.isReplaying()) { - core.plugin.introAndLoop(data.intro, data.time, data.loop); - core.doAction(); - } else { - core.doAction(); - } - }); - core.registerEvent("setq", function (data) { - core.setFlag("任务地点", data.id); + core.doAction(); + }); + core.registerEvent("deleteanimate", function (data) { + core.deleteanimate(data.name); + core.doAction(); + }); + core.registerEvent("playanimate", function (data) { + if (!main.replayChecking && !core.isReplaying()) { + data.x = data.x ?? 0; + data.y = data.y ?? 0; + data.scalex = data.scalex ?? 1; + data.scaley = data.scaley ?? 1; + core.playanimate( + data.name, + data.x, + data.y, + data.hero, + data.scalex, + data.scaley + ); + core.doAction(); + } else { + core.doAction(); + } + }); + core.registerEvent("cgtextList", function (data) { + core.ui.cgText.textList = core.plugin[data.textList]; + core.doAction(); + }); + core.registerEvent("cgtext", function (data) { + if (!main.replayChecking && !core.isReplaying()) { + core.ui.cgText.image = data.bg; + core.ui.cgText.nobg = data.nobg ?? false; + core.ui.cgText.memory = data.memory; + core.ui.cgText.head = core.clone(data.head); + core.ui.cgText.index = data.index; + core.ui.cgText.name = core.ui.cgText.textList[data.index][0]; + core.ui.cgText.text = data.text + ? data.text + : core.ui.cgText.textList[data.index][1]; + core.ui.cgText.time = data.time; + core.ui.cgText.wait = data.wait; + core.ui.cgText.WindowSkin = data.WindowSkin; + core.ui.cgText.sound = + data.sound === "" + ? data.sound + : core.ui.cgText.textList[data.index][2] || ""; + core.ui.cgText.bodyList = core.clone(data.bodyList); + main.dom.cgText.style.display = "block"; + core.ui.cgText.update(); + } else { + core.doAction(); + } + }); + core.registerEvent("introAndLoop", function (data) { + if (!main.replayChecking && !core.isReplaying()) { + core.plugin.introAndLoop(data.intro, data.time, data.loop); + core.doAction(); + } else { + core.doAction(); + } + }); + core.registerEvent("setq", function (data) { + core.setFlag("任务地点", data.id); - core.doAction(); - }); + core.doAction(); + }); - core.registerEvent("setmusics", function (data) { - if ( - (core.getLocalStorage("musics") && - core.getLocalStorage("musics").length === 0) || - !core.getLocalStorage("musics") - ) - core.setLocalStorage("musics", ["theme.mp3"]); - let a = core.getLocalStorage("musics"); - if (!data.bgm) { - core.setLocalStorage("musics", ["theme.mp3"]); - } else { - if (!a.includes(data.bgm)) a.push(data.bgm); - core.setLocalStorage("musics", a); - } - core.doAction(); - }); - core.registerEvent("setcgs", function (data) { - if (!data.img) { - core.setLocalStorage("cgs", []); - } else { - let a = core.getLocalStorage("cgs") ?? []; - if (!a.includes(data.img)) a.push(data.img); - core.setLocalStorage("cgs", a); - } - core.doAction(); - }); - }; -}, + core.registerEvent("setmusics", function (data) { + if ( + (core.getLocalStorage("musics") && + core.getLocalStorage("musics").length === 0) || + !core.getLocalStorage("musics") + ) + core.setLocalStorage("musics", ["theme.mp3"]); + let a = core.getLocalStorage("musics"); + if (!data.bgm) { + core.setLocalStorage("musics", ["theme.mp3"]); + } else { + if (!a.includes(data.bgm)) a.push(data.bgm); + core.setLocalStorage("musics", a); + } + core.doAction(); + }); + core.registerEvent("setcgs", function (data) { + if (!data.img) { + core.setLocalStorage("cgs", []); + } else { + let a = core.getLocalStorage("cgs") ?? []; + if (!a.includes(data.img)) a.push(data.img); + core.setLocalStorage("cgs", a); + } + core.doAction(); + }); + }; + }, "drawLight": function () { // 绘制灯光/漆黑层效果。调用方式 core.plugin.drawLight(...) // 【参数说明】 @@ -698,118 +700,118 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = var __enable = true; if (!__enable) return; - // 创建新图层 - function createCanvas(name, zIndex) { - if (!name) return; - var canvas = document.createElement("canvas"); - canvas.id = name; - canvas.className = "gameCanvas anti-aliasing"; - // 编辑器模式下设置zIndex会导致加入的图层覆盖优先级过高 - if (main.mode != "editor") canvas.style.zIndex = zIndex || 0; - // 将图层插入进游戏内容 - document.getElementById("gameDraw").appendChild(canvas); - var ctx = canvas.getContext("2d"); - core.canvas[name] = ctx; - canvas.width = core._PX_ || core.__PIXELS__; - canvas.height = core._PY_ || core.__PIXELS__; - return canvas; - } + // 创建新图层 + function createCanvas(name, zIndex) { + if (!name) return; + var canvas = document.createElement("canvas"); + canvas.id = name; + canvas.className = "gameCanvas anti-aliasing"; + // 编辑器模式下设置zIndex会导致加入的图层覆盖优先级过高 + if (main.mode != "editor") canvas.style.zIndex = zIndex || 0; + // 将图层插入进游戏内容 + document.getElementById("gameDraw").appendChild(canvas); + var ctx = canvas.getContext("2d"); + core.canvas[name] = ctx; + canvas.width = core._PX_ || core.__PIXELS__; + canvas.height = core._PY_ || core.__PIXELS__; + return canvas; + } - var bg2Canvas = createCanvas("bg2", 20); - var fg2Canvas = createCanvas("fg2", 63); - // 大地图适配 - core.bigmap.canvas = [ - "bg2", - "fg2", - "bg", - "event", - "event2", - "fg", - "damage", - ]; - core.initStatus.bg2maps = {}; - core.initStatus.fg2maps = {}; + var bg2Canvas = createCanvas("bg2", 20); + var fg2Canvas = createCanvas("fg2", 63); + // 大地图适配 + core.bigmap.canvas = [ + "bg2", + "fg2", + "bg", + "event", + "event2", + "fg", + "damage", + ]; + core.initStatus.bg2maps = {}; + core.initStatus.fg2maps = {}; - if (main.mode == "editor") { - /*插入编辑器的图层 不做此步新增图层无法在编辑器显示*/ - // 编辑器图层覆盖优先级 eui > efg > fg(前景层) > event2(48*32图块的事件层) > event(事件层) > bg(背景层) - // 背景层2(bg2) 插入事件层(event)之前(即bg与event之间) - document - .getElementById("mapEdit") - .insertBefore(bg2Canvas, document.getElementById("event")); - // 前景层2(fg2) 插入编辑器前景(efg)之前(即fg之后) - document - .getElementById("mapEdit") - .insertBefore(fg2Canvas, document.getElementById("ebm")); - // 原本有三个图层 从4开始添加 - var num = 4; - // 新增图层存入editor.dom中 - editor.dom.bg2c = core.canvas.bg2.canvas; - editor.dom.bg2Ctx = core.canvas.bg2; - editor.dom.fg2c = core.canvas.fg2.canvas; - editor.dom.fg2Ctx = core.canvas.fg2; - editor.dom.maps.push("bg2map", "fg2map"); - editor.dom.canvas.push("bg2", "fg2"); + if (main.mode == "editor") { + /*插入编辑器的图层 不做此步新增图层无法在编辑器显示*/ + // 编辑器图层覆盖优先级 eui > efg > fg(前景层) > event2(48*32图块的事件层) > event(事件层) > bg(背景层) + // 背景层2(bg2) 插入事件层(event)之前(即bg与event之间) + document + .getElementById("mapEdit") + .insertBefore(bg2Canvas, document.getElementById("event")); + // 前景层2(fg2) 插入编辑器前景(efg)之前(即fg之后) + document + .getElementById("mapEdit") + .insertBefore(fg2Canvas, document.getElementById("ebm")); + // 原本有三个图层 从4开始添加 + var num = 4; + // 新增图层存入editor.dom中 + editor.dom.bg2c = core.canvas.bg2.canvas; + editor.dom.bg2Ctx = core.canvas.bg2; + editor.dom.fg2c = core.canvas.fg2.canvas; + editor.dom.fg2Ctx = core.canvas.fg2; + editor.dom.maps.push("bg2map", "fg2map"); + editor.dom.canvas.push("bg2", "fg2"); - // 创建编辑器上的按钮 - var createCanvasBtn = function (name) { - // 电脑端创建按钮 - var input = document.createElement("input"); - // layerMod4/layerMod5 - var id = "layerMod" + num++; - // bg2map/fg2map - var value = name + "map"; - input.type = "radio"; - input.name = "layerMod"; - input.id = id; - input.value = value; - editor.dom[id] = input; - input.onchange = function () { - editor.uifunctions.setLayerMod(value); - }; - return input; - }; + // 创建编辑器上的按钮 + var createCanvasBtn = function (name) { + // 电脑端创建按钮 + var input = document.createElement("input"); + // layerMod4/layerMod5 + var id = "layerMod" + num++; + // bg2map/fg2map + var value = name + "map"; + input.type = "radio"; + input.name = "layerMod"; + input.id = id; + input.value = value; + editor.dom[id] = input; + input.onchange = function () { + editor.uifunctions.setLayerMod(value); + }; + return input; + }; - var createCanvasBtn_mobile = function (name) { - // 手机端往选择列表中添加子选项 - var input = document.createElement("option"); - var id = "layerMod" + num++; - var value = name + "map"; - input.name = "layerMod"; - input.value = value; - editor.dom[id] = input; - return input; - }; - if (!editor.isMobile) { - var input = createCanvasBtn("bg2"); - var input2 = createCanvasBtn("fg2"); - // 获取事件层及其父节点 - var child = document.getElementById("layerMod"), - parent = child.parentNode; - // 背景层2插入事件层前 - parent.insertBefore(input, child); - // 不能直接更改背景层2的innerText 所以创建文本节点 - var txt = document.createTextNode("bg2"); - // 插入事件层前(即新插入的背景层2前) - parent.insertBefore(txt, child); - // 向最后插入前景层2(即插入前景层后) - parent.appendChild(input2); - var txt2 = document.createTextNode("fg2"); - parent.appendChild(txt2); - parent.childNodes[2].replaceWith("bg"); - parent.childNodes[6].replaceWith("事件"); - parent.childNodes[8].replaceWith("fg"); - } else { - var input = createCanvasBtn_mobile("bg2"); - var input2 = createCanvasBtn_mobile("fg2"); - // 手机端因为是选项 所以可以直接改innerText - input.innerText = "背景层2"; - input2.innerText = "前景层2"; - var parent = document.getElementById("layerMod"); - parent.insertBefore(input, parent.children[1]); - parent.appendChild(input2); - } - } + var createCanvasBtn_mobile = function (name) { + // 手机端往选择列表中添加子选项 + var input = document.createElement("option"); + var id = "layerMod" + num++; + var value = name + "map"; + input.name = "layerMod"; + input.value = value; + editor.dom[id] = input; + return input; + }; + if (!editor.isMobile) { + var input = createCanvasBtn("bg2"); + var input2 = createCanvasBtn("fg2"); + // 获取事件层及其父节点 + var child = document.getElementById("layerMod"), + parent = child.parentNode; + // 背景层2插入事件层前 + parent.insertBefore(input, child); + // 不能直接更改背景层2的innerText 所以创建文本节点 + var txt = document.createTextNode("bg2"); + // 插入事件层前(即新插入的背景层2前) + parent.insertBefore(txt, child); + // 向最后插入前景层2(即插入前景层后) + parent.appendChild(input2); + var txt2 = document.createTextNode("fg2"); + parent.appendChild(txt2); + parent.childNodes[2].replaceWith("bg"); + parent.childNodes[6].replaceWith("事件"); + parent.childNodes[8].replaceWith("fg"); + } else { + var input = createCanvasBtn_mobile("bg2"); + var input2 = createCanvasBtn_mobile("fg2"); + // 手机端因为是选项 所以可以直接改innerText + input.innerText = "背景层2"; + input2.innerText = "前景层2"; + var parent = document.getElementById("layerMod"); + parent.insertBefore(input, parent.children[1]); + parent.appendChild(input2); + } + } var _loadFloor_doNotCopy = core.maps._loadFloor_doNotCopy; core.maps._loadFloor_doNotCopy = function () { @@ -2538,7 +2540,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = const BORDER_HEIGHT = 0; //游戏画面上侧偏移距离 const ITEM_BOX_LEFT = 549 * 3; //横屏道具栏左侧距离(右侧边栏需增加BAR_WIDTH+GAMEVIEW_HEIGHT) - const ITEM_BOX_TOP = 155 * 3; //横屏道具栏上侧距离 + const ITEM_BOX_TOP = 175 * 3; //横屏道具栏上侧距离 const ITEM_BOX_LEFT_VERTICAL = 160 * 3; //竖屏道具栏左侧距离 const ITEM_BOX_TOP_VERTICAL = 549 * 3; //竖屏道具栏上侧距离(下侧边栏需增加BAR_HEIGHT_VERTICAL+GAMEVIEW_WIDTH_VERTICAL) @@ -2553,12 +2555,12 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = const MAP_BLOCK_TOP_VERTICAL = 551 * 3; //竖屏小地图上侧距离(下侧边栏需增加BAR_HEIGHT_VERTICAL+GAMEVIEW_WIDTH_VERTICAL) const KEY_BLOCK_LEFT = EQUIP_BLOCK_LEFT; //横屏钥匙栏左侧距离(右侧边栏需增加BAR_WIDTH+GAMEVIEW_HEIGHT) - const KEY_BLOCK_TOP = 110 * 3; //横屏钥匙栏上侧距离 + const KEY_BLOCK_TOP = 130 * 3; //横屏钥匙栏上侧距离 const KEY_BLOCK_LEFT_VERTICAL = 110 * 3; //竖屏钥匙栏左侧距离 const KEY_BLOCK_TOP_VERTICAL = EQUIP_BLOCK_TOP_VERTICAL; //竖屏钥匙栏上侧距离(下侧边栏需增加BAR_HEIGHT_VERTICAL+GAMEVIEW_WIDTH_VERTICAL) const INFO_BLOCK_LEFT = 10 * 3; //横屏道具说明左侧距离(右侧边栏需增加BAR_WIDTH+GAMEVIEW_HEIGHT) - const INFO_BLOCK_TOP = 180 * 3; //横屏道具说明上侧距离 + const INFO_BLOCK_TOP = 290 * 3; //横屏道具说明上侧距离 const INFO_BLOCK_LEFT_VERTICAL = 113 * 3; //竖屏道具说明左侧距离 const INFO_BLOCK_TOP_VERTICAL = 8 * 3; //竖屏道具说明上侧距离(下侧边栏需增加BAR_HEIGHT_VERTICAL+GAMEVIEW_WIDTH_VERTICAL) @@ -2690,6 +2692,10 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = main.dom.over.style.width = obj.totalWidth + 3 + "px"; main.dom.over.style.height = obj.totalHeight + 3 + "px"; } + if (main.dom.book) { + main.dom.book.style.width = obj.totalWidth + 3 + "px"; + main.dom.book.style.height = obj.totalHeight + 3 + "px"; + } if (main.dom.video) { main.dom.video.style.width = obj.totalWidth + 3 + "px"; main.dom.video.style.height = obj.totalHeight + 3 + "px"; @@ -2713,15 +2719,12 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = main.dom.boss1.style.width = obj.totalWidth + 3 + "px"; main.dom.boss1.style.height = obj.totalHeight + 3 + "px"; - main.dom.boss2.style.width = obj.totalWidth + 3 + "px"; main.dom.boss2.style.height = obj.totalHeight + 3 + "px"; - main.dom.boss3.style.width = obj.totalWidth + 3 + "px"; main.dom.boss3.style.height = obj.totalHeight + 3 + "px"; - main.dom.boss4.style.width = obj.totalWidth + 3 + "px"; main.dom.boss4.style.height = obj.totalHeight + 3 + "px"; @@ -2906,7 +2909,6 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = core.ui.boss.update(); }; - class StatusBar { constructor() { //道具栏列表 @@ -2933,16 +2935,22 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ]; this.replayAction = [ [core.triggerReplay, core.stopReplay, core.rewindReplay], - [core.speedDownReplay, core.speedUpReplay, function () { core.control._replay_SL() }], + [ + core.speedDownReplay, + core.speedUpReplay, + function () { + core.control._replay_SL(); + }, + ], ]; } //更新 update() { this._update_background(); //更新背景 this._update_props(); //更新属性 - //this._update_items(); //更新道具 + this._update_items(); //更新道具 //this._update_equips(); //更新装备 - //this._update_keys(); //更新钥匙 + this._update_keys(); //更新钥匙 //this._update_infoWindow(); //更新道具说明 this._update_toolBox(); //更新工具栏 this._redrawMap(); @@ -3032,33 +3040,66 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = if (!updatedFloorTitle && core.status.floorId) { updatedFloorTitle = core.status.maps[core.status.floorId].title; } - const statusList = ["hp", "atk", "def", "money"]; //属性列表,图标在函数复写core.statusBar.icons中声明,数字为project\materials\icons.png中的图标序号(可使用便捷ps追加,第一个序号为0) + const statusList = [ + "hp", + "atk", + "def", + "spell", + "mdef", + "matk", + "mhp", + "speed", + "money", + ]; //属性列表,图标在函数复写core.statusBar.icons中声明,数字为project\materials\icons.png中的图标序号(可使用便捷ps追加,第一个序号为0) const drawStatusList = (baseX, baseY) => { let curh = baseY; core.setTextAlign("outerUI", "right"); statusList.forEach((item) => { // 绘制图标 - core.drawIcon( - "outerUI", - item, - baseX - 95 * 3, - curh - 18 * 3, - 22 * 3, - 22 * 3 - ); - - // 四舍五入 - core.status.hero[item] = Math.round(core.status.hero[item]); - // 大数据格式化 + /*core.drawIcon( + "outerUI", + item, + baseX - 95 * 3, + curh - 18 * 3, + 22 * 3, + 22 * 3 + );*/ + core.strokeRect("outerUI", baseX - 96 * 3, + curh - 16 * 3, 100 * 3, 22 * 3, "#FFFFFF", 3) + core.setFont("outerUI", "bold 24px Verdana"); core.fillBoldText1( "outerUI", - core.getRealStatus(item), + core.getStatusLabel(item), + baseX - 65 * 3, + curh - 4 * 3, + TEXT_COLOR, + "#000000", + 6 + ); + core.setFont("outerUI", "bold 36px Verdana"); + // 四舍五入 + core.status.hero[item] = Math.round(core.status.hero[item]); + let text = core.getRealStatus(item); + // 大数据格式化 + switch (item) { + case "mdef": + text += "%"; + break; + case "matk": + case "mhp": + text += `(${core.status.hero[item]})%`; + break; + } + core.fillBoldText1( + "outerUI", + text, baseX, curh, TEXT_COLOR, "#000000", 6 ); + curh += 24 * 3; if (curh > 130 * 3 && core.domStyle.isVertical) { curh = 24 * 3; @@ -3081,9 +3122,9 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = 6 ); } - //drawStatusList(96 * 3, 46 * 3); + drawStatusList(96 * 3, 46 * 3); //core.drawImage("outerUI", "lane1.png", 0, 0) - core.drawImage("outerUI", "cao.webp", 0, 0); + //core.drawImage("outerUI", "cao.webp", 0, 0); } else { core.clearMap("outerUI", 10 * 3, 40 * 3, 105 * 3, 250 * 3); core.setFont("outerUI", "bold 48px Verdana"); @@ -3098,8 +3139,8 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = 6 ); } - //drawStatusList(110 * 3, 93 * 3); - //core.drawImage("outerUI", "lane1.png", 0, 30) + drawStatusList(110 * 3, 93 * 3); + //core.drawImage("outerUI", "lane1.png", 0, 30); core.drawImage( "outerUI", "cao.webp", @@ -3462,7 +3503,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = top: INFO_BLOCK_TOP_VERTICAL + 40 * 3, maxWidth: 275 * 3, color: "#D1CEFF", - fontSize: 36, + fontSize: 24, }); } } else { @@ -3473,7 +3514,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = 115 * 3, 230 * 3 ); - + core.setFont("outerUI", "bold 36px Verdana") if (this.selectedItem) { const icon = core.material.icons.items[itemId]; core.setTextAlign("outerUI", "center"); @@ -3501,7 +3542,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = top: INFO_BLOCK_TOP + 60 * 3, maxWidth: 105 * 3, color: "#D1CEFF", - fontSize: 36, + fontSize: 24, }); } } @@ -3892,7 +3933,8 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = return nextInfo == null || typeof nextInfo == "number" || nextInfo.damage >= pre ? - null : [start, nextInfo.damage]; + null : + [start, nextInfo.damage]; }; var currAtk = start_atk; while (true) { @@ -4348,93 +4390,93 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = if (core.status.played && !core.status.lockControl) return false; switch (core.status.event.id) { - case 'battle': + case "battle": core.plugin.battle_onclick(x, y, px, py); break; - case 'centerFly': + case "centerFly": this._clickCenterFly(x, y, px, py); break; - case 'book': + case "book": this._clickBook(x, y, px, py); break; - case 'book-detail': + case "book-detail": this._clickBookDetail(x, y, px, py); break; - case 'fly': + case "fly": this._clickFly(x, y, px, py); break; - case 'viewMaps': + case "viewMaps": this._clickViewMaps(x, y, px, py); break; - case 'switchs': + case "switchs": this._clickSwitchs(x, y, px, py); break; - case 'switchs-sounds': + case "switchs-sounds": this._clickSwitchs_sounds(x, y, px, py); break; - case 'switchs-display': + case "switchs-display": this._clickSwitchs_display(x, y, px, py); break; - case 'switchs-action': + case "switchs-action": this._clickSwitchs_action(x, y, px, py); break; - case 'settings': + case "settings": this._clickSettings(x, y, px, py); break; - case 'selectShop': + case "selectShop": this._clickQuickShop(x, y, px, py); break; - case 'equipbox': + case "equipbox": this._clickEquipbox(x, y, px, py); break; - case 'toolbox': + case "toolbox": this._clickToolbox(x, y, px, py); break; - case 'save': - case 'load': - case 'replayLoad': - case 'replayRemain': - case 'replaySince': + case "save": + case "load": + case "replayLoad": + case "replayRemain": + case "replaySince": this._clickSL(x, y, px, py); break; - case 'confirmBox': + case "confirmBox": this._clickConfirmBox(x, y, px, py); break; - case 'keyBoard': + case "keyBoard": this._clickKeyBoard(x, y, px, py); break; - case 'action': + case "action": this._clickAction(x, y, px, py); break; - case 'text': + case "text": core.drawText(); break; - case 'notes': + case "notes": this._clickNotes(x, y, px, py); break; - case 'syncSave': + case "syncSave": this._clickSyncSave(x, y, px, py); break; - case 'syncSelect': + case "syncSelect": this._clickSyncSelect(x, y, px, py); break; - case 'localSaveSelect': + case "localSaveSelect": this._clickLocalSaveSelect(x, y, px, py); break; - case 'storageRemove': + case "storageRemove": this._clickStorageRemove(x, y, px, py); break; - case 'cursor': + case "cursor": this._clickCursor(x, y, px, py); break; - case 'replay': + case "replay": this._clickReplay(x, y, px, py); break; - case 'gameInfo': + case "gameInfo": this._clickGameInfo(x, y, px, py); break; - case 'about': - case 'help': + case "about": + case "help": core.ui.closePanel(); break; } @@ -4448,13 +4490,18 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = clearInterval(core.interval.onDownInterval); core.interval.onDownInterval = null; } - }, 40) + }, 40); } }, 500); } return true; - } - core.registerAction('ondown', '_sys_ondown_lockControl', core.actions._sys_ondown_lockControl, 30);; + }; + core.registerAction( + "ondown", + "_sys_ondown_lockControl", + core.actions._sys_ondown_lockControl, + 30 + ); }, "额外信息": function () { /* 宝石血瓶左下角显示数值 @@ -4614,8 +4661,8 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = } }, "跳伤": function () { - // 在此增加新插件 - /** + // 在此增加新插件 + /** 函数使用说明 Dove.MorePerform.ShowDamagePop.PopDamage( 'ui', // 画布名称或画布2d上下文对象 @@ -4630,170 +4677,235 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = 0.5, // 重力 (gravity) 120 // 显示时长(帧数) */ - if (!core.registerAnimationFrame) { - throw new Error('require 2.6.1 or higher version'); - } + if (!core.registerAnimationFrame) { + throw new Error("require 2.6.1 or higher version"); + } - window.Dove = window.Dove || {}; - Dove.MorePerform = Dove.MorePerform || {}; + window.Dove = window.Dove || {}; + Dove.MorePerform = Dove.MorePerform || {}; - Dove.MorePerform.ShowDamagePop = {}; - Dove.MorePerform.ShowDamagePop.version = 1.0; + Dove.MorePerform.ShowDamagePop = {}; + Dove.MorePerform.ShowDamagePop.version = 1.0; - Dove.MorePerform.ShowDamagePop.AllPopingCanvas = []; + Dove.MorePerform.ShowDamagePop.AllPopingCanvas = []; - // 每帧的处理 - Dove.MorePerform.ShowDamagePop.Update = function () { - this.AllPopingCanvas = this.AllPopingCanvas.filter(function (spr) { - spr.update(); - return spr.isAlive(); - }); - if (!this.AllPopingCanvas.length) PopSprite._count = 0; - }; + // 每帧的处理 + Dove.MorePerform.ShowDamagePop.Update = function () { + this.AllPopingCanvas = this.AllPopingCanvas.filter(function (spr) { + spr.update(); + return spr.isAlive(); + }); + if (!this.AllPopingCanvas.length) PopSprite._count = 0; + }; - // 弹出伤害气泡 - Dove.MorePerform.ShowDamagePop.PopDamage = function (canvasName, x, y, damageValue, fontSize, font, fontColor, outlineColor, speedX, speedY, gravity, duration) { - if (damageValue) { - var poper = new PopSprite(canvasName, x, y, damageValue, fontSize, font, fontColor, outlineColor, speedX, speedY, gravity, duration); - Dove.MorePerform.ShowDamagePop.AllPopingCanvas.push(poper); - } - }; + // 弹出伤害气泡 + Dove.MorePerform.ShowDamagePop.PopDamage = function ( + canvasName, + x, + y, + damageValue, + fontSize, + font, + fontColor, + outlineColor, + speedX, + speedY, + gravity, + duration + ) { + if (damageValue) { + var poper = new PopSprite( + canvasName, + x, + y, + damageValue, + fontSize, + font, + fontColor, + outlineColor, + speedX, + speedY, + gravity, + duration + ); + Dove.MorePerform.ShowDamagePop.AllPopingCanvas.push(poper); + } + }; - // 战斗发生前后记录生命值并处理 - Dove.MorePerform.ShowDamagePop.OnBattle = core.events.battle; - core.events.battle = function () { - var hpBeforeBattle = core.status.hero.hp; - Dove.MorePerform.ShowDamagePop.OnBattle.apply(core.events, arguments); - if (core.getFlag('noAnimate')) Dove.MorePerform.ShowDamagePop.PopDamage( - "ui", // 默认画布名称 - core.getHeroLoc('x') * 32, // 英雄位置 x - core.getHeroLoc('y') * 32, // 英雄位置 y - Math.floor(core.status.hero.hp - hpBeforeBattle), // 伤害值 - 16, // 默认字体大小 - "Arial", //默认字体 - null, // 默认颜色 - null, // 默认描边颜色 - null, // 默认水平速度 - null, // 默认垂直速度 - null, // 默认重力 - 90 // 默认显示时长(帧数) - ); + // 战斗发生前后记录生命值并处理 + Dove.MorePerform.ShowDamagePop.OnBattle = core.events.battle; + core.events.battle = function () { + var hpBeforeBattle = core.status.hero.hp; + Dove.MorePerform.ShowDamagePop.OnBattle.apply(core.events, arguments); + if (core.getFlag("noAnimate")) + Dove.MorePerform.ShowDamagePop.PopDamage( + "ui", // 默认画布名称 + core.getHeroLoc("x") * 32, // 英雄位置 x + core.getHeroLoc("y") * 32, // 英雄位置 y + Math.floor(core.status.hero.hp - hpBeforeBattle), // 伤害值 + 16, // 默认字体大小 + "Arial", //默认字体 + null, // 默认颜色 + null, // 默认描边颜色 + null, // 默认水平速度 + null, // 默认垂直速度 + null, // 默认重力 + 90 // 默认显示时长(帧数) + ); + }; + let time = 0; + // 注册每帧事件 + core.registerAnimationFrame("ShowDamagePop", true, (temptime) => { + if (temptime - time > 1000 / 60) { + time = temptime; - }; - let time = 0 - // 注册每帧事件 - core.registerAnimationFrame("ShowDamagePop", true, - (temptime) => { - if (temptime - time > 1000 / 60) { - time = temptime + Dove.MorePerform.ShowDamagePop.Update.bind( + Dove.MorePerform.ShowDamagePop + )(); + } + }); - Dove.MorePerform.ShowDamagePop.Update.bind(Dove.MorePerform.ShowDamagePop)() - } - } + // 弹出精灵类 + function PopSprite( + canvasName, + x, + y, + damage, + fontSize, + font, + fontColor, + outlineColor, + speedX, + speedY, + gravity, + duration + ) { + this.initialize.apply(this, arguments); + } - ); + PopSprite.prototype = Object.create(Object.prototype); + PopSprite.prototype.constructor = PopSprite; - // 弹出精灵类 - function PopSprite(canvasName, x, y, damage, fontSize, font, fontColor, outlineColor, speedX, speedY, gravity, duration) { - this.initialize.apply(this, arguments); - } + // 常量 + PopSprite._count = 0; + PopSprite._baseZOrder = 50; + PopSprite._floorDis = 20; - PopSprite.prototype = Object.create(Object.prototype); - PopSprite.prototype.constructor = PopSprite; + // 初始化 + PopSprite.prototype.initialize = function ( + canvasName, + x, + y, + damage, + fontSize, + font, + fontColor, + outlineColor, + speedX, + speedY, + gravity, + duration + ) { + this._canvasName = canvasName ?? "ui"; // 默认画布名称 + this._x = x; + this._y = y; + this._damage = damage; + this._fontSize = fontSize ?? 16; // 默认字体大小 + this._font = font ?? "Arial"; + this._fontColor = fontColor ?? (damage > 0 ? "#22FF44" : "lightcoral"); // 默认颜色 + this._outlineColor = outlineColor ?? "#FFFFFF"; // 默认描边颜色 + this._speedX = speedX ?? -1 + Math.random() * 2; // 水平速度,默认随机 + this._speedY = speedY ?? -3 - Math.random() * 4; // 垂直速度,默认随机 + this._gravity = gravity ?? 0.3; // 重力加速度,默认 0.3 + this._duration = duration ?? 180; // 显示时长(帧数),默认 180 帧 + this.initAllMembers(); + this.requestCanvas(); + }; - // 常量 - PopSprite._count = 0; - PopSprite._baseZOrder = 50; - PopSprite._floorDis = 20; + // 自更新 + PopSprite.prototype.update = function () { + if (this._timer < this._duration) { + // 使用传入的显示时长 + this._x += this._vx; + this._y += this._vy; + this._vy += this._gravity; + if (this._y >= this._floorY) { + this._y = this._floorY; + this._vy *= -0.75; // 反弹衰减 + } + core.relocateCanvas(this._symbol, this._x, this._y); + core.setOpacity(this._symbol, 1 - this._timer / this._duration); // 根据显示时长设置透明度 + } else { + this.dispose(); + } + this._timer++; + }; - // 初始化 - PopSprite.prototype.initialize = function (canvasName, x, y, damage, fontSize, font, fontColor, outlineColor, speedX, speedY, gravity, duration) { - this._canvasName = canvasName ?? 'ui'; // 默认画布名称 - this._x = x; - this._y = y; - this._damage = damage; - this._fontSize = fontSize ?? 16; // 默认字体大小 - this._font = font ?? "Arial" - this._fontColor = fontColor ?? (damage > 0 ? '#22FF44' : 'lightcoral'); // 默认颜色 - this._outlineColor = outlineColor ?? '#FFFFFF'; // 默认描边颜色 - this._speedX = speedX ?? (-1 + Math.random() * 2); // 水平速度,默认随机 - this._speedY = speedY ?? (-3 - Math.random() * 4); // 垂直速度,默认随机 - this._gravity = gravity ?? 0.3; // 重力加速度,默认 0.3 - this._duration = duration ?? 180; // 显示时长(帧数),默认 180 帧 - this.initAllMembers(); - this.requestCanvas(); - }; + // 申请并描绘canvas + PopSprite.prototype.requestCanvas = function () { + core.createCanvas( + this._symbol, + this._x, + this._y, + this._width + 4, + this._height + 4, + this._z + ); - // 自更新 - PopSprite.prototype.update = function () { - if (this._timer < this._duration) { // 使用传入的显示时长 - this._x += this._vx; - this._y += this._vy; - this._vy += this._gravity; - if (this._y >= this._floorY) { - this._y = this._floorY; - this._vy *= -0.75; // 反弹衰减 - } - core.relocateCanvas(this._symbol, this._x, this._y); - core.setOpacity(this._symbol, 1 - this._timer / this._duration); // 根据显示时长设置透明度 - } else { - this.dispose(); - } - this._timer++; - }; + var canvas = core.getContextByName(this._symbol); + canvas.font = this._fontSize + "px " + this._font; // 动态设置字体大小 + canvas.fillStyle = this._fontColor; // 动态设置字体颜色 + canvas.strokeStyle = this._outlineColor; // 动态设置描边颜色 + canvas.strokeText(this._text, 2, this._height); + canvas.fillText(this._text, 2, this._height); + }; + // 初始化所有成员变量 + PopSprite.prototype.initAllMembers = function () { + this._text = String(this._damage); + var uiContext = core.ui.getContextByName(this._canvasName); // 使用指定画布 + uiContext.font = this._fontSize + "px " + this._font; // 动态设置字体大小 + var textRect = uiContext.measureText(this._text); + this._width = textRect.width + 4; + this._height = this._fontSize + 4; // 动态设置高度 + this._z = uiContext.canvas.style.zIndex + ? Number(uiContext.canvas.style.zIndex) + PopSprite._count + : PopSprite._baseZOrder + PopSprite._count; + this._symbol = "popSprite" + PopSprite._count++; + this._alive = true; + this._vx = this._speedX; // 使用传入的水平速度 + this._vy = this._speedY; // 使用传入的垂直速度 + this._floorY = this._y + PopSprite._floorDis; + this._timer = 0; + }; - // 申请并描绘canvas - PopSprite.prototype.requestCanvas = function () { - core.createCanvas(this._symbol, this._x, this._y, this._width + 4, this._height + 4, this._z); + // 判断是否存活 + PopSprite.prototype.isAlive = function () { + return this._alive; + }; - var canvas = core.getContextByName(this._symbol) - canvas.font = this._fontSize + 'px ' + this._font; // 动态设置字体大小 - canvas.fillStyle = this._fontColor; // 动态设置字体颜色 - canvas.strokeStyle = this._outlineColor; // 动态设置描边颜色 - canvas.strokeText(this._text, 2, this._height); - canvas.fillText(this._text, 2, this._height); - }; - - // 初始化所有成员变量 - PopSprite.prototype.initAllMembers = function () { - this._text = String(this._damage); - var uiContext = core.ui.getContextByName(this._canvasName); // 使用指定画布 - uiContext.font = this._fontSize + 'px ' + this._font; // 动态设置字体大小 - var textRect = uiContext.measureText(this._text); - this._width = textRect.width + 4; - this._height = this._fontSize + 4; // 动态设置高度 - this._z = uiContext.canvas.style.zIndex ? Number(uiContext.canvas.style.zIndex) + PopSprite._count : PopSprite._baseZOrder + PopSprite._count; - this._symbol = 'popSprite' + PopSprite._count++; - this._alive = true; - this._vx = this._speedX; // 使用传入的水平速度 - this._vy = this._speedY; // 使用传入的垂直速度 - this._floorY = this._y + PopSprite._floorDis; - this._timer = 0; - - }; - - // 判断是否存活 - PopSprite.prototype.isAlive = function () { - return this._alive; - }; - - - - // 释放 - PopSprite.prototype.dispose = function () { - this._alive = false; - core.deleteCanvas(this._symbol, ); - }; - -}, + // 释放 + PopSprite.prototype.dispose = function () { + this._alive = false; + core.deleteCanvas(this._symbol); + }; + }, "编辑器显伤": function () { // 在此增加新插件 /////// 用户设置 /////// // 将__enable置为false将关闭插件 var __enable = true; // 魔防攻速之类的属性可以在这里加 ['atk', 'def', 'mdef'] - var heroStatus = ["atk", "def", "mdef", "hp"]; + var heroStatus = [ + "atk", + "def", + "spell", + "mdef", + "matk", + "mhp", + "speed", + "hp", + ]; // saveHero为true 将会把每次造塔测试时的角色数据存下来 否则会读取初始属性 // 用不着可以关了 节约缓存空间 (虽然根本没多少 还没一个存档大 // 也可以手动清理 控制台输入core.removeLocalStorage('editorHero')即可 @@ -4802,12 +4914,17 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = // 下为具体实现 懒得写注释了 大概就是写HTML然后注册交互 if (!__enable || main.mode != "editor") return; core.plugin.initEditorDamage = false; - if (heroStatus.length >= 4 && !editor.isMobile) + if (heroStatus.length >= 4 && !editor.isMobile) { editor.dom.mid2.style.top = 650 + 30 * (heroStatus.length - 3) + "px"; + editor.dom.mid.style.height = 730 + "px"; + document.querySelector("#mid .tools").style.height = 280 + "px"; + } editor.statusRatio = core.getLocalStorage("statusRatio", 1); editor.saveHero = saveHero; editor._heroStatus = heroStatus; editor.dom.mapEdit.appendChild(core.canvas.damage.canvas); + const viewportButtons = document.getElementById("viewportButtons"); + var HTML = ""; @@ -4818,7 +4935,11 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = id3 = status + "rec", id4 = status + "help"; HTML += - "
nowValue ? "#00FF00" : "#FF0000"; - nowValue = core.formatBigNumber(nowValue); - newValue = core.formatBigNumber(newValue); - - if (name === "mdef") { - nowValue += '%'; - newValue += '%' - } - statusText += - core.getStatusLabel(name) + - " " + - nowValue + - "->\r[" + - color + - "]" + - newValue + - "\r\n"; - } - } - itemText = statusText + itemText; - if (item.equip) { - core.drawTextContent(ctx, itemText, { - left: itemText_x, - top: itemCls_middle, - bold: false, - color: "white", - align: "left", - fontSize: itemTextFontSize, - maxWidth: rightbar_width - - (itemText_x - rightbar_x) * 2 + - itemTextFontSize / 2, - }); - } else { - core.drawTextContent(ctx, itemText, { - left: itemText_x, - top: itemText_y, - bold: false, - color: "white", - align: "left", - fontSize: itemTextFontSize, - maxWidth: rightbar_width - - (itemText_x - rightbar_x) * 2 + - itemTextFontSize / 2, - }); - } - - ///// *** 退出按钮设置 - var btnRadius = 10; - var btnBorderWidth = 2; - var btnRight = toolboxRight - 2; - var btnBottom = toolboxBottom - 2; - var btnBorderStyle = "#fff"; - ///// *** - - // 获取圆心位置 - var btn_x = btnRight - btnRadius - btnBorderWidth / 2; - btn_y = btnBottom - btnRadius - btnBorderWidth / 2; - drawToolbox_setExitBtn(ctx, btn_x, btn_y, btnRadius, btnBorderStyle, btnBorderWidth); - - ///// *** 使用按钮设置 - var useBtnHeight = btnRadius * 2; - // 这里不设置useBtnWidth而是根据各项数据自动得出width - var useBtnRadius = useBtnHeight / 4; - var useBtn_x = rightbar_x + 4, - useBtn_y = btnBottom - useBtnHeight; - var useBtnBorderStyle = "#fff"; - var useBtnBorderWidth = btnBorderWidth; - const batchUseBtn_x = useBtn_x + 50; // 个人觉得,搞这么多参数还不如硬编码 - const hideBtn_y = useBtn_y - useBtnHeight - 8; - ///// *** - - drawToolbox_setUseBtn(ctx, useBtn_x, useBtn_y, useBtnRadius, useBtnHeight, useBtnBorderStyle, useBtnBorderWidth); - if (core.status.event.id === 'toolbox') { - drawToolbox_setBatchUseBtn(ctx, batchUseBtn_x, useBtn_y, useBtnRadius, useBtnHeight, useBtnBorderStyle, useBtnBorderWidth); - } - drawToolbox_setHideBtn(ctx, useBtn_x, hideBtn_y, useBtnRadius, useBtnHeight, useBtnBorderStyle, useBtnBorderWidth); - drawToolbox_setShowHideBtn(ctx, rightbar_x, useBtn_y, useBtnHeight, useBtnBorderStyle); - } - - function drawEquipbox_drawOthers(ctx, obj) { - var info = core.status.thisUIEventInfo; - - ///// *** 装备格设置 - var equipList_lineWidth = 2; - var equipList_boxSize = 32; - var equipList_borderWidth = 2; - var equipList_borderStyle = "#fff"; - var equipList_nameColor = "#fff"; - ///// *** - - var equipList_x = obj.x + 4, - equipList_bottom = obj.obj.y - equipList_lineWidth, - equipList_y = equipList_bottom - obj.obj.oneItemHeight * reduceItem - 2, - equipList_height = equipList_bottom - equipList_y; - var equipList_right = obj.leftbar_right, - equipList_width = equipList_right - equipList_x; - core.drawLine( - ctx, - obj.x, - equipList_bottom + equipList_lineWidth / 2, - equipList_right, - equipList_bottom + equipList_lineWidth / 2, - equipList_borderStyle, - equipList_lineWidth - ); - var toDrawList = core.status.globalAttribute.equipName, - len = toDrawList.length; - - ///// *** 装备格设置 - var maxItem = 2; - var box_width = 32, - box_height = 32, - box_borderStyle = "#fff", - box_selectBorderStyle = "gold", // 选中的装备格的颜色 - box_borderWidth = 2; - var boxName_fontSize = 14, - boxName_space = 2, - boxName_color = "#fff"; // 装备格名称与上面的装备格框的距离 - var maxLine = Math.ceil(len / maxItem); - ///// *** - var l = Math.sqrt(len); - if (Math.pow(l) == len && len != 4) { - if (l <= maxItem) maxItem = l; - } - maxItem = Math.min(toDrawList.length, maxItem); - info.equips = maxItem; - - var boxName_font = core.ui._buildFont(boxName_fontSize); - // 总宽高减去所有装备格宽高得到空隙大小 - var oneBoxWidth = box_width + box_borderWidth * 2; - var oneBoxHeight = - box_height + boxName_fontSize + boxName_space + 2 * box_borderWidth; - var space_y = (equipList_height - maxLine * oneBoxHeight) / (1 + maxLine), - space_x = (equipList_width - maxItem * oneBoxWidth) / (1 + maxItem); - var box_x = equipList_x + space_x, - box_y = equipList_y + space_y + 12; - for (var i = 0; i < 2; i++) { - var id = core.getEquip(i), - name = toDrawList[i]; - if (i === 0) name = "主手"; - if (i === 1) name = "副手"; - var selectBorder = false; - if (core.status.thisUIEventInfo.select.type == i) selectBorder = true; - var borderStyle = selectBorder ? - box_selectBorderStyle : - box_borderStyle; - drawEquipbox_drawOne( - ctx, - name, - id, - box_x, - box_y, - box_width, - box_height, - boxName_space, - boxName_font, - boxName_color, - borderStyle, - box_borderWidth - ); - var todo = new Function( - "core.clickOneEquipbox('" + id + "'," + i + ")" - ); - addUIEventListener( - box_x - box_borderWidth / 2, - box_y - box_borderWidth / 2, - oneBoxWidth, - oneBoxHeight, - todo - ); - box_x += space_x + oneBoxWidth; - if ((i + 1) % maxItem == 0) { - box_x = equipList_x + space_x; - box_y += space_y + oneBoxHeight; - } - } - if (core.material.items[core.getEquip(0)]?.equipCls === "双手剑") { - core.drawLine( - ctx, - equipList_x + space_x + space_x + oneBoxWidth, - equipList_y + space_y + 12, - equipList_x + - space_x + - space_x + - oneBoxWidth + - box_width + - box_borderWidth, - equipList_y + space_y + box_height + 12 - ); - core.drawLine( - ctx, - equipList_x + space_x + space_x + oneBoxWidth, - equipList_y + space_y + box_height + 12, - equipList_x + - space_x + - space_x + - oneBoxWidth + - box_width + - box_borderWidth, - equipList_y + space_y + 12 - ); - } - ///// *** 装备格设置 - var maxItem = 3; - var box_width = 32, - box_height = 32, - box_borderStyle = "#fff", - box_selectBorderStyle = "gold", // 选中的装备格的颜色 - box_borderWidth = 2; - var boxName_fontSize = 14, - boxName_space = 2, - boxName_color = "#fff"; // 装备格名称与上面的装备格框的距离 - var maxLine = Math.ceil(len / maxItem); - ///// *** - var l = Math.sqrt(len); - if (Math.pow(l) == len && len != 4) { - if (l <= maxItem) maxItem = l; - } - maxItem = Math.min(toDrawList.length, maxItem); - info.equips = maxItem; - - var boxName_font = core.ui._buildFont(boxName_fontSize); - // 总宽高减去所有装备格宽高得到空隙大小 - var oneBoxWidth = box_width + box_borderWidth * 2; - var oneBoxHeight = - box_height + boxName_fontSize + boxName_space + 2 * box_borderWidth; - var space_y = (equipList_height - maxLine * oneBoxHeight) / (1 + maxLine), - space_x = (equipList_width - maxItem * oneBoxWidth) / (1 + maxItem); - var box_x = equipList_x + space_x, - box_y = equipList_y + space_y + space_y + oneBoxHeight; - for (var i = 2; i < len; i++) { - var id = core.getEquip(i), - name = toDrawList[i]; - var selectBorder = false; - if (core.status.thisUIEventInfo.select.type == i) selectBorder = true; - var borderStyle = selectBorder ? - box_selectBorderStyle : - box_borderStyle; - drawEquipbox_drawOne( - ctx, - name, - id, - box_x, - box_y, - box_width, - box_height, - boxName_space, - boxName_font, - boxName_color, - borderStyle, - box_borderWidth - ); - var todo = new Function( - "core.clickOneEquipbox('" + id + "'," + i + ")" - ); - addUIEventListener( - box_x - box_borderWidth / 2, - box_y - box_borderWidth / 2, - oneBoxWidth, - oneBoxHeight, - todo - ); - box_x += space_x + oneBoxWidth; - } - - } - - this.drawToolbox = function (ctx) { - ctx = ctx || core.canvas.ui; - core.status.thisEventClickArea = []; - - var info = drawBoxBackground(ctx); - info.itemNum = itemNum; - drawItemListbox(ctx, info.obj); - drawToolboxRightbar(ctx, info); - core.setTextBaseline(ctx, "alphabetic"); - core.setTextAlign("left"); - } - - var reduceItem = 4; - this.drawEquipbox = function (ctx) { - ctx = ctx || core.canvas.ui; - core.status.thisEventClickArea = []; - var info = drawBoxBackground(ctx); - info.itemNum = itemNum - reduceItem; - info.obj.y += info.obj.oneItemHeight * reduceItem; - info.obj.height -= info.obj.oneItemHeight * reduceItem; - drawItemListbox(ctx, info.obj); - drawEquipbox_drawOthers(ctx, info); - drawToolboxRightbar(ctx, info); - core.setTextBaseline(ctx, "alphabetic"); - core.setTextAlign("left"); - } - - - function drawEquipbox_drawOne(ctx, name, id, x, y, width, height, space, font, color, style, lineWidth) { - if (id) core.drawIcon(ctx, id, x + lineWidth / 2, y + lineWidth / 2, width, height); - core.strokeRect(ctx, x, y, width + lineWidth, height + lineWidth, style, lineWidth); - core.setTextAlign(ctx, "center"); - core.setTextBaseline(ctx, "top"); - var tx = (x + x + lineWidth / 2 + width) / 2, - ty = y + height + lineWidth / 2 * 3 + space; - core.fillText(ctx, name, tx, ty, color, font); - - core.setAlpha(ctx, 1); - - core.setTextBaseline(ctx, "alphabetic"); - core.setTextAlign("left"); - } - - function drawItemListbox_drawItem(ctx, left, right, top, height, marginLeft, marginHeight, style, id) { - var info = core.status.thisUIEventInfo; - var nowClick = info.index; - var item = core.material.items[id] || {}; - var name = item.name || "???"; - var num = core.itemCount(id) || 0; - var fontSize = Math.floor(height - marginHeight * 2); - core.setTextAlign(ctx, "right"); - var numText = "x" + num; - core.fillText(ctx, numText, right - marginLeft, top + height / 2, style, core.ui._buildFont(fontSize)); - - const hideInfo = core.getFlag('hideInfo', {}); - if (item && (hideInfo.hasOwnProperty(id) ? hideInfo[id] : item.hideInToolbox)) core.setAlpha(ctx, 0.5); - - if (name != "???") core.drawIcon(ctx, id, left + marginLeft, top + marginHeight, fontSize, fontSize); - var text_x = left + marginLeft + fontSize + 2; - var maxWidth = right - core.calWidth(ctx, numText) - text_x; - core.setTextAlign(ctx, "left"); - core.fillText(ctx, name, text_x, top + height / 2, style, core.ui._buildFont(fontSize), maxWidth); - core.setAlpha(ctx, 1); - - var todo = new Function("core.clickItemFunc('" + id + "');"); - addUIEventListener(left, top, right - left, height, todo); - } - - function setPageItems(page) { - var num = itemNum; - if (core.status.event.id == "equipbox") num -= reduceItem; - var info = core.status.thisUIEventInfo; - if (!info) return; - page = page || info.page; - var items = core.getToolboxItems(core.status.event.id == "toolbox" ? "all" : "equips", core.getFlag('showHideItem', false)); - info.allItems = items; - var maxPage = Math.ceil(items.length / num); - info.maxPage = maxPage; - var pageItems = items.slice((page - 1) * num, page * num); - info.pageItems = pageItems; - info.maxItem = pageItems.length; - if (items.length == 0 && pageItems.length == 0) info.index = null; - if (pageItems.length == 0 && info.page > 1) { - info.page = Math.max(1, info.page - 1); - return setPageItems(info.page); - } - return pageItems; - } - - function drawToolbox_setExitBtn(ctx, x, y, r, style, lineWidth) { - core.strokeCircle(ctx, x, y, r, style, lineWidth); - ctx.textAlign = "center"; - ctx.textBaseline = "middle"; - var textSize = Math.sqrt(2) * r; - core.fillText(ctx, "x", x, y, style, core.ui._buildFont(textSize), textSize); - core.setTextAlign(ctx, "start"); - core.setTextBaseline(ctx, "top"); - - var todo = function () { - core.closePanel(); - } - addUIEventListener(x - r, y - r, r * 2, r * 2, todo); - } - - function drawToolbox_setUseBtn(ctx, x, y, r, h, style, lineWidth) { - core.setTextAlign(ctx, "left"); - core.setTextBaseline(ctx, "top"); - var fontSize = h - 4; - var font = core.ui._buildFont(fontSize); - var text = core.status.event.id == "toolbox" ? "使用" : "装备"; - if (core.status.thisUIEventInfo.select.action == "unload") text = "卸下"; - var w = core.calWidth(ctx, text, font) + 2 * r + lineWidth / 2; - - core.strokeRoundRect(ctx, x, y, w, h, r, style, lineWidth); - core.fillText(ctx, text, x + r, y + lineWidth / 2 + 2, style, font); - - var todo = function () { - core.useSelectItemInBox(); - } - addUIEventListener(x, y, w, h, todo); - } - - function getSelectedItem() { - var info = core.status.thisUIEventInfo; - if (!(info && info.select.id && ["toolbox", "equipbox"].includes(core.status.event.id))) { - core.drawFailTip('发生了未知错误!'); - return; - } - return info.select.id; - } - - function batchUse(item, count) { - try { - const itemCount = core.itemCount(item); - if (count > itemCount) count = itemCount; - core.closePanel(); - for (let i = 0; i < count; i++) { - if (core.canUseItem(item)) core.useItem(item); - else return; - } - } catch (e) { - console.error(e); - core.drawFailTip('批量使用时出现未知错误!'); - } - } - - function drawToolbox_setBatchUseBtn(ctx, x, y, r, h, style, lineWidth) { - try { - const selectedItem = getSelectedItem(); - let canBatchUse = eval(core.material.items[selectedItem]?.canBatchUse); - if (!canBatchUse) return; - } catch (error) { - console.error(error); - return; - } - core.setTextAlign(ctx, "left"); - core.setTextBaseline(ctx, "top"); - var fontSize = h - 4; - var font = core.ui._buildFont(fontSize); - var text = "批量使用"; - var w = core.calWidth(ctx, text, font) + 2 * r + lineWidth / 2; - - core.strokeRoundRect(ctx, x, y, w, h, r, style, lineWidth); - core.fillText(ctx, text, x + r, y + lineWidth / 2 + 2, style, font); - - var todo = function () { - core.utils.myprompt('输入要使用该物品的次数(0~99)。', null, (value) => { - - value = parseInt(value); - const id = getSelectedItem(); - - if (Number.isNaN(value) || value < 0 || value > 99) { - core.drawFailTip('输入不合法!'); - return; - } - if (!core.canUseItem(id)) { - core.drawFailTip('当前无法使用该道具!'); - return; - } - core.closePanel(); - batchUse(id, value); - }); - } - addUIEventListener(x, y, w, h, todo); - } - - function drawToolbox_setHideBtn(ctx, x, y, r, h, style, lineWidth) { - core.setTextAlign(ctx, "left"); - core.setTextBaseline(ctx, "top"); - var fontSize = h - 4; - var font = core.ui._buildFont(fontSize); - var text = "显示/隐藏"; - var w = core.calWidth(ctx, text, font) + 2 * r + lineWidth / 2; - - core.strokeRoundRect(ctx, x, y, w, h, r, style, lineWidth); - core.fillText(ctx, text, x + r, y + lineWidth / 2 + 2, style, font); - - var todo = function () { - //debugger; - var id = getSelectedItem(); - let hideInfo = core.getFlag('hideInfo', {}); - console.log(id); - if (hideInfo.hasOwnProperty(id)) { - hideInfo[id] = !hideInfo[id]; - core.setFlag('hideInfo', hideInfo); - } else { - hideInfo[id] = !core.material.items[id].hideInToolbox; - core.setFlag('hideInfo', hideInfo); - } - if (core.status.event.id === 'toolbox') core.plugin.drawToolbox(); - else if (core.status.event.id === 'equipbox') core.plugin.drawEquipbox(); - } - addUIEventListener(x, y, w, h, todo); - } - - ui.prototype.getToolboxItems = function (cls, showHide) { - let list = Object.keys(core.status.hero.items[cls] || {});; - if (cls === "all") { - for (let name in core.status.hero.items) { - if (name == "equips") continue; - list = list.concat(Object.keys(core.status.hero.items[name])); - } - if (!showHide) list = list.filter(function (id2) { - const hideInfo = core.getFlag("hideInfo", {}); - if (hideInfo.hasOwnProperty(id2)) return !hideInfo[id2]; - else return !core.material.items[id2].hideInToolbox; - }); - list = list.sort(); - return list; - } - if (cls === "equips") { - if (!showHide) list = list.filter(function (id2) { - const hideInfo = core.getFlag("hideInfo", {}); - if (hideInfo.hasOwnProperty(id2)) return !hideInfo[id2]; - else return !core.material.items[id2].hideInToolbox; - }); - - list = list.sort(); - return list; - } - if (this.uidata.getToolboxItems) { - return this.uidata.getToolboxItems(cls, showHide); - } - if (!showHide) list = list.filter(function (id2) { - return !core.material.items[id2].hideInToolbox; - }); - list = list.sort(); - return list; - }; - - function drawToolbox_setShowHideBtn(ctx, x, y, h, style) { - core.setTextAlign(ctx, "left"); - core.setTextBaseline(ctx, "top"); - var fontSize = h - 6; - var font = core.ui._buildFont(fontSize); - var text = "显示隐藏"; - var w = core.calWidth(ctx, text, font) - h += 4; - const squareSize = h - 6; - - x -= w + squareSize + 26; - - const border = 2; - core.fillRect(ctx, x, y, squareSize, squareSize, ' #F5F5F5'); - if (core.hasFlag('showHideItem')) { - core.fillRect(ctx, x + border, y + border, squareSize - 2 * border, squareSize - 2 * border, 'lime'); - } - core.fillText(ctx, text, x + squareSize + 2, y + 4, style, font); - - var todo = function () { - core.setFlag('showHideItem', !core.getFlag('showHideItem', false)); - if (core.status.event.id === 'toolbox') core.plugin.drawToolbox(); - else if (core.status.event.id === 'equipbox') core.plugin.drawEquipbox(); - } - addUIEventListener(x, y, w, h, todo); - } - - function drawItemListbox_setPageBtn(ctx, left, right, bottom, r, style, lineWidth) { - var offset = lineWidth / 2 + r; - - var x = left + offset; - var y = bottom - offset; - var pos = Math.sqrt(2) / 2 * (r - lineWidth / 2); - core.fillPolygon(ctx, [ - [x - pos, y], - [x + pos - 2, y - pos], - [x + pos - 2, y + pos] - ], style); - core.strokeCircle(ctx, x, y, r, style, lineWidth); - var todo = function () { - core.addItemListboxPage(-1); - } - addUIEventListener(x - r - 2, y - r - 2, r * 2 + 4, r * 2 + 4, todo); - - x = right - offset; - core.fillPolygon(ctx, [ - [x + pos, y], - [x - pos + 2, y - pos], - [x - pos + 2, y + pos] - ], style); - core.strokeCircle(ctx, x, y, r, style, lineWidth); - var todo = function () { - core.addItemListboxPage(1); - } - addUIEventListener(x - r - 2, y - r - 2, r * 2 + 4, r * 2 + 4, todo); - } - - this.clickItemFunc = function (id) { - var info = core.status.thisUIEventInfo; - if (!info) return; - if (info.select.id == id) return core.useSelectItemInBox(); - info.select = {}; - info.select.id = id; - core.setIndexAndSelect('index'); - refreshBox(); - } - - this.clickOneEquipbox = function (id, type) { - var info = core.status.thisUIEventInfo; - if (!info) return; - if (info.select.id == id && info.select.type == type) core.useSelectItemInBox(); - else core.status.thisUIEventInfo.select = { - id: id, - type: type, - action: "unload" - } - return refreshBox(); - } - - this.useSelectItemInBox = function () { - var info = core.status.thisUIEventInfo; - if (!info) return; - if (!info.select.id) return; - var id = info.select.id; - if (core.status.event.id == "toolbox") { - core.events.tryUseItem(id); - // core.closePanel(); - } else if (core.status.event.id == "equipbox") { - var action = info.select.action || "load"; - info.index = 1; - if (action == "load") { - var type = core.getEquipTypeById(id); - let equipClsid = core.material.items[id]?.equipCls; - let equipCls0 = core.material.items[core.getEquip(0)]?.equipCls; - let equipCls1 = core.material.items[core.getEquip(1)]?.equipCls; - if (equipClsid === "双手剑") { - core.unloadEquip(0, function () { - core.status.route.push("unEquip:" + 0); - }); - core.unloadEquip(1, function () { - core.status.route.push("unEquip:" + 1); - }); - } - if (equipCls0 === "双手剑" && !(equipClsid === "饰品" || equipClsid === "护具")) { - core.unloadEquip(0, function () { - core.status.route.push("unEquip:" + 0); - }); - } - core.loadEquip(id, function () { - core.status.route.push("equip:" + id); - info.select.type = type; - core.setIndexAndSelect("select"); - core.drawEquipbox(); - }); - } else { - var type = info.select.type; - core.unloadEquip(type, function () { - core.status.route.push("unEquip:" + type); - info.select.type = type; - info.select.action = 'load' - core.setIndexAndSelect("select"); - core.drawEquipbox(); - }); - } - } - core.updateStatusBar(); - } - - this.setIndexAndSelect = function (toChange) { - var info = core.status.thisUIEventInfo; - if (!info) return; - setPageItems(info.page); - var index = info.index || 1; - var items = info.pageItems; - - info.select.action = null; - info.select.type = null; - if (toChange == "index") info.index = items.indexOf(info.select.id) + 1; - info.select.id = items[info.index - 1]; - - - } - - this.addItemListboxPage = function (num) { - var info = core.status.thisUIEventInfo; - if (!info) return; - var maxPage = info.maxPage || 1; - info.page = info.page || 1; - info.page += num; - if (info.page <= 0) info.page = maxPage; - if (info.page > maxPage) info.page = 1; - info.index = 1; - setPageItems(info.page); - core.setIndexAndSelect("select"); - refreshBox(); - } - - this.addItemListboxIndex = function (num) { - var info = core.status.thisUIEventInfo; - if (!info) return; - var maxItem = info.maxItem || 0; - info.index = info.index || 0; - info.index += num; - if (info.index <= 0) info.index = 1; - if (info.index > maxItem) info.index = maxItem; - core.setIndexAndSelect("select"); - refreshBox(); - } - - this.addEquipboxType = function (num) { - var info = core.status.thisUIEventInfo; - var type = info.select.type; - if (type == null && num > 0) info.select.type = 0; - else info.select.type = type + num; - var max = core.status.globalAttribute.equipName.length; - if (info.select.type >= max) { - info.select = {}; - core.setIndexAndSelect("select") - return core.addItemListboxPage(0); - } else { - var m = Math.abs(info.select.type); - if (info.select.type < 0) info.select.type = max - m; - core.setIndexAndSelect("select") - refreshBox(); - return; - } - } - - core.actions._keyDownToolbox = function (keycode) { - if (!core.status.thisEventClickArea) return; - if (keycode == 37) { // left - core.addItemListboxPage(-1); - return; - } - if (keycode == 38) { // up - core.addItemListboxIndex(-1); - return; - } - if (keycode == 39) { // right - core.addItemListboxPage(1); - return; - } - if (keycode == 40) { // down - core.addItemListboxIndex(1); - return; - } - } - - ////// 工具栏界面时,放开某个键的操作 ////// - core.actions._keyUpToolbox = function (keycode) { - if (keycode == 81) { - core.ui.closePanel(); - if (core.isReplaying()) - core.control._replay_equipbox(); - else - core.openEquipbox(); - return; - } - if (keycode == 84 || keycode == 27 || keycode == 88) { - core.closePanel(); - return; - } - if (keycode == 13 || keycode == 32 || keycode == 67) { - var info = core.status.thisUIEventInfo; - if (info.select) { - core.useSelectItemInBox(); - } - return; - } - } - - core.actions._keyDownEquipbox = function (keycode) { - if (!core.status.thisEventClickArea) return; - if (keycode == 37) { // left - var info = core.status.thisUIEventInfo; - if (info.index != null) return core.addItemListboxPage(-1); - return core.addEquipboxType(-1); - } - if (keycode == 38) { // up - var info = core.status.thisUIEventInfo; - if (info.index == 1) { - info.select.type = core.status.globalAttribute.equipName.length - 1; - core.setIndexAndSelect(); - return refreshBox(); - } - if (info.index) return core.addItemListboxIndex(-1); - return core.addEquipboxType(-1 * info.equips); - } - if (keycode == 39) { // right - var info = core.status.thisUIEventInfo; - if (info.index != null) return core.addItemListboxPage(1); - return core.addEquipboxType(1); - } - if (keycode == 40) { // down - var info = core.status.thisUIEventInfo; - if (info.index) return core.addItemListboxIndex(1); - return core.addEquipboxType(info.equips); - } - } - - core.actions._keyUpEquipbox = function (keycode, altKey) { - if (altKey && keycode >= 48 && keycode <= 57) { - core.items.quickSaveEquip(keycode - 48); - return; - } - if (keycode == 84) { - core.ui.closePanel(); - if (core.isReplaying()) - core.control._replay_toolbox(); - else - core.openToolbox(); - return; - } - if (keycode == 81 || keycode == 27 || keycode == 88) { - core.closePanel(); - return; - } - if (keycode == 13 || keycode == 32 || keycode == 67) { - var info = core.status.thisUIEventInfo; - if (info.select) core.useSelectItemInBox(); - return; - } - } - - core.registerAction("ondown", "inEventClickAction", function (x, y, px, py) { - if (!core.status.thisEventClickArea) return false; - var info = core.status.thisEventClickArea; - for (var i = 0; i < info.length; i++) { - var obj = info[i]; - if (px >= obj.x && px <= obj.x + obj.width && py > obj.y && py < obj.y + obj.height) { - if (obj.todo) obj.todo(); - break; - } - } - return true; - }, 51); - core.registerAction("onclick", "stopClick", function () { - if (core.status.thisEventClickArea) return true; - }, 51); - - function addUIEventListener(x, y, width, height, todo) { - if (!core.status.thisEventClickArea) return; - var obj = { - x: x, - y: y, - width: width, - height: height, - todo: todo - } - core.status.thisEventClickArea.push(obj); - } - - this.initThisEventInfo = function () { - core.status.thisUIEventInfo = { - page: 1, - select: {} - }; - core.status.thisEventClickArea = []; - } - - function refreshBox() { - if (!core.status.event.id) return; - if (core.status.event.id == "toolbox") core.drawToolbox(); - else core.drawEquipbox(); - } - - core.ui.closePanel = function () { - if (core.status.hero && core.status.hero.flags) { - // 清除全部临时变量 - Object.keys(core.status.hero.flags).forEach(function (name) { - if (name.startsWith("@temp@") || /^arg\d+$/.test(name)) { - delete core.status.hero.flags[name]; - } - }); - } - this.clearUI(); - core.maps.generateGroundPattern(); - core.updateStatusBar(true); - core.unlockControl(); - core.status.event.data = null; - core.status.event.id = null; - core.status.event.selection = null; - core.status.event.ui = null; - core.status.event.interval = null; - core.status.thisUIEventInfo = null; - core.status.thisEventClickArea = null - } - - this.getItemClsName = function (item) { - if (item == null) return itemClsName; - if (item.cls == "equips") { - if (typeof item.equip.type == "string") return item.equip.type; - var type = core.getEquipTypeById(item.id); - return core.status.globalAttribute.equipName[type]; - } else return itemClsName[item.cls] || item.cls; - } - - core.events.openToolbox = function (fromUserAction) { - if (core.isReplaying()) return; - if (!this._checkStatus('toolbox', fromUserAction)) return; - core.initThisEventInfo(); - let info = core.status.thisUIEventInfo - info.index = 1 - core.setIndexAndSelect('select') - core.drawToolbox(); - } - - core.events.openEquipbox = function (fromUserAction) { - if (core.isReplaying()) return; - if (!this._checkStatus('equipbox', fromUserAction)) return; - core.initThisEventInfo(); - let info = core.status.thisUIEventInfo - info.select.type = 0 - core.setIndexAndSelect('select') - core.drawEquipbox(); - } - - core.control._replay_toolbox = function () { - if (!core.isPlaying() || !core.isReplaying()) return; - if (!core.status.replay.pausing) return core.drawTip("请先暂停录像"); - if (core.isMoving() || core.status.replay.animate || core.status.event.id) - return core.drawTip("请等待当前事件的处理结束"); - - core.lockControl(); - core.status.event.id = 'toolbox'; - core.drawToolbox(); - } - - core.control._replay_equipbox = function () { - if (!core.isPlaying() || !core.isReplaying()) return; - if (!core.status.replay.pausing) return core.drawTip("请先暂停录像"); - if (core.isMoving() || core.status.replay.animate || core.status.event.id) - return core.drawTip("请等待当前事件的处理结束"); - - core.lockControl(); - core.status.event.id = 'equipbox'; - core.drawEquipbox(); - } - - core.control._replayAction_item = function (action) { - if (action.indexOf("item:") != 0) return false; - var itemId = action.substring(5); - if (!core.canUseItem(itemId)) return false; - if (core.material.items[itemId].hideInReplay || core.status.replay.speed == 24) { - core.useItem(itemId, false, core.replay); - return true; - } - core.status.event.id = "toolbox"; - core.initThisEventInfo(); - var info = core.status.thisUIEventInfo; - var items = core.getToolboxItems("all", core.getFlag('showHideItem', false)); - setPageItems(1); - var index = items.indexOf(itemId) + 1; - info.page = Math.ceil(index / info.maxItem); - info.index = index % info.maxItem || info.maxItem; - core.setIndexAndSelect("select"); - setPageItems(info.page); - core.drawToolbox(); - setTimeout(function () { - core.ui.closePanel(); - core.useItem(itemId, false, core.replay); - }, core.control.__replay_getTimeout()); - return true; - } - - core.control._replayAction_equip = function (action) { - if (action.indexOf("equip:") != 0) return false; - var itemId = action.substring(6); - var items = core.getToolboxItems('equips', core.getFlag('showHideItem', false)); - var index = items.indexOf(itemId) + 1; - if (index < 1) { - core.removeFlag('__doNotCheckAutoEvents__'); - return false; - } - - var cb = function () { - var next = core.status.replay.toReplay[0] || ""; - if (!next.startsWith('equip:') && !next.startsWith('unEquip:')) { - core.removeFlag('__doNotCheckAutoEvents__'); - core.checkAutoEvents(); - } - core.replay(); - } - core.setFlag('__doNotCheckAutoEvents__', true); - - core.status.route.push(action); - if (core.material.items[itemId].hideInReplay || core.status.replay.speed == 24) { - core.loadEquip(itemId, cb); - return true; - } - core.status.event.id = "equipbox"; - core.initThisEventInfo(); - var info = core.status.thisUIEventInfo; - setPageItems(1); - info.page = Math.ceil(index / info.maxItem); - info.index = index % info.maxItem || info.maxItem; - core.setIndexAndSelect("select"); - setPageItems(info.page); - core.drawEquipbox(); - setTimeout(function () { - core.ui.closePanel(); - core.loadEquip(itemId, cb); - }, core.control.__replay_getTimeout()); - return true; - } - - core.control._replayAction_unEquip = function (action) { - if (action.indexOf("unEquip:") != 0) return false; - var equipType = parseInt(action.substring(8)); - if (!core.isset(equipType)) { - core.removeFlag('__doNotCheckAutoEvents__'); - return false; - } - - var cb = function () { - var next = core.status.replay.toReplay[0] || ""; - if (!next.startsWith('equip:') && !next.startsWith('unEquip:')) { - core.removeFlag('__doNotCheckAutoEvents__'); - core.checkAutoEvents(); - } - core.replay(); - } - core.setFlag('__doNotCheckAutoEvents__', true); - - core.status.route.push(action); - if (core.status.replay.speed == 24) { - core.unloadEquip(equipType, cb); - return true; - } - core.status.event.id = "equipbox"; - core.initThisEventInfo(); - var info = core.status.thisUIEventInfo; - setPageItems(1); - info.select.type = equipType; - core.setIndexAndSelect(); - core.drawEquipbox(); - setTimeout(function () { - core.ui.closePanel(); - core.unloadEquip(equipType, cb); - }, core.control.__replay_getTimeout()); - return true; - } - core.registerReplayAction("item", core.control._replayAction_item); - core.registerReplayAction("equip", core.control._replayAction_equip); - core.registerReplayAction("unEquip", core.control._replayAction_unEquip); -}, + core.setAlpha(ctx, backgroundAlpha); + core.strokeRoundRect( + ctx, + x, + y, + w, + h, + borderRadius, + borderStyle, + borderWidth + ); + core.fillRoundRect( + ctx, + start_x, + start_y, + width, + height, + borderRadius, + backgroundColor + ); + core.setAlpha(ctx, 1); + + ///// *** 左栏配置 + var leftbar_height = height; + // 左边栏宽度(width*0.6) 本身仅为坐标使用 需要与底下的rightbar_width(width*0.4)同时更改 + var leftbar_width = width * 0.6; + ///// *** + + // xxx_right参数 代表最右侧坐标 + var leftbar_right = start_x + leftbar_width - borderWidth / 2; + var leftbar_bottom = start_y + leftbar_height; + var leftbar_x = start_x; + var leftbar_y = start_y; + + ///// *** 道具栏配置 + var boxName_color = "#fff"; + var boxName_fontSize = 15; + var boxName_font = core.ui._buildFont(boxName_fontSize, true); + var arrow_x = 10 + start_x; + var arrow_y = 10 + start_y; + var arrow_width = 20; + var arrow_style = "white"; + // 暂时只能是1 否则不太行 等待新样板(2.7.3)之后对drawArrow做优化 + var arrow_lineWidth = 2; + // 右箭头 + var rightArrow_right = leftbar_right - 10; + // 道具内栏顶部坐标 本质是通过该项 控制(道具栏顶部文字和箭头)与道具内栏顶部的间隔 + var itembar_top = arrow_y + 15; + ///// *** + + var itembar_right = rightArrow_right; + var boxName = + core.status.event.id == "toolbox" + ? "\r[yellow]道具栏\r | 装备栏" + : "道具栏 | \r[yellow]装备栏\r"; + core.drawArrow( + ctx, + arrow_x + arrow_width, + arrow_y, + arrow_x, + arrow_y, + arrow_style, + arrow_lineWidth + ); + core.drawArrow( + ctx, + rightArrow_right - arrow_width, + arrow_y, + rightArrow_right, + arrow_y, + arrow_style, + arrow_lineWidth + ); + core.setTextAlign(ctx, "center"); + core.setTextBaseline(ctx, "middle"); + var changeBox = function () { + var id = core.status.event.id; + core.closePanel(); + if (id == "toolbox") core.openEquipbox(); + else core.openToolbox(); + }; + core.fillText( + ctx, + boxName, + (leftbar_right + leftbar_x) / 2, + arrow_y + 2, + boxName_color, + boxName_font + ); + + ///// *** 底栏按钮 + var pageBtn_radius = 8; + // xxx_left 最左侧坐标 + var pageBtn_left = leftbar_x + 3; + var pageBtn_right = leftbar_right - 3; + // xxx_bottom 最底部坐标 + var pageBtn_bottom = leftbar_bottom - 2; + var pageBtn_borderStyle = "#fff"; + var pageBtn_borderWidth = 2; + var pageText_color = "#fff"; + // 底部按钮与上面的道具内栏的间隔大小 + var bottomSpace = 8; + ///// *** + + drawItemListbox_setPageBtn( + ctx, + pageBtn_left, + pageBtn_right, + pageBtn_bottom, + pageBtn_radius, + pageBtn_borderStyle, + pageBtn_borderWidth + ); + var page = info.page || 1; + var pageFontSize = pageBtn_radius * 2 - 4; + var pageFont = core.ui._buildFont(pageFontSize); + setPageItems(page); + var num = itemNum; + if (core.status.event.id == "equipbox") num -= 5; + var maxPage = info.maxPage; + var pageText = page + " / " + maxPage; + core.setTextAlign(ctx, "center"); + core.setTextBaseline(ctx, "bottom"); + core.fillText( + ctx, + pageText, + (leftbar_x + leftbar_right) / 2, + pageBtn_bottom, + pageText_color, + pageFont + ); + addUIEventListener( + start_x, + start_y, + leftbar_right - start_x, + arrow_y - start_y + 13, + changeBox + ); + var itembar_height = Math.ceil( + pageBtn_bottom - + pageBtn_radius * 2 - + pageBtn_borderWidth / 2 - + bottomSpace - + itembar_top + ); + var oneItemHeight = (itembar_height - 4) / itemNum; + return { + x: start_x, + y: start_y, + width: width, + height: height, + leftbar_right: leftbar_right, + obj: { + x: arrow_x, + y: itembar_top, + width: itembar_right - arrow_x, + height: itembar_height, + oneItemHeight: oneItemHeight, + }, + }; + } + + function drawItemListbox(ctx, obj) { + ctx = ctx || core.canvas.ui; + var itembar_x = obj.x, + itembar_y = obj.y, + itembar_width = obj.width, + itembar_height = obj.height, + itemNum = obj.itemNum, + oneItemHeight = obj.oneItemHeight; + var itembar_right = itembar_x + itembar_width; + var info = core.status.thisUIEventInfo || {}; + var obj = {}; + var page = info.page || 1, + index = info.index, + select = info.select || {}; + + ///// *** 道具栏内栏配置 + var itembar_style = "black"; + var itembar_alpha = 0.7; + // 一个竖屏下减少道具显示的例子: + // if (core.domStyle.isVertical) itemNum = 10; + // 每个道具项的上下空隙占总高度的比例 + var itembar_marginHeightRatio = 0.2; + // 左右间隔空隙 + var item_marginLeft = 2; + var item_x = itembar_x + 2, + item_y = itembar_y + 2, + item_right = itembar_right - 2, + itemName_color = "#fff"; + // 修改此项以更换闪烁光标 + var item_selector = "winskin.webp"; + ///// *** + + core.setAlpha(ctx, itembar_alpha); + core.fillRect( + ctx, + itembar_x, + itembar_y, + itembar_width, + itembar_height, + itembar_style + ); + core.setAlpha(ctx, 1); + var pageItems = setPageItems(page); + var marginHeight = itembar_marginHeightRatio * oneItemHeight; + core.setTextBaseline(ctx, "middle"); + var originColor = itemName_color; + for (var i = 0; i < pageItems.length; i++) { + itemName_color = originColor; + var item = pageItems[i]; + // 设置某个的字体颜色的一个例子 + // if (item.id == "xxx") itemName_color = "green"; + drawItemListbox_drawItem( + ctx, + item_x, + item_right, + item_y, + oneItemHeight, + item_marginLeft, + marginHeight, + itemName_color, + pageItems[i] + ); + if (index == i + 1) + core.ui._drawWindowSelector( + item_selector, + item_x + 1, + item_y - 1, + item_right - item_x - 2, + oneItemHeight - 2 + ); + item_y += oneItemHeight; + } + } + + function drawToolboxRightbar(ctx, obj) { + ctx = ctx || core.canvas.ui; + var info = core.status.thisUIEventInfo || {}; + var page = info.page || 1, + index = info.index || 1, + select = info.select || {}; + var start_x = obj.x, + start_y = obj.y, + width = obj.width, + height = obj.height; + var toolboxRight = start_x + width, + toolboxBottom = start_y + height; + + ///// *** 侧边栏(rightbar)背景设置(物品介绍) + var rightbar_width = width * 0.4; + var rightbar_height = height; + var rightbar_lineWidth = 2; + var rightbar_lineStyle = "#fff"; + ///// *** + + var rightbar_x = toolboxRight - rightbar_width - rightbar_lineWidth / 2; + var rightbar_y = start_y; + core.drawLine( + ctx, + rightbar_x, + rightbar_y, + rightbar_x, + rightbar_y + rightbar_height, + rightbar_lineStyle, + rightbar_lineWidth + ); + + // 获取道具id(有可能为null) + var itemId = select.id; + var item = core.material.items[itemId]; + + ///// *** 侧边栏物品Icon信息 + var iconRect_y = rightbar_y + 10; + // space:间距 + // 这里布局设定iconRect与侧边栏左边框 itemName与工具栏右边框 itemRect与itemName的间距均为space + var space = 15; + var iconRect_x = rightbar_x + space; + var iconRect_radius = 2, + iconRect_width = 32, + iconRect_height = 32, + iconRect_style = "#fff", + iconRect_lineWidth = 2; + ///// *** + + var iconRect_bottom = iconRect_y + iconRect_height, + iconRect_right = iconRect_x + iconRect_width; + + ///// *** 侧边栏各项信息 + var itemTextFontSize = 15, + itemText_x = iconRect_x - 4, + itemText_y = Math.floor(start_y + rightbar_height * 0.25), // 坐标取整防止模糊 + itemClsFontSize = 15, + itemClsFont = core.ui._buildFont(itemClsFontSize), + itemClsColor = "#fff", + itemCls_x = itemText_x - itemClsFontSize / 2, + itemCls_middle = (iconRect_bottom + itemText_y) / 2, //_middle代表文字的中心y坐标 + itemNameFontSize = 18, + itemNameColor = "#fff", + itemNameFont = core.ui._buildFont(itemNameFontSize, true); + var itemName_x = iconRect_right + space; + var itemName_middle = + iconRect_y + iconRect_height / 2 + iconRect_lineWidth; + // 修改这里可以编辑未选中道具时的默认值 + var defaultItem = { + cls: "constants", + name: "未知道具", + text: "没有道具最永久", + }; + var defaultEquip = { + cls: "equips", + name: "未知装备", + text: "一无所有,又何尝不是一种装备", + equip: { + type: "装备", + }, + }; + ///// *** + + var originItem = item; + if (core.status.event.id == "equipbox") item = item || defaultEquip; + item = item || defaultItem; + var itemCls = item.cls, + itemName = item.name, + itemText = item.text; + itemText = core.replaceText(itemText); + if (!itemText) itemText = "该道具无描述。"; + /* 一个根据道具id修改道具名字(右栏)的例子 + * if (item.id == "xxx") itemNameColor = "red"; + */ + var itemClsName = core.getItemClsName(item); + var itemNameMaxWidth = + rightbar_width - iconRect_width - iconRect_lineWidth * 2 - space * 2; + core.strokeRoundRect( + ctx, + iconRect_x, + iconRect_y, + iconRect_width, + iconRect_height, + iconRect_radius, + iconRect_style, + iconRect_lineWidth + ); + if (item.id) + core.drawIcon( + ctx, + item.id, + iconRect_x + iconRect_lineWidth / 2, + iconRect_y + iconRect_lineWidth / 2, + iconRect_width - iconRect_lineWidth, + iconRect_height - iconRect_lineWidth + ); + core.setTextAlign(ctx, "left"); + core.setTextBaseline(ctx, "middle"); + if (itemCls === "equips" && item.id) { + itemName = "【" + item.equipCls + "】" + itemName; + } + core.fillText( + ctx, + itemName, + itemName_x, + itemName_middle, + itemNameColor, + itemNameFont, + itemNameMaxWidth + ); + if (!item.equip) + core.fillText( + ctx, + "【" + itemClsName + "】", + itemCls_x, + itemCls_middle, + itemClsColor, + itemClsFont + ); + + var statusText = ""; + if (core.status.event.id == "equipbox") { + var type = item.equip.type; + if (typeof type == "string") type = core.getEquipTypeByName(type); + var compare = core.compareEquipment(item.id, core.getEquip(type)); + var compare2; + if (item.equipCls === "双手剑") + compare2 = core.compareEquipment(null, core.getEquip(1)); + if ( + item.equipCls === "盾牌" && + core.material.items[core.getEquip(0)]?.equipCls === "双手剑" + ) + compare2 = core.compareEquipment(null, core.getEquip(0)); + if (info.select.action == "unload") + compare = core.compareEquipment(null, item.id); + // --- 变化值... + for (var name in core.status.hero) { + if (typeof core.status.hero[name] != "number") continue; + var nowValue = core.getRealStatus(name); + // 查询新值 + var newValue = Math.floor( + ((core.getStatus(name) + + (compare.value[name] || 0) + + (compare2?.value[name] || 0)) * + (core.getBuff(name) * 100 + + (compare.percentage[name] || 0) + + (compare2?.percentage[name] || 0))) / + 100 + ); + if (name === "mdef") { + var nowValue = core.getRealStatus(name); + var newValue = Math.round( + (core.getStatus(name) - + (compare.value[name] || 0) - + (compare2?.value[name] || 0)) * + (1 - + (1 - core.getBuff(name)) * + (compare.percentage[name] || 1) * + (compare2?.percentage[name] || 1)) + ); + } + if (nowValue == newValue) continue; + var color = newValue > nowValue ? "#00FF00" : "#FF0000"; + nowValue = core.formatBigNumber(nowValue); + newValue = core.formatBigNumber(newValue); + + if (name === "mdef") { + nowValue += "%"; + newValue += "%"; + } + statusText += + core.getStatusLabel(name) + + " " + + nowValue + + "->\r[" + + color + + "]" + + newValue + + "\r\n"; + } + } + itemText = statusText + itemText; + if (item.equip) { + core.drawTextContent(ctx, itemText, { + left: itemText_x, + top: itemCls_middle, + bold: false, + color: "white", + align: "left", + fontSize: itemTextFontSize, + maxWidth: + rightbar_width - + (itemText_x - rightbar_x) * 2 + + itemTextFontSize / 2, + }); + } else { + core.drawTextContent(ctx, itemText, { + left: itemText_x, + top: itemText_y, + bold: false, + color: "white", + align: "left", + fontSize: itemTextFontSize, + maxWidth: + rightbar_width - + (itemText_x - rightbar_x) * 2 + + itemTextFontSize / 2, + }); + } + + ///// *** 退出按钮设置 + var btnRadius = 10; + var btnBorderWidth = 2; + var btnRight = toolboxRight - 2; + var btnBottom = toolboxBottom - 2; + var btnBorderStyle = "#fff"; + ///// *** + + // 获取圆心位置 + var btn_x = btnRight - btnRadius - btnBorderWidth / 2; + btn_y = btnBottom - btnRadius - btnBorderWidth / 2; + drawToolbox_setExitBtn( + ctx, + btn_x, + btn_y, + btnRadius, + btnBorderStyle, + btnBorderWidth + ); + + ///// *** 使用按钮设置 + var useBtnHeight = btnRadius * 2; + // 这里不设置useBtnWidth而是根据各项数据自动得出width + var useBtnRadius = useBtnHeight / 4; + var useBtn_x = rightbar_x + 4, + useBtn_y = btnBottom - useBtnHeight; + var useBtnBorderStyle = "#fff"; + var useBtnBorderWidth = btnBorderWidth; + const batchUseBtn_x = useBtn_x + 50; // 个人觉得,搞这么多参数还不如硬编码 + const hideBtn_y = useBtn_y - useBtnHeight - 8; + ///// *** + + drawToolbox_setUseBtn( + ctx, + useBtn_x, + useBtn_y, + useBtnRadius, + useBtnHeight, + useBtnBorderStyle, + useBtnBorderWidth + ); + if (core.status.event.id === "toolbox") { + drawToolbox_setBatchUseBtn( + ctx, + batchUseBtn_x, + useBtn_y, + useBtnRadius, + useBtnHeight, + useBtnBorderStyle, + useBtnBorderWidth + ); + } + drawToolbox_setHideBtn( + ctx, + useBtn_x, + hideBtn_y, + useBtnRadius, + useBtnHeight, + useBtnBorderStyle, + useBtnBorderWidth + ); + drawToolbox_setShowHideBtn( + ctx, + rightbar_x, + useBtn_y, + useBtnHeight, + useBtnBorderStyle + ); + } + + function drawEquipbox_drawOthers(ctx, obj) { + var info = core.status.thisUIEventInfo; + + ///// *** 装备格设置 + var equipList_lineWidth = 2; + var equipList_boxSize = 32; + var equipList_borderWidth = 2; + var equipList_borderStyle = "#fff"; + var equipList_nameColor = "#fff"; + ///// *** + + var equipList_x = obj.x + 4, + equipList_bottom = obj.obj.y - equipList_lineWidth, + equipList_y = equipList_bottom - obj.obj.oneItemHeight * reduceItem - 2, + equipList_height = equipList_bottom - equipList_y; + var equipList_right = obj.leftbar_right, + equipList_width = equipList_right - equipList_x; + core.drawLine( + ctx, + obj.x, + equipList_bottom + equipList_lineWidth / 2, + equipList_right, + equipList_bottom + equipList_lineWidth / 2, + equipList_borderStyle, + equipList_lineWidth + ); + var toDrawList = core.status.globalAttribute.equipName, + len = toDrawList.length; + + ///// *** 装备格设置 + var maxItem = 2; + var box_width = 32, + box_height = 32, + box_borderStyle = "#fff", + box_selectBorderStyle = "gold", // 选中的装备格的颜色 + box_borderWidth = 2; + var boxName_fontSize = 14, + boxName_space = 2, + boxName_color = "#fff"; // 装备格名称与上面的装备格框的距离 + var maxLine = Math.ceil(len / maxItem); + ///// *** + var l = Math.sqrt(len); + if (Math.pow(l) == len && len != 4) { + if (l <= maxItem) maxItem = l; + } + maxItem = Math.min(toDrawList.length, maxItem); + info.equips = maxItem; + + var boxName_font = core.ui._buildFont(boxName_fontSize); + // 总宽高减去所有装备格宽高得到空隙大小 + var oneBoxWidth = box_width + box_borderWidth * 2; + var oneBoxHeight = + box_height + boxName_fontSize + boxName_space + 2 * box_borderWidth; + var space_y = (equipList_height - maxLine * oneBoxHeight) / (1 + maxLine), + space_x = (equipList_width - maxItem * oneBoxWidth) / (1 + maxItem); + var box_x = equipList_x + space_x, + box_y = equipList_y + space_y + 12; + for (var i = 0; i < 2; i++) { + var id = core.getEquip(i), + name = toDrawList[i]; + if (i === 0) name = "主手"; + if (i === 1) name = "副手"; + var selectBorder = false; + if (core.status.thisUIEventInfo.select.type == i) selectBorder = true; + var borderStyle = selectBorder + ? box_selectBorderStyle + : box_borderStyle; + drawEquipbox_drawOne( + ctx, + name, + id, + box_x, + box_y, + box_width, + box_height, + boxName_space, + boxName_font, + boxName_color, + borderStyle, + box_borderWidth + ); + var todo = new Function( + "core.clickOneEquipbox('" + id + "'," + i + ")" + ); + addUIEventListener( + box_x - box_borderWidth / 2, + box_y - box_borderWidth / 2, + oneBoxWidth, + oneBoxHeight, + todo + ); + box_x += space_x + oneBoxWidth; + if ((i + 1) % maxItem == 0) { + box_x = equipList_x + space_x; + box_y += space_y + oneBoxHeight; + } + } + if (core.material.items[core.getEquip(0)]?.equipCls === "双手剑") { + core.drawLine( + ctx, + equipList_x + space_x + space_x + oneBoxWidth, + equipList_y + space_y + 12, + equipList_x + + space_x + + space_x + + oneBoxWidth + + box_width + + box_borderWidth, + equipList_y + space_y + box_height + 12 + ); + core.drawLine( + ctx, + equipList_x + space_x + space_x + oneBoxWidth, + equipList_y + space_y + box_height + 12, + equipList_x + + space_x + + space_x + + oneBoxWidth + + box_width + + box_borderWidth, + equipList_y + space_y + 12 + ); + } + ///// *** 装备格设置 + var maxItem = 3; + var box_width = 32, + box_height = 32, + box_borderStyle = "#fff", + box_selectBorderStyle = "gold", // 选中的装备格的颜色 + box_borderWidth = 2; + var boxName_fontSize = 14, + boxName_space = 2, + boxName_color = "#fff"; // 装备格名称与上面的装备格框的距离 + var maxLine = Math.ceil(len / maxItem); + ///// *** + var l = Math.sqrt(len); + if (Math.pow(l) == len && len != 4) { + if (l <= maxItem) maxItem = l; + } + maxItem = Math.min(toDrawList.length, maxItem); + info.equips = maxItem; + + var boxName_font = core.ui._buildFont(boxName_fontSize); + // 总宽高减去所有装备格宽高得到空隙大小 + var oneBoxWidth = box_width + box_borderWidth * 2; + var oneBoxHeight = + box_height + boxName_fontSize + boxName_space + 2 * box_borderWidth; + var space_y = (equipList_height - maxLine * oneBoxHeight) / (1 + maxLine), + space_x = (equipList_width - maxItem * oneBoxWidth) / (1 + maxItem); + var box_x = equipList_x + space_x, + box_y = equipList_y + space_y + space_y + oneBoxHeight; + for (var i = 2; i < len; i++) { + var id = core.getEquip(i), + name = toDrawList[i]; + var selectBorder = false; + if (core.status.thisUIEventInfo.select.type == i) selectBorder = true; + var borderStyle = selectBorder + ? box_selectBorderStyle + : box_borderStyle; + drawEquipbox_drawOne( + ctx, + name, + id, + box_x, + box_y, + box_width, + box_height, + boxName_space, + boxName_font, + boxName_color, + borderStyle, + box_borderWidth + ); + var todo = new Function( + "core.clickOneEquipbox('" + id + "'," + i + ")" + ); + addUIEventListener( + box_x - box_borderWidth / 2, + box_y - box_borderWidth / 2, + oneBoxWidth, + oneBoxHeight, + todo + ); + box_x += space_x + oneBoxWidth; + } + } + + this.drawToolbox = function (ctx) { + ctx = ctx || core.canvas.ui; + core.status.thisEventClickArea = []; + + var info = drawBoxBackground(ctx); + info.itemNum = itemNum; + drawItemListbox(ctx, info.obj); + drawToolboxRightbar(ctx, info); + core.setTextBaseline(ctx, "alphabetic"); + core.setTextAlign("left"); + }; + + var reduceItem = 4; + this.drawEquipbox = function (ctx) { + ctx = ctx || core.canvas.ui; + core.status.thisEventClickArea = []; + var info = drawBoxBackground(ctx); + info.itemNum = itemNum - reduceItem; + info.obj.y += info.obj.oneItemHeight * reduceItem; + info.obj.height -= info.obj.oneItemHeight * reduceItem; + drawItemListbox(ctx, info.obj); + drawEquipbox_drawOthers(ctx, info); + drawToolboxRightbar(ctx, info); + core.setTextBaseline(ctx, "alphabetic"); + core.setTextAlign("left"); + }; + + function drawEquipbox_drawOne( + ctx, + name, + id, + x, + y, + width, + height, + space, + font, + color, + style, + lineWidth + ) { + if (id) + core.drawIcon( + ctx, + id, + x + lineWidth / 2, + y + lineWidth / 2, + width, + height + ); + core.strokeRect( + ctx, + x, + y, + width + lineWidth, + height + lineWidth, + style, + lineWidth + ); + core.setTextAlign(ctx, "center"); + core.setTextBaseline(ctx, "top"); + var tx = (x + x + lineWidth / 2 + width) / 2, + ty = y + height + (lineWidth / 2) * 3 + space; + core.fillText(ctx, name, tx, ty, color, font); + + core.setAlpha(ctx, 1); + + core.setTextBaseline(ctx, "alphabetic"); + core.setTextAlign("left"); + } + + function drawItemListbox_drawItem( + ctx, + left, + right, + top, + height, + marginLeft, + marginHeight, + style, + id + ) { + var info = core.status.thisUIEventInfo; + var nowClick = info.index; + var item = core.material.items[id] || {}; + var name = item.name || "???"; + var num = core.itemCount(id) || 0; + var fontSize = Math.floor(height - marginHeight * 2); + core.setTextAlign(ctx, "right"); + var numText = "x" + num; + core.fillText( + ctx, + numText, + right - marginLeft, + top + height / 2, + style, + core.ui._buildFont(fontSize) + ); + + const hideInfo = core.getFlag("hideInfo", {}); + if ( + item && + (hideInfo.hasOwnProperty(id) ? hideInfo[id] : item.hideInToolbox) + ) + core.setAlpha(ctx, 0.5); + + if (name != "???") + core.drawIcon( + ctx, + id, + left + marginLeft, + top + marginHeight, + fontSize, + fontSize + ); + var text_x = left + marginLeft + fontSize + 2; + var maxWidth = right - core.calWidth(ctx, numText) - text_x; + core.setTextAlign(ctx, "left"); + core.fillText( + ctx, + name, + text_x, + top + height / 2, + style, + core.ui._buildFont(fontSize), + maxWidth + ); + core.setAlpha(ctx, 1); + + var todo = new Function("core.clickItemFunc('" + id + "');"); + addUIEventListener(left, top, right - left, height, todo); + } + + function setPageItems(page) { + var num = itemNum; + if (core.status.event.id == "equipbox") num -= reduceItem; + var info = core.status.thisUIEventInfo; + if (!info) return; + page = page || info.page; + var items = core.getToolboxItems( + core.status.event.id == "toolbox" ? "all" : "equips", + core.getFlag("showHideItem", false) + ); + info.allItems = items; + var maxPage = Math.ceil(items.length / num); + info.maxPage = maxPage; + var pageItems = items.slice((page - 1) * num, page * num); + info.pageItems = pageItems; + info.maxItem = pageItems.length; + if (items.length == 0 && pageItems.length == 0) info.index = null; + if (pageItems.length == 0 && info.page > 1) { + info.page = Math.max(1, info.page - 1); + return setPageItems(info.page); + } + return pageItems; + } + + function drawToolbox_setExitBtn(ctx, x, y, r, style, lineWidth) { + core.strokeCircle(ctx, x, y, r, style, lineWidth); + ctx.textAlign = "center"; + ctx.textBaseline = "middle"; + var textSize = Math.sqrt(2) * r; + core.fillText( + ctx, + "x", + x, + y, + style, + core.ui._buildFont(textSize), + textSize + ); + core.setTextAlign(ctx, "start"); + core.setTextBaseline(ctx, "top"); + + var todo = function () { + core.closePanel(); + }; + addUIEventListener(x - r, y - r, r * 2, r * 2, todo); + } + + function drawToolbox_setUseBtn(ctx, x, y, r, h, style, lineWidth) { + core.setTextAlign(ctx, "left"); + core.setTextBaseline(ctx, "top"); + var fontSize = h - 4; + var font = core.ui._buildFont(fontSize); + var text = core.status.event.id == "toolbox" ? "使用" : "装备"; + if (core.status.thisUIEventInfo.select.action == "unload") text = "卸下"; + var w = core.calWidth(ctx, text, font) + 2 * r + lineWidth / 2; + + core.strokeRoundRect(ctx, x, y, w, h, r, style, lineWidth); + core.fillText(ctx, text, x + r, y + lineWidth / 2 + 2, style, font); + + var todo = function () { + core.useSelectItemInBox(); + }; + addUIEventListener(x, y, w, h, todo); + } + + function getSelectedItem() { + var info = core.status.thisUIEventInfo; + if ( + !( + info && + info.select.id && + ["toolbox", "equipbox"].includes(core.status.event.id) + ) + ) { + core.drawFailTip("发生了未知错误!"); + return; + } + return info.select.id; + } + + function batchUse(item, count) { + try { + const itemCount = core.itemCount(item); + if (count > itemCount) count = itemCount; + core.closePanel(); + for (let i = 0; i < count; i++) { + if (core.canUseItem(item)) core.useItem(item); + else return; + } + } catch (e) { + console.error(e); + core.drawFailTip("批量使用时出现未知错误!"); + } + } + + function drawToolbox_setBatchUseBtn(ctx, x, y, r, h, style, lineWidth) { + try { + const selectedItem = getSelectedItem(); + let canBatchUse = eval(core.material.items[selectedItem]?.canBatchUse); + if (!canBatchUse) return; + } catch (error) { + console.error(error); + return; + } + core.setTextAlign(ctx, "left"); + core.setTextBaseline(ctx, "top"); + var fontSize = h - 4; + var font = core.ui._buildFont(fontSize); + var text = "批量使用"; + var w = core.calWidth(ctx, text, font) + 2 * r + lineWidth / 2; + + core.strokeRoundRect(ctx, x, y, w, h, r, style, lineWidth); + core.fillText(ctx, text, x + r, y + lineWidth / 2 + 2, style, font); + + var todo = function () { + core.utils.myprompt("输入要使用该物品的次数(0~99)。", null, (value) => { + value = parseInt(value); + const id = getSelectedItem(); + + if (Number.isNaN(value) || value < 0 || value > 99) { + core.drawFailTip("输入不合法!"); + return; + } + if (!core.canUseItem(id)) { + core.drawFailTip("当前无法使用该道具!"); + return; + } + core.closePanel(); + batchUse(id, value); + }); + }; + addUIEventListener(x, y, w, h, todo); + } + + function drawToolbox_setHideBtn(ctx, x, y, r, h, style, lineWidth) { + core.setTextAlign(ctx, "left"); + core.setTextBaseline(ctx, "top"); + var fontSize = h - 4; + var font = core.ui._buildFont(fontSize); + var text = "显示/隐藏"; + var w = core.calWidth(ctx, text, font) + 2 * r + lineWidth / 2; + + core.strokeRoundRect(ctx, x, y, w, h, r, style, lineWidth); + core.fillText(ctx, text, x + r, y + lineWidth / 2 + 2, style, font); + + var todo = function () { + //debugger; + var id = getSelectedItem(); + let hideInfo = core.getFlag("hideInfo", {}); + console.log(id); + if (hideInfo.hasOwnProperty(id)) { + hideInfo[id] = !hideInfo[id]; + core.setFlag("hideInfo", hideInfo); + } else { + hideInfo[id] = !core.material.items[id].hideInToolbox; + core.setFlag("hideInfo", hideInfo); + } + if (core.status.event.id === "toolbox") core.plugin.drawToolbox(); + else if (core.status.event.id === "equipbox") + core.plugin.drawEquipbox(); + }; + addUIEventListener(x, y, w, h, todo); + } + + ui.prototype.getToolboxItems = function (cls, showHide) { + let list = Object.keys(core.status.hero.items[cls] || {}); + if (cls === "all") { + for (let name in core.status.hero.items) { + if (name == "equips") continue; + list = list.concat(Object.keys(core.status.hero.items[name])); + } + if (!showHide) + list = list.filter(function (id2) { + const hideInfo = core.getFlag("hideInfo", {}); + if (hideInfo.hasOwnProperty(id2)) return !hideInfo[id2]; + else return !core.material.items[id2].hideInToolbox; + }); + list = list.sort(); + return list; + } + if (cls === "equips") { + if (!showHide) + list = list.filter(function (id2) { + const hideInfo = core.getFlag("hideInfo", {}); + if (hideInfo.hasOwnProperty(id2)) return !hideInfo[id2]; + else return !core.material.items[id2].hideInToolbox; + }); + + list = list.sort(); + return list; + } + if (this.uidata.getToolboxItems) { + return this.uidata.getToolboxItems(cls, showHide); + } + if (!showHide) + list = list.filter(function (id2) { + return !core.material.items[id2].hideInToolbox; + }); + list = list.sort(); + return list; + }; + + function drawToolbox_setShowHideBtn(ctx, x, y, h, style) { + core.setTextAlign(ctx, "left"); + core.setTextBaseline(ctx, "top"); + var fontSize = h - 6; + var font = core.ui._buildFont(fontSize); + var text = "显示隐藏"; + var w = core.calWidth(ctx, text, font); + h += 4; + const squareSize = h - 6; + + x -= w + squareSize + 26; + + const border = 2; + core.fillRect(ctx, x, y, squareSize, squareSize, " #F5F5F5"); + if (core.hasFlag("showHideItem")) { + core.fillRect( + ctx, + x + border, + y + border, + squareSize - 2 * border, + squareSize - 2 * border, + "lime" + ); + } + core.fillText(ctx, text, x + squareSize + 2, y + 4, style, font); + + var todo = function () { + core.setFlag("showHideItem", !core.getFlag("showHideItem", false)); + if (core.status.event.id === "toolbox") core.plugin.drawToolbox(); + else if (core.status.event.id === "equipbox") + core.plugin.drawEquipbox(); + }; + addUIEventListener(x, y, w, h, todo); + } + + function drawItemListbox_setPageBtn( + ctx, + left, + right, + bottom, + r, + style, + lineWidth + ) { + var offset = lineWidth / 2 + r; + + var x = left + offset; + var y = bottom - offset; + var pos = (Math.sqrt(2) / 2) * (r - lineWidth / 2); + core.fillPolygon( + ctx, + [ + [x - pos, y], + [x + pos - 2, y - pos], + [x + pos - 2, y + pos], + ], + style + ); + core.strokeCircle(ctx, x, y, r, style, lineWidth); + var todo = function () { + core.addItemListboxPage(-1); + }; + addUIEventListener(x - r - 2, y - r - 2, r * 2 + 4, r * 2 + 4, todo); + + x = right - offset; + core.fillPolygon( + ctx, + [ + [x + pos, y], + [x - pos + 2, y - pos], + [x - pos + 2, y + pos], + ], + style + ); + core.strokeCircle(ctx, x, y, r, style, lineWidth); + var todo = function () { + core.addItemListboxPage(1); + }; + addUIEventListener(x - r - 2, y - r - 2, r * 2 + 4, r * 2 + 4, todo); + } + + this.clickItemFunc = function (id) { + var info = core.status.thisUIEventInfo; + if (!info) return; + if (info.select.id == id) return core.useSelectItemInBox(); + info.select = {}; + info.select.id = id; + core.setIndexAndSelect("index"); + refreshBox(); + }; + + this.clickOneEquipbox = function (id, type) { + var info = core.status.thisUIEventInfo; + if (!info) return; + if (info.select.id == id && info.select.type == type) + core.useSelectItemInBox(); + else + core.status.thisUIEventInfo.select = { + id: id, + type: type, + action: "unload", + }; + return refreshBox(); + }; + + this.useSelectItemInBox = function () { + var info = core.status.thisUIEventInfo; + if (!info) return; + if (!info.select.id) return; + var id = info.select.id; + if (core.status.event.id == "toolbox") { + core.events.tryUseItem(id); + // core.closePanel(); + } else if (core.status.event.id == "equipbox") { + var action = info.select.action || "load"; + info.index = 1; + if (action == "load") { + var type = core.getEquipTypeById(id); + let equipClsid = core.material.items[id]?.equipCls; + let equipCls0 = core.material.items[core.getEquip(0)]?.equipCls; + let equipCls1 = core.material.items[core.getEquip(1)]?.equipCls; + if (equipClsid === "双手剑") { + core.unloadEquip(0, function () { + core.status.route.push("unEquip:" + 0); + }); + core.unloadEquip(1, function () { + core.status.route.push("unEquip:" + 1); + }); + } + if ( + equipCls0 === "双手剑" && + !(equipClsid === "饰品" || equipClsid === "护具") + ) { + core.unloadEquip(0, function () { + core.status.route.push("unEquip:" + 0); + }); + } + core.loadEquip(id, function () { + core.status.route.push("equip:" + id); + info.select.type = type; + core.setIndexAndSelect("select"); + core.drawEquipbox(); + }); + } else { + var type = info.select.type; + core.unloadEquip(type, function () { + core.status.route.push("unEquip:" + type); + info.select.type = type; + info.select.action = "load"; + core.setIndexAndSelect("select"); + core.drawEquipbox(); + }); + } + } + core.updateStatusBar(); + }; + + this.setIndexAndSelect = function (toChange) { + var info = core.status.thisUIEventInfo; + if (!info) return; + setPageItems(info.page); + var index = info.index || 1; + var items = info.pageItems; + + info.select.action = null; + info.select.type = null; + if (toChange == "index") info.index = items.indexOf(info.select.id) + 1; + info.select.id = items[info.index - 1]; + }; + + this.addItemListboxPage = function (num) { + var info = core.status.thisUIEventInfo; + if (!info) return; + var maxPage = info.maxPage || 1; + info.page = info.page || 1; + info.page += num; + if (info.page <= 0) info.page = maxPage; + if (info.page > maxPage) info.page = 1; + info.index = 1; + setPageItems(info.page); + core.setIndexAndSelect("select"); + refreshBox(); + }; + + this.addItemListboxIndex = function (num) { + var info = core.status.thisUIEventInfo; + if (!info) return; + var maxItem = info.maxItem || 0; + info.index = info.index || 0; + info.index += num; + if (info.index <= 0) info.index = 1; + if (info.index > maxItem) info.index = maxItem; + core.setIndexAndSelect("select"); + refreshBox(); + }; + + this.addEquipboxType = function (num) { + var info = core.status.thisUIEventInfo; + var type = info.select.type; + if (type == null && num > 0) info.select.type = 0; + else info.select.type = type + num; + var max = core.status.globalAttribute.equipName.length; + if (info.select.type >= max) { + info.select = {}; + core.setIndexAndSelect("select"); + return core.addItemListboxPage(0); + } else { + var m = Math.abs(info.select.type); + if (info.select.type < 0) info.select.type = max - m; + core.setIndexAndSelect("select"); + refreshBox(); + return; + } + }; + + core.actions._keyDownToolbox = function (keycode) { + if (!core.status.thisEventClickArea) return; + if (keycode == 37) { + // left + core.addItemListboxPage(-1); + return; + } + if (keycode == 38) { + // up + core.addItemListboxIndex(-1); + return; + } + if (keycode == 39) { + // right + core.addItemListboxPage(1); + return; + } + if (keycode == 40) { + // down + core.addItemListboxIndex(1); + return; + } + }; + + ////// 工具栏界面时,放开某个键的操作 ////// + core.actions._keyUpToolbox = function (keycode) { + if (keycode == 81) { + core.ui.closePanel(); + if (core.isReplaying()) core.control._replay_equipbox(); + else core.openEquipbox(); + return; + } + if (keycode == 84 || keycode == 27 || keycode == 88) { + core.closePanel(); + return; + } + if (keycode == 13 || keycode == 32 || keycode == 67) { + var info = core.status.thisUIEventInfo; + if (info.select) { + core.useSelectItemInBox(); + } + return; + } + }; + + core.actions._keyDownEquipbox = function (keycode) { + if (!core.status.thisEventClickArea) return; + if (keycode == 37) { + // left + var info = core.status.thisUIEventInfo; + if (info.index != null) return core.addItemListboxPage(-1); + return core.addEquipboxType(-1); + } + if (keycode == 38) { + // up + var info = core.status.thisUIEventInfo; + if (info.index == 1) { + info.select.type = core.status.globalAttribute.equipName.length - 1; + core.setIndexAndSelect(); + return refreshBox(); + } + if (info.index) return core.addItemListboxIndex(-1); + return core.addEquipboxType(-1 * info.equips); + } + if (keycode == 39) { + // right + var info = core.status.thisUIEventInfo; + if (info.index != null) return core.addItemListboxPage(1); + return core.addEquipboxType(1); + } + if (keycode == 40) { + // down + var info = core.status.thisUIEventInfo; + if (info.index) return core.addItemListboxIndex(1); + return core.addEquipboxType(info.equips); + } + }; + + core.actions._keyUpEquipbox = function (keycode, altKey) { + if (altKey && keycode >= 48 && keycode <= 57) { + core.items.quickSaveEquip(keycode - 48); + return; + } + if (keycode == 84) { + core.ui.closePanel(); + if (core.isReplaying()) core.control._replay_toolbox(); + else core.openToolbox(); + return; + } + if (keycode == 81 || keycode == 27 || keycode == 88) { + core.closePanel(); + return; + } + if (keycode == 13 || keycode == 32 || keycode == 67) { + var info = core.status.thisUIEventInfo; + if (info.select) core.useSelectItemInBox(); + return; + } + }; + + core.registerAction( + "ondown", + "inEventClickAction", + function (x, y, px, py) { + if (!core.status.thisEventClickArea) return false; + var info = core.status.thisEventClickArea; + for (var i = 0; i < info.length; i++) { + var obj = info[i]; + if ( + px >= obj.x && + px <= obj.x + obj.width && + py > obj.y && + py < obj.y + obj.height + ) { + if (obj.todo) obj.todo(); + break; + } + } + return true; + }, + 51 + ); + core.registerAction( + "onclick", + "stopClick", + function () { + if (core.status.thisEventClickArea) return true; + }, + 51 + ); + + function addUIEventListener(x, y, width, height, todo) { + if (!core.status.thisEventClickArea) return; + var obj = { + x: x, + y: y, + width: width, + height: height, + todo: todo, + }; + core.status.thisEventClickArea.push(obj); + } + + this.initThisEventInfo = function () { + core.status.thisUIEventInfo = { + page: 1, + select: {}, + }; + core.status.thisEventClickArea = []; + }; + + function refreshBox() { + if (!core.status.event.id) return; + if (core.status.event.id == "toolbox") core.drawToolbox(); + else core.drawEquipbox(); + } + + core.ui.closePanel = function () { + if (core.status.hero && core.status.hero.flags) { + // 清除全部临时变量 + Object.keys(core.status.hero.flags).forEach(function (name) { + if (name.startsWith("@temp@") || /^arg\d+$/.test(name)) { + delete core.status.hero.flags[name]; + } + }); + } + this.clearUI(); + core.maps.generateGroundPattern(); + core.updateStatusBar(true); + core.unlockControl(); + core.status.event.data = null; + core.status.event.id = null; + core.status.event.selection = null; + core.status.event.ui = null; + core.status.event.interval = null; + core.status.thisUIEventInfo = null; + core.status.thisEventClickArea = null; + }; + + this.getItemClsName = function (item) { + if (item == null) return itemClsName; + if (item.cls == "equips") { + if (typeof item.equip.type == "string") return item.equip.type; + var type = core.getEquipTypeById(item.id); + return core.status.globalAttribute.equipName[type]; + } else return itemClsName[item.cls] || item.cls; + }; + + core.events.openToolbox = function (fromUserAction) { + if (core.isReplaying()) return; + if (!this._checkStatus("toolbox", fromUserAction)) return; + core.initThisEventInfo(); + let info = core.status.thisUIEventInfo; + info.index = 1; + core.setIndexAndSelect("select"); + core.drawToolbox(); + }; + + core.events.openEquipbox = function (fromUserAction) { + if (core.isReplaying()) return; + if (!this._checkStatus("equipbox", fromUserAction)) return; + core.initThisEventInfo(); + let info = core.status.thisUIEventInfo; + info.select.type = 0; + core.setIndexAndSelect("select"); + core.drawEquipbox(); + }; + + core.control._replay_toolbox = function () { + if (!core.isPlaying() || !core.isReplaying()) return; + if (!core.status.replay.pausing) return core.drawTip("请先暂停录像"); + if (core.isMoving() || core.status.replay.animate || core.status.event.id) + return core.drawTip("请等待当前事件的处理结束"); + + core.lockControl(); + core.status.event.id = "toolbox"; + core.drawToolbox(); + }; + + core.control._replay_equipbox = function () { + if (!core.isPlaying() || !core.isReplaying()) return; + if (!core.status.replay.pausing) return core.drawTip("请先暂停录像"); + if (core.isMoving() || core.status.replay.animate || core.status.event.id) + return core.drawTip("请等待当前事件的处理结束"); + + core.lockControl(); + core.status.event.id = "equipbox"; + core.drawEquipbox(); + }; + + core.control._replayAction_item = function (action) { + if (action.indexOf("item:") != 0) return false; + var itemId = action.substring(5); + if (!core.canUseItem(itemId)) return false; + if ( + core.material.items[itemId].hideInReplay || + core.status.replay.speed == 24 + ) { + core.useItem(itemId, false, core.replay); + return true; + } + core.status.event.id = "toolbox"; + core.initThisEventInfo(); + var info = core.status.thisUIEventInfo; + var items = core.getToolboxItems( + "all", + core.getFlag("showHideItem", false) + ); + setPageItems(1); + var index = items.indexOf(itemId) + 1; + info.page = Math.ceil(index / info.maxItem); + info.index = index % info.maxItem || info.maxItem; + core.setIndexAndSelect("select"); + setPageItems(info.page); + core.drawToolbox(); + setTimeout(function () { + core.ui.closePanel(); + core.useItem(itemId, false, core.replay); + }, core.control.__replay_getTimeout()); + return true; + }; + + core.control._replayAction_equip = function (action) { + if (action.indexOf("equip:") != 0) return false; + var itemId = action.substring(6); + var items = core.getToolboxItems( + "equips", + core.getFlag("showHideItem", false) + ); + var index = items.indexOf(itemId) + 1; + if (index < 1) { + core.removeFlag("__doNotCheckAutoEvents__"); + return false; + } + + var cb = function () { + var next = core.status.replay.toReplay[0] || ""; + if (!next.startsWith("equip:") && !next.startsWith("unEquip:")) { + core.removeFlag("__doNotCheckAutoEvents__"); + core.checkAutoEvents(); + } + core.replay(); + }; + core.setFlag("__doNotCheckAutoEvents__", true); + + core.status.route.push(action); + if ( + core.material.items[itemId].hideInReplay || + core.status.replay.speed == 24 + ) { + core.loadEquip(itemId, cb); + return true; + } + core.status.event.id = "equipbox"; + core.initThisEventInfo(); + var info = core.status.thisUIEventInfo; + setPageItems(1); + info.page = Math.ceil(index / info.maxItem); + info.index = index % info.maxItem || info.maxItem; + core.setIndexAndSelect("select"); + setPageItems(info.page); + core.drawEquipbox(); + setTimeout(function () { + core.ui.closePanel(); + core.loadEquip(itemId, cb); + }, core.control.__replay_getTimeout()); + return true; + }; + + core.control._replayAction_unEquip = function (action) { + if (action.indexOf("unEquip:") != 0) return false; + var equipType = parseInt(action.substring(8)); + if (!core.isset(equipType)) { + core.removeFlag("__doNotCheckAutoEvents__"); + return false; + } + + var cb = function () { + var next = core.status.replay.toReplay[0] || ""; + if (!next.startsWith("equip:") && !next.startsWith("unEquip:")) { + core.removeFlag("__doNotCheckAutoEvents__"); + core.checkAutoEvents(); + } + core.replay(); + }; + core.setFlag("__doNotCheckAutoEvents__", true); + + core.status.route.push(action); + if (core.status.replay.speed == 24) { + core.unloadEquip(equipType, cb); + return true; + } + core.status.event.id = "equipbox"; + core.initThisEventInfo(); + var info = core.status.thisUIEventInfo; + setPageItems(1); + info.select.type = equipType; + core.setIndexAndSelect(); + core.drawEquipbox(); + setTimeout(function () { + core.ui.closePanel(); + core.unloadEquip(equipType, cb); + }, core.control.__replay_getTimeout()); + return true; + }; + core.registerReplayAction("item", core.control._replayAction_item); + core.registerReplayAction("equip", core.control._replayAction_equip); + core.registerReplayAction("unEquip", core.control._replayAction_unEquip); + }, "技能树": function () { // 在此增加新插件 // @@ -8557,519 +8967,517 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = }; }, "func": function () { - // 功能函数集,具体有哪些函数看每个函数前的注释即可 - // 安装方式:直接复制到插件里面,注意新建插件自带的 function () { } 不能删 - // 使用方式:可以直接使用对象解构按需引入 - // 例如:const { has, slide } = core.plugin.utils; - // slide([1, 2, 3], -1); // [2, 3, 1] + // 功能函数集,具体有哪些函数看每个函数前的注释即可 + // 安装方式:直接复制到插件里面,注意新建插件自带的 function () { } 不能删 + // 使用方式:可以直接使用对象解构按需引入 + // 例如:const { has, slide } = core.plugin.utils; + // slide([1, 2, 3], -1); // [2, 3, 1] - /** - * 滑动数组,使数组元素平移若干项 - * @example slide([1, 2, 3], -1); // [2, 3, 1] - * @example slide([1, 3, 5], 10); // [5, 3, 1]; - * @param {any[]} arr 需要滑动的数组 - * @param {number} delta 滑动的项数,正负均可 - */ - function slide(arr, delta) { - if (delta === 0) return arr; - delta %= arr.length; - if (delta > 0) { - arr.unshift(...arr.splice(arr.length - delta, delta)); - return arr; - } - if (delta < 0) { - arr.push(...arr.splice(0, -delta)); - return arr; - } - } - /** - * 图片叠加滤镜 - * @param {img} image 需要叠加的图片, - * @param {color} style 需要叠加的颜色 - */ - function imagelighter(image, style) { - // 创建一个canvas元素 - const canvas = document.createElement('canvas'); - const ctx = canvas.getContext('2d'); + /** + * 滑动数组,使数组元素平移若干项 + * @example slide([1, 2, 3], -1); // [2, 3, 1] + * @example slide([1, 3, 5], 10); // [5, 3, 1]; + * @param {any[]} arr 需要滑动的数组 + * @param {number} delta 滑动的项数,正负均可 + */ + function slide(arr, delta) { + if (delta === 0) return arr; + delta %= arr.length; + if (delta > 0) { + arr.unshift(...arr.splice(arr.length - delta, delta)); + return arr; + } + if (delta < 0) { + arr.push(...arr.splice(0, -delta)); + return arr; + } + } + /** + * 图片叠加滤镜 + * @param {img} image 需要叠加的图片, + * @param {color} style 需要叠加的颜色 + */ + function imagelighter(image, style) { + // 创建一个canvas元素 + const canvas = document.createElement("canvas"); + const ctx = canvas.getContext("2d"); - // 设置canvas的尺寸与图片相同 - canvas.width = image.width; - canvas.height = image.height; - ctx.drawImage(image, 0, 0); - // 创建一个临时canvas用于红色滤镜 - const tempCanvas = document.createElement('canvas'); - const tempCtx = tempCanvas.getContext('2d'); - tempCanvas.width = image.width; - tempCanvas.height = image.height; + // 设置canvas的尺寸与图片相同 + canvas.width = image.width; + canvas.height = image.height; + ctx.drawImage(image, 0, 0); + // 创建一个临时canvas用于红色滤镜 + const tempCanvas = document.createElement("canvas"); + const tempCtx = tempCanvas.getContext("2d"); + tempCanvas.width = image.width; + tempCanvas.height = image.height; - // 在临时canvas上绘制红色滤镜 - tempCtx.fillStyle = style ?? 'rgba(255, 0, 0, 0.5)'; // 半透明红色 - tempCtx.fillRect(0, 0, tempCanvas.width, tempCanvas.height); - // 使用lighter混合模式叠加红色滤镜 - ctx.globalCompositeOperation = 'lighter'; - ctx.drawImage(tempCanvas, 0, 0); - // 使用destination-in混合模式保留原始图片的透明度 - ctx.globalCompositeOperation = 'destination-in'; - ctx.drawImage(image, 0, 0); + // 在临时canvas上绘制红色滤镜 + tempCtx.fillStyle = style ?? "rgba(255, 0, 0, 0.5)"; // 半透明红色 + tempCtx.fillRect(0, 0, tempCanvas.width, tempCanvas.height); + // 使用lighter混合模式叠加红色滤镜 + ctx.globalCompositeOperation = "lighter"; + ctx.drawImage(tempCanvas, 0, 0); + // 使用destination-in混合模式保留原始图片的透明度 + ctx.globalCompositeOperation = "destination-in"; + ctx.drawImage(image, 0, 0); + // 恢复默认混合模式 + ctx.globalCompositeOperation = "source-over"; + // 返回处理后的canvas + return canvas; + } + /** + * 获取一个方向的反方向 + * @example backDir('up'); // 'down' + * @example backDir('leftup'); // 'rightdown' + * @param {string} dir 方向 + */ + function backDir(dir) { + const map = { + up: "down", + down: "up", + left: "right", + right: "left", + leftup: "rightdown", + leftdown: "rightup", + rightdown: "leftup", + rightup: "leftdown", + }; + if (!dir in map) { + throw new TypeError( + `Wrong dir is delivered when getting back direction.` + ); + } + return map[dir]; + } - // 恢复默认混合模式 - ctx.globalCompositeOperation = 'source-over'; + /** + * 判断一个值是否不是undefined和null + * @example has(0); // true + * @example has(false); // true + * @example has(NaN); // true + * @example has(null); // false + * @param {any} v 要判断的值 + */ + function has(v) { + return v !== null && v !== void 0; + } - // 返回处理后的canvas - return canvas; - } - /** - * 获取一个方向的反方向 - * @example backDir('up'); // 'down' - * @example backDir('leftup'); // 'rightdown' - * @param {string} dir 方向 - */ - function backDir(dir) { - const map = { - up: "down", - down: "up", - left: "right", - right: "left", - leftup: "rightdown", - leftdown: "rightup", - rightdown: "leftup", - rightup: "leftdown", - }; - if (!dir in map) { - throw new TypeError( - `Wrong dir is delivered when getting back direction.` - ); - } - return map[dir]; - } + /** + * 解析css字符串为CSSStyleDeclaration对象 + * @example + * parseCss('background-color: cyan; cursor: pointer; user-select: none'); + * // 输出 { backgroundColor: 'cyan', cursor: 'pointer', userSelect: 'none' } + * @param {string} css 要解析的css字符串 + */ + function parseCss(css) { + const str = css.replace(/[\n\s\t]*/g, "").replace(/;*/g, ";"); + const styles = str.split(";"); + const res = {}; - /** - * 判断一个值是否不是undefined和null - * @example has(0); // true - * @example has(false); // true - * @example has(NaN); // true - * @example has(null); // false - * @param {any} v 要判断的值 - */ - function has(v) { - return v !== null && v !== void 0; - } + for (const one of styles) { + const [key, data] = one.split(":"); + const cssKey = key.replace(/\-([a-z])/g, (str, $1) => $1.toUpperCase()); + res[cssKey] = data; + } + return res; + } - /** - * 解析css字符串为CSSStyleDeclaration对象 - * @example - * parseCss('background-color: cyan; cursor: pointer; user-select: none'); - * // 输出 { backgroundColor: 'cyan', cursor: 'pointer', userSelect: 'none' } - * @param {string} css 要解析的css字符串 - */ - function parseCss(css) { - const str = css.replace(/[\n\s\t]*/g, "").replace(/;*/g, ";"); - const styles = str.split(";"); - const res = {}; + /** + * 等待一段时间,需在async function中使用,否则报错 + * @example await sleep(500); // 等待500毫秒 + * @param {number} time 等待的毫秒数 + */ + async function sleep(time) { + return new Promise((res) => setTimeout(res, time)); + } - for (const one of styles) { - const [key, data] = one.split(":"); - const cssKey = key.replace(/\-([a-z])/g, (str, $1) => $1.toUpperCase()); - res[cssKey] = data; - } - return res; - } + /** + * 在下一帧的下一帧执行一个函数 + * @example nextFrame(() => console.log(1)); // 两帧后在控制台输出1 + * @param cb 执行的函数 + */ + function nextFrame(cb) { + requestAnimationFrame(() => { + requestAnimationFrame(cb); + }); + } - /** - * 等待一段时间,需在async function中使用,否则报错 - * @example await sleep(500); // 等待500毫秒 - * @param {number} time 等待的毫秒数 - */ - async function sleep(time) { - return new Promise((res) => setTimeout(res, time)); - } + /** + * 将一个css颜色解析成一个rgba数组 + * 目前仅支持 #RGB #RGBA #RRGGBB #RRGGBBAA rgb() rgba() hsl() hsla() css自带颜色 这几种的转换 + * @exmaple parseColor('#fff'); // [255, 255, 255] + * @example parseColor('#abcd'); // [170, 187, 204, 0.8666666666666667] + * @example parseColor('rgba(170, 230, 13, 0.2)'); // [170, 230, 13, 0.2] + * @example parseColor('cyan'); // [0, 255, 255] + * @example parseColor('lightcoral'); // [240, 128, 128] + * @example parseColor('hsla(0.2, 0.3, 0.4, 0.2)'); // [120, 133, 71, 0.2] + * @example parseColor('rgba(20%, 50, 33%, 0.2)'); // [51, 50, 84.15, 0.2] + * @param color 要解析的颜色字符串 + */ + function parseColor(color) { + if (color.startsWith("rgb")) { + // rgb + const match = color.match(/rgba?\([\d\,\s\.%]+\)/); + if (!has(match)) throw new Error(`Invalid color is delivered!`); + const l = color.includes("a"); + return match[0] + .slice(l ? 5 : 4, -1) + .split(",") + .map((v, i) => { + const vv = v.trim(); + if (vv.endsWith("%")) { + if (i === 3) { + return parseInt(vv) / 100; + } else { + return (parseInt(vv) * 255) / 100; + } + } else return parseFloat(vv); + }) + .slice(0, l ? 4 : 3); + } else if (color.startsWith("#")) { + // 十六进制 + const content = color.slice(1); + if (![3, 4, 6, 8].includes(content.length)) { + throw new Error(`Invalid color is delivered!`); + } - /** - * 在下一帧的下一帧执行一个函数 - * @example nextFrame(() => console.log(1)); // 两帧后在控制台输出1 - * @param cb 执行的函数 - */ - function nextFrame(cb) { - requestAnimationFrame(() => { - requestAnimationFrame(cb); - }); - } + if (content.length <= 4) { + const res = content.split("").map((v) => Number(`0x${v}${v}`)); + if (res.length === 4) res[3] /= 255; + return res; + } else { + const res = Array(content.length / 2) + .fill(1) + .map((v, i) => Number(`0x${content[i * 2]}${content[i * 2 + 1]}`)); + if (res.length === 4) res[3] /= 255; + return res; + } + } else if (color.startsWith("hsl")) { + // hsl,转成rgb后输出 + const match = color.match(/hsla?\([\d\,\s\.%]+\)/); + if (!has(match)) throw new Error(`Invalid color is delivered!`); + const l = color.includes("a"); + const hsl = match[0] + .slice(l ? 5 : 4, -1) + .split(",") + .map((v) => { + const vv = v.trim(); + if (vv.endsWith("%")) return parseInt(vv) / 100; + else return parseFloat(vv); + }); + const rgb = hslToRgb(hsl[0], hsl[1], hsl[2]); + return l ? rgb.concat([hsl[3]]) : rgb; + } else { + // 单词 + const rgb = cssColors[color]; + if (!has(rgb)) { + throw new Error(`Invalid color is delivered!`); + } + return parseColor(rgb); + } + } - /** - * 将一个css颜色解析成一个rgba数组 - * 目前仅支持 #RGB #RGBA #RRGGBB #RRGGBBAA rgb() rgba() hsl() hsla() css自带颜色 这几种的转换 - * @exmaple parseColor('#fff'); // [255, 255, 255] - * @example parseColor('#abcd'); // [170, 187, 204, 0.8666666666666667] - * @example parseColor('rgba(170, 230, 13, 0.2)'); // [170, 230, 13, 0.2] - * @example parseColor('cyan'); // [0, 255, 255] - * @example parseColor('lightcoral'); // [240, 128, 128] - * @example parseColor('hsla(0.2, 0.3, 0.4, 0.2)'); // [120, 133, 71, 0.2] - * @example parseColor('rgba(20%, 50, 33%, 0.2)'); // [51, 50, 84.15, 0.2] - * @param color 要解析的颜色字符串 - */ - function parseColor(color) { - if (color.startsWith("rgb")) { - // rgb - const match = color.match(/rgba?\([\d\,\s\.%]+\)/); - if (!has(match)) throw new Error(`Invalid color is delivered!`); - const l = color.includes("a"); - return match[0] - .slice(l ? 5 : 4, -1) - .split(",") - .map((v, i) => { - const vv = v.trim(); - if (vv.endsWith("%")) { - if (i === 3) { - return parseInt(vv) / 100; - } else { - return (parseInt(vv) * 255) / 100; - } - } else return parseFloat(vv); - }) - .slice(0, l ? 4 : 3); - } else if (color.startsWith("#")) { - // 十六进制 - const content = color.slice(1); - if (![3, 4, 6, 8].includes(content.length)) { - throw new Error(`Invalid color is delivered!`); - } + /** + * hsl转rgb + * @param h 色相 + * @param s 饱和度 + * @param l 亮度 + */ + function hslToRgb(h, s, l) { + if (s == 0) { + return [0, 0, 0]; + } else { + const hue2rgb = (p, q, t) => { + if (t < 0) t += 1; + if (t > 1) t -= 1; + if (t < 1 / 6) return p + (q - p) * 6 * t; + if (t < 1 / 2) return q; + if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; + return p; + }; - if (content.length <= 4) { - const res = content.split("").map((v) => Number(`0x${v}${v}`)); - if (res.length === 4) res[3] /= 255; - return res; - } else { - const res = Array(content.length / 2) - .fill(1) - .map((v, i) => Number(`0x${content[i * 2]}${content[i * 2 + 1]}`)); - if (res.length === 4) res[3] /= 255; - return res; - } - } else if (color.startsWith("hsl")) { - // hsl,转成rgb后输出 - const match = color.match(/hsla?\([\d\,\s\.%]+\)/); - if (!has(match)) throw new Error(`Invalid color is delivered!`); - const l = color.includes("a"); - const hsl = match[0] - .slice(l ? 5 : 4, -1) - .split(",") - .map((v) => { - const vv = v.trim(); - if (vv.endsWith("%")) return parseInt(vv) / 100; - else return parseFloat(vv); - }); - const rgb = hslToRgb(hsl[0], hsl[1], hsl[2]); - return l ? rgb.concat([hsl[3]]) : rgb; - } else { - // 单词 - const rgb = cssColors[color]; - if (!has(rgb)) { - throw new Error(`Invalid color is delivered!`); - } - return parseColor(rgb); - } - } + const q = l < 0.5 ? l * (1 + s) : l + s - l * s; + const p = 2 * l - q; + const r = hue2rgb(p, q, h + 1 / 3); + const g = hue2rgb(p, q, h); + const b = hue2rgb(p, q, h - 1 / 3); + return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; + } + } - /** - * hsl转rgb - * @param h 色相 - * @param s 饱和度 - * @param l 亮度 - */ - function hslToRgb(h, s, l) { - if (s == 0) { - return [0, 0, 0]; - } else { - const hue2rgb = (p, q, t) => { - if (t < 0) t += 1; - if (t > 1) t -= 1; - if (t < 1 / 6) return p + (q - p) * 6 * t; - if (t < 1 / 2) return q; - if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; - return p; - }; + /** + * 确保一个变量是一个数组,不是的话转为数组并返回,是的话直接返回传入的数组 + * @param arr 要判断的变量 + * @example ensureArray(1); // [1] + * @example ensureArray([1, 2]); // [1, 2] + * @example ensureArray('test'); // ['test'] + */ + function ensureArray(arr) { + // @ts-ignore + return arr instanceof Array ? arr : [arr]; + } - const q = l < 0.5 ? l * (1 + s) : l + s - l * s; - const p = 2 * l - q; - const r = hue2rgb(p, q, h + 1 / 3); - const g = hue2rgb(p, q, h); - const b = hue2rgb(p, q, h - 1 / 3); - return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; - } - } + /** + * 返回一个坐标在某个方向上移动 d 格后的坐标 + * @param d 移动多少格,默认为1 + * @example ofDir(7, 7, 'left'); // [6, 7] + * @example ofDir(10, 8, 'leftup', 5); // [5, 3] + */ + function ofDir(x, y, dir, d = 1) { + const { x: dx, y: dy } = core.utils.scan2[dir]; + return [x + dx * d, y + dy * d]; + } - /** - * 确保一个变量是一个数组,不是的话转为数组并返回,是的话直接返回传入的数组 - * @param arr 要判断的变量 - * @example ensureArray(1); // [1] - * @example ensureArray([1, 2]); // [1, 2] - * @example ensureArray('test'); // ['test'] - */ - function ensureArray(arr) { - // @ts-ignore - return arr instanceof Array ? arr : [arr]; - } + const cssColors = { + black: "#000000", + silver: "#c0c0c0", + gray: "#808080", + white: "#ffffff", + maroon: "#800000", + red: "#ff0000", + purple: "#800080", + fuchsia: "#ff00ff", + green: "#008000", + lime: "#00ff00", + olive: "#808000", + yellow: "#ffff00", + navy: "#000080", + blue: "#0000ff", + teal: "#008080", + aqua: "#00ffff", + orange: "#ffa500", + aliceblue: "#f0f8ff", + antiquewhite: "#faebd7", + aquamarine: "#7fffd4", + azure: "#f0ffff", + beige: "#f5f5dc", + bisque: "#ffe4c4", + blanchedalmond: "#ffebcd", + blueviolet: "#8a2be2", + brown: "#a52a2a", + burlywood: "#deb887", + cadetblue: "#5f9ea0", + chartreuse: "#7fff00", + chocolate: "#d2691e", + coral: "#ff7f50", + cornflowerblue: "#6495ed", + cornsilk: "#fff8dc", + crimson: "#dc143c", + cyan: "#00ffff", + darkblue: "#00008b", + darkcyan: "#008b8b", + darkgoldenrod: "#b8860b", + darkgray: "#a9a9a9", + darkgreen: "#006400", + darkgrey: "#a9a9a9", + darkkhaki: "#bdb76b", + darkmagenta: "#8b008b", + darkolivegreen: "#556b2f", + darkorange: "#ff8c00", + darkorchid: "#9932cc", + darkred: "#8b0000", + darksalmon: "#e9967a", + darkseagreen: "#8fbc8f", + darkslateblue: "#483d8b", + darkslategray: "#2f4f4f", + darkslategrey: "#2f4f4f", + darkturquoise: "#00ced1", + darkviolet: "#9400d3", + deeppink: "#ff1493", + deepskyblue: "#00bfff", + dimgray: "#696969", + dimgrey: "#696969", + dodgerblue: "#1e90ff", + firebrick: "#b22222", + floralwhite: "#fffaf0", + forestgreen: "#228b22", + gainsboro: "#dcdcdc", + ghostwhite: "#f8f8ff", + gold: "#ffd700", + goldenrod: "#daa520", + greenyellow: "#adff2f", + grey: "#808080", + honeydew: "#f0fff0", + hotpink: "#ff69b4", + indianred: "#cd5c5c", + indigo: "#4b0082", + ivory: "#fffff0", + khaki: "#f0e68c", + lavender: "#e6e6fa", + lavenderblush: "#fff0f5", + lawngreen: "#7cfc00", + lemonchiffon: "#fffacd", + lightblue: "#add8e6", + lightcoral: "#f08080", + lightcyan: "#e0ffff", + lightgoldenrodyellow: "#fafad2", + lightgray: "#d3d3d3", + lightgreen: "#90ee90", + lightgrey: "#d3d3d3", + lightpink: "#ffb6c1", + lightsalmon: "#ffa07a", + lightseagreen: "#20b2aa", + lightskyblue: "#87cefa", + lightslategray: "#778899", + lightslategrey: "#778899", + lightsteelblue: "#b0c4de", + lightyellow: "#ffffe0", + limegreen: "#32cd32", + linen: "#faf0e6", + magenta: "#ff00ff", + mediumaquamarine: "#66cdaa", + mediumblue: "#0000cd", + mediumorchid: "#ba55d3", + mediumpurple: "#9370db", + mediumseagreen: "#3cb371", + mediumslateblue: "#7b68ee", + mediumspringgreen: "#00fa9a", + mediumturquoise: "#48d1cc", + mediumvioletred: "#c71585", + midnightblue: "#191970", + mintcream: "#f5fffa", + mistyrose: "#ffe4e1", + moccasin: "#ffe4b5", + navajowhite: "#ffdead", + oldlace: "#fdf5e6", + olivedrab: "#6b8e23", + orangered: "#ff4500", + orchid: "#da70d6", + palegoldenrod: "#eee8aa", + palegreen: "#98fb98", + paleturquoise: "#afeeee", + palevioletred: "#db7093", + papayawhip: "#ffefd5", + peachpuff: "#ffdab9", + peru: "#cd853f", + pink: "#ffc0cb", + plum: "#dda0dd", + powderblue: "#b0e0e6", + rosybrown: "#bc8f8f", + royalblue: "#4169e1", + saddlebrown: "#8b4513", + salmon: "#fa8072", + sandybrown: "#f4a460", + seagreen: "#2e8b57", + seashell: "#fff5ee", + sienna: "#a0522d", + skyblue: "#87ceeb", + slateblue: "#6a5acd", + slategray: "#708090", + slategrey: "#708090", + snow: "#fffafa", + springgreen: "#00ff7f", + steelblue: "#4682b4", + tan: "#d2b48c", + thistle: "#d8bfd8", + tomato: "#ff6347", + turquoise: "#40e0d0", + violet: "#ee82ee", + wheat: "#f5deb3", + whitesmoke: "#f5f5f5", + yellowgreen: "#9acd32", + transparent: "#0000", + }; + // 计算两个数的最大公约数 + function gcdOfTwo(a, b) { + while (b !== 0) { + let temp = b; + b = a % b; + a = temp; + } + return a; + } - /** - * 返回一个坐标在某个方向上移动 d 格后的坐标 - * @param d 移动多少格,默认为1 - * @example ofDir(7, 7, 'left'); // [6, 7] - * @example ofDir(10, 8, 'leftup', 5); // [5, 3] - */ - function ofDir(x, y, dir, d = 1) { - const { x: dx, y: dy } = core.utils.scan2[dir]; - return [x + dx * d, y + dy * d]; - } + // 计算任意项整数的最大公约数 + function gcd(...numbers) { + if (numbers.length < 2) { + throw new Error("至少需要两个数"); + } + return numbers.reduce((a, b) => gcdOfTwo(a, b)); + } + // 计算两个数的最小公倍数 + function lcmOfTwo(a, b) { + return (a * b) / gcdOfTwo(a, b); + } - const cssColors = { - black: "#000000", - silver: "#c0c0c0", - gray: "#808080", - white: "#ffffff", - maroon: "#800000", - red: "#ff0000", - purple: "#800080", - fuchsia: "#ff00ff", - green: "#008000", - lime: "#00ff00", - olive: "#808000", - yellow: "#ffff00", - navy: "#000080", - blue: "#0000ff", - teal: "#008080", - aqua: "#00ffff", - orange: "#ffa500", - aliceblue: "#f0f8ff", - antiquewhite: "#faebd7", - aquamarine: "#7fffd4", - azure: "#f0ffff", - beige: "#f5f5dc", - bisque: "#ffe4c4", - blanchedalmond: "#ffebcd", - blueviolet: "#8a2be2", - brown: "#a52a2a", - burlywood: "#deb887", - cadetblue: "#5f9ea0", - chartreuse: "#7fff00", - chocolate: "#d2691e", - coral: "#ff7f50", - cornflowerblue: "#6495ed", - cornsilk: "#fff8dc", - crimson: "#dc143c", - cyan: "#00ffff", - darkblue: "#00008b", - darkcyan: "#008b8b", - darkgoldenrod: "#b8860b", - darkgray: "#a9a9a9", - darkgreen: "#006400", - darkgrey: "#a9a9a9", - darkkhaki: "#bdb76b", - darkmagenta: "#8b008b", - darkolivegreen: "#556b2f", - darkorange: "#ff8c00", - darkorchid: "#9932cc", - darkred: "#8b0000", - darksalmon: "#e9967a", - darkseagreen: "#8fbc8f", - darkslateblue: "#483d8b", - darkslategray: "#2f4f4f", - darkslategrey: "#2f4f4f", - darkturquoise: "#00ced1", - darkviolet: "#9400d3", - deeppink: "#ff1493", - deepskyblue: "#00bfff", - dimgray: "#696969", - dimgrey: "#696969", - dodgerblue: "#1e90ff", - firebrick: "#b22222", - floralwhite: "#fffaf0", - forestgreen: "#228b22", - gainsboro: "#dcdcdc", - ghostwhite: "#f8f8ff", - gold: "#ffd700", - goldenrod: "#daa520", - greenyellow: "#adff2f", - grey: "#808080", - honeydew: "#f0fff0", - hotpink: "#ff69b4", - indianred: "#cd5c5c", - indigo: "#4b0082", - ivory: "#fffff0", - khaki: "#f0e68c", - lavender: "#e6e6fa", - lavenderblush: "#fff0f5", - lawngreen: "#7cfc00", - lemonchiffon: "#fffacd", - lightblue: "#add8e6", - lightcoral: "#f08080", - lightcyan: "#e0ffff", - lightgoldenrodyellow: "#fafad2", - lightgray: "#d3d3d3", - lightgreen: "#90ee90", - lightgrey: "#d3d3d3", - lightpink: "#ffb6c1", - lightsalmon: "#ffa07a", - lightseagreen: "#20b2aa", - lightskyblue: "#87cefa", - lightslategray: "#778899", - lightslategrey: "#778899", - lightsteelblue: "#b0c4de", - lightyellow: "#ffffe0", - limegreen: "#32cd32", - linen: "#faf0e6", - magenta: "#ff00ff", - mediumaquamarine: "#66cdaa", - mediumblue: "#0000cd", - mediumorchid: "#ba55d3", - mediumpurple: "#9370db", - mediumseagreen: "#3cb371", - mediumslateblue: "#7b68ee", - mediumspringgreen: "#00fa9a", - mediumturquoise: "#48d1cc", - mediumvioletred: "#c71585", - midnightblue: "#191970", - mintcream: "#f5fffa", - mistyrose: "#ffe4e1", - moccasin: "#ffe4b5", - navajowhite: "#ffdead", - oldlace: "#fdf5e6", - olivedrab: "#6b8e23", - orangered: "#ff4500", - orchid: "#da70d6", - palegoldenrod: "#eee8aa", - palegreen: "#98fb98", - paleturquoise: "#afeeee", - palevioletred: "#db7093", - papayawhip: "#ffefd5", - peachpuff: "#ffdab9", - peru: "#cd853f", - pink: "#ffc0cb", - plum: "#dda0dd", - powderblue: "#b0e0e6", - rosybrown: "#bc8f8f", - royalblue: "#4169e1", - saddlebrown: "#8b4513", - salmon: "#fa8072", - sandybrown: "#f4a460", - seagreen: "#2e8b57", - seashell: "#fff5ee", - sienna: "#a0522d", - skyblue: "#87ceeb", - slateblue: "#6a5acd", - slategray: "#708090", - slategrey: "#708090", - snow: "#fffafa", - springgreen: "#00ff7f", - steelblue: "#4682b4", - tan: "#d2b48c", - thistle: "#d8bfd8", - tomato: "#ff6347", - turquoise: "#40e0d0", - violet: "#ee82ee", - wheat: "#f5deb3", - whitesmoke: "#f5f5f5", - yellowgreen: "#9acd32", - transparent: "#0000", - }; - // 计算两个数的最大公约数 - function gcdOfTwo(a, b) { - while (b !== 0) { - let temp = b; - b = a % b; - a = temp; - } - return a; - } + // 计算任意项整数的最小公倍数 + function lcm(...numbers) { + if (numbers.length < 2) { + throw new Error("至少需要两个数"); + } + return numbers.reduce((a, b) => lcmOfTwo(a, b)); + } - // 计算任意项整数的最大公约数 - function gcd(...numbers) { - if (numbers.length < 2) { - throw new Error("至少需要两个数"); - } - return numbers.reduce((a, b) => gcdOfTwo(a, b)); - } - // 计算两个数的最小公倍数 - function lcmOfTwo(a, b) { - return (a * b) / gcdOfTwo(a, b); - } + if (has(core.plugin.utils)) { + throw new ReferenceError( + `core.plugin上已经有'utils'属性,因此功能函数插件将无法使用!` + ); + } + core.plugin.utils = { + imagelighter, + gcdOfTwo, + lcmOfTwo, + gcd, + lcm, + has, + slide, + backDir, + parseCss, + sleep, + nextFrame, + parseColor, + hslToRgb, + ensureArray, + ofDir, + }; + // Utility.js + // 通用函數插件 + // 本插件與古祠發佈的《功能插件 --- 实用功能函数集》不同,函數是定義在全域的。 + // 自訂常見事件模板插件(editorBlocklyconfigPlus.js)的前置插件 - // 计算任意项整数的最小公倍数 - function lcm(...numbers) { - if (numbers.length < 2) { - throw new Error("至少需要两个数"); - } - return numbers.reduce((a, b) => lcmOfTwo(a, b)); - } + /** + * 使js暫停指定時間 + * async環境下await Sleep(500) + * @param {number} millisecond 暫停毫秒數 + */ + self.Sleep = async function (millisecond) { + return new Promise((resolve) => setTimeout(resolve, millisecond)); + }; - if (has(core.plugin.utils)) { - throw new ReferenceError( - `core.plugin上已经有'utils'属性,因此功能函数插件将无法使用!` - ); - } - core.plugin.utils = { - imagelighter, - gcdOfTwo, - lcmOfTwo, - gcd, - lcm, - has, - slide, - backDir, - parseCss, - sleep, - nextFrame, - parseColor, - hslToRgb, - ensureArray, - ofDir, - }; - // Utility.js - // 通用函數插件 - // 本插件與古祠發佈的《功能插件 --- 实用功能函数集》不同,函數是定義在全域的。 - // 自訂常見事件模板插件(editorBlocklyconfigPlus.js)的前置插件 + /** + * 使js暫停一幀 + * async環境下await SleepFrame() + */ + self.SleepFrame = async function () { + return new Promise((resolve) => requestAnimationFrame(resolve)); + }; - /** - * 使js暫停指定時間 - * async環境下await Sleep(500) - * @param {number} millisecond 暫停毫秒數 - */ - self.Sleep = async function (millisecond) { - return new Promise((resolve) => setTimeout(resolve, millisecond)); - }; + /** + * editor_file的isset函數 + */ + self.isset = function (val) { + if (val == undefined || val == null) { + return false; + } + return true; + }; - /** - * 使js暫停一幀 - * async環境下await SleepFrame() - */ - self.SleepFrame = async function () { - return new Promise((resolve) => requestAnimationFrame(resolve)); - }; - - /** - * editor_file的isset函數 - */ - self.isset = function (val) { - if (val == undefined || val == null) { - return false; - } - return true; - }; - - /** - * editor_file的checkCallback函數 - */ - self.checkCallback = function (callback) { - if (!isset(callback)) { - printe("未设置callback"); - throw "未设置callback"; - } - }; -}, + /** + * editor_file的checkCallback函數 + */ + self.checkCallback = function (callback) { + if (!isset(callback)) { + printe("未设置callback"); + throw "未设置callback"; + } + }; + }, "音频系统": function () { - // 在此增加新插件 - /*首先,在造塔群下载所需的库文件,然后放置在塔目录下的 libs/thirdparty 或其他目录下,之后在 index.html 的最后加上下面这几行: + // 在此增加新插件 + /*首先,在造塔群下载所需的库文件,然后放置在塔目录下的 libs/thirdparty 或其他目录下,之后在 index.html 的最后加上下面这几行: @@ -9077,2097 +9485,2099 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = */ - // 将__enable置为false将关闭插件 - let __enable = true; - if (!__enable || main.mode === "editor") return; - const { OggOpusDecoderWebWorker } = window["ogg-opus-decoder"]; - const { OggVorbisDecoderWebWorker } = window["ogg-vorbis-decoder"]; - const { CodecParser } = window.CodecParser; - const { Transition, linear } = core.plugin.animate; - - const audio = new Audio(); - const AudioStatus = { - Playing: 0, - Pausing: 1, - Paused: 2, - Stoping: 3, - Stoped: 4, - }; - const supportMap = new Map(); - const AudioType = { - Mp3: "audio/mpeg", - Wav: 'audio/wav; codecs="1"', - Flac: "audio/flac", - Opus: 'audio/ogg; codecs="opus"', - Ogg: 'audio/ogg; codecs="vorbis"', - Aac: "audio/aac", - }; - /** - * 检查一种音频类型是否能被播放 - * @param type 音频类型 AudioType - */ - function isAudioSupport(type) { - if (supportMap.has(type)) return supportMap.get(type); - else { - const support = audio.canPlayType(type); - const canPlay = support === "maybe" || support === "probably"; - supportMap.set(type, canPlay); - return canPlay; - } - } - - const typeMap = new Map([ - ["ogg", AudioType.Ogg], - ["mp3", AudioType.Mp3], - ["wav", AudioType.Wav], - ["flac", AudioType.Flac], - ["opus", AudioType.Opus], - ["aac", AudioType.Aac], - ]); - - /** - * 根据文件名拓展猜测其类型 - * @param file 文件名 string - */ - function guessTypeByExt(file) { - const ext = /\.[a-zA-Z\d]+$/.exec(file); - if (!ext?.[0]) return ""; - const type = ext[0].slice(1); - return typeMap.get(type.toLocaleLowerCase()) ?? ""; - } - - isAudioSupport(AudioType.Ogg); - isAudioSupport(AudioType.Mp3); - isAudioSupport(AudioType.Wav); - isAudioSupport(AudioType.Flac); - isAudioSupport(AudioType.Opus); - isAudioSupport(AudioType.Aac); - - function isNil(value) { - return value === void 0 || value === null; - } - - function sleep(time) { - return new Promise((res) => setTimeout(res, time)); - } - class AudioEffect { - constructor(ac) {} - /** - * 连接至其他效果器 - * @param target 目标输入 IAudioInput - * @param output 当前效果器输出通道 Number - * @param input 目标效果器的输入通道 Number - */ - connect(target, output, input) { - this.output.connect(target.input, output, input); - } - - /** - * 与其他效果器取消连接 - * @param target 目标输入 IAudioInput - * @param output 当前效果器输出通道 Number - * @param input 目标效果器的输入通道 Number - */ - disconnect(target, output, input) { - if (!target) { - if (!isNil(output)) { - this.output.disconnect(output); - } else { - this.output.disconnect(); - } - } else { - if (!isNil(output)) { - if (!isNil(input)) { - this.output.disconnect(target.input, output, input); - } else { - this.output.disconnect(target.input, output); - } - } else { - this.output.disconnect(target.input); - } - } - } - } - - class StereoEffect extends AudioEffect { - constructor(ac) { - super(ac); - const panner = ac.createPanner(); - this.input = panner; - this.output = panner; - } - - /** - * 设置音频朝向,x正方形水平向右,y正方形垂直于地面向上,z正方向垂直屏幕远离用户 - * @param x 朝向x坐标 Number - * @param y 朝向y坐标 Number - * @param z 朝向z坐标 Number - */ - setOrientation(x, y, z) { - this.output.orientationX.value = x; - this.output.orientationY.value = y; - this.output.orientationZ.value = z; - } - /** - * 设置音频位置,x正方形水平向右,y正方形垂直于地面向上,z正方向垂直屏幕远离用户 - * @param x 位置x坐标 Number - * @param y 位置y坐标 Number - * @param z 位置z坐标 Number - */ - setPosition(x, y, z) { - this.output.positionX.value = x; - this.output.positionY.value = y; - this.output.positionZ.value = z; - } - end() {} - - start() {} - } - class VolumeEffect extends AudioEffect { - constructor(ac) { - super(ac); - const gain = ac.createGain(); - this.input = gain; - this.output = gain; - } - - /** - * 设置音量大小 - * @param volume 音量大小 Number - */ - setVolume(volume) { - this.output.gain.value = volume; - } - - /** - * 获取音量大小 Number - */ - getVolume() { - return this.output.gain.value; - } - - end() {} - - start() {} - } - class ChannelVolumeEffect extends AudioEffect { - /** 所有的音量控制节点 */ - - constructor(ac) { - super(ac); - /** 所有的音量控制节点 */ - this.gain = []; - const splitter = ac.createChannelSplitter(); - const merger = ac.createChannelMerger(); - this.output = merger; - this.input = splitter; - for (let i = 0; i < 6; i++) { - const gain = ac.createGain(); - splitter.connect(gain, i); - gain.connect(merger, 0, i); - this.gain.push(gain); - } - } - - /** - * 设置某个声道的音量大小 - * @param channel 要设置的声道,可填0-5 Number - * @param volume 这个声道的音量大小 Number - */ - setVolume(channel, volume) { - if (!this.gain[channel]) return; - this.gain[channel].gain.value = volume; - } - - /** - * 获取某个声道的音量大小,可填0-5 - * @param channel 要获取的声道 Number - */ - getVolume(channel) { - if (!this.gain[channel]) return 0; - return this.gain[channel].gain.value; - } - - end() {} - - start() {} - } - class DelayEffect extends AudioEffect { - constructor(ac) { - super(ac); - - const delay = ac.createDelay(); - this.input = delay; - this.output = delay; - } - - /** - * 设置延迟时长 - * @param delay 延迟时长,单位秒 Number - */ - setDelay(delay) { - this.output.delayTime.value = delay; - } - - /** - * 获取延迟时长 - */ - getDelay() { - return this.output.delayTime.value; - } - - end() {} - - start() {} - } - class EchoEffect extends AudioEffect { - constructor(ac) { - super(ac); - /** 当前增益 */ - this.gain = 0.5; - /** 是否正在播放 */ - this.playing = false; - const delay = ac.createDelay(); - const gain = ac.createGain(); - gain.gain.value = 0.5; - delay.delayTime.value = 0.05; - delay.connect(gain); - gain.connect(delay); - /** 延迟节点 */ - this.delay = delay; - /** 反馈增益节点 */ - this.gainNode = gain; - - this.input = gain; - this.output = gain; - } - - /** - * 设置回声反馈增益大小 - * @param gain 增益大小,范围 0-1,大于等于1的视为0.5,小于0的视为0 Number - */ - setFeedbackGain(gain) { - const resolved = gain >= 1 ? 0.5 : gain < 0 ? 0 : gain; - this.gain = resolved; - if (this.playing) this.gainNode.gain.value = resolved; - } - - /** - * 设置回声间隔时长 - * @param delay 回声时长,范围 0.01-Infinity,小于0.01的视为0.01 Number - */ - setEchoDelay(delay) { - const resolved = delay < 0.01 ? 0.01 : delay; - this.delay.delayTime.value = resolved; - } - - /** - * 获取反馈节点增益 - */ - getFeedbackGain() { - return this.gain; - } - - /** - * 获取回声间隔时长 - */ - getEchoDelay() { - return this.delay.delayTime.value; - } - - end() { - this.playing = false; - const echoTime = Math.ceil(Math.log(0.001) / Math.log(this.gain)) + 10; - sleep(this.delay.delayTime.value * echoTime).then(() => { - if (!this.playing) this.gainNode.gain.value = 0; - }); - } - - start() { - this.playing = true; - this.gainNode.gain.value = this.gain; - } - } - - class StreamLoader { - constructor(url) { - /** 传输目标 Set*/ - this.target = new Set(); - this.loading = false; - } - - /** - * 将加载流传递给字节流读取对象 - * @param reader 字节流读取对象 IStreamReader - */ - pipe(reader) { - if (this.loading) { - console.warn( - "Cannot pipe new StreamReader object when stream is loading." - ); - return; - } - this.target.add(reader); - reader.piped(this); - return this; - } - - async start() { - if (this.loading) return; - this.loading = true; - const response = await window.fetch(this.url); - const stream = response.body; - if (!stream) { - console.error("Cannot get reader when fetching '" + this.url + "'."); - return; - } - // 获取读取器 - this.stream = stream; - const reader = response.body?.getReader(); - const targets = [...this.target]; - - await Promise.all(targets.map((v) => v.start(stream, this, response))); - if (reader && reader.read) { - // 开始流传输 - while (true) { - const { value, done } = await reader.read(); - await Promise.all( - targets.map((v) => v.pump(value, done, response)) - ); - if (done) break; - } - } else { - // 如果不支持流传输 - const buffer = await response.arrayBuffer(); - const data = new Uint8Array(buffer); - await Promise.all(targets.map((v) => v.pump(data, true, response))); - } - - this.loading = false; - targets.forEach((v) => v.end(true)); - - // - } - - cancel(reason) { - if (!this.stream) return; - this.stream.cancel(reason); - this.loading = false; - this.target.forEach((v) => v.end(false, reason)); - } - } - const fileSignatures = [ - [AudioType.Mp3, [0x49, 0x44, 0x33]], - [AudioType.Ogg, [0x4f, 0x67, 0x67, 0x53]], - [AudioType.Wav, [0x52, 0x49, 0x46, 0x46]], - [AudioType.Flac, [0x66, 0x4c, 0x61, 0x43]], - [AudioType.Aac, [0xff, 0xf1]], - [AudioType.Aac, [0xff, 0xf9]], - ]; - const oggHeaders = [ - [AudioType.Opus, [0x4f, 0x70, 0x75, 0x73, 0x48, 0x65, 0x61, 0x64]], - ]; - - function checkAudioType(data) { - let audioType = ""; - // 检查头文件获取音频类型,仅检查前256个字节 - const toCheck = data.slice(0, 256); - for (const [type, value] of fileSignatures) { - if (value.every((v, i) => toCheck[i] === v)) { - audioType = type; - break; - } - } - if (audioType === AudioType.Ogg) { - // 如果是ogg的话,进一步判断是不是opus - for (const [key, value] of oggHeaders) { - const has = toCheck.some((_, i) => { - return value.every((v, ii) => toCheck[i + ii] === v); - }); - if (has) { - audioType = key; - break; - } - } - } - - return audioType; - } - class AudioDecoder { - /** - * 注册一个解码器 - * @param type 要注册的解码器允许解码的类型 - * @param decoder 解码器对象 - */ - static registerDecoder(type, decoder) { - if (!this.decoderMap) this.decoderMap = new Map(); - if (this.decoderMap.has(type)) { - console.warn( - "Audio stream decoder for audio type '" + - type + - "' has already existed." - ); - return; - } - - this.decoderMap.set(type, decoder); - } - - /** - * 解码音频数据 - * @param data 音频文件数据 - * @param player AudioPlayer实例 - */ - static async decodeAudioData(data, player) { - // 检查头文件获取音频类型,仅检查前256个字节 - const toCheck = data.slice(0, 256); - const type = checkAudioType(data); - if (type === "") { - console.error( - "Unknown audio type. Header: '" + [...toCheck] - .map((v) => v.toString().padStart(2, "0")) - .join(" ") - .toUpperCase() + - "'" - ); - return null; - } - if (isAudioSupport(type)) { - if (data.buffer instanceof ArrayBuffer) { - return player.ac.decodeAudioData(data.buffer); - } else { - return null; - } - } else { - const Decoder = this.decoderMap.get(type); - if (!Decoder) { - return null; - } else { - const decoder = new Decoder(); - await decoder.create(); - const decodedData = await decoder.decode(data); - if (!decodedData) return null; - const buffer = player.ac.createBuffer( - decodedData.channelData.length, - decodedData.channelData[0].length, - decodedData.sampleRate - ); - decodedData.channelData.forEach((v, i) => { - buffer.copyToChannel(v, i); - }); - decoder.destroy(); - return buffer; - } - } - } - } - - class VorbisDecoder { - /** - * 创建音频解码器 - */ - async create() { - this.decoder = new OggVorbisDecoderWebWorker(); - await this.decoder.ready; - } - /** - * 摧毁这个解码器 - */ - destroy() { - this.decoder?.free(); - } - /** - * 解码流数据 - * @param data 流数据 - */ - - async decode(data) { - return this.decoder?.decode(data); - } - /** - * 解码整个文件 - * @param data 文件数据 - */ - async decodeAll(data) { - return this.decoder?.decodeFile(data); - } - /** - * 当音频解码完成后,会调用此函数,需要返回之前还未解析或未返回的音频数据。调用后,该解码器将不会被再次使用 - */ - async flush() { - return this.decoder?.flush(); - } - } - - class OpusDecoder { - /** - * 创建音频解码器 - */ - async create() { - this.decoder = new OggOpusDecoderWebWorker(); - await this.decoder.ready; - } - /** - * 摧毁这个解码器 - */ - destroy() { - this.decoder?.free(); - } - /** - * 解码流数据 - * @param data 流数据 - */ - async decode(data) { - return this.decoder?.decode(data); - } - /** - * 解码整个文件 - * @param data 文件数据 - */ - async decodeAll(data) { - return this.decoder?.decodeFile(data); - } - /** - * 当音频解码完成后,会调用此函数,需要返回之前还未解析或未返回的音频数据。调用后,该解码器将不会被再次使用 - */ - async flush() { - return await this.decoder?.flush(); - } - } - const mimeTypeMap = { - [AudioType.Aac]: "audio/aac", - [AudioType.Flac]: "audio/flac", - [AudioType.Mp3]: "audio/mpeg", - [AudioType.Ogg]: "application/ogg", - [AudioType.Opus]: "application/ogg", - [AudioType.Wav]: "application/ogg", - }; - - function isOggPage(data) { - return !isNil(data.isFirstPage); - } - class AudioStreamSource { - constructor(context) { - this.output = context.createBufferSource(); - /** 是否已经完全加载完毕 */ - this.loaded = false; - /** 是否正在播放 */ - this.playing = false; - /** 已经缓冲了多长时间,如果缓冲完那么跟歌曲时长一致 */ - this.buffered = 0; - /** 已经缓冲的采样点数量 */ - this.bufferedSamples = 0; - /** 歌曲时长,加载完毕之前保持为 0 */ - this.duration = 0; - /** 在流传输阶段,至少缓冲多长时间的音频之后才开始播放,单位秒 */ - this.bufferPlayDuration = 1; - /** 音频的采样率,未成功解析出之前保持为 0 */ - this.sampleRate = 0; - //是否循环播放 - this.loop = false; - /** 上一次播放是从何时开始的 */ - this.lastStartWhen = 0; - /** 开始播放时刻 */ - this.lastStartTime = 0; - /** 上一次播放的缓存长度 */ - this.lastBufferSamples = 0; - - /** 是否已经获取到头文件 */ - this.headerRecieved = false; - /** 音频类型 */ - this.audioType = ""; - /** 每多长时间组成一个缓存 Float32Array */ - this.bufferChunkSize = 10; - /** 缓存音频数据,每 bufferChunkSize 秒钟组成一个 Float32Array,用于流式解码 */ - this.audioData = []; - - this.errored = false; - this.ac = context; - } - /** 当前已经播放了多长时间 */ - get currentTime() { - return this.ac.currentTime - this.lastStartTime + this.lastStartWhen; - } - /** - * 设置每个缓存数据的大小,默认为10秒钟一个缓存数据 - * @param size 每个缓存数据的时长,单位秒 - */ - setChunkSize(size) { - if (this.controller?.loading || this.loaded) return; - this.bufferChunkSize = size; - } - - piped(controller) { - this.controller = controller; - } - - async pump(data, done) { - if (!data || this.errored) return; - if (!this.headerRecieved) { - // 检查头文件获取音频类型,仅检查前256个字节 - const toCheck = data.slice(0, 256); - this.audioType = checkAudioType(data); - if (!this.audioType) { - console.error( - "Unknown audio type. Header: '" + [...toCheck] - .map((v) => v.toString(16).padStart(2, "0")) - .join(" ") - .toUpperCase() + - "'" - ); - return; - } - // 创建解码器 - const Decoder = AudioDecoder.decoderMap.get(this.audioType); - if (!Decoder) { - this.errored = true; - console.error( - "Cannot decode stream source type of '" + - this.audioType + - "', since there is no registered decoder for that type." - ); - return Promise.reject( - `Cannot decode stream source type of '${this.audioType}', since there is no registered decoder for that type.` - ); - } - this.decoder = new Decoder(); - // 创建数据解析器 - const mime = mimeTypeMap[this.audioType]; - const parser = new CodecParser(mime); - this.parser = parser; - await this.decoder.create(); - this.headerRecieved = true; - } - - const decoder = this.decoder; - const parser = this.parser; - if (!decoder || !parser) { - this.errored = true; - return Promise.reject( - "No parser or decoder attached in this AudioStreamSource" - ); - } - - await this.decodeData(data, decoder, parser); - if (done) await this.decodeFlushData(decoder, parser); - this.checkBufferedPlay(); - } - - /** - * 检查采样率,如果还未解析出采样率,那么将设置采样率,如果当前采样率与之前不同,那么发出警告 - */ - checkSampleRate(info) { - for (const one of info) { - const frame = isOggPage(one) ? one.codecFrames[0] : one; - if (frame) { - const rate = frame.header.sampleRate; - if (this.sampleRate === 0) { - this.sampleRate = rate; - break; - } else { - if (rate !== this.sampleRate) { - console.warn("Sample rate in stream audio must be constant."); - } - } - } - } - } - - /** - * 解析音频数据 - */ - async decodeData(data, decoder, parser) { - // 解析音频数据 - const audioData = await decoder.decode(data); - if (!audioData) return; - // @ts-expect-error 库类型声明错误 - const audioInfo = [...parser.parseChunk(data)]; - - // 检查采样率 - this.checkSampleRate(audioInfo); - // 追加音频数据 - this.appendDecodedData(audioData, audioInfo); - } - - /** - * 解码剩余数据 - */ - async decodeFlushData(decoder, parser) { - const audioData = await decoder.flush(); - if (!audioData) return; - // @ts-expect-error 库类型声明错误 - const audioInfo = [...parser.flush()]; - - this.checkSampleRate(audioInfo); - this.appendDecodedData(audioData, audioInfo); - } - - /** - * 追加音频数据 - */ - appendDecodedData(data, info) { - const channels = data.channelData.length; - if (channels === 0) return; - if (this.audioData.length !== channels) { - this.audioData = []; - for (let i = 0; i < channels; i++) { - this.audioData.push([]); - } - } - // 计算出应该放在哪 - const chunk = this.sampleRate * this.bufferChunkSize; - const sampled = this.bufferedSamples; - const pushIndex = Math.floor(sampled / chunk); - const bufferIndex = sampled % chunk; - const dataLength = data.channelData[0].length; - let buffered = 0; - let nowIndex = pushIndex; - let toBuffer = bufferIndex; - while (buffered < dataLength) { - const rest = toBuffer !== 0 ? chunk - bufferIndex : chunk; - - for (let i = 0; i < channels; i++) { - const audioData = this.audioData[i]; - if (!audioData[nowIndex]) { - audioData.push(new Float32Array(chunk)); - } - const toPush = data.channelData[i].slice(buffered, buffered + rest); - - audioData[nowIndex].set(toPush, toBuffer); - } - buffered += rest; - nowIndex++; - toBuffer = 0; - } - - this.buffered += - info.reduce((prev, curr) => prev + curr.duration, 0) / 1000; - this.bufferedSamples += info.reduce( - (prev, curr) => prev + curr.samples, - 0 - ); - } - - /** - * 检查已缓冲内容,并在未开始播放时播放 - */ - checkBufferedPlay() { - if (this.playing || this.sampleRate === 0) return; - const played = this.lastBufferSamples / this.sampleRate; - const dt = this.buffered - played; - if (this.loaded) { - this.playAudio(played); - return; - } - if (dt < this.bufferPlayDuration) return; - - this.lastBufferSamples = this.bufferedSamples; - // 需要播放 - this.mergeBuffers(); - if (!this.buffer) return; - if (this.playing) this.output.stop(); - this.createSourceNode(this.buffer); - this.output.loop = false; - this.output.start(0, played); - this.lastStartTime = this.ac.currentTime; - this.playing = true; - this.output.addEventListener("ended", () => { - this.playing = false; - this.checkBufferedPlay(); - }); - } - - mergeBuffers() { - const buffer = this.ac.createBuffer( - this.audioData.length, - this.bufferedSamples, - this.sampleRate - ); - const chunk = this.sampleRate * this.bufferChunkSize; - const bufferedChunks = Math.floor(this.bufferedSamples / chunk); - const restLength = this.bufferedSamples % chunk; - for (let i = 0; i < this.audioData.length; i++) { - const audio = this.audioData[i]; - const data = new Float32Array(this.bufferedSamples); - for (let j = 0; j < bufferedChunks; j++) { - data.set(audio[j], chunk * j); - } - if (restLength !== 0) { - data.set( - audio[bufferedChunks].slice(0, restLength), - chunk * bufferedChunks - ); - } - - buffer.copyToChannel(data, i, 0); - } - this.buffer = buffer; - } - - async start() { - delete this.buffer; - this.headerRecieved = false; - this.audioType = ""; - this.errored = false; - this.buffered = 0; - this.sampleRate = 0; - this.bufferedSamples = 0; - this.duration = 0; - this.loaded = false; - if (this.playing) this.output.stop(); - this.playing = false; - this.lastStartTime = this.ac.currentTime; - } - - end(done, reason) { - if (done && this.buffer) { - this.loaded = true; - delete this.controller; - this.mergeBuffers(); - - this.duration = this.buffered; - this.audioData = []; - this.decoder?.destroy(); - delete this.decoder; - delete this.parser; - } else { - console.warn( - "Unexpected end when loading stream audio, reason: '" + - (reason ?? "") + - "'" - ); - } - } - - playAudio(when) { - if (!this.buffer) return; - this.lastStartTime = this.ac.currentTime; - if (this.playing) this.output.stop(); - if (this.route.status !== AudioStatus.Playing) { - this.route.status = AudioStatus.Playing; - } - this.createSourceNode(this.buffer); - this.output.start(0, when); - this.playing = true; - - this.output.addEventListener("ended", () => { - this.playing = false; - if (this.route.status === AudioStatus.Playing) { - this.route.status = AudioStatus.Stoped; - } - if (this.loop && !this.output.loop) this.play(0); - }); - } - /** - * 开始播放这个音频源 - */ - play(when) { - if (this.playing || this.errored) return; - if (this.loaded && this.buffer) { - this.playing = true; - this.playAudio(when); - } else { - this.controller?.start(); - } - } - - createSourceNode(buffer) { - if (!this.target) return; - const node = this.ac.createBufferSource(); - node.buffer = buffer; - if (this.playing) this.output.stop(); - this.playing = false; - this.output = node; - node.connect(this.target.input); - node.loop = this.loop; - } - /** - * 停止播放这个音频源 - * @returns 音频暂停的时刻 number - */ - stop() { - if (this.playing) this.output.stop(); - this.playing = false; - return this.ac.currentTime - this.lastStartTime; - } - /** - * 连接到音频路由图上,每次调用播放的时候都会执行一次 - * @param target 连接至的目标 IAudioInput - */ - connect(target) { - this.target = target; - } - /** - * 设置是否循环播放 - * @param loop 是否循环 boolean) - */ - setLoop(loop) { - this.loop = loop; - } - } - class AudioElementSource { - constructor(context) { - const audio = new Audio(); - audio.preload = "none"; - this.output = context.createMediaElementSource(audio); - this.audio = audio; - this.ac = context; - audio.addEventListener("play", () => { - this.playing = true; - if (this.route.status !== AudioStatus.Playing) { - this.route.status = AudioStatus.Playing; - } - }); - audio.addEventListener("ended", () => { - this.playing = false; - if (this.route.status === AudioStatus.Playing) { - this.route.status = AudioStatus.Stoped; - } - }); - } - get duration() { - return this.audio.duration; - } - get currentTime() { - return this.audio.currentTime; - } - /** - * 设置音频源的路径 - * @param url 音频路径 - */ - setSource(url) { - this.audio.src = url; - } - - play(when = 0) { - if (this.playing) return; - this.audio.currentTime = when; - this.audio.play(); - } - - stop() { - this.audio.pause(); - this.playing = false; - if (this.route.status === AudioStatus.Playing) { - this.route.status = AudioStatus.Stoped; - } - return this.audio.currentTime; - } - - connect(target) { - this.output.connect(target.input); - } - - setLoop(loop) { - this.audio.loop = loop; - } - } - class AudioBufferSource { - constructor(context) { - this.output = context.createBufferSource(); - /** 是否循环 */ - this.loop = false; - /** 上一次播放是从何时开始的 */ - this.lastStartWhen = 0; - /** 播放开始时刻 */ - this.lastStartTime = 0; - this.duration = 0; - this.ac = context; - } - get currentTime() { - return this.ac.currentTime - this.lastStartTime + this.lastStartWhen; - } - - /** - * 设置音频源数据 - * @param buffer 音频源,可以是未解析的 ArrayBuffer,也可以是已解析的 AudioBuffer - */ - async setBuffer(buffer) { - if (buffer instanceof ArrayBuffer) { - this.buffer = await this.ac.decodeAudioData(buffer); - } else { - this.buffer = buffer; - } - this.duration = this.buffer.duration; - } - - play(when) { - if (this.playing || !this.buffer) return; - this.playing = true; - this.lastStartTime = this.ac.currentTime; - if (this.route.status !== AudioStatus.Playing) { - this.route.status = AudioStatus.Playing; - } - this.createSourceNode(this.buffer); - this.output.start(0, when); - this.output.addEventListener("ended", () => { - this.playing = false; - if (this.route.status === AudioStatus.Playing) { - this.route.status = AudioStatus.Stoped; - } - if (this.loop && !this.output.loop) this.play(0); - }); - } - - createSourceNode(buffer) { - if (!this.target) return; - const node = this.ac.createBufferSource(); - node.buffer = buffer; - this.output = node; - node.connect(this.target.input); - node.loop = this.loop; - } - - stop() { - this.output.stop(); - return this.ac.currentTime - this.lastStartTime; - } - - connect(target) { - this.target = target; - } - - setLoop(loop) { - this.loop = loop; - } - } - class AudioPlayer { - constructor() { - /** 音频播放上下文 */ - this.ac = new AudioContext(); - /** 音量节点 */ - this.gain = this.ac.createGain(); - this.gain.connect(this.ac.destination); - this.audioRoutes = new Map(); - } - /** - * 解码音频数据 - * @param data 音频数据 - */ - decodeAudioData(data) { - return AudioDecoder.decodeAudioData(data, this); - } - /** - * 设置音量 - * @param volume 音量 - */ - setVolume(volume) { - this.gain.gain.value = volume; - } - - /** - * 获取音量 - */ - getVolume() { - return this.gain.gain.value; - } - - /** - * 创建一个音频源 - * @param Source 音频源类 - */ - createSource(Source) { - return new Source(this.ac); - } - - /** - * 创建一个兼容流式音频源,可以与流式加载相结合,主要用于处理 opus ogg 不兼容的情况 - */ - createStreamSource() { - return new AudioStreamSource(this.ac); - } - - /** - * 创建一个通过 audio 元素播放的音频源 - */ - createElementSource() { - return new AudioElementSource(this.ac); - } - - /** - * 创建一个通过 AudioBuffer 播放的音频源 - */ - createBufferSource() { - return new AudioBufferSource(this.ac); - } - - /** - * 获取音频目的地 - */ - getDestination() { - return this.gain; - } - - /** - * 创建一个音频效果器 - * @param Effect 效果器类 - */ - createEffect(Effect) { - return new Effect(this.ac); - } - - /** - * 创建一个修改音量的效果器 - * ```txt - * |----------| - * Input ----> | GainNode | ----> Output - * |----------| - * ``` - */ - createVolumeEffect() { - return new VolumeEffect(this.ac); - } - - /** - * 创建一个立体声效果器 - * ```txt - * |------------| - * Input ----> | PannerNode | ----> Output - * |------------| - * ``` - */ - createStereoEffect() { - return new StereoEffect(this.ac); - } - - /** - * 创建一个修改单个声道音量的效果器 - * ```txt - * |----------| - * -> | GainNode | \ - * |--------------| / |----------| -> |------------| - * Input ----> | SplitterNode | ...... | MergerNode | ----> Output - * |--------------| \ |----------| -> |------------| - * -> | GainNode | / - * |----------| - * ``` - */ - createChannelVolumeEffect() { - return new ChannelVolumeEffect(this.ac); - } - - /** - * 创建一个延迟效果器 - * |-----------| - * Input ----> | DelayNode | ----> Output - * |-----------| - */ - createDelay() { - return new DelayEffect(this.ac); - } - - /** - * 创建一个回声效果器 - * ```txt - * |----------| - * Input ----> | GainNode | ----> Output - * ^ |----------| | - * | | - * | |------------| ↓ - * |-- | Delay Node | <-- - * |------------| - * ``` - */ - createEchoEffect() { - return new EchoEffect(this.ac); - } - - /** - * 创建一个音频播放路由 - * @param source 音频源 - */ - createRoute(source) { - return new AudioRoute(source, this); - } - - /** - * 添加一个音频播放路由,可以直接被播放 - * @param id 这个音频播放路由的名称 - * @param route 音频播放路由对象 - */ - addRoute(id, route) { - if (!this.audioRoutes) this.audioRoutes = new Map(); - if (this.audioRoutes.has(id)) { - console.warn( - "Audio route with id of '" + - id + - "' has already existed. New route will override old route." - ); - } - this.audioRoutes.set(id, route); - } - - /** - * 根据名称获取音频播放路由对象 - * @param id 音频播放路由的名称 - */ - getRoute(id) { - return this.audioRoutes.get(id); - } - /** - * 移除一个音频播放路由 - * @param id 要移除的播放路由的名称 - */ - removeRoute(id) { - this.audioRoutes.delete(id); - } - /** - * 播放音频 - * @param id 音频名称 - * @param when 从音频的哪个位置开始播放,单位秒 - */ - play(id, when) { - const route = this.getRoute(id); - if (!route) { - console.warn( - "Cannot play audio route '" + - id + - "', since there is not added route named it." - ); - return; - } - - route.play(when); - } - - /** - * 暂停音频播放 - * @param id 音频名称 - * @returns 当音乐真正停止时兑现 - */ - pause(id) { - const route = this.getRoute(id); - if (!route) { - console.warn( - "Cannot pause audio route '" + - id + - "', since there is not added route named it." - ); - return; - } - return route.pause(); - } - - /** - * 停止音频播放 - * @param id 音频名称 - * @returns 当音乐真正停止时兑现 - */ - stop(id) { - const route = this.getRoute(id); - if (!route) { - console.warn( - "Cannot stop audio route '" + - id + - "', since there is not added route named it." - ); - return; - } - return route.stop(); - } - - /** - * 继续音频播放 - * @param id 音频名称 - */ - resume(id) { - const route = this.getRoute(id); - if (!route) { - console.warn( - "Cannot pause audio route '" + - id + - "', since there is not added route named it." - ); - return; - } - route.resume(); - } - - /** - * 设置听者位置,x正方向水平向右,y正方向垂直于地面向上,z正方向垂直屏幕远离用户 - * @param x 位置x坐标 - * @param y 位置y坐标 - * @param z 位置z坐标 - */ - setListenerPosition(x, y, z) { - const listener = this.ac.listener; - listener.positionX.value = x; - listener.positionY.value = y; - listener.positionZ.value = z; - } - - /** - * 设置听者朝向,x正方向水平向右,y正方向垂直于地面向上,z正方向垂直屏幕远离用户 - * @param x 朝向x坐标 - * @param y 朝向y坐标 - * @param z 朝向z坐标 - */ - setListenerOrientation(x, y, z) { - const listener = this.ac.listener; - listener.forwardX.value = x; - listener.forwardY.value = y; - listener.forwardZ.value = z; - } - - /** - * 设置听者头顶朝向,x正方向水平向右,y正方向垂直于地面向上,z正方向垂直屏幕远离用户 - * @param x 头顶朝向x坐标 - * @param y 头顶朝向y坐标 - * @param z 头顶朝向z坐标 - */ - setListenerUp(x, y, z) { - const listener = this.ac.listener; - listener.upX.value = x; - listener.upY.value = y; - listener.upZ.value = z; - } - } - class AudioRoute { - constructor(source, player) { - source.route = this; - this.output = source.output; - - /** 效果器路由图 */ - this.effectRoute = []; - - /** 结束时长,当音频暂停或停止时,会经过这么长时间之后才真正终止播放,期间可以做音频淡入淡出等效果 */ - this.endTime = 0; - /** 暂停时播放了多长时间 */ - this.pauseCurrentTime = 0; - /** 当前播放状态 */ - this.player = player; - this.status = AudioStatus.Stoped; - - this.shouldStop = false; - /** - * 每次暂停或停止时自增,用于判断当前正在处理的情况。 - * 假如暂停后很快播放,然后很快暂停,那么需要根据这个来判断实际是否应该执行暂停后操作 - */ - this.stopIdentifier = 0; - /** 暂停时刻 */ - this.pauseTime = 0; - this.source = source; - this.source.player = player; - } - /** 音频时长,单位秒 */ - get duration() { - return this.source.duration; - } - /** 当前播放了多长时间,单位秒 */ - get currentTime() { - if (this.status === AudioStatus.Paused) { - return this.pauseCurrentTime; - } else { - return this.source.currentTime; - } - } - set currentTime(time) { - this.source.stop(); - this.source.play(time); - } - /** - * 设置结束时间,暂停或停止时,会经过这么长时间才终止音频的播放,这期间可以做一下音频淡出的效果。 - * @param time 暂停或停止时,经过多长时间之后才会结束音频的播放 - */ - setEndTime(time) { - this.endTime = time; - } - - /** - * 当音频播放时执行的函数,可以用于音频淡入效果 - * @param fn 音频开始播放时执行的函数 - */ - onStart(fn) { - this.audioStartHook = fn; - } - - /** - * 当音频暂停或停止时执行的函数,可以用于音频淡出效果 - * @param fn 音频在暂停或停止时执行的函数,不填时表示取消这个钩子。 - * 包含两个参数,第一个参数是结束时长,第二个参数是当前音频播放路由对象 - */ - onEnd(fn) { - this.audioEndHook = fn; - } - - /** - * 开始播放这个音频 - * @param when 从音频的什么时候开始播放,单位秒 - */ - async play(when = 0) { - if (this.status === AudioStatus.Playing) return; - this.link(); - await this.player.ac.resume(); - if (this.effectRoute.length > 0) { - const first = this.effectRoute[0]; - this.source.connect(first); - const last = this.effectRoute.at(-1); - last.connect({ input: this.player.getDestination() }); - } else { - this.source.connect({ input: this.player.getDestination() }); - } - this.source.play(when); - this.status = AudioStatus.Playing; - this.pauseTime = 0; - this.audioStartHook?.(this); - this.startAllEffect(); - if (this.status !== AudioStatus.Playing) { - this.status = AudioStatus.Playing; - } - } - - /** - * 暂停音频播放 - */ - async pause() { - if (this.status !== AudioStatus.Playing) return; - this.status = AudioStatus.Pausing; - this.stopIdentifier++; - const identifier = this.stopIdentifier; - if (this.audioEndHook) { - this.audioEndHook(this.endTime, this); - await sleep(this.endTime); - } - if ( - this.status !== AudioStatus.Pausing || - this.stopIdentifier !== identifier - ) { - return; - } - this.pauseCurrentTime = this.source.currentTime; - const time = this.source.stop(); - this.pauseTime = time; - if (this.shouldStop) { - this.status = AudioStatus.Stoped; - this.endAllEffect(); - - this.shouldStop = false; - } else { - this.status = AudioStatus.Paused; - this.endAllEffect(); - } - this.endAllEffect(); - } - - /** - * 继续音频播放 - */ - resume() { - if (this.status === AudioStatus.Playing) return; - if ( - this.status === AudioStatus.Pausing || - this.status === AudioStatus.Stoping - ) { - this.audioStartHook?.(this); - - return; - } - if (this.status === AudioStatus.Paused) { - this.play(this.pauseTime); - } else { - this.play(0); - } - this.status = AudioStatus.Playing; - this.pauseTime = 0; - this.audioStartHook?.(this); - this.startAllEffect(); - } - - /** - * 停止音频播放 - */ - async stop() { - if (this.status !== AudioStatus.Playing) { - if (this.status === AudioStatus.Pausing) { - this.shouldStop = true; - } - return; - } - this.status = AudioStatus.Stoping; - this.stopIdentifier++; - const identifier = this.stopIdentifier; - if (this.audioEndHook) { - this.audioEndHook(this.endTime, this); - await sleep(this.endTime); - } - if ( - this.status !== AudioStatus.Stoping || - this.stopIdentifier !== identifier - ) { - return; - } - this.source.stop(); - this.status = AudioStatus.Stoped; - this.pauseTime = 0; - this.endAllEffect(); - } - - /** - * 添加效果器 - * @param effect 要添加的效果,可以是数组,表示一次添加多个 - * @param index 从哪个位置开始添加,如果大于数组长度,那么加到末尾,如果小于0,那么将会从后面往前数。默认添加到末尾 - */ - addEffect(effect, index) { - if (isNil(index)) { - if (effect instanceof Array) { - this.effectRoute.push(...effect); - } else { - this.effectRoute.push(effect); - } - } else { - if (effect instanceof Array) { - this.effectRoute.splice(index, 0, ...effect); - } else { - this.effectRoute.splice(index, 0, effect); - } - } - this.setOutput(); - if (this.source.playing) this.link(); - } - - /** - * 移除一个效果器 - * @param effect 要移除的效果 - */ - removeEffect(effect) { - const index = this.effectRoute.indexOf(effect); - if (index === -1) return; - this.effectRoute.splice(index, 1); - effect.disconnect(); - this.setOutput(); - if (this.source.playing) this.link(); - } - - setOutput() { - const effect = this.effectRoute.at(-1); - if (!effect) this.output = this.source.output; - else this.output = effect.output; - } - - /** - * 连接音频路由图 - */ - link() { - this.effectRoute.forEach((v) => v.disconnect()); - this.effectRoute.forEach((v, i) => { - const next = this.effectRoute[i + 1]; - if (next) { - v.connect(next); - } - }); - } - - startAllEffect() { - this.effectRoute.forEach((v) => v.start()); - } - - endAllEffect() { - this.effectRoute.forEach((v) => v.end()); - } - } - - const audioPlayer = new AudioPlayer(); - - class BgmController { - constructor(player) { - this.mainGain = player.createVolumeEffect(); - this.player = player; - /** bgm音频名称的前缀 */ - this.prefix = "bgms."; - /** 每个 bgm 的音量控制器 */ - this.gain = new Map(); - - /** 正在播放的 bgm */ - this.playingBgm = ""; - /** 是否正在播放 */ - this.playing = false; - - /** 是否已经启用 */ - this.enabled = true; - /** 是否屏蔽所有的音乐切换 */ - this.blocking = false; - /** 渐变时长 */ - this.transitionTime = 2000; - } - - /** - * 设置音频渐变时长 - * @param time 渐变时长 - */ - setTransitionTime(time) { - this.transitionTime = time; - for (const [, value] of this.gain) { - value.transition.time(time); - } - } - - /** - * 屏蔽音乐切换 - */ - blockChange() { - this.blocking = true; - } - - /** - * 取消屏蔽音乐切换 - */ - unblockChange() { - this.blocking = false; - } - - /** - * 设置总音量大小 - * @param volume 音量大小 - */ - setVolume(volume) { - this.mainGain.setVolume(volume); - this._volume = volume; - } - /** - * 获取总音量大小 - */ - getVolume() { - return this.mainGain.getVolume(); - } - /** - * 设置是否启用 - * @param enabled 是否启用 - */ - setEnabled(enabled) { - if (enabled) this.resume(); - else this.stop(); - this.enabled = enabled; - } - - /** - * 设置 bgm 音频名称的前缀 - */ - setPrefix(prefix) { - this.prefix = prefix; - } - - getId(name) { - return `${this.prefix}${name}`; - } - - /** - * 根据 bgm 名称获取其 AudioRoute 实例 - * @param id 音频名称 - */ - get(id) { - return this.player.getRoute(this.getId(id)); - } - - /** - * 添加一个 bgm - * @param id 要添加的 bgm 的名称 - * @param url 指定 bgm 的加载地址 - */ - addBgm(id, url = `project/bgms/${id}`) { - const type = guessTypeByExt(id); - if (!type) { - console.warn( - "Unknown audio extension name: '" + - id.split(".").slice(0, -1).join(".") + - "'" - ); - return; - } - const gain = this.player.createVolumeEffect(); - if (isAudioSupport(type)) { - const source = audioPlayer.createElementSource(); - source.setSource(url); - source.setLoop(true); - const route = new AudioRoute(source, audioPlayer); - route.addEffect([gain, this.mainGain]); - audioPlayer.addRoute(this.getId(id), route); - this.setTransition(id, route, gain); - } else { - const source = audioPlayer.createStreamSource(); - const stream = new StreamLoader(url); - stream.pipe(source); - source.setLoop(true); - const route = new AudioRoute(source, audioPlayer); - route.addEffect([gain, this.mainGain]); - audioPlayer.addRoute(this.getId(id), route); - this.setTransition(id, route, gain); - } - } - - /** - * 移除一个 bgm - * @param id 要移除的 bgm 的名称 - */ - removeBgm(id) { - this.player.removeRoute(this.getId(id)); - const gain = this.gain.get(id); - gain?.transition.ticker.destroy(); - this.gain.delete(id); - } - - setTransition(id, route, gain) { - const transition = new Transition(); - transition - .time(this.transitionTime) - .mode(linear()) - .transition("volume", 0); - - const tick = () => { - gain.setVolume(transition.value.volume); - }; - - /** - * @param expect 在结束时应该是正在播放还是停止 - */ - const setTick = async (expect) => { - transition.ticker.remove(tick); - transition.ticker.add(tick); - const identifier = route.stopIdentifier; - await sleep(this.transitionTime + 500); - if (route.status === expect && identifier === route.stopIdentifier) { - transition.ticker.remove(tick); - if (route.status === AudioStatus.Playing) { - gain.setVolume(1); - } else { - gain.setVolume(0); - } - } - }; - - route.onStart(async () => { - transition.transition("volume", 1); - setTick(AudioStatus.Playing); - }); - route.onEnd(() => { - transition.transition("volume", 0); - setTick(AudioStatus.Paused); - }); - route.setEndTime(this.transitionTime); - - this.gain.set(id, { effect: gain, transition }); - } - - /** - * 播放一个 bgm - * @param id 要播放的 bgm 名称 - */ - play(id, when) { - if (this.blocking) return; - if (id !== this.playingBgm && this.playingBgm) { - this.player.pause(this.getId(this.playingBgm)); - } - this.playingBgm = id; - if (!this.enabled) return; - this.player.play(this.getId(id), when); - this.playing = true; - } - - /** - * 继续当前的 bgm - */ - resume() { - if (this.blocking || !this.enabled || this.playing) return; - if (this.playingBgm) { - this.player.resume(this.getId(this.playingBgm)); - } - this.playing = true; - } - - /** - * 暂停当前的 bgm - */ - pause() { - if (this.blocking || !this.enabled) return; - if (this.playingBgm) { - this.player.pause(this.getId(this.playingBgm)); - } - this.playing = false; - } - - /** - * 停止当前的 bgm - */ - stop() { - if (this.blocking || !this.enabled) return; - if (this.playingBgm) { - this.player.stop(this.getId(this.playingBgm)); - } - this.playing = false; - } - } - const bgmController = new BgmController(audioPlayer); - - class SoundPlayer { - constructor(player) { - /** 每个音效的唯一标识符 */ - this.num = 0; - this.enabled = true; - this.gain = player.createVolumeEffect(); - /** 每个音效的数据 */ - this.buffer = new Map(); - /** 所有正在播放的音乐 */ - this.playing = new Set(); - this.player = player; - } - /** - * 设置是否启用音效 - * @param enabled 是否启用音效 - */ - setEnabled(enabled) { - if (!enabled) this.stopAllSounds(); - this.enabled = enabled; - } - - /** - * 设置音量大小 - * @param volume 音量大小 - */ - setVolume(volume) { - this.gain.setVolume(volume); - } - /** - * 获取音量大小 - */ - getVolume() { - return this.gain.getVolume(); - } - /** - * 添加一个音效 - * @param id 音效名称 - * @param data 音效的Uint8Array数据 - */ - async add(id, data) { - const buffer = await this.player.decodeAudioData(data); - if (!buffer) { - console.warn( - "Cannot decode sound '" + - id + - "', since audio file may not supported by 2.b." - ); - return; - } - this.buffer.set(id, buffer); - } - - /** - * 播放一个音效 - * @param id 音效名称 - * @param position 音频位置,[0, 0, 0]表示正中心,x轴指向水平向右,y轴指向水平向上,z轴指向竖直向上 - * @param orientation 音频朝向,[0, 1, 0]表示朝向前方 - */ - play(id, position = [0, 0, 0], orientation = [1, 0, 0]) { - if (!this.enabled || !id) return -1; - const buffer = this.buffer.get(id); - if (!buffer) { - console.warn( - "Cannot play sound '" + - id + - "', since there is no added data named it." - ); - return -1; - } - const soundNum = this.num++; - - const source = this.player.createBufferSource(); - source.setBuffer(buffer); - const route = this.player.createRoute(source); - const stereo = this.player.createStereoEffect(); - stereo.setPosition(position[0], position[1], position[2]); - stereo.setOrientation(orientation[0], orientation[1], orientation[2]); - route.addEffect([stereo, this.gain]); - this.player.addRoute(`sounds.${soundNum}`, route); - route.play(); - source.output.addEventListener("ended", () => { - this.playing.delete(soundNum); - }); - this.playing.add(soundNum); - return soundNum; - } - - /** - * 停止一个音效 - * @param num 音效的唯一 id - */ - stop(num) { - const id = `sounds.${num}`; - const route = this.player.getRoute(id); - if (route) { - route.stop(); - this.player.removeRoute(id); - this.playing.delete(num); - } - } - - /** - * 停止播放所有音效 - */ - stopAllSounds() { - this.playing.forEach((v) => { - const id = `sounds.${v}`; - const route = this.player.getRoute(id); - if (route) { - route.stop(); - this.player.removeRoute(id); - } - }); - this.playing.clear(); - } - } - const soundPlayer = new SoundPlayer(audioPlayer); - - function loadAllBgm() { - const data = data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d; - for (const bgm of data.main.bgms) { - bgmController.addBgm(bgm); - } - } - loadAllBgm(); - AudioDecoder.registerDecoder(AudioType.Ogg, VorbisDecoder); - AudioDecoder.registerDecoder(AudioType.Opus, OpusDecoder); - - core.plugin.audioSystem = { - AudioType, - AudioDecoder, - AudioStatus, - checkAudioType, - isAudioSupport, - audioPlayer, - soundPlayer, - bgmController, - guessTypeByExt, - BgmController, - SoundPlayer, - EchoEffect, - DelayEffect, - ChannelVolumeEffect, - VolumeEffect, - StereoEffect, - AudioEffect, - AudioPlayer, - AudioRoute, - AudioStreamSource, - AudioElementSource, - AudioBufferSource, - loadAllBgm, - StreamLoader, - }; - //bgm相关复写 - control.prototype.playBgm = (bgm, when) => { - bgm = core.getMappedName(bgm); - bgmController.play(bgm, when); - core.setMusicBtn(); - }; - control.prototype.pauseBgm = () => { - bgmController.pause(); - core.setMusicBtn(); - }; - - control.prototype.resumeBgm = function () { - bgmController.resume(); - core.setMusicBtn(); - }; - control.prototype.checkBgm = function () { - core.playBgm(bgmController.playingBgm || main.startBgm); - }; - control.prototype.triggerBgm = function () { - core.musicStatus.bgmStatus = !core.musicStatus.bgmStatus; - if (bgmController.playing) bgmController.pause(); - else bgmController.resume(); - core.setMusicBtn(); - core.setLocalStorage("bgmStatus", core.musicStatus.bgmStatus); - }; - //sound相关复写 - control.prototype.playSound = function ( - sound, - _pitch, - callback, - position, - orientation - ) { - if (main.mode != "play" || !core.musicStatus.soundStatus) return; - const name = core.getMappedName(sound); - const num = soundPlayer.play(name, position, orientation); - const route = audioPlayer.getRoute(`sounds.${num}`); - if (!route) { - callback?.(); - return -1; - } else { - sleep(route.duration * 1000).then(() => callback?.()); - return num; - } - }; - control.prototype.stopSound = function (id) { - if (isNil(id)) { - soundPlayer.stopAllSounds(); - } else { - soundPlayer.stop(id); - } - }; - control.prototype.getPlayingSounds = function () { - return [...soundPlayer.playing]; - }; - //sound加载复写 - loader.prototype._loadOneSound_decodeData = function (name, data) { - if (data instanceof Blob) { - var blobReader = new zip.BlobReader(data); - blobReader.init(function () { - blobReader.readUint8Array(0, blobReader.size, function (uint8) { - //core.loader._loadOneSound_decodeData(name, uint8.buffer); - soundPlayer.add(name, uint8); - }); - }); - return; - } - if (data instanceof ArrayBuffer) { - const uint8 = new Uint8Array(data); - soundPlayer.add(name, uint8); - } - }; - //音量控制复写 - soundPlayer.setVolume( - core.musicStatus.userVolume * core.musicStatus.designVolume - ); - bgmController.setVolume( - core.musicStatus.userVolume * core.musicStatus.designVolume - ); - actions.prototype._clickSwitchs_sounds_userVolume = function (delta) { - var value = Math.round(Math.sqrt(100 * core.musicStatus.userVolume)); - if (value == 0 && delta < 0) return; - core.musicStatus.userVolume = core.clamp( - Math.pow(value + delta, 2) / 100, - 0, - 1 - ); - //audioContext 音效 不受designVolume 影响 - if (core.musicStatus.gainNode != null) - core.musicStatus.gainNode.gain.value = core.musicStatus.userVolume; - soundPlayer.setVolume( - core.musicStatus.userVolume * core.musicStatus.designVolume - ); - bgmController.setVolume( - core.musicStatus.userVolume * core.musicStatus.designVolume - ); - core.setLocalStorage("userVolume", core.musicStatus.userVolume); - core.playSound("确定"); - core.ui._drawSwitchs_sounds(); - }; -}, + // 将__enable置为false将关闭插件 + let __enable = true; + if (!__enable || main.mode === "editor") return; + const { OggOpusDecoderWebWorker } = window["ogg-opus-decoder"]; + const { OggVorbisDecoderWebWorker } = window["ogg-vorbis-decoder"]; + const { CodecParser } = window.CodecParser; + const { Transition, linear } = core.plugin.animate; + + const audio = new Audio(); + const AudioStatus = { + Playing: 0, + Pausing: 1, + Paused: 2, + Stoping: 3, + Stoped: 4, + }; + const supportMap = new Map(); + const AudioType = { + Mp3: "audio/mpeg", + Wav: 'audio/wav; codecs="1"', + Flac: "audio/flac", + Opus: 'audio/ogg; codecs="opus"', + Ogg: 'audio/ogg; codecs="vorbis"', + Aac: "audio/aac", + }; + /** + * 检查一种音频类型是否能被播放 + * @param type 音频类型 AudioType + */ + function isAudioSupport(type) { + if (supportMap.has(type)) return supportMap.get(type); + else { + const support = audio.canPlayType(type); + const canPlay = support === "maybe" || support === "probably"; + supportMap.set(type, canPlay); + return canPlay; + } + } + + const typeMap = new Map([ + ["ogg", AudioType.Ogg], + ["mp3", AudioType.Mp3], + ["wav", AudioType.Wav], + ["flac", AudioType.Flac], + ["opus", AudioType.Opus], + ["aac", AudioType.Aac], + ]); + + /** + * 根据文件名拓展猜测其类型 + * @param file 文件名 string + */ + function guessTypeByExt(file) { + const ext = /\.[a-zA-Z\d]+$/.exec(file); + if (!ext?.[0]) return ""; + const type = ext[0].slice(1); + return typeMap.get(type.toLocaleLowerCase()) ?? ""; + } + + isAudioSupport(AudioType.Ogg); + isAudioSupport(AudioType.Mp3); + isAudioSupport(AudioType.Wav); + isAudioSupport(AudioType.Flac); + isAudioSupport(AudioType.Opus); + isAudioSupport(AudioType.Aac); + + function isNil(value) { + return value === void 0 || value === null; + } + + function sleep(time) { + return new Promise((res) => setTimeout(res, time)); + } + class AudioEffect { + constructor(ac) {} + /** + * 连接至其他效果器 + * @param target 目标输入 IAudioInput + * @param output 当前效果器输出通道 Number + * @param input 目标效果器的输入通道 Number + */ + connect(target, output, input) { + this.output.connect(target.input, output, input); + } + + /** + * 与其他效果器取消连接 + * @param target 目标输入 IAudioInput + * @param output 当前效果器输出通道 Number + * @param input 目标效果器的输入通道 Number + */ + disconnect(target, output, input) { + if (!target) { + if (!isNil(output)) { + this.output.disconnect(output); + } else { + this.output.disconnect(); + } + } else { + if (!isNil(output)) { + if (!isNil(input)) { + this.output.disconnect(target.input, output, input); + } else { + this.output.disconnect(target.input, output); + } + } else { + this.output.disconnect(target.input); + } + } + } + } + + class StereoEffect extends AudioEffect { + constructor(ac) { + super(ac); + const panner = ac.createPanner(); + this.input = panner; + this.output = panner; + } + + /** + * 设置音频朝向,x正方形水平向右,y正方形垂直于地面向上,z正方向垂直屏幕远离用户 + * @param x 朝向x坐标 Number + * @param y 朝向y坐标 Number + * @param z 朝向z坐标 Number + */ + setOrientation(x, y, z) { + this.output.orientationX.value = x; + this.output.orientationY.value = y; + this.output.orientationZ.value = z; + } + /** + * 设置音频位置,x正方形水平向右,y正方形垂直于地面向上,z正方向垂直屏幕远离用户 + * @param x 位置x坐标 Number + * @param y 位置y坐标 Number + * @param z 位置z坐标 Number + */ + setPosition(x, y, z) { + this.output.positionX.value = x; + this.output.positionY.value = y; + this.output.positionZ.value = z; + } + end() {} + + start() {} + } + class VolumeEffect extends AudioEffect { + constructor(ac) { + super(ac); + const gain = ac.createGain(); + this.input = gain; + this.output = gain; + } + + /** + * 设置音量大小 + * @param volume 音量大小 Number + */ + setVolume(volume) { + this.output.gain.value = volume; + } + + /** + * 获取音量大小 Number + */ + getVolume() { + return this.output.gain.value; + } + + end() {} + + start() {} + } + class ChannelVolumeEffect extends AudioEffect { + /** 所有的音量控制节点 */ + + constructor(ac) { + super(ac); + /** 所有的音量控制节点 */ + this.gain = []; + const splitter = ac.createChannelSplitter(); + const merger = ac.createChannelMerger(); + this.output = merger; + this.input = splitter; + for (let i = 0; i < 6; i++) { + const gain = ac.createGain(); + splitter.connect(gain, i); + gain.connect(merger, 0, i); + this.gain.push(gain); + } + } + + /** + * 设置某个声道的音量大小 + * @param channel 要设置的声道,可填0-5 Number + * @param volume 这个声道的音量大小 Number + */ + setVolume(channel, volume) { + if (!this.gain[channel]) return; + this.gain[channel].gain.value = volume; + } + + /** + * 获取某个声道的音量大小,可填0-5 + * @param channel 要获取的声道 Number + */ + getVolume(channel) { + if (!this.gain[channel]) return 0; + return this.gain[channel].gain.value; + } + + end() {} + + start() {} + } + class DelayEffect extends AudioEffect { + constructor(ac) { + super(ac); + + const delay = ac.createDelay(); + this.input = delay; + this.output = delay; + } + + /** + * 设置延迟时长 + * @param delay 延迟时长,单位秒 Number + */ + setDelay(delay) { + this.output.delayTime.value = delay; + } + + /** + * 获取延迟时长 + */ + getDelay() { + return this.output.delayTime.value; + } + + end() {} + + start() {} + } + class EchoEffect extends AudioEffect { + constructor(ac) { + super(ac); + /** 当前增益 */ + this.gain = 0.5; + /** 是否正在播放 */ + this.playing = false; + const delay = ac.createDelay(); + const gain = ac.createGain(); + gain.gain.value = 0.5; + delay.delayTime.value = 0.05; + delay.connect(gain); + gain.connect(delay); + /** 延迟节点 */ + this.delay = delay; + /** 反馈增益节点 */ + this.gainNode = gain; + + this.input = gain; + this.output = gain; + } + + /** + * 设置回声反馈增益大小 + * @param gain 增益大小,范围 0-1,大于等于1的视为0.5,小于0的视为0 Number + */ + setFeedbackGain(gain) { + const resolved = gain >= 1 ? 0.5 : gain < 0 ? 0 : gain; + this.gain = resolved; + if (this.playing) this.gainNode.gain.value = resolved; + } + + /** + * 设置回声间隔时长 + * @param delay 回声时长,范围 0.01-Infinity,小于0.01的视为0.01 Number + */ + setEchoDelay(delay) { + const resolved = delay < 0.01 ? 0.01 : delay; + this.delay.delayTime.value = resolved; + } + + /** + * 获取反馈节点增益 + */ + getFeedbackGain() { + return this.gain; + } + + /** + * 获取回声间隔时长 + */ + getEchoDelay() { + return this.delay.delayTime.value; + } + + end() { + this.playing = false; + const echoTime = Math.ceil(Math.log(0.001) / Math.log(this.gain)) + 10; + sleep(this.delay.delayTime.value * echoTime).then(() => { + if (!this.playing) this.gainNode.gain.value = 0; + }); + } + + start() { + this.playing = true; + this.gainNode.gain.value = this.gain; + } + } + + class StreamLoader { + constructor(url) { + /** 传输目标 Set*/ + this.target = new Set(); + this.loading = false; + } + + /** + * 将加载流传递给字节流读取对象 + * @param reader 字节流读取对象 IStreamReader + */ + pipe(reader) { + if (this.loading) { + console.warn( + "Cannot pipe new StreamReader object when stream is loading." + ); + return; + } + this.target.add(reader); + reader.piped(this); + return this; + } + + async start() { + if (this.loading) return; + this.loading = true; + const response = await window.fetch(this.url); + const stream = response.body; + if (!stream) { + console.error("Cannot get reader when fetching '" + this.url + "'."); + return; + } + // 获取读取器 + this.stream = stream; + const reader = response.body?.getReader(); + const targets = [...this.target]; + + await Promise.all(targets.map((v) => v.start(stream, this, response))); + if (reader && reader.read) { + // 开始流传输 + while (true) { + const { value, done } = await reader.read(); + await Promise.all( + targets.map((v) => v.pump(value, done, response)) + ); + if (done) break; + } + } else { + // 如果不支持流传输 + const buffer = await response.arrayBuffer(); + const data = new Uint8Array(buffer); + await Promise.all(targets.map((v) => v.pump(data, true, response))); + } + + this.loading = false; + targets.forEach((v) => v.end(true)); + + // + } + + cancel(reason) { + if (!this.stream) return; + this.stream.cancel(reason); + this.loading = false; + this.target.forEach((v) => v.end(false, reason)); + } + } + const fileSignatures = [ + [AudioType.Mp3, [0x49, 0x44, 0x33]], + [AudioType.Ogg, [0x4f, 0x67, 0x67, 0x53]], + [AudioType.Wav, [0x52, 0x49, 0x46, 0x46]], + [AudioType.Flac, [0x66, 0x4c, 0x61, 0x43]], + [AudioType.Aac, [0xff, 0xf1]], + [AudioType.Aac, [0xff, 0xf9]], + ]; + const oggHeaders = [ + [AudioType.Opus, [0x4f, 0x70, 0x75, 0x73, 0x48, 0x65, 0x61, 0x64]], + ]; + + function checkAudioType(data) { + let audioType = ""; + // 检查头文件获取音频类型,仅检查前256个字节 + const toCheck = data.slice(0, 256); + for (const [type, value] of fileSignatures) { + if (value.every((v, i) => toCheck[i] === v)) { + audioType = type; + break; + } + } + if (audioType === AudioType.Ogg) { + // 如果是ogg的话,进一步判断是不是opus + for (const [key, value] of oggHeaders) { + const has = toCheck.some((_, i) => { + return value.every((v, ii) => toCheck[i + ii] === v); + }); + if (has) { + audioType = key; + break; + } + } + } + + return audioType; + } + class AudioDecoder { + /** + * 注册一个解码器 + * @param type 要注册的解码器允许解码的类型 + * @param decoder 解码器对象 + */ + static registerDecoder(type, decoder) { + if (!this.decoderMap) this.decoderMap = new Map(); + if (this.decoderMap.has(type)) { + console.warn( + "Audio stream decoder for audio type '" + + type + + "' has already existed." + ); + return; + } + + this.decoderMap.set(type, decoder); + } + + /** + * 解码音频数据 + * @param data 音频文件数据 + * @param player AudioPlayer实例 + */ + static async decodeAudioData(data, player) { + // 检查头文件获取音频类型,仅检查前256个字节 + const toCheck = data.slice(0, 256); + const type = checkAudioType(data); + if (type === "") { + console.error( + "Unknown audio type. Header: '" + + [...toCheck] + .map((v) => v.toString().padStart(2, "0")) + .join(" ") + .toUpperCase() + + "'" + ); + return null; + } + if (isAudioSupport(type)) { + if (data.buffer instanceof ArrayBuffer) { + return player.ac.decodeAudioData(data.buffer); + } else { + return null; + } + } else { + const Decoder = this.decoderMap.get(type); + if (!Decoder) { + return null; + } else { + const decoder = new Decoder(); + await decoder.create(); + const decodedData = await decoder.decode(data); + if (!decodedData) return null; + const buffer = player.ac.createBuffer( + decodedData.channelData.length, + decodedData.channelData[0].length, + decodedData.sampleRate + ); + decodedData.channelData.forEach((v, i) => { + buffer.copyToChannel(v, i); + }); + decoder.destroy(); + return buffer; + } + } + } + } + + class VorbisDecoder { + /** + * 创建音频解码器 + */ + async create() { + this.decoder = new OggVorbisDecoderWebWorker(); + await this.decoder.ready; + } + /** + * 摧毁这个解码器 + */ + destroy() { + this.decoder?.free(); + } + /** + * 解码流数据 + * @param data 流数据 + */ + + async decode(data) { + return this.decoder?.decode(data); + } + /** + * 解码整个文件 + * @param data 文件数据 + */ + async decodeAll(data) { + return this.decoder?.decodeFile(data); + } + /** + * 当音频解码完成后,会调用此函数,需要返回之前还未解析或未返回的音频数据。调用后,该解码器将不会被再次使用 + */ + async flush() { + return this.decoder?.flush(); + } + } + + class OpusDecoder { + /** + * 创建音频解码器 + */ + async create() { + this.decoder = new OggOpusDecoderWebWorker(); + await this.decoder.ready; + } + /** + * 摧毁这个解码器 + */ + destroy() { + this.decoder?.free(); + } + /** + * 解码流数据 + * @param data 流数据 + */ + async decode(data) { + return this.decoder?.decode(data); + } + /** + * 解码整个文件 + * @param data 文件数据 + */ + async decodeAll(data) { + return this.decoder?.decodeFile(data); + } + /** + * 当音频解码完成后,会调用此函数,需要返回之前还未解析或未返回的音频数据。调用后,该解码器将不会被再次使用 + */ + async flush() { + return await this.decoder?.flush(); + } + } + const mimeTypeMap = { + [AudioType.Aac]: "audio/aac", + [AudioType.Flac]: "audio/flac", + [AudioType.Mp3]: "audio/mpeg", + [AudioType.Ogg]: "application/ogg", + [AudioType.Opus]: "application/ogg", + [AudioType.Wav]: "application/ogg", + }; + + function isOggPage(data) { + return !isNil(data.isFirstPage); + } + class AudioStreamSource { + constructor(context) { + this.output = context.createBufferSource(); + /** 是否已经完全加载完毕 */ + this.loaded = false; + /** 是否正在播放 */ + this.playing = false; + /** 已经缓冲了多长时间,如果缓冲完那么跟歌曲时长一致 */ + this.buffered = 0; + /** 已经缓冲的采样点数量 */ + this.bufferedSamples = 0; + /** 歌曲时长,加载完毕之前保持为 0 */ + this.duration = 0; + /** 在流传输阶段,至少缓冲多长时间的音频之后才开始播放,单位秒 */ + this.bufferPlayDuration = 1; + /** 音频的采样率,未成功解析出之前保持为 0 */ + this.sampleRate = 0; + //是否循环播放 + this.loop = false; + /** 上一次播放是从何时开始的 */ + this.lastStartWhen = 0; + /** 开始播放时刻 */ + this.lastStartTime = 0; + /** 上一次播放的缓存长度 */ + this.lastBufferSamples = 0; + + /** 是否已经获取到头文件 */ + this.headerRecieved = false; + /** 音频类型 */ + this.audioType = ""; + /** 每多长时间组成一个缓存 Float32Array */ + this.bufferChunkSize = 10; + /** 缓存音频数据,每 bufferChunkSize 秒钟组成一个 Float32Array,用于流式解码 */ + this.audioData = []; + + this.errored = false; + this.ac = context; + } + /** 当前已经播放了多长时间 */ + get currentTime() { + return this.ac.currentTime - this.lastStartTime + this.lastStartWhen; + } + /** + * 设置每个缓存数据的大小,默认为10秒钟一个缓存数据 + * @param size 每个缓存数据的时长,单位秒 + */ + setChunkSize(size) { + if (this.controller?.loading || this.loaded) return; + this.bufferChunkSize = size; + } + + piped(controller) { + this.controller = controller; + } + + async pump(data, done) { + if (!data || this.errored) return; + if (!this.headerRecieved) { + // 检查头文件获取音频类型,仅检查前256个字节 + const toCheck = data.slice(0, 256); + this.audioType = checkAudioType(data); + if (!this.audioType) { + console.error( + "Unknown audio type. Header: '" + + [...toCheck] + .map((v) => v.toString(16).padStart(2, "0")) + .join(" ") + .toUpperCase() + + "'" + ); + return; + } + // 创建解码器 + const Decoder = AudioDecoder.decoderMap.get(this.audioType); + if (!Decoder) { + this.errored = true; + console.error( + "Cannot decode stream source type of '" + + this.audioType + + "', since there is no registered decoder for that type." + ); + return Promise.reject( + `Cannot decode stream source type of '${this.audioType}', since there is no registered decoder for that type.` + ); + } + this.decoder = new Decoder(); + // 创建数据解析器 + const mime = mimeTypeMap[this.audioType]; + const parser = new CodecParser(mime); + this.parser = parser; + await this.decoder.create(); + this.headerRecieved = true; + } + + const decoder = this.decoder; + const parser = this.parser; + if (!decoder || !parser) { + this.errored = true; + return Promise.reject( + "No parser or decoder attached in this AudioStreamSource" + ); + } + + await this.decodeData(data, decoder, parser); + if (done) await this.decodeFlushData(decoder, parser); + this.checkBufferedPlay(); + } + + /** + * 检查采样率,如果还未解析出采样率,那么将设置采样率,如果当前采样率与之前不同,那么发出警告 + */ + checkSampleRate(info) { + for (const one of info) { + const frame = isOggPage(one) ? one.codecFrames[0] : one; + if (frame) { + const rate = frame.header.sampleRate; + if (this.sampleRate === 0) { + this.sampleRate = rate; + break; + } else { + if (rate !== this.sampleRate) { + console.warn("Sample rate in stream audio must be constant."); + } + } + } + } + } + + /** + * 解析音频数据 + */ + async decodeData(data, decoder, parser) { + // 解析音频数据 + const audioData = await decoder.decode(data); + if (!audioData) return; + // @ts-expect-error 库类型声明错误 + const audioInfo = [...parser.parseChunk(data)]; + + // 检查采样率 + this.checkSampleRate(audioInfo); + // 追加音频数据 + this.appendDecodedData(audioData, audioInfo); + } + + /** + * 解码剩余数据 + */ + async decodeFlushData(decoder, parser) { + const audioData = await decoder.flush(); + if (!audioData) return; + // @ts-expect-error 库类型声明错误 + const audioInfo = [...parser.flush()]; + + this.checkSampleRate(audioInfo); + this.appendDecodedData(audioData, audioInfo); + } + + /** + * 追加音频数据 + */ + appendDecodedData(data, info) { + const channels = data.channelData.length; + if (channels === 0) return; + if (this.audioData.length !== channels) { + this.audioData = []; + for (let i = 0; i < channels; i++) { + this.audioData.push([]); + } + } + // 计算出应该放在哪 + const chunk = this.sampleRate * this.bufferChunkSize; + const sampled = this.bufferedSamples; + const pushIndex = Math.floor(sampled / chunk); + const bufferIndex = sampled % chunk; + const dataLength = data.channelData[0].length; + let buffered = 0; + let nowIndex = pushIndex; + let toBuffer = bufferIndex; + while (buffered < dataLength) { + const rest = toBuffer !== 0 ? chunk - bufferIndex : chunk; + + for (let i = 0; i < channels; i++) { + const audioData = this.audioData[i]; + if (!audioData[nowIndex]) { + audioData.push(new Float32Array(chunk)); + } + const toPush = data.channelData[i].slice(buffered, buffered + rest); + + audioData[nowIndex].set(toPush, toBuffer); + } + buffered += rest; + nowIndex++; + toBuffer = 0; + } + + this.buffered += + info.reduce((prev, curr) => prev + curr.duration, 0) / 1000; + this.bufferedSamples += info.reduce( + (prev, curr) => prev + curr.samples, + 0 + ); + } + + /** + * 检查已缓冲内容,并在未开始播放时播放 + */ + checkBufferedPlay() { + if (this.playing || this.sampleRate === 0) return; + const played = this.lastBufferSamples / this.sampleRate; + const dt = this.buffered - played; + if (this.loaded) { + this.playAudio(played); + return; + } + if (dt < this.bufferPlayDuration) return; + + this.lastBufferSamples = this.bufferedSamples; + // 需要播放 + this.mergeBuffers(); + if (!this.buffer) return; + if (this.playing) this.output.stop(); + this.createSourceNode(this.buffer); + this.output.loop = false; + this.output.start(0, played); + this.lastStartTime = this.ac.currentTime; + this.playing = true; + this.output.addEventListener("ended", () => { + this.playing = false; + this.checkBufferedPlay(); + }); + } + + mergeBuffers() { + const buffer = this.ac.createBuffer( + this.audioData.length, + this.bufferedSamples, + this.sampleRate + ); + const chunk = this.sampleRate * this.bufferChunkSize; + const bufferedChunks = Math.floor(this.bufferedSamples / chunk); + const restLength = this.bufferedSamples % chunk; + for (let i = 0; i < this.audioData.length; i++) { + const audio = this.audioData[i]; + const data = new Float32Array(this.bufferedSamples); + for (let j = 0; j < bufferedChunks; j++) { + data.set(audio[j], chunk * j); + } + if (restLength !== 0) { + data.set( + audio[bufferedChunks].slice(0, restLength), + chunk * bufferedChunks + ); + } + + buffer.copyToChannel(data, i, 0); + } + this.buffer = buffer; + } + + async start() { + delete this.buffer; + this.headerRecieved = false; + this.audioType = ""; + this.errored = false; + this.buffered = 0; + this.sampleRate = 0; + this.bufferedSamples = 0; + this.duration = 0; + this.loaded = false; + if (this.playing) this.output.stop(); + this.playing = false; + this.lastStartTime = this.ac.currentTime; + } + + end(done, reason) { + if (done && this.buffer) { + this.loaded = true; + delete this.controller; + this.mergeBuffers(); + + this.duration = this.buffered; + this.audioData = []; + this.decoder?.destroy(); + delete this.decoder; + delete this.parser; + } else { + console.warn( + "Unexpected end when loading stream audio, reason: '" + + (reason ?? "") + + "'" + ); + } + } + + playAudio(when) { + if (!this.buffer) return; + this.lastStartTime = this.ac.currentTime; + if (this.playing) this.output.stop(); + if (this.route.status !== AudioStatus.Playing) { + this.route.status = AudioStatus.Playing; + } + this.createSourceNode(this.buffer); + this.output.start(0, when); + this.playing = true; + + this.output.addEventListener("ended", () => { + this.playing = false; + if (this.route.status === AudioStatus.Playing) { + this.route.status = AudioStatus.Stoped; + } + if (this.loop && !this.output.loop) this.play(0); + }); + } + /** + * 开始播放这个音频源 + */ + play(when) { + if (this.playing || this.errored) return; + if (this.loaded && this.buffer) { + this.playing = true; + this.playAudio(when); + } else { + this.controller?.start(); + } + } + + createSourceNode(buffer) { + if (!this.target) return; + const node = this.ac.createBufferSource(); + node.buffer = buffer; + if (this.playing) this.output.stop(); + this.playing = false; + this.output = node; + node.connect(this.target.input); + node.loop = this.loop; + } + /** + * 停止播放这个音频源 + * @returns 音频暂停的时刻 number + */ + stop() { + if (this.playing) this.output.stop(); + this.playing = false; + return this.ac.currentTime - this.lastStartTime; + } + /** + * 连接到音频路由图上,每次调用播放的时候都会执行一次 + * @param target 连接至的目标 IAudioInput + */ + connect(target) { + this.target = target; + } + /** + * 设置是否循环播放 + * @param loop 是否循环 boolean) + */ + setLoop(loop) { + this.loop = loop; + } + } + class AudioElementSource { + constructor(context) { + const audio = new Audio(); + audio.preload = "none"; + this.output = context.createMediaElementSource(audio); + this.audio = audio; + this.ac = context; + audio.addEventListener("play", () => { + this.playing = true; + if (this.route.status !== AudioStatus.Playing) { + this.route.status = AudioStatus.Playing; + } + }); + audio.addEventListener("ended", () => { + this.playing = false; + if (this.route.status === AudioStatus.Playing) { + this.route.status = AudioStatus.Stoped; + } + }); + } + get duration() { + return this.audio.duration; + } + get currentTime() { + return this.audio.currentTime; + } + /** + * 设置音频源的路径 + * @param url 音频路径 + */ + setSource(url) { + this.audio.src = url; + } + + play(when = 0) { + if (this.playing) return; + this.audio.currentTime = when; + this.audio.play(); + } + + stop() { + this.audio.pause(); + this.playing = false; + if (this.route.status === AudioStatus.Playing) { + this.route.status = AudioStatus.Stoped; + } + return this.audio.currentTime; + } + + connect(target) { + this.output.connect(target.input); + } + + setLoop(loop) { + this.audio.loop = loop; + } + } + class AudioBufferSource { + constructor(context) { + this.output = context.createBufferSource(); + /** 是否循环 */ + this.loop = false; + /** 上一次播放是从何时开始的 */ + this.lastStartWhen = 0; + /** 播放开始时刻 */ + this.lastStartTime = 0; + this.duration = 0; + this.ac = context; + } + get currentTime() { + return this.ac.currentTime - this.lastStartTime + this.lastStartWhen; + } + + /** + * 设置音频源数据 + * @param buffer 音频源,可以是未解析的 ArrayBuffer,也可以是已解析的 AudioBuffer + */ + async setBuffer(buffer) { + if (buffer instanceof ArrayBuffer) { + this.buffer = await this.ac.decodeAudioData(buffer); + } else { + this.buffer = buffer; + } + this.duration = this.buffer.duration; + } + + play(when) { + if (this.playing || !this.buffer) return; + this.playing = true; + this.lastStartTime = this.ac.currentTime; + if (this.route.status !== AudioStatus.Playing) { + this.route.status = AudioStatus.Playing; + } + this.createSourceNode(this.buffer); + this.output.start(0, when); + this.output.addEventListener("ended", () => { + this.playing = false; + if (this.route.status === AudioStatus.Playing) { + this.route.status = AudioStatus.Stoped; + } + if (this.loop && !this.output.loop) this.play(0); + }); + } + + createSourceNode(buffer) { + if (!this.target) return; + const node = this.ac.createBufferSource(); + node.buffer = buffer; + this.output = node; + node.connect(this.target.input); + node.loop = this.loop; + } + + stop() { + this.output.stop(); + return this.ac.currentTime - this.lastStartTime; + } + + connect(target) { + this.target = target; + } + + setLoop(loop) { + this.loop = loop; + } + } + class AudioPlayer { + constructor() { + /** 音频播放上下文 */ + this.ac = new AudioContext(); + /** 音量节点 */ + this.gain = this.ac.createGain(); + this.gain.connect(this.ac.destination); + this.audioRoutes = new Map(); + } + /** + * 解码音频数据 + * @param data 音频数据 + */ + decodeAudioData(data) { + return AudioDecoder.decodeAudioData(data, this); + } + /** + * 设置音量 + * @param volume 音量 + */ + setVolume(volume) { + this.gain.gain.value = volume; + } + + /** + * 获取音量 + */ + getVolume() { + return this.gain.gain.value; + } + + /** + * 创建一个音频源 + * @param Source 音频源类 + */ + createSource(Source) { + return new Source(this.ac); + } + + /** + * 创建一个兼容流式音频源,可以与流式加载相结合,主要用于处理 opus ogg 不兼容的情况 + */ + createStreamSource() { + return new AudioStreamSource(this.ac); + } + + /** + * 创建一个通过 audio 元素播放的音频源 + */ + createElementSource() { + return new AudioElementSource(this.ac); + } + + /** + * 创建一个通过 AudioBuffer 播放的音频源 + */ + createBufferSource() { + return new AudioBufferSource(this.ac); + } + + /** + * 获取音频目的地 + */ + getDestination() { + return this.gain; + } + + /** + * 创建一个音频效果器 + * @param Effect 效果器类 + */ + createEffect(Effect) { + return new Effect(this.ac); + } + + /** + * 创建一个修改音量的效果器 + * ```txt + * |----------| + * Input ----> | GainNode | ----> Output + * |----------| + * ``` + */ + createVolumeEffect() { + return new VolumeEffect(this.ac); + } + + /** + * 创建一个立体声效果器 + * ```txt + * |------------| + * Input ----> | PannerNode | ----> Output + * |------------| + * ``` + */ + createStereoEffect() { + return new StereoEffect(this.ac); + } + + /** + * 创建一个修改单个声道音量的效果器 + * ```txt + * |----------| + * -> | GainNode | \ + * |--------------| / |----------| -> |------------| + * Input ----> | SplitterNode | ...... | MergerNode | ----> Output + * |--------------| \ |----------| -> |------------| + * -> | GainNode | / + * |----------| + * ``` + */ + createChannelVolumeEffect() { + return new ChannelVolumeEffect(this.ac); + } + + /** + * 创建一个延迟效果器 + * |-----------| + * Input ----> | DelayNode | ----> Output + * |-----------| + */ + createDelay() { + return new DelayEffect(this.ac); + } + + /** + * 创建一个回声效果器 + * ```txt + * |----------| + * Input ----> | GainNode | ----> Output + * ^ |----------| | + * | | + * | |------------| ↓ + * |-- | Delay Node | <-- + * |------------| + * ``` + */ + createEchoEffect() { + return new EchoEffect(this.ac); + } + + /** + * 创建一个音频播放路由 + * @param source 音频源 + */ + createRoute(source) { + return new AudioRoute(source, this); + } + + /** + * 添加一个音频播放路由,可以直接被播放 + * @param id 这个音频播放路由的名称 + * @param route 音频播放路由对象 + */ + addRoute(id, route) { + if (!this.audioRoutes) this.audioRoutes = new Map(); + if (this.audioRoutes.has(id)) { + console.warn( + "Audio route with id of '" + + id + + "' has already existed. New route will override old route." + ); + } + this.audioRoutes.set(id, route); + } + + /** + * 根据名称获取音频播放路由对象 + * @param id 音频播放路由的名称 + */ + getRoute(id) { + return this.audioRoutes.get(id); + } + /** + * 移除一个音频播放路由 + * @param id 要移除的播放路由的名称 + */ + removeRoute(id) { + this.audioRoutes.delete(id); + } + /** + * 播放音频 + * @param id 音频名称 + * @param when 从音频的哪个位置开始播放,单位秒 + */ + play(id, when) { + const route = this.getRoute(id); + if (!route) { + console.warn( + "Cannot play audio route '" + + id + + "', since there is not added route named it." + ); + return; + } + + route.play(when); + } + + /** + * 暂停音频播放 + * @param id 音频名称 + * @returns 当音乐真正停止时兑现 + */ + pause(id) { + const route = this.getRoute(id); + if (!route) { + console.warn( + "Cannot pause audio route '" + + id + + "', since there is not added route named it." + ); + return; + } + return route.pause(); + } + + /** + * 停止音频播放 + * @param id 音频名称 + * @returns 当音乐真正停止时兑现 + */ + stop(id) { + const route = this.getRoute(id); + if (!route) { + console.warn( + "Cannot stop audio route '" + + id + + "', since there is not added route named it." + ); + return; + } + return route.stop(); + } + + /** + * 继续音频播放 + * @param id 音频名称 + */ + resume(id) { + const route = this.getRoute(id); + if (!route) { + console.warn( + "Cannot pause audio route '" + + id + + "', since there is not added route named it." + ); + return; + } + route.resume(); + } + + /** + * 设置听者位置,x正方向水平向右,y正方向垂直于地面向上,z正方向垂直屏幕远离用户 + * @param x 位置x坐标 + * @param y 位置y坐标 + * @param z 位置z坐标 + */ + setListenerPosition(x, y, z) { + const listener = this.ac.listener; + listener.positionX.value = x; + listener.positionY.value = y; + listener.positionZ.value = z; + } + + /** + * 设置听者朝向,x正方向水平向右,y正方向垂直于地面向上,z正方向垂直屏幕远离用户 + * @param x 朝向x坐标 + * @param y 朝向y坐标 + * @param z 朝向z坐标 + */ + setListenerOrientation(x, y, z) { + const listener = this.ac.listener; + listener.forwardX.value = x; + listener.forwardY.value = y; + listener.forwardZ.value = z; + } + + /** + * 设置听者头顶朝向,x正方向水平向右,y正方向垂直于地面向上,z正方向垂直屏幕远离用户 + * @param x 头顶朝向x坐标 + * @param y 头顶朝向y坐标 + * @param z 头顶朝向z坐标 + */ + setListenerUp(x, y, z) { + const listener = this.ac.listener; + listener.upX.value = x; + listener.upY.value = y; + listener.upZ.value = z; + } + } + class AudioRoute { + constructor(source, player) { + source.route = this; + this.output = source.output; + + /** 效果器路由图 */ + this.effectRoute = []; + + /** 结束时长,当音频暂停或停止时,会经过这么长时间之后才真正终止播放,期间可以做音频淡入淡出等效果 */ + this.endTime = 0; + /** 暂停时播放了多长时间 */ + this.pauseCurrentTime = 0; + /** 当前播放状态 */ + this.player = player; + this.status = AudioStatus.Stoped; + + this.shouldStop = false; + /** + * 每次暂停或停止时自增,用于判断当前正在处理的情况。 + * 假如暂停后很快播放,然后很快暂停,那么需要根据这个来判断实际是否应该执行暂停后操作 + */ + this.stopIdentifier = 0; + /** 暂停时刻 */ + this.pauseTime = 0; + this.source = source; + this.source.player = player; + } + /** 音频时长,单位秒 */ + get duration() { + return this.source.duration; + } + /** 当前播放了多长时间,单位秒 */ + get currentTime() { + if (this.status === AudioStatus.Paused) { + return this.pauseCurrentTime; + } else { + return this.source.currentTime; + } + } + set currentTime(time) { + this.source.stop(); + this.source.play(time); + } + /** + * 设置结束时间,暂停或停止时,会经过这么长时间才终止音频的播放,这期间可以做一下音频淡出的效果。 + * @param time 暂停或停止时,经过多长时间之后才会结束音频的播放 + */ + setEndTime(time) { + this.endTime = time; + } + + /** + * 当音频播放时执行的函数,可以用于音频淡入效果 + * @param fn 音频开始播放时执行的函数 + */ + onStart(fn) { + this.audioStartHook = fn; + } + + /** + * 当音频暂停或停止时执行的函数,可以用于音频淡出效果 + * @param fn 音频在暂停或停止时执行的函数,不填时表示取消这个钩子。 + * 包含两个参数,第一个参数是结束时长,第二个参数是当前音频播放路由对象 + */ + onEnd(fn) { + this.audioEndHook = fn; + } + + /** + * 开始播放这个音频 + * @param when 从音频的什么时候开始播放,单位秒 + */ + async play(when = 0) { + if (this.status === AudioStatus.Playing) return; + this.link(); + await this.player.ac.resume(); + if (this.effectRoute.length > 0) { + const first = this.effectRoute[0]; + this.source.connect(first); + const last = this.effectRoute.at(-1); + last.connect({ input: this.player.getDestination() }); + } else { + this.source.connect({ input: this.player.getDestination() }); + } + this.source.play(when); + this.status = AudioStatus.Playing; + this.pauseTime = 0; + this.audioStartHook?.(this); + this.startAllEffect(); + if (this.status !== AudioStatus.Playing) { + this.status = AudioStatus.Playing; + } + } + + /** + * 暂停音频播放 + */ + async pause() { + if (this.status !== AudioStatus.Playing) return; + this.status = AudioStatus.Pausing; + this.stopIdentifier++; + const identifier = this.stopIdentifier; + if (this.audioEndHook) { + this.audioEndHook(this.endTime, this); + await sleep(this.endTime); + } + if ( + this.status !== AudioStatus.Pausing || + this.stopIdentifier !== identifier + ) { + return; + } + this.pauseCurrentTime = this.source.currentTime; + const time = this.source.stop(); + this.pauseTime = time; + if (this.shouldStop) { + this.status = AudioStatus.Stoped; + this.endAllEffect(); + + this.shouldStop = false; + } else { + this.status = AudioStatus.Paused; + this.endAllEffect(); + } + this.endAllEffect(); + } + + /** + * 继续音频播放 + */ + resume() { + if (this.status === AudioStatus.Playing) return; + if ( + this.status === AudioStatus.Pausing || + this.status === AudioStatus.Stoping + ) { + this.audioStartHook?.(this); + + return; + } + if (this.status === AudioStatus.Paused) { + this.play(this.pauseTime); + } else { + this.play(0); + } + this.status = AudioStatus.Playing; + this.pauseTime = 0; + this.audioStartHook?.(this); + this.startAllEffect(); + } + + /** + * 停止音频播放 + */ + async stop() { + if (this.status !== AudioStatus.Playing) { + if (this.status === AudioStatus.Pausing) { + this.shouldStop = true; + } + return; + } + this.status = AudioStatus.Stoping; + this.stopIdentifier++; + const identifier = this.stopIdentifier; + if (this.audioEndHook) { + this.audioEndHook(this.endTime, this); + await sleep(this.endTime); + } + if ( + this.status !== AudioStatus.Stoping || + this.stopIdentifier !== identifier + ) { + return; + } + this.source.stop(); + this.status = AudioStatus.Stoped; + this.pauseTime = 0; + this.endAllEffect(); + } + + /** + * 添加效果器 + * @param effect 要添加的效果,可以是数组,表示一次添加多个 + * @param index 从哪个位置开始添加,如果大于数组长度,那么加到末尾,如果小于0,那么将会从后面往前数。默认添加到末尾 + */ + addEffect(effect, index) { + if (isNil(index)) { + if (effect instanceof Array) { + this.effectRoute.push(...effect); + } else { + this.effectRoute.push(effect); + } + } else { + if (effect instanceof Array) { + this.effectRoute.splice(index, 0, ...effect); + } else { + this.effectRoute.splice(index, 0, effect); + } + } + this.setOutput(); + if (this.source.playing) this.link(); + } + + /** + * 移除一个效果器 + * @param effect 要移除的效果 + */ + removeEffect(effect) { + const index = this.effectRoute.indexOf(effect); + if (index === -1) return; + this.effectRoute.splice(index, 1); + effect.disconnect(); + this.setOutput(); + if (this.source.playing) this.link(); + } + + setOutput() { + const effect = this.effectRoute.at(-1); + if (!effect) this.output = this.source.output; + else this.output = effect.output; + } + + /** + * 连接音频路由图 + */ + link() { + this.effectRoute.forEach((v) => v.disconnect()); + this.effectRoute.forEach((v, i) => { + const next = this.effectRoute[i + 1]; + if (next) { + v.connect(next); + } + }); + } + + startAllEffect() { + this.effectRoute.forEach((v) => v.start()); + } + + endAllEffect() { + this.effectRoute.forEach((v) => v.end()); + } + } + + const audioPlayer = new AudioPlayer(); + + class BgmController { + constructor(player) { + this.mainGain = player.createVolumeEffect(); + this.player = player; + /** bgm音频名称的前缀 */ + this.prefix = "bgms."; + /** 每个 bgm 的音量控制器 */ + this.gain = new Map(); + + /** 正在播放的 bgm */ + this.playingBgm = ""; + /** 是否正在播放 */ + this.playing = false; + + /** 是否已经启用 */ + this.enabled = true; + /** 是否屏蔽所有的音乐切换 */ + this.blocking = false; + /** 渐变时长 */ + this.transitionTime = 2000; + } + + /** + * 设置音频渐变时长 + * @param time 渐变时长 + */ + setTransitionTime(time) { + this.transitionTime = time; + for (const [, value] of this.gain) { + value.transition.time(time); + } + } + + /** + * 屏蔽音乐切换 + */ + blockChange() { + this.blocking = true; + } + + /** + * 取消屏蔽音乐切换 + */ + unblockChange() { + this.blocking = false; + } + + /** + * 设置总音量大小 + * @param volume 音量大小 + */ + setVolume(volume) { + this.mainGain.setVolume(volume); + this._volume = volume; + } + /** + * 获取总音量大小 + */ + getVolume() { + return this.mainGain.getVolume(); + } + /** + * 设置是否启用 + * @param enabled 是否启用 + */ + setEnabled(enabled) { + if (enabled) this.resume(); + else this.stop(); + this.enabled = enabled; + } + + /** + * 设置 bgm 音频名称的前缀 + */ + setPrefix(prefix) { + this.prefix = prefix; + } + + getId(name) { + return `${this.prefix}${name}`; + } + + /** + * 根据 bgm 名称获取其 AudioRoute 实例 + * @param id 音频名称 + */ + get(id) { + return this.player.getRoute(this.getId(id)); + } + + /** + * 添加一个 bgm + * @param id 要添加的 bgm 的名称 + * @param url 指定 bgm 的加载地址 + */ + addBgm(id, url = `project/bgms/${id}`) { + const type = guessTypeByExt(id); + if (!type) { + console.warn( + "Unknown audio extension name: '" + + id.split(".").slice(0, -1).join(".") + + "'" + ); + return; + } + const gain = this.player.createVolumeEffect(); + if (isAudioSupport(type)) { + const source = audioPlayer.createElementSource(); + source.setSource(url); + source.setLoop(true); + const route = new AudioRoute(source, audioPlayer); + route.addEffect([gain, this.mainGain]); + audioPlayer.addRoute(this.getId(id), route); + this.setTransition(id, route, gain); + } else { + const source = audioPlayer.createStreamSource(); + const stream = new StreamLoader(url); + stream.pipe(source); + source.setLoop(true); + const route = new AudioRoute(source, audioPlayer); + route.addEffect([gain, this.mainGain]); + audioPlayer.addRoute(this.getId(id), route); + this.setTransition(id, route, gain); + } + } + + /** + * 移除一个 bgm + * @param id 要移除的 bgm 的名称 + */ + removeBgm(id) { + this.player.removeRoute(this.getId(id)); + const gain = this.gain.get(id); + gain?.transition.ticker.destroy(); + this.gain.delete(id); + } + + setTransition(id, route, gain) { + const transition = new Transition(); + transition + .time(this.transitionTime) + .mode(linear()) + .transition("volume", 0); + + const tick = () => { + gain.setVolume(transition.value.volume); + }; + + /** + * @param expect 在结束时应该是正在播放还是停止 + */ + const setTick = async (expect) => { + transition.ticker.remove(tick); + transition.ticker.add(tick); + const identifier = route.stopIdentifier; + await sleep(this.transitionTime + 500); + if (route.status === expect && identifier === route.stopIdentifier) { + transition.ticker.remove(tick); + if (route.status === AudioStatus.Playing) { + gain.setVolume(1); + } else { + gain.setVolume(0); + } + } + }; + + route.onStart(async () => { + transition.transition("volume", 1); + setTick(AudioStatus.Playing); + }); + route.onEnd(() => { + transition.transition("volume", 0); + setTick(AudioStatus.Paused); + }); + route.setEndTime(this.transitionTime); + + this.gain.set(id, { effect: gain, transition }); + } + + /** + * 播放一个 bgm + * @param id 要播放的 bgm 名称 + */ + play(id, when) { + if (this.blocking) return; + if (id !== this.playingBgm && this.playingBgm) { + this.player.pause(this.getId(this.playingBgm)); + } + this.playingBgm = id; + if (!this.enabled) return; + this.player.play(this.getId(id), when); + this.playing = true; + } + + /** + * 继续当前的 bgm + */ + resume() { + if (this.blocking || !this.enabled || this.playing) return; + if (this.playingBgm) { + this.player.resume(this.getId(this.playingBgm)); + } + this.playing = true; + } + + /** + * 暂停当前的 bgm + */ + pause() { + if (this.blocking || !this.enabled) return; + if (this.playingBgm) { + this.player.pause(this.getId(this.playingBgm)); + } + this.playing = false; + } + + /** + * 停止当前的 bgm + */ + stop() { + if (this.blocking || !this.enabled) return; + if (this.playingBgm) { + this.player.stop(this.getId(this.playingBgm)); + } + this.playing = false; + } + } + const bgmController = new BgmController(audioPlayer); + + class SoundPlayer { + constructor(player) { + /** 每个音效的唯一标识符 */ + this.num = 0; + this.enabled = true; + this.gain = player.createVolumeEffect(); + /** 每个音效的数据 */ + this.buffer = new Map(); + /** 所有正在播放的音乐 */ + this.playing = new Set(); + this.player = player; + } + /** + * 设置是否启用音效 + * @param enabled 是否启用音效 + */ + setEnabled(enabled) { + if (!enabled) this.stopAllSounds(); + this.enabled = enabled; + } + + /** + * 设置音量大小 + * @param volume 音量大小 + */ + setVolume(volume) { + this.gain.setVolume(volume); + } + /** + * 获取音量大小 + */ + getVolume() { + return this.gain.getVolume(); + } + /** + * 添加一个音效 + * @param id 音效名称 + * @param data 音效的Uint8Array数据 + */ + async add(id, data) { + const buffer = await this.player.decodeAudioData(data); + if (!buffer) { + console.warn( + "Cannot decode sound '" + + id + + "', since audio file may not supported by 2.b." + ); + return; + } + this.buffer.set(id, buffer); + } + + /** + * 播放一个音效 + * @param id 音效名称 + * @param position 音频位置,[0, 0, 0]表示正中心,x轴指向水平向右,y轴指向水平向上,z轴指向竖直向上 + * @param orientation 音频朝向,[0, 1, 0]表示朝向前方 + */ + play(id, position = [0, 0, 0], orientation = [1, 0, 0]) { + if (!this.enabled || !id) return -1; + const buffer = this.buffer.get(id); + if (!buffer) { + console.warn( + "Cannot play sound '" + + id + + "', since there is no added data named it." + ); + return -1; + } + const soundNum = this.num++; + + const source = this.player.createBufferSource(); + source.setBuffer(buffer); + const route = this.player.createRoute(source); + const stereo = this.player.createStereoEffect(); + stereo.setPosition(position[0], position[1], position[2]); + stereo.setOrientation(orientation[0], orientation[1], orientation[2]); + route.addEffect([stereo, this.gain]); + this.player.addRoute(`sounds.${soundNum}`, route); + route.play(); + source.output.addEventListener("ended", () => { + this.playing.delete(soundNum); + }); + this.playing.add(soundNum); + return soundNum; + } + + /** + * 停止一个音效 + * @param num 音效的唯一 id + */ + stop(num) { + const id = `sounds.${num}`; + const route = this.player.getRoute(id); + if (route) { + route.stop(); + this.player.removeRoute(id); + this.playing.delete(num); + } + } + + /** + * 停止播放所有音效 + */ + stopAllSounds() { + this.playing.forEach((v) => { + const id = `sounds.${v}`; + const route = this.player.getRoute(id); + if (route) { + route.stop(); + this.player.removeRoute(id); + } + }); + this.playing.clear(); + } + } + const soundPlayer = new SoundPlayer(audioPlayer); + + function loadAllBgm() { + const data = data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d; + for (const bgm of data.main.bgms) { + bgmController.addBgm(bgm); + } + } + loadAllBgm(); + AudioDecoder.registerDecoder(AudioType.Ogg, VorbisDecoder); + AudioDecoder.registerDecoder(AudioType.Opus, OpusDecoder); + + core.plugin.audioSystem = { + AudioType, + AudioDecoder, + AudioStatus, + checkAudioType, + isAudioSupport, + audioPlayer, + soundPlayer, + bgmController, + guessTypeByExt, + BgmController, + SoundPlayer, + EchoEffect, + DelayEffect, + ChannelVolumeEffect, + VolumeEffect, + StereoEffect, + AudioEffect, + AudioPlayer, + AudioRoute, + AudioStreamSource, + AudioElementSource, + AudioBufferSource, + loadAllBgm, + StreamLoader, + }; + //bgm相关复写 + control.prototype.playBgm = (bgm, when) => { + bgm = core.getMappedName(bgm); + bgmController.play(bgm, when); + core.setMusicBtn(); + }; + control.prototype.pauseBgm = () => { + bgmController.pause(); + core.setMusicBtn(); + }; + + control.prototype.resumeBgm = function () { + bgmController.resume(); + core.setMusicBtn(); + }; + control.prototype.checkBgm = function () { + core.playBgm(bgmController.playingBgm || main.startBgm); + }; + control.prototype.triggerBgm = function () { + core.musicStatus.bgmStatus = !core.musicStatus.bgmStatus; + if (bgmController.playing) bgmController.pause(); + else bgmController.resume(); + core.setMusicBtn(); + core.setLocalStorage("bgmStatus", core.musicStatus.bgmStatus); + }; + //sound相关复写 + control.prototype.playSound = function ( + sound, + _pitch, + callback, + position, + orientation + ) { + if (main.mode != "play" || !core.musicStatus.soundStatus) return; + const name = core.getMappedName(sound); + const num = soundPlayer.play(name, position, orientation); + const route = audioPlayer.getRoute(`sounds.${num}`); + if (!route) { + callback?.(); + return -1; + } else { + sleep(route.duration * 1000).then(() => callback?.()); + return num; + } + }; + control.prototype.stopSound = function (id) { + if (isNil(id)) { + soundPlayer.stopAllSounds(); + } else { + soundPlayer.stop(id); + } + }; + control.prototype.getPlayingSounds = function () { + return [...soundPlayer.playing]; + }; + //sound加载复写 + loader.prototype._loadOneSound_decodeData = function (name, data) { + if (data instanceof Blob) { + var blobReader = new zip.BlobReader(data); + blobReader.init(function () { + blobReader.readUint8Array(0, blobReader.size, function (uint8) { + //core.loader._loadOneSound_decodeData(name, uint8.buffer); + soundPlayer.add(name, uint8); + }); + }); + return; + } + if (data instanceof ArrayBuffer) { + const uint8 = new Uint8Array(data); + soundPlayer.add(name, uint8); + } + }; + //音量控制复写 + soundPlayer.setVolume( + core.musicStatus.userVolume * core.musicStatus.designVolume + ); + bgmController.setVolume( + core.musicStatus.userVolume * core.musicStatus.designVolume + ); + actions.prototype._clickSwitchs_sounds_userVolume = function (delta) { + var value = Math.round(Math.sqrt(100 * core.musicStatus.userVolume)); + if (value == 0 && delta < 0) return; + core.musicStatus.userVolume = core.clamp( + Math.pow(value + delta, 2) / 100, + 0, + 1 + ); + //audioContext 音效 不受designVolume 影响 + if (core.musicStatus.gainNode != null) + core.musicStatus.gainNode.gain.value = core.musicStatus.userVolume; + soundPlayer.setVolume( + core.musicStatus.userVolume * core.musicStatus.designVolume + ); + bgmController.setVolume( + core.musicStatus.userVolume * core.musicStatus.designVolume + ); + core.setLocalStorage("userVolume", core.musicStatus.userVolume); + core.playSound("确定"); + core.ui._drawSwitchs_sounds(); + }; + }, "自定义常用事件": function () { - // editorBlocklyconfigPlus.js - // 自訂常見事件模板插件 - // 本插件引用了通用函數插件(Utility.js) - // 適用樣板:2.10.3 - // 請注意: - // 此插件對事件編輯器(editor_blocklyconfig)進行複寫,若還有其它針對事件編輯器做複寫的插件,請謹慎使用! - // 此插件對表格操作行為(editor_mode.doActionList)進行複寫,若還有其它對表格操作行為做複寫的插件,請謹慎使用! - // 使用方法: - // 現在在主頁下拉選單多了個常用事件模版,在那邊可以自由設定常用事件模板。 - // 設定完後按F5刷新,再到事件編輯器看就有你設定好的常用事件模板了。 + // editorBlocklyconfigPlus.js + // 自訂常見事件模板插件 + // 本插件引用了通用函數插件(Utility.js) + // 適用樣板:2.10.3 + // 請注意: + // 此插件對事件編輯器(editor_blocklyconfig)進行複寫,若還有其它針對事件編輯器做複寫的插件,請謹慎使用! + // 此插件對表格操作行為(editor_mode.doActionList)進行複寫,若還有其它對表格操作行為做複寫的插件,請謹慎使用! + // 使用方法: + // 現在在主頁下拉選單多了個常用事件模版,在那邊可以自由設定常用事件模板。 + // 設定完後按F5刷新,再到事件編輯器看就有你設定好的常用事件模板了。 - if (main.mode == "editor") { - //#region 配置表格初始化 - let TableFileName = "project/table/CommonEventTemplate_comment.js"; - let TableRow = ` + if (main.mode == "editor") { + //#region 配置表格初始化 + let TableFileName = "project/table/CommonEventTemplate_comment.js"; + let TableRow = ` var CommonEventTemplate_comment = {"_type": "object", "_data": { "CommonEventTemplate": { @@ -11210,221 +11620,241 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = } }} `; - if (!events_c12a15a8_c380_4b28_8144_256cba95f760.CommonEventTemplate) { - /** - * @type {{[EvnetName:actionParserJson]}} - */ - events_c12a15a8_c380_4b28_8144_256cba95f760.CommonEventTemplate = { - 检测音乐如果没有开启则系统提示开启: [{ - type: "if", - condition: "!core.musicStatus.bgmStatus", - true: [ - "\t[系统提示]你当前音乐处于关闭状态,本塔开音乐游戏效果更佳", - ], - false: [], - }, ], - 仿新新魔塔一次性商人: [{ - type: "if", - condition: "switch:A", - true: [ - "\t[行商,trader]\b[this]这是购买我的道具后我给玩家的提示。", - { - type: "comment", - text: "下一条指令可视情况使用或不使用", - }, - { - type: "hide", - remove: true, - time: 250, - }, - ], - false: [{ - type: "confirm", - text: "我有3把黄钥匙,\n你出50金币就卖给你。", - yes: [{ - type: "if", - condition: "status:money>=50", - true: [{ - type: "setValue", - name: "status:money", - operator: "-=", - value: "50", - }, - { - type: "setValue", - name: "item:yellowKey", - operator: "+=", - value: "3", - }, - { - type: "playSound", - name: "确定", - stop: true, - }, - { - type: "setValue", - name: "switch:A", - value: "true", - }, - ], - false: [{ - type: "playSound", - name: "操作失败", - }, - "\t[行商,trader]\b[this]你的金币不足!", - ], - }, ], - no: [], - }, ], - }, ], - 全地图选中一个点: [{ - type: "comment", - text: "全地图选中一个点,需要用鼠标或触屏操作", - }, - { - type: "setValue", - name: "temp:X", - value: "status:x", - }, - { - type: "setValue", - name: "temp:Y", - value: "status:y", - }, - { - type: "tip", - text: "再次点击闪烁位置确认", - }, - { - type: "while", - condition: "true", - data: [{ - type: "drawSelector", - image: "winskin.webp", - code: 1, - x: "32*temp:X", - y: "32*temp:Y", - width: 32, - height: 32, - }, - { - type: "wait", - }, - { - type: "if", - condition: "(flag:type === 1)", - true: [{ - type: "if", - condition: "((temp:X===flag:x)&&(temp:Y===flag:y))", - true: [{ - type: "break", - n: 1, - }, ], - }, - { - type: "setValue", - name: "temp:X", - value: "flag:x", - }, - { - type: "setValue", - name: "temp:Y", - value: "flag:y", - }, - ], - }, - ], - }, - { - type: "drawSelector", - code: 1, - }, - { - type: "comment", - text: "流程进行到这里可以对[X,Y]点进行处理,比如", - }, - { - type: "closeDoor", - id: "yellowDoor", - loc: ["temp:X", "temp:Y"], - }, - ], - 多阶段Boss战斗: [{ - type: "comment", - text: "多阶段boss,请直接作为战后事件使用", - }, - { - type: "setValue", - name: "switch:A", - operator: "+=", - value: "1", - }, - { - type: "switch", - condition: "switch:A", - caseList: [{ - case: "1", - action: [{ - type: "setBlock", - number: "redSlime", - }, - "\t[2阶段boss,redSlime]\b[this]你以为你已经打败我了吗?没听说过史莱姆有九条命吗?", - ], - }, - { - case: "2", - action: [{ - type: "setBlock", - number: "blackSlime", - }, - "\t[3阶段boss,blackSlime]\b[this]不能消灭我的,只会让我更强大!", - ], - }, - { - case: "3", - action: [{ - type: "setBlock", - number: "slimelord", - }, - "\t[4阶段boss,slimelord]\b[this]我还能打!", - ], - }, - { - case: "4", - action: ["\t[4阶段boss,slimelord]我一定会回来的!"], - }, - ], - }, - ], - }; - } - //#endregion + if (!events_c12a15a8_c380_4b28_8144_256cba95f760.CommonEventTemplate) { + /** + * @type {{[EvnetName:actionParserJson]}} + */ + events_c12a15a8_c380_4b28_8144_256cba95f760.CommonEventTemplate = { + 检测音乐如果没有开启则系统提示开启: [ + { + type: "if", + condition: "!core.musicStatus.bgmStatus", + true: [ + "\t[系统提示]你当前音乐处于关闭状态,本塔开音乐游戏效果更佳", + ], + false: [], + }, + ], + 仿新新魔塔一次性商人: [ + { + type: "if", + condition: "switch:A", + true: [ + "\t[行商,trader]\b[this]这是购买我的道具后我给玩家的提示。", + { + type: "comment", + text: "下一条指令可视情况使用或不使用", + }, + { + type: "hide", + remove: true, + time: 250, + }, + ], + false: [ + { + type: "confirm", + text: "我有3把黄钥匙,\n你出50金币就卖给你。", + yes: [ + { + type: "if", + condition: "status:money>=50", + true: [ + { + type: "setValue", + name: "status:money", + operator: "-=", + value: "50", + }, + { + type: "setValue", + name: "item:yellowKey", + operator: "+=", + value: "3", + }, + { + type: "playSound", + name: "确定", + stop: true, + }, + { + type: "setValue", + name: "switch:A", + value: "true", + }, + ], + false: [ + { + type: "playSound", + name: "操作失败", + }, + "\t[行商,trader]\b[this]你的金币不足!", + ], + }, + ], + no: [], + }, + ], + }, + ], + 全地图选中一个点: [ + { + type: "comment", + text: "全地图选中一个点,需要用鼠标或触屏操作", + }, + { + type: "setValue", + name: "temp:X", + value: "status:x", + }, + { + type: "setValue", + name: "temp:Y", + value: "status:y", + }, + { + type: "tip", + text: "再次点击闪烁位置确认", + }, + { + type: "while", + condition: "true", + data: [ + { + type: "drawSelector", + image: "winskin.webp", + code: 1, + x: "32*temp:X", + y: "32*temp:Y", + width: 32, + height: 32, + }, + { + type: "wait", + }, + { + type: "if", + condition: "(flag:type === 1)", + true: [ + { + type: "if", + condition: "((temp:X===flag:x)&&(temp:Y===flag:y))", + true: [ + { + type: "break", + n: 1, + }, + ], + }, + { + type: "setValue", + name: "temp:X", + value: "flag:x", + }, + { + type: "setValue", + name: "temp:Y", + value: "flag:y", + }, + ], + }, + ], + }, + { + type: "drawSelector", + code: 1, + }, + { + type: "comment", + text: "流程进行到这里可以对[X,Y]点进行处理,比如", + }, + { + type: "closeDoor", + id: "yellowDoor", + loc: ["temp:X", "temp:Y"], + }, + ], + 多阶段Boss战斗: [ + { + type: "comment", + text: "多阶段boss,请直接作为战后事件使用", + }, + { + type: "setValue", + name: "switch:A", + operator: "+=", + value: "1", + }, + { + type: "switch", + condition: "switch:A", + caseList: [ + { + case: "1", + action: [ + { + type: "setBlock", + number: "redSlime", + }, + "\t[2阶段boss,redSlime]\b[this]你以为你已经打败我了吗?没听说过史莱姆有九条命吗?", + ], + }, + { + case: "2", + action: [ + { + type: "setBlock", + number: "blackSlime", + }, + "\t[3阶段boss,blackSlime]\b[this]不能消灭我的,只会让我更强大!", + ], + }, + { + case: "3", + action: [ + { + type: "setBlock", + number: "slimelord", + }, + "\t[4阶段boss,slimelord]\b[this]我还能打!", + ], + }, + { + case: "4", + action: ["\t[4阶段boss,slimelord]我一定会回来的!"], + }, + ], + }, + ], + }; + } + //#endregion - // 新增模板選項 - let editModeSelect = document.getElementById("editModeSelect"); - let newEditModeOption = document.createElement("option"); - newEditModeOption.value = "CommonEventTemplate"; - newEditModeOption.text = "常見事件模板"; - editModeSelect.add(newEditModeOption); + // 新增模板選項 + let editModeSelect = document.getElementById("editModeSelect"); + let newEditModeOption = document.createElement("option"); + newEditModeOption.value = "CommonEventTemplate"; + newEditModeOption.text = "常見事件模板"; + editModeSelect.add(newEditModeOption); - //檢查可用的編輯模板ID - let leftIDNumber = 11 - 1; - let ExistLeftElement = document.querySelector(".main"); - while (ExistLeftElement) { - leftIDNumber++; - ExistLeftElement = document.getElementById(`left${leftIDNumber}`); - } + //檢查可用的編輯模板ID + let leftIDNumber = 11 - 1; + let ExistLeftElement = document.querySelector(".main"); + while (ExistLeftElement) { + leftIDNumber++; + ExistLeftElement = document.getElementById(`left${leftIDNumber}`); + } - //新增編輯模板 - let MainDiv = document.querySelector(".main"); + //新增編輯模板 + let MainDiv = document.querySelector(".main"); - let CommonEventTemplateMainDiv = document.createElement("div"); - CommonEventTemplateMainDiv.id = `left${leftIDNumber}`; - CommonEventTemplateMainDiv.className = "leftTab"; - CommonEventTemplateMainDiv.style.zIndex = "-1"; - CommonEventTemplateMainDiv.style.opacity = "0"; + let CommonEventTemplateMainDiv = document.createElement("div"); + CommonEventTemplateMainDiv.id = `left${leftIDNumber}`; + CommonEventTemplateMainDiv.className = "leftTab"; + CommonEventTemplateMainDiv.style.zIndex = "-1"; + CommonEventTemplateMainDiv.style.opacity = "0"; - CommonEventTemplateMainDiv.innerHTML = ` + CommonEventTemplateMainDiv.innerHTML = `

常見事件模板   @@ -11447,958 +11877,980 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = `; - MainDiv.appendChild(CommonEventTemplateMainDiv); + MainDiv.appendChild(CommonEventTemplateMainDiv); - (async function () { - //等待編輯器初始化 - while (!editor_mode.ids) { - await Sleep(100); - } - //新增編輯模板ID - editor_mode.ids["CommonEventTemplate"] = `left${leftIDNumber}`; - editor_mode.init_dom_ids(); - //切換至常見事件模板 - editor_mode.CommonEventTemplate = function (callback) { - var objs = []; - editor.file.editCommonEventTemplate([], function (objs_) { - objs = objs_; - //console.log(objs_) - }); - //只查询不修改时,内部实现不是异步的,所以可以这么写 - var tableinfo = editor.table.objToTable(objs[0], objs[1]); - document.getElementById( - "table_298572d8-93dd-4c6e-a278-6a7d49831e3a" - ).innerHTML = tableinfo.HTML; - tableinfo.listen(tableinfo.guids); - if (Boolean(callback)) callback(); - }; + (async function () { + //等待編輯器初始化 + while (!editor_mode.ids) { + await Sleep(100); + } + //新增編輯模板ID + editor_mode.ids["CommonEventTemplate"] = `left${leftIDNumber}`; + editor_mode.init_dom_ids(); + //切換至常見事件模板 + editor_mode.CommonEventTemplate = function (callback) { + var objs = []; + editor.file.editCommonEventTemplate([], function (objs_) { + objs = objs_; + //console.log(objs_) + }); + //只查询不修改时,内部实现不是异步的,所以可以这么写 + var tableinfo = editor.table.objToTable(objs[0], objs[1]); + document.getElementById( + "table_298572d8-93dd-4c6e-a278-6a7d49831e3a" + ).innerHTML = tableinfo.HTML; + tableinfo.listen(tableinfo.guids); + if (Boolean(callback)) callback(); + }; - //檢查配置表格存在 - let TableRowExist = null; - fs.readFile(TableFileName, "base64", function (err, data) { - if (err) { - console.log(`察覺常見事件模板配置表格不存在,原因:${err}`); - console.log("新建一個常見事件模板配置表格。"); - TableRowExist = false; - } else { - TableRowExist = true; - } - }); - //等待配置表格載入完畢(最多0.3秒,超過則視為失敗) - for (let i = 0; i < 3; i++) { - if (TableRowExist == null) { - await Sleep(100); - } - } - //配置表格初始化 - if (TableRowExist != true) { - fs.mkdir("project/table", function (err, data) { - if (err) throw `常見事件模板配置表格目錄初始化失敗,原因:${err}`; - }); - fs.writeFile( - TableFileName, - editor.util.encode64(TableRow || ""), - "base64", - function (err, data) { - if (err) throw `常見事件模板配置表格文件初始化失敗,原因:${err}`; - } - ); - } - //載入配置表格 - //editor.file.loadCommentjs(callback); - (function () { - var key = "CommonEventTemplate_comment"; - var script = document.createElement("script"); - script.src = "project/table/" + key + ".js"; - document.body.appendChild(script); - script.onload = function () { - editor.file[key] = eval(key.replace(".", "_")); - var loaded = Boolean(editor.file[key]); - }; - })(); - //按下配置表格 - editor_multi.CommonEventTemplateEditCommentJs = function (mod) { - editor_multi.lintAutocomplete = true; - editor_multi.setLint(); - editor_multi.importFile(TableFileName); - }; + //檢查配置表格存在 + let TableRowExist = null; + fs.readFile(TableFileName, "base64", function (err, data) { + if (err) { + console.log(`察覺常見事件模板配置表格不存在,原因:${err}`); + console.log("新建一個常見事件模板配置表格。"); + TableRowExist = false; + } else { + TableRowExist = true; + } + }); + //等待配置表格載入完畢(最多0.3秒,超過則視為失敗) + for (let i = 0; i < 3; i++) { + if (TableRowExist == null) { + await Sleep(100); + } + } + //配置表格初始化 + if (TableRowExist != true) { + fs.mkdir("project/table", function (err, data) { + if (err) throw `常見事件模板配置表格目錄初始化失敗,原因:${err}`; + }); + fs.writeFile( + TableFileName, + editor.util.encode64(TableRow || ""), + "base64", + function (err, data) { + if (err) throw `常見事件模板配置表格文件初始化失敗,原因:${err}`; + } + ); + } + //載入配置表格 + //editor.file.loadCommentjs(callback); + (function () { + var key = "CommonEventTemplate_comment"; + var script = document.createElement("script"); + script.src = "project/table/" + key + ".js"; + document.body.appendChild(script); + script.onload = function () { + editor.file[key] = eval(key.replace(".", "_")); + var loaded = Boolean(editor.file[key]); + }; + })(); + //按下配置表格 + editor_multi.CommonEventTemplateEditCommentJs = function (mod) { + editor_multi.lintAutocomplete = true; + editor_multi.setLint(); + editor_multi.importFile(TableFileName); + }; - //定義表格操作行為 - editor_mode.OriginDoActionList = editor_mode.doActionList; - editor_mode.doActionList = function (mode, actionList, callback) { - if (editor_mode.mode == "CommonEventTemplate") { - if (actionList.length == 0) return; - printf("修改中..."); - var cb = function (objs_) { - if (objs_.slice(-1)[0] != null) { - printe(objs_.slice(-1)[0]); - throw objs_.slice(-1)[0]; - } - var str = "修改成功!"; - if ( - data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.firstData.name == - "template" - ) - str += "
请注意:全塔属性的name尚未修改,请及时予以设置。"; - printf(str); - if (callback) callback(); - }; - editor.file.editCommonEventTemplate(actionList, cb); - } else { - editor_mode.OriginDoActionList(mode, actionList, callback); - } - }; - //添加表格列 - editor.table.CommonEventTemplateAddFunc = function () { - let obj = events_c12a15a8_c380_4b28_8144_256cba95f760; + //定義表格操作行為 + editor_mode.OriginDoActionList = editor_mode.doActionList; + editor_mode.doActionList = function (mode, actionList, callback) { + if (editor_mode.mode == "CommonEventTemplate") { + if (actionList.length == 0) return; + printf("修改中..."); + var cb = function (objs_) { + if (objs_.slice(-1)[0] != null) { + printe(objs_.slice(-1)[0]); + throw objs_.slice(-1)[0]; + } + var str = "修改成功!"; + if ( + data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.firstData.name == + "template" + ) + str += "
请注意:全塔属性的name尚未修改,请及时予以设置。"; + printf(str); + if (callback) callback(); + }; + editor.file.editCommonEventTemplate(actionList, cb); + } else { + editor_mode.OriginDoActionList(mode, actionList, callback); + } + }; + //添加表格列 + editor.table.CommonEventTemplateAddFunc = function () { + let obj = events_c12a15a8_c380_4b28_8144_256cba95f760; - // 1.输入id - let newid = prompt("请输入新项的ID(支持中文)"); - if (newid == null || newid.length == 0) { - return; - } + // 1.输入id + let newid = prompt("请输入新项的ID(支持中文)"); + if (newid == null || newid.length == 0) { + return; + } - // 2.检查id是否符合规范或与已有id重复 - var conflict = true; - var basefield = "".replace(/\[[^\[]*\]$/, ""); + // 2.检查id是否符合规范或与已有id重复 + var conflict = true; + var basefield = "".replace(/\[[^\[]*\]$/, ""); - try { - var baseobj = eval("obj" + basefield); - conflict = newid in baseobj; - } catch (ee) { - // 理论上这里不会发生错误 - printe(ee); - throw ee; - } + try { + var baseobj = eval("obj" + basefield); + conflict = newid in baseobj; + } catch (ee) { + // 理论上这里不会发生错误 + printe(ee); + throw ee; + } - if (conflict) { - printe("id已存在, 请直接修改该项的值"); - return; - } + if (conflict) { + printe("id已存在, 请直接修改该项的值"); + return; + } - // 3.添加 - editor_mode.addAction(["add", basefield + "['" + newid + "']", null]); - editor_mode.onmode("save", function () { - printf("添加成功,刷新后生效;也可以继续新增其他项目。"); - }); //自动保存 删掉此行的话点保存按钮才会保存 - }; - //對表格的存讀 - editor.file.editCommonEventTemplate = function (actionList, callback) { - /*actionList:[ + // 3.添加 + editor_mode.addAction(["add", basefield + "['" + newid + "']", null]); + editor_mode.onmode("save", function () { + printf("添加成功,刷新后生效;也可以继续新增其他项目。"); + }); //自动保存 删掉此行的话点保存按钮才会保存 + }; + //對表格的存讀 + editor.file.editCommonEventTemplate = function (actionList, callback) { + /*actionList:[ ["change","['test']",['123']], ] 为[]时只查询不修改 */ - var data_obj = - events_c12a15a8_c380_4b28_8144_256cba95f760.CommonEventTemplate; - checkCallback(callback); - if (isset(actionList) && actionList.length > 0) { - actionList.forEach(function (value) { - value[1] = "['CommonEventTemplate']" + value[1]; - }); - editor.file.saveSetting("events", actionList, function (err) { - callback([err]); - }); - } else { - callback([ - Object.assign({}, data_obj), - editor.file.CommonEventTemplate_comment._data.CommonEventTemplate, - null, - ]); - } - }; - })(); + var data_obj = + events_c12a15a8_c380_4b28_8144_256cba95f760.CommonEventTemplate; + checkCallback(callback); + if (isset(actionList) && actionList.length > 0) { + actionList.forEach(function (value) { + value[1] = "['CommonEventTemplate']" + value[1]; + }); + editor.file.saveSetting("events", actionList, function (err) { + callback([err]); + }); + } else { + callback([ + Object.assign({}, data_obj), + editor.file.CommonEventTemplate_comment._data.CommonEventTemplate, + null, + ]); + } + }; + })(); - //複寫事件編輯器(editor_blocklyconfig) - editor_blocklyconfig = function () { - // start mark sfergsvae + //複寫事件編輯器(editor_blocklyconfig) + editor_blocklyconfig = function () { + // start mark sfergsvae - (function () { - var getCategory = function (name, custom) { - for (var node of document.getElementById("toolbox").children) { - if (node.getAttribute("name") == name) return node; - } - var node = document.createElement("category"); - node.setAttribute("name", name); - if (custom) node.setAttribute("custom", custom); - document.getElementById("toolbox").appendChild(node); - return node; - }; + (function () { + var getCategory = function (name, custom) { + for (var node of document.getElementById("toolbox").children) { + if (node.getAttribute("name") == name) return node; + } + var node = document.createElement("category"); + node.setAttribute("name", name); + if (custom) node.setAttribute("custom", custom); + document.getElementById("toolbox").appendChild(node); + return node; + }; - var toolboxObj = { - 入口方块: [ - '', - MotaActionFunctions.actionParser.parse( - [ - "欢迎使用事件编辑器", - "本事件触发一次后会消失", - { type: "hide", time: 500 }, - ], - "event" - ), - MotaActionFunctions.actionParser.parse({ - condition: "flag:__door__===2", - currentFloor: true, - priority: 0, - delayExecute: false, - multiExecute: false, - data: [{ type: "openDoor", loc: [10, 5] }], - }, - "autoEvent" - ), - MotaActionBlocks["changeFloor_m"].xmlText(), - MotaActionFunctions.actionParser.parse( - [{ - id: "shop1", - text: "\t[贪婪之神,moneyShop]勇敢的武士啊, 给我${20+2*flag:shop1}金币就可以:", - textInList: "1F金币商店", - choices: [{ - text: "生命+800", - need: "status:money>=20+2*flag:shop1", - action: [{ - type: "comment", - text: "新版商店中需要手动扣减金币和增加访问次数", - }, - { - type: "setValue", - name: "status:money", - operator: "-=", - value: "20+2*flag:shop1", - }, - { - type: "setValue", - name: "flag:shop1", - operator: "+=", - value: "1", - }, - { - type: "setValue", - name: "status:hp", - operator: "+=", - value: "800", - }, - ], - }, ], - }, - { - id: "itemShop", - item: true, - textInList: "道具商店", - choices: [{ id: "yellowKey", number: 10, money: 10 }], - }, - { - id: "keyShop1", - textInList: "回收钥匙商店", - commonEvent: "回收钥匙商店", - args: "", - }, - ], - "shop" - ), - MotaActionBlocks["common_m"].xmlText(), - MotaActionBlocks["beforeBattle_m"].xmlText(), - MotaActionBlocks["afterBattle_m"].xmlText(), - MotaActionBlocks["afterGetItem_m"].xmlText(), - MotaActionBlocks["afterOpenDoor_m"].xmlText(), - MotaActionBlocks["firstArrive_m"].xmlText(), - MotaActionBlocks["eachArrive_m"].xmlText(), - MotaActionBlocks["level_m"].xmlText(), - MotaActionFunctions.actionParser.parse( - [ - ["MTx", ""] - ], - "floorPartition" - ), - MotaActionBlocks["commonEvent_m"].xmlText(), - MotaActionBlocks["item_m"].xmlText(), - MotaActionFunctions.actionParser.parse( - [{ - title: "简单", - name: "Easy", - hard: 1, - action: [ - { type: "comment", text: "在这里写该难度需执行的事件" }, - ], - }, ], - "levelChoose" - ), - MotaActionFunctions.actionParser.parse({ - type: 0, - value: { atk: 10 }, - percentage: { speed: 10 }, - }, - "equip" - ), - MotaActionFunctions.actionParser.parse( - [{ - name: "bg.webp", - x: 0, - y: 0, - canvas: "bg", - }, ], - "floorImage" - ), - MotaActionFunctions.actionParser.parse({ - time: 160, - openSound: "door.opus", - closeSound: "door.opus", - keys: { yellowKey: 1, orangeKey: 1 }, - }, - "doorInfo" - ), - MotaActionBlocks["faceIds_m"].xmlText(), - MotaActionBlocks["mainStyle_m"].xmlText(), - MotaActionFunctions.actionParser.parse({ - 背景音乐: "bgm.opus", - 确定: "confirm.opus", - 攻击: "attack.opus", - 背景图: "bg.webp", - 领域: "zone", - 文件名: "file.jpg", - }, - "nameMap" - ), - MotaActionFunctions.actionParser.parse( - [{ name: "hero.webp", width: 32, height: 32, prefix: "hero_" }], - "splitImages" - ), - ], - 显示文字: [ - MotaActionBlocks["text_0_s"].xmlText(), - MotaActionBlocks["text_1_s"].xmlText(), - MotaActionFunctions.actionParser.parseList( - "\t[小妖精,fairy]\f[fairy.webp,0,0]欢迎使用事件编辑器(双击方块可直接预览)" - ), - MotaActionBlocks["over_s"].xmlText(), - MotaActionFunctions.actionParser.parseList([{ - type: "overlist", - image: "bg_5043.webp", - memory: false, - hidetime: 30, - list: [{ - text: "", - sound: "", - time: 50, - textColor: "255,255,255,1", - boldColor: "0,0,0,1", - font: "bold 48px Verdana", - frame: 0, - }, ], - }, ]), - MotaActionBlocks["cgtextList_s"].xmlText(), - MotaActionFunctions.actionParser.parseList([{ - type: "cgtext", - bg: "bg_5043.webp", - memory: false, - WindowSkin: false, - index: 0, - head: { name: "face_050445.webp", px: -300 }, + var toolboxObj = { + 入口方块: [ + '', + MotaActionFunctions.actionParser.parse( + [ + "欢迎使用事件编辑器", + "本事件触发一次后会消失", + { type: "hide", time: 500 }, + ], + "event" + ), + MotaActionFunctions.actionParser.parse( + { + condition: "flag:__door__===2", + currentFloor: true, + priority: 0, + delayExecute: false, + multiExecute: false, + data: [{ type: "openDoor", loc: [10, 5] }], + }, + "autoEvent" + ), + MotaActionBlocks["changeFloor_m"].xmlText(), + MotaActionFunctions.actionParser.parse( + [ + { + id: "shop1", + text: "\t[贪婪之神,moneyShop]勇敢的武士啊, 给我${20+2*flag:shop1}金币就可以:", + textInList: "1F金币商店", + choices: [ + { + text: "生命+800", + need: "status:money>=20+2*flag:shop1", + action: [ + { + type: "comment", + text: "新版商店中需要手动扣减金币和增加访问次数", + }, + { + type: "setValue", + name: "status:money", + operator: "-=", + value: "20+2*flag:shop1", + }, + { + type: "setValue", + name: "flag:shop1", + operator: "+=", + value: "1", + }, + { + type: "setValue", + name: "status:hp", + operator: "+=", + value: "800", + }, + ], + }, + ], + }, + { + id: "itemShop", + item: true, + textInList: "道具商店", + choices: [{ id: "yellowKey", number: 10, money: 10 }], + }, + { + id: "keyShop1", + textInList: "回收钥匙商店", + commonEvent: "回收钥匙商店", + args: "", + }, + ], + "shop" + ), + MotaActionBlocks["common_m"].xmlText(), + MotaActionBlocks["beforeBattle_m"].xmlText(), + MotaActionBlocks["afterBattle_m"].xmlText(), + MotaActionBlocks["afterGetItem_m"].xmlText(), + MotaActionBlocks["afterOpenDoor_m"].xmlText(), + MotaActionBlocks["firstArrive_m"].xmlText(), + MotaActionBlocks["eachArrive_m"].xmlText(), + MotaActionBlocks["level_m"].xmlText(), + MotaActionFunctions.actionParser.parse( + [["MTx", ""]], + "floorPartition" + ), + MotaActionBlocks["commonEvent_m"].xmlText(), + MotaActionBlocks["item_m"].xmlText(), + MotaActionFunctions.actionParser.parse( + [ + { + title: "简单", + name: "Easy", + hard: 1, + action: [ + { type: "comment", text: "在这里写该难度需执行的事件" }, + ], + }, + ], + "levelChoose" + ), + MotaActionFunctions.actionParser.parse( + { + type: 0, + value: { atk: 10 }, + percentage: { speed: 10 }, + }, + "equip" + ), + MotaActionFunctions.actionParser.parse( + [ + { + name: "bg.webp", + x: 0, + y: 0, + canvas: "bg", + }, + ], + "floorImage" + ), + MotaActionFunctions.actionParser.parse( + { + time: 160, + openSound: "door.opus", + closeSound: "door.opus", + keys: { yellowKey: 1, orangeKey: 1 }, + }, + "doorInfo" + ), + MotaActionBlocks["faceIds_m"].xmlText(), + MotaActionBlocks["mainStyle_m"].xmlText(), + MotaActionFunctions.actionParser.parse( + { + 背景音乐: "bgm.opus", + 确定: "confirm.opus", + 攻击: "attack.opus", + 背景图: "bg.webp", + 领域: "zone", + 文件名: "file.jpg", + }, + "nameMap" + ), + MotaActionFunctions.actionParser.parse( + [{ name: "hero.webp", width: 32, height: 32, prefix: "hero_" }], + "splitImages" + ), + ], + 显示文字: [ + MotaActionBlocks["text_0_s"].xmlText(), + MotaActionBlocks["text_1_s"].xmlText(), + MotaActionFunctions.actionParser.parseList( + "\t[小妖精,fairy]\f[fairy.webp,0,0]欢迎使用事件编辑器(双击方块可直接预览)" + ), + MotaActionBlocks["over_s"].xmlText(), + MotaActionFunctions.actionParser.parseList([ + { + type: "overlist", + image: "bg_5043.webp", + memory: false, + hidetime: 30, + list: [ + { + text: "", + sound: "", + time: 50, + textColor: "255,255,255,1", + boldColor: "0,0,0,1", + font: "bold 48px Verdana", + frame: 0, + }, + ], + }, + ]), + MotaActionBlocks["cgtextList_s"].xmlText(), + MotaActionFunctions.actionParser.parseList([ + { + type: "cgtext", + bg: "bg_5043.webp", + memory: false, + WindowSkin: false, + index: 0, + head: { name: "face_050445.webp", px: -300 }, - time: 0, - wait: 2000, - sound: "", + time: 0, + wait: 2000, + sound: "", - bodyList: [ - { name: "tati_050145a.webp", px: 100, filter: false }, - ], - }, ]), - MotaActionBlocks["moveTextBox_s"].xmlText(), - MotaActionBlocks["clearTextBox_s"].xmlText(), - MotaActionBlocks["comment_s"].xmlText(), - MotaActionBlocks["autoText_s"].xmlText(), - MotaActionBlocks["scrollText_s"].xmlText(), - MotaActionBlocks["setText_s"].xmlText(), - MotaActionBlocks["tip_s"].xmlText(), - MotaActionBlocks["addPop_s"].xmlText(), - MotaActionBlocks["confirm_s"].xmlText(), - MotaActionBlocks["choices_s"].xmlText([ - "选择剑或者盾", - "流浪者", - "man", - 0, - "", - MotaActionBlocks["choicesContext"].xmlText([ - "剑", - "", - "", - null, - "", - "", - MotaActionFunctions.actionParser.parseList([ - { type: "openDoor", loc: [3, 3] }, - ]), - ]), - ]), - MotaActionBlocks["win_s"].xmlText(), - MotaActionBlocks["lose_s"].xmlText(), - MotaActionBlocks["restart_s"].xmlText(), - ], - 数据相关: [ - MotaActionBlocks["setValue_s"].xmlText([ - MotaActionBlocks["idIdList_e"].xmlText(["status", "生命"]), - "=", - "", - false, - ]), - MotaActionBlocks["setEnemy_s"].xmlText(), - MotaActionBlocks["setEnemyOnPoint_s"].xmlText(), - MotaActionBlocks["resetEnemyOnPoint_s"].xmlText(), - MotaActionBlocks["moveEnemyOnPoint_s"].xmlText(), - MotaActionBlocks["moveEnemyOnPoint_1_s"].xmlText(), - MotaActionBlocks["setEquip_s"].xmlText(), - MotaActionBlocks["setFloor_s"].xmlText(), - MotaActionBlocks["setGlobalAttribute_s"].xmlText(), - MotaActionBlocks["setGlobalValue_s"].xmlText(), - MotaActionBlocks["setGlobalFlag_s"].xmlText(), - MotaActionBlocks["setNameMap_s"].xmlText(), - MotaActionBlocks["input_s"].xmlText(), - MotaActionBlocks["input2_s"].xmlText(), - MotaActionBlocks["update_s"].xmlText(), - MotaActionBlocks["moveAction_s"].xmlText(), - MotaActionBlocks["changeFloor_s"].xmlText(), - MotaActionBlocks["changePos_s"].xmlText(), - MotaActionBlocks["battle_s"].xmlText(), - MotaActionBlocks["useItem_s"].xmlText(), - MotaActionBlocks["loadEquip_s"].xmlText(), - MotaActionBlocks["unloadEquip_s"].xmlText(), - MotaActionBlocks["openShop_s"].xmlText(), - MotaActionBlocks["disableShop_s"].xmlText(), - MotaActionBlocks["setHeroIcon_s"].xmlText(), - MotaActionBlocks["follow_s"].xmlText(), - MotaActionBlocks["unfollow_s"].xmlText(), - ], - 地图处理: [ - MotaActionBlocks["battle_1_s"].xmlText(), - MotaActionBlocks["openDoor_s"].xmlText(), - MotaActionBlocks["closeDoor_s"].xmlText(), - MotaActionBlocks["show_s"].xmlText(), - MotaActionBlocks["hide_s"].xmlText(), - MotaActionBlocks["setBlock_s"].xmlText(), - MotaActionBlocks["setBlockOpacity_s"].xmlText(), - MotaActionBlocks["setBlockFilter_s"].xmlText(), - MotaActionBlocks["turnBlock_s"].xmlText(), - MotaActionBlocks["moveHero_s"].xmlText(), - MotaActionBlocks["move_s"].xmlText(), - MotaActionBlocks["jumpHero_s"].xmlText(), - MotaActionBlocks["jumpHero_1_s"].xmlText(), - MotaActionBlocks["jump_s"].xmlText(), - MotaActionBlocks["jump_1_s"].xmlText(), - MotaActionBlocks["showBgFgMap_s"].xmlText(), - MotaActionBlocks["hideBgFgMap_s"].xmlText(), - MotaActionBlocks["setBgFgBlock_s"].xmlText(), - MotaActionBlocks["showFloorImg_s"].xmlText(), - MotaActionBlocks["hideFloorImg_s"].xmlText(), - ], - 事件控制: [ - MotaActionBlocks["if_1_s"].xmlText(), - MotaActionBlocks["if_s"].xmlText(), - MotaActionFunctions.actionParser.parseList({ - type: "switch", - condition: "判别值", - caseList: [{ - action: [ - { type: "comment", text: "当判别值是值的场合执行此事件" }, - ], - }, - { - case: "default", - action: [{ - type: "comment", - text: "当没有符合的值的场合执行default事件", - }, ], - }, - ], - }), - MotaActionFunctions.actionParser.parseList({ - type: "for", - name: "temp:A", - from: "0", - to: "12", - step: "1", - data: [], - }), - MotaActionFunctions.actionParser.parseList({ - type: "forEach", - name: "temp:A", - list: ["status:atk", "status:def"], - data: [], - }), - MotaActionBlocks["while_s"].xmlText(), - MotaActionBlocks["dowhile_s"].xmlText(), - MotaActionBlocks["break_s"].xmlText(), - MotaActionBlocks["continue_s"].xmlText(), - MotaActionBlocks["exit_s"].xmlText(), - MotaActionBlocks["trigger_s"].xmlText(), - MotaActionBlocks["insert_1_s"].xmlText(), - MotaActionBlocks["insert_2_s"].xmlText(), - ], - 特效表现: [ - MotaActionBlocks["sleep_s"].xmlText(), - MotaActionBlocks["setq_s"].xmlText(), - MotaActionBlocks["setcgs_s"].xmlText(), - MotaActionBlocks["setmusics_s"].xmlText(), - MotaActionBlocks["changebg_s"].xmlText(), - MotaActionFunctions.actionParser.parseList({ - type: "wait", - timeout: 0, - data: [{ - case: "keyboard", - keycode: "13,32", - action: [{ - type: "comment", - text: "当按下回车(keycode=13)或空格(keycode=32)时执行此事件\n超时剩余时间会写入flag:timeout", - }, ], - }, - { - case: "mouse", - px: [0, 32], - py: [0, 32], - action: [{ - type: "comment", - text: "当点击地图左上角时执行此事件\n超时剩余时间会写入flag:timeout", - }, ], - }, - { - case: "condition", - condition: "flag:type==0\n&&flag:keycode==13", - action: [{ - type: "comment", - text: "当满足自定义条件时会执行此事件\n超时剩余时间会写入flag:timeout", - }, ], - }, - { - case: "timeout", - action: [ - { type: "comment", text: "当超时未操作时执行此事件" }, - ], - }, - ], - }), - MotaActionBlocks["waitAsync_s"].xmlText(), - MotaActionBlocks["stopAsync_s"].xmlText(), - MotaActionBlocks["op_s"].xmlText(), - MotaActionBlocks["drawWarning_s"].xmlText(), - MotaActionBlocks["changeMouse_s"].xmlText(), - MotaActionBlocks["removeMouse_s"].xmlText(), - MotaActionBlocks["vibrate_s"].xmlText(), - MotaActionBlocks["animate_s"].xmlText(), - MotaActionBlocks["animate_1_s"].xmlText(), - MotaActionBlocks["stopAnimate_s"].xmlText(), - MotaActionBlocks["setViewport_s"].xmlText(), - MotaActionBlocks["setViewport_1_s"].xmlText(), - MotaActionBlocks["lockViewport_s"].xmlText(), - MotaActionBlocks["showStatusBar_s"].xmlText(), - MotaActionBlocks["hideStatusBar_s"].xmlText(), - MotaActionBlocks["setHeroOpacity_s"].xmlText(), - MotaActionBlocks["setCurtain_0_s"].xmlText(), - MotaActionBlocks["setCurtain_1_s"].xmlText(), - MotaActionBlocks["screenFlash_s"].xmlText(), - MotaActionBlocks["setWeather_s"].xmlText(), - MotaActionBlocks["callBook_s"].xmlText(), - MotaActionBlocks["callSave_s"].xmlText(), - MotaActionBlocks["autoSave_s"].xmlText(), - MotaActionBlocks["forbidSave_s"].xmlText(), - MotaActionBlocks["callLoad_s"].xmlText(), - ], - 音像处理: [ - MotaActionBlocks["animationDrawable_s"].xmlText(), - MotaActionBlocks["introAndLoop_s"].xmlText(), - MotaActionBlocks["setanimate_s"].xmlText(), - MotaActionBlocks["deleteanimate_s"].xmlText(), - MotaActionBlocks["playanimate_s"].xmlText(), - MotaActionBlocks["clearanimate_s"].xmlText(), - MotaActionBlocks["showImage_s"].xmlText(), - MotaActionBlocks["showImage_1_s"].xmlText(), - MotaActionBlocks["hideImage_s"].xmlText(), - MotaActionBlocks["showTextImage_s"].xmlText(), - MotaActionBlocks["moveImage_s"].xmlText(), - MotaActionBlocks["rotateImage_s"].xmlText(), - MotaActionBlocks["scaleImage_s"].xmlText(), - MotaActionBlocks["showGif_s"].xmlText(), - MotaActionBlocks["playBgm_s"].xmlText(), - MotaActionBlocks["pauseBgm_s"].xmlText(), - MotaActionBlocks["resumeBgm_s"].xmlText(), - MotaActionBlocks["loadBgm_s"].xmlText(), - MotaActionBlocks["freeBgm_s"].xmlText(), - MotaActionBlocks["playSound_s"].xmlText(), - MotaActionBlocks["playSound_1_s"].xmlText(), - MotaActionBlocks["stopSound_s"].xmlText(), - MotaActionBlocks["setVolume_s"].xmlText(), - MotaActionBlocks["setBgmSpeed_s"].xmlText(), - ], - UI绘制: [ - MotaActionBlocks["previewUI_s"].xmlText(), - MotaActionBlocks["clearMap_s"].xmlText(), - MotaActionBlocks["setAttribute_s"].xmlText(), - MotaActionBlocks["setFilter_s"].xmlText(), - MotaActionBlocks["fillText_s"].xmlText(), - MotaActionBlocks["fillBoldText_s"].xmlText(), - MotaActionBlocks["drawTextContent_s"].xmlText(), - MotaActionBlocks["fillRect_s"].xmlText(), - MotaActionBlocks["strokeRect_s"].xmlText(), - MotaActionBlocks["drawLine_s"].xmlText(), - MotaActionBlocks["drawArrow_s"].xmlText(), - MotaActionBlocks["fillPolygon_s"].xmlText(), - MotaActionBlocks["strokePolygon_s"].xmlText(), - MotaActionBlocks["fillEllipse_s"].xmlText(), - MotaActionBlocks["strokeEllipse_s"].xmlText(), - MotaActionBlocks["fillArc_s"].xmlText(), - MotaActionBlocks["strokeArc_s"].xmlText(), - MotaActionBlocks["drawImage_s"].xmlText(), - MotaActionBlocks["drawImage_1_s"].xmlText(), - MotaActionBlocks["drawIcon_s"].xmlText(), - MotaActionBlocks["drawBackground_s"].xmlText(), - MotaActionBlocks["drawSelector_s"].xmlText(), - MotaActionBlocks["drawSelector_1_s"].xmlText(), - ], - 原生脚本: [ - MotaActionBlocks["function_s"].xmlText(), - MotaActionBlocks["unknown_s"].xmlText(), - ], - 值块: [ - MotaActionBlocks["setValue_s"].xmlText([ - MotaActionBlocks["idIdList_e"].xmlText(["status", "生命"]), - "=", - "", - false, - ]), - MotaActionBlocks["expression_arithmetic_0"].xmlText(), - MotaActionBlocks["idFlag_e"].xmlText(), - MotaActionBlocks["idTemp_e"].xmlText(), - MotaActionBlocks["negate_e"].xmlText(), - MotaActionBlocks["unaryOperation_e"].xmlText(), - MotaActionBlocks["bool_e"].xmlText(), - MotaActionBlocks["idString_e"].xmlText(), - MotaActionBlocks["idIdList_e"].xmlText(), - MotaActionBlocks["idFixedList_e"].xmlText(), - MotaActionBlocks["enemyattr_e"].xmlText(), - MotaActionBlocks["blockId_e"].xmlText(), - MotaActionBlocks["blockNumber_e"].xmlText(), - MotaActionBlocks["blockCls_e"].xmlText(), - MotaActionBlocks["hasEquip_e"].xmlText(), - MotaActionBlocks["equip_e"].xmlText(), - MotaActionBlocks["nextXY_e"].xmlText(), - MotaActionBlocks["isReplaying_e"].xmlText(), - MotaActionBlocks["hasVisitedFloor_e"].xmlText(), - MotaActionBlocks["isShopVisited_e"].xmlText(), - MotaActionBlocks["canBattle_e"].xmlText(), - MotaActionBlocks["damage_e"].xmlText(), - MotaActionBlocks["damage_1_e"].xmlText(), - MotaActionBlocks["rand_e"].xmlText(), - MotaActionBlocks["evalString_e"].xmlText(), - ], - 常见事件模板: [ - '', - ], - 最近使用事件: [ - '', - ], - }; - var toolboxgap = ''; - //xml_text = MotaActionFunctions.actionParser.parse(obj,type||'event') - //MotaActionBlocks['idString_e'].xmlText() + bodyList: [ + { name: "tati_050145a.webp", px: 100, filter: false }, + ], + }, + ]), + MotaActionBlocks["moveTextBox_s"].xmlText(), + MotaActionBlocks["clearTextBox_s"].xmlText(), + MotaActionBlocks["comment_s"].xmlText(), + MotaActionBlocks["autoText_s"].xmlText(), + MotaActionBlocks["scrollText_s"].xmlText(), + MotaActionBlocks["setText_s"].xmlText(), + MotaActionBlocks["tip_s"].xmlText(), + MotaActionBlocks["addPop_s"].xmlText(), + MotaActionBlocks["confirm_s"].xmlText(), + MotaActionBlocks["choices_s"].xmlText([ + "选择剑或者盾", + "流浪者", + "man", + 0, + "", + MotaActionBlocks["choicesContext"].xmlText([ + "剑", + "", + "", + null, + "", + "", + MotaActionFunctions.actionParser.parseList([ + { type: "openDoor", loc: [3, 3] }, + ]), + ]), + ]), + MotaActionBlocks["win_s"].xmlText(), + MotaActionBlocks["lose_s"].xmlText(), + MotaActionBlocks["restart_s"].xmlText(), + ], + 数据相关: [ + MotaActionBlocks["setValue_s"].xmlText([ + MotaActionBlocks["idIdList_e"].xmlText(["status", "生命"]), + "=", + "", + false, + ]), + MotaActionBlocks["setEnemy_s"].xmlText(), + MotaActionBlocks["setEnemyOnPoint_s"].xmlText(), + MotaActionBlocks["resetEnemyOnPoint_s"].xmlText(), + MotaActionBlocks["moveEnemyOnPoint_s"].xmlText(), + MotaActionBlocks["moveEnemyOnPoint_1_s"].xmlText(), + MotaActionBlocks["setEquip_s"].xmlText(), + MotaActionBlocks["setFloor_s"].xmlText(), + MotaActionBlocks["setGlobalAttribute_s"].xmlText(), + MotaActionBlocks["setGlobalValue_s"].xmlText(), + MotaActionBlocks["setGlobalFlag_s"].xmlText(), + MotaActionBlocks["setNameMap_s"].xmlText(), + MotaActionBlocks["input_s"].xmlText(), + MotaActionBlocks["input2_s"].xmlText(), + MotaActionBlocks["update_s"].xmlText(), + MotaActionBlocks["moveAction_s"].xmlText(), + MotaActionBlocks["changeFloor_s"].xmlText(), + MotaActionBlocks["changePos_s"].xmlText(), + MotaActionBlocks["battle_s"].xmlText(), + MotaActionBlocks["useItem_s"].xmlText(), + MotaActionBlocks["loadEquip_s"].xmlText(), + MotaActionBlocks["unloadEquip_s"].xmlText(), + MotaActionBlocks["openShop_s"].xmlText(), + MotaActionBlocks["disableShop_s"].xmlText(), + MotaActionBlocks["setHeroIcon_s"].xmlText(), + MotaActionBlocks["follow_s"].xmlText(), + MotaActionBlocks["unfollow_s"].xmlText(), + ], + 地图处理: [ + MotaActionBlocks["battle_1_s"].xmlText(), + MotaActionBlocks["openDoor_s"].xmlText(), + MotaActionBlocks["closeDoor_s"].xmlText(), + MotaActionBlocks["show_s"].xmlText(), + MotaActionBlocks["hide_s"].xmlText(), + MotaActionBlocks["setBlock_s"].xmlText(), + MotaActionBlocks["setBlockOpacity_s"].xmlText(), + MotaActionBlocks["setBlockFilter_s"].xmlText(), + MotaActionBlocks["turnBlock_s"].xmlText(), + MotaActionBlocks["moveHero_s"].xmlText(), + MotaActionBlocks["move_s"].xmlText(), + MotaActionBlocks["jumpHero_s"].xmlText(), + MotaActionBlocks["jumpHero_1_s"].xmlText(), + MotaActionBlocks["jump_s"].xmlText(), + MotaActionBlocks["jump_1_s"].xmlText(), + MotaActionBlocks["showBgFgMap_s"].xmlText(), + MotaActionBlocks["hideBgFgMap_s"].xmlText(), + MotaActionBlocks["setBgFgBlock_s"].xmlText(), + MotaActionBlocks["showFloorImg_s"].xmlText(), + MotaActionBlocks["hideFloorImg_s"].xmlText(), + ], + 事件控制: [ + MotaActionBlocks["if_1_s"].xmlText(), + MotaActionBlocks["if_s"].xmlText(), + MotaActionFunctions.actionParser.parseList({ + type: "switch", + condition: "判别值", + caseList: [ + { + action: [ + { type: "comment", text: "当判别值是值的场合执行此事件" }, + ], + }, + { + case: "default", + action: [ + { + type: "comment", + text: "当没有符合的值的场合执行default事件", + }, + ], + }, + ], + }), + MotaActionFunctions.actionParser.parseList({ + type: "for", + name: "temp:A", + from: "0", + to: "12", + step: "1", + data: [], + }), + MotaActionFunctions.actionParser.parseList({ + type: "forEach", + name: "temp:A", + list: ["status:atk", "status:def"], + data: [], + }), + MotaActionBlocks["while_s"].xmlText(), + MotaActionBlocks["dowhile_s"].xmlText(), + MotaActionBlocks["break_s"].xmlText(), + MotaActionBlocks["continue_s"].xmlText(), + MotaActionBlocks["exit_s"].xmlText(), + MotaActionBlocks["trigger_s"].xmlText(), + MotaActionBlocks["insert_1_s"].xmlText(), + MotaActionBlocks["insert_2_s"].xmlText(), + ], + 特效表现: [ + MotaActionBlocks["sleep_s"].xmlText(), + MotaActionBlocks["setq_s"].xmlText(), + MotaActionBlocks["setcgs_s"].xmlText(), + MotaActionBlocks["setmusics_s"].xmlText(), + MotaActionBlocks["changebg_s"].xmlText(), + MotaActionFunctions.actionParser.parseList({ + type: "wait", + timeout: 0, + data: [ + { + case: "keyboard", + keycode: "13,32", + action: [ + { + type: "comment", + text: "当按下回车(keycode=13)或空格(keycode=32)时执行此事件\n超时剩余时间会写入flag:timeout", + }, + ], + }, + { + case: "mouse", + px: [0, 32], + py: [0, 32], + action: [ + { + type: "comment", + text: "当点击地图左上角时执行此事件\n超时剩余时间会写入flag:timeout", + }, + ], + }, + { + case: "condition", + condition: "flag:type==0\n&&flag:keycode==13", + action: [ + { + type: "comment", + text: "当满足自定义条件时会执行此事件\n超时剩余时间会写入flag:timeout", + }, + ], + }, + { + case: "timeout", + action: [ + { type: "comment", text: "当超时未操作时执行此事件" }, + ], + }, + ], + }), + MotaActionBlocks["waitAsync_s"].xmlText(), + MotaActionBlocks["stopAsync_s"].xmlText(), + MotaActionBlocks["op_s"].xmlText(), + MotaActionBlocks["drawWarning_s"].xmlText(), + MotaActionBlocks["changeMouse_s"].xmlText(), + MotaActionBlocks["removeMouse_s"].xmlText(), + MotaActionBlocks["vibrate_s"].xmlText(), + MotaActionBlocks["animate_s"].xmlText(), + MotaActionBlocks["animate_1_s"].xmlText(), + MotaActionBlocks["stopAnimate_s"].xmlText(), + MotaActionBlocks["setViewport_s"].xmlText(), + MotaActionBlocks["setViewport_1_s"].xmlText(), + MotaActionBlocks["lockViewport_s"].xmlText(), + MotaActionBlocks["showStatusBar_s"].xmlText(), + MotaActionBlocks["hideStatusBar_s"].xmlText(), + MotaActionBlocks["setHeroOpacity_s"].xmlText(), + MotaActionBlocks["setCurtain_0_s"].xmlText(), + MotaActionBlocks["setCurtain_1_s"].xmlText(), + MotaActionBlocks["screenFlash_s"].xmlText(), + MotaActionBlocks["setWeather_s"].xmlText(), + MotaActionBlocks["callBook_s"].xmlText(), + MotaActionBlocks["callSave_s"].xmlText(), + MotaActionBlocks["autoSave_s"].xmlText(), + MotaActionBlocks["forbidSave_s"].xmlText(), + MotaActionBlocks["callLoad_s"].xmlText(), + ], + 音像处理: [ + MotaActionBlocks["animationDrawable_s"].xmlText(), + MotaActionBlocks["introAndLoop_s"].xmlText(), + MotaActionBlocks["setanimate_s"].xmlText(), + MotaActionBlocks["deleteanimate_s"].xmlText(), + MotaActionBlocks["playanimate_s"].xmlText(), + MotaActionBlocks["clearanimate_s"].xmlText(), + MotaActionBlocks["showImage_s"].xmlText(), + MotaActionBlocks["showImage_1_s"].xmlText(), + MotaActionBlocks["hideImage_s"].xmlText(), + MotaActionBlocks["showTextImage_s"].xmlText(), + MotaActionBlocks["moveImage_s"].xmlText(), + MotaActionBlocks["rotateImage_s"].xmlText(), + MotaActionBlocks["scaleImage_s"].xmlText(), + MotaActionBlocks["showGif_s"].xmlText(), + MotaActionBlocks["playBgm_s"].xmlText(), + MotaActionBlocks["pauseBgm_s"].xmlText(), + MotaActionBlocks["resumeBgm_s"].xmlText(), + MotaActionBlocks["loadBgm_s"].xmlText(), + MotaActionBlocks["freeBgm_s"].xmlText(), + MotaActionBlocks["playSound_s"].xmlText(), + MotaActionBlocks["playSound_1_s"].xmlText(), + MotaActionBlocks["stopSound_s"].xmlText(), + MotaActionBlocks["setVolume_s"].xmlText(), + MotaActionBlocks["setBgmSpeed_s"].xmlText(), + ], + UI绘制: [ + MotaActionBlocks["previewUI_s"].xmlText(), + MotaActionBlocks["clearMap_s"].xmlText(), + MotaActionBlocks["setAttribute_s"].xmlText(), + MotaActionBlocks["setFilter_s"].xmlText(), + MotaActionBlocks["fillText_s"].xmlText(), + MotaActionBlocks["fillBoldText_s"].xmlText(), + MotaActionBlocks["drawTextContent_s"].xmlText(), + MotaActionBlocks["fillRect_s"].xmlText(), + MotaActionBlocks["strokeRect_s"].xmlText(), + MotaActionBlocks["drawLine_s"].xmlText(), + MotaActionBlocks["drawArrow_s"].xmlText(), + MotaActionBlocks["fillPolygon_s"].xmlText(), + MotaActionBlocks["strokePolygon_s"].xmlText(), + MotaActionBlocks["fillEllipse_s"].xmlText(), + MotaActionBlocks["strokeEllipse_s"].xmlText(), + MotaActionBlocks["fillArc_s"].xmlText(), + MotaActionBlocks["strokeArc_s"].xmlText(), + MotaActionBlocks["drawImage_s"].xmlText(), + MotaActionBlocks["drawImage_1_s"].xmlText(), + MotaActionBlocks["drawIcon_s"].xmlText(), + MotaActionBlocks["drawBackground_s"].xmlText(), + MotaActionBlocks["drawSelector_s"].xmlText(), + MotaActionBlocks["drawSelector_1_s"].xmlText(), + ], + 原生脚本: [ + MotaActionBlocks["function_s"].xmlText(), + MotaActionBlocks["unknown_s"].xmlText(), + ], + 值块: [ + MotaActionBlocks["setValue_s"].xmlText([ + MotaActionBlocks["idIdList_e"].xmlText(["status", "生命"]), + "=", + "", + false, + ]), + MotaActionBlocks["expression_arithmetic_0"].xmlText(), + MotaActionBlocks["idFlag_e"].xmlText(), + MotaActionBlocks["idTemp_e"].xmlText(), + MotaActionBlocks["negate_e"].xmlText(), + MotaActionBlocks["unaryOperation_e"].xmlText(), + MotaActionBlocks["bool_e"].xmlText(), + MotaActionBlocks["idString_e"].xmlText(), + MotaActionBlocks["idIdList_e"].xmlText(), + MotaActionBlocks["idFixedList_e"].xmlText(), + MotaActionBlocks["enemyattr_e"].xmlText(), + MotaActionBlocks["blockId_e"].xmlText(), + MotaActionBlocks["blockNumber_e"].xmlText(), + MotaActionBlocks["blockCls_e"].xmlText(), + MotaActionBlocks["hasEquip_e"].xmlText(), + MotaActionBlocks["equip_e"].xmlText(), + MotaActionBlocks["nextXY_e"].xmlText(), + MotaActionBlocks["isReplaying_e"].xmlText(), + MotaActionBlocks["hasVisitedFloor_e"].xmlText(), + MotaActionBlocks["isShopVisited_e"].xmlText(), + MotaActionBlocks["canBattle_e"].xmlText(), + MotaActionBlocks["damage_e"].xmlText(), + MotaActionBlocks["damage_1_e"].xmlText(), + MotaActionBlocks["rand_e"].xmlText(), + MotaActionBlocks["evalString_e"].xmlText(), + ], + 常见事件模板: [ + '', + ], + 最近使用事件: [ + '', + ], + }; + var toolboxgap = ''; + //xml_text = MotaActionFunctions.actionParser.parse(obj,type||'event') + //MotaActionBlocks['idString_e'].xmlText() - //#region 動態常見事件模板 - let CommonEventTemplateHTML = []; + //#region 動態常見事件模板 + let CommonEventTemplateHTML = []; - for (let commonEventName in events_c12a15a8_c380_4b28_8144_256cba95f760.CommonEventTemplate) { - if ( - events_c12a15a8_c380_4b28_8144_256cba95f760.CommonEventTemplate.hasOwnProperty( - commonEventName - ) - ) { - let actionParserJson = Array.from( - events_c12a15a8_c380_4b28_8144_256cba95f760.CommonEventTemplate[ - commonEventName - ] ?? [] - ); + for (let commonEventName in events_c12a15a8_c380_4b28_8144_256cba95f760.CommonEventTemplate) { + if ( + events_c12a15a8_c380_4b28_8144_256cba95f760.CommonEventTemplate.hasOwnProperty( + commonEventName + ) + ) { + let actionParserJson = Array.from( + events_c12a15a8_c380_4b28_8144_256cba95f760.CommonEventTemplate[ + commonEventName + ] ?? [] + ); - let labelHTML = ""; - let blockHTML = ""; + let labelHTML = ""; + let blockHTML = ""; - labelHTML = ``; + labelHTML = ``; - if (actionParserJson.length > 1) { - actionParserJson = { - type: "if", - condition: "true", - true: actionParserJson, - }; - } else if (actionParserJson.length < 1) { - actionParserJson = [ - "空的常用事件模板。\n請在主頁下拉菜單中,選擇常用事件模板,進行編輯。\n編輯後需按F5刷新事件編輯器。", - ]; - } - blockHTML = - MotaActionFunctions.actionParser.parseList(actionParserJson); + if (actionParserJson.length > 1) { + actionParserJson = { + type: "if", + condition: "true", + true: actionParserJson, + }; + } else if (actionParserJson.length < 1) { + actionParserJson = [ + "空的常用事件模板。\n請在主頁下拉菜單中,選擇常用事件模板,進行編輯。\n編輯後需按F5刷新事件編輯器。", + ]; + } + blockHTML = + MotaActionFunctions.actionParser.parseList(actionParserJson); - CommonEventTemplateHTML.push(labelHTML); - CommonEventTemplateHTML.push(blockHTML); - } - } + CommonEventTemplateHTML.push(labelHTML); + CommonEventTemplateHTML.push(blockHTML); + } + } - toolboxObj["常见事件模板"] = CommonEventTemplateHTML; - //#endregion + toolboxObj["常见事件模板"] = CommonEventTemplateHTML; + //#endregion - for (var name in toolboxObj) { - var custom = null; - if (name == "最近使用事件") custom = "searchBlockCategory"; - if (name == "入口方块") custom = "entranceCategory"; - getCategory(name, custom).innerHTML = - toolboxObj[name].join(toolboxgap); - } + for (var name in toolboxObj) { + var custom = null; + if (name == "最近使用事件") custom = "searchBlockCategory"; + if (name == "入口方块") custom = "entranceCategory"; + getCategory(name, custom).innerHTML = + toolboxObj[name].join(toolboxgap); + } - var blocklyArea = document.getElementById("blocklyArea"); - var blocklyDiv = document.getElementById("blocklyDiv"); - var workspace = Blockly.inject(blocklyDiv, { - media: "_server/blockly/media/", - toolbox: document.getElementById("toolbox"), - zoom: { - controls: true, - wheel: false, //滚轮改为上下(shift:左右)翻滚 - startScale: 1.0, - maxScale: 3, - minScale: 0.3, - scaleSpeed: 1.08, - }, - trashcan: false, - }); + var blocklyArea = document.getElementById("blocklyArea"); + var blocklyDiv = document.getElementById("blocklyDiv"); + var workspace = Blockly.inject(blocklyDiv, { + media: "_server/blockly/media/", + toolbox: document.getElementById("toolbox"), + zoom: { + controls: true, + wheel: false, //滚轮改为上下(shift:左右)翻滚 + startScale: 1.0, + maxScale: 3, + minScale: 0.3, + scaleSpeed: 1.08, + }, + trashcan: false, + }); - editor_blockly.isCommonEntry = function () { - var commonEntries = [ - "beforeBattle", - "afterBattle", - "afterOpenDoor", - "firstArrive", - "eachArrive", - "commonEvent", - "item", - ]; - return commonEntries.indexOf(editor_blockly.entryType) >= 0; - }; + editor_blockly.isCommonEntry = function () { + var commonEntries = [ + "beforeBattle", + "afterBattle", + "afterOpenDoor", + "firstArrive", + "eachArrive", + "commonEvent", + "item", + ]; + return commonEntries.indexOf(editor_blockly.entryType) >= 0; + }; - editor_blockly.entranceCategoryCallback = function (workspace) { - var list = toolboxObj["入口方块"]; - var xmlList = []; - var eventType = - (editor_blockly.isCommonEntry() ? - "common" : - editor_blockly.entryType) + "_m"; - for (var ii = 0, blockText; - (blockText = list[ii]); ii++) { - if ( - new RegExp('').exec(blockText) - ) { - var block = Blockly.Xml.textToDom( - "" + blockText + "" - ).firstChild; - block.setAttribute("gap", 5); - xmlList.push(block); - } - } - return xmlList; - }; + editor_blockly.entranceCategoryCallback = function (workspace) { + var list = toolboxObj["入口方块"]; + var xmlList = []; + var eventType = + (editor_blockly.isCommonEntry() + ? "common" + : editor_blockly.entryType) + "_m"; + for (var ii = 0, blockText; (blockText = list[ii]); ii++) { + if ( + new RegExp('').exec(blockText) + ) { + var block = Blockly.Xml.textToDom( + "" + blockText + "" + ).firstChild; + block.setAttribute("gap", 5); + xmlList.push(block); + } + } + return xmlList; + }; - workspace.registerToolboxCategoryCallback( - "entranceCategory", - editor_blockly.entranceCategoryCallback - ); + workspace.registerToolboxCategoryCallback( + "entranceCategory", + editor_blockly.entranceCategoryCallback + ); - editor_blockly.searchBlockCategoryCallback = function (workspace) { - var xmlList = []; - var labels = editor_blockly.searchBlock(); - for (var i = 0; i < labels.length; i++) { - var blockText = - "" + MotaActionBlocks[labels[i]].xmlText() + ""; - var block = Blockly.Xml.textToDom(blockText).firstChild; - block.setAttribute("gap", 5); - xmlList.push(block); - } - return xmlList; - }; + editor_blockly.searchBlockCategoryCallback = function (workspace) { + var xmlList = []; + var labels = editor_blockly.searchBlock(); + for (var i = 0; i < labels.length; i++) { + var blockText = + "" + MotaActionBlocks[labels[i]].xmlText() + ""; + var block = Blockly.Xml.textToDom(blockText).firstChild; + block.setAttribute("gap", 5); + xmlList.push(block); + } + return xmlList; + }; - workspace.registerToolboxCategoryCallback( - "searchBlockCategory", - editor_blockly.searchBlockCategoryCallback - ); + workspace.registerToolboxCategoryCallback( + "searchBlockCategory", + editor_blockly.searchBlockCategoryCallback + ); - var onresize = function (e) { - blocklyDiv.style.width = blocklyArea.offsetWidth + "px"; - blocklyDiv.style.height = blocklyArea.offsetHeight + "px"; - Blockly.svgResize(workspace); - }; - if (typeof editor !== "undefined" && !editor.isMobile) - window.addEventListener("resize", onresize, false); - onresize(); - //Blockly.svgResize(workspace); + var onresize = function (e) { + blocklyDiv.style.width = blocklyArea.offsetWidth + "px"; + blocklyDiv.style.height = blocklyArea.offsetHeight + "px"; + Blockly.svgResize(workspace); + }; + if (typeof editor !== "undefined" && !editor.isMobile) + window.addEventListener("resize", onresize, false); + onresize(); + //Blockly.svgResize(workspace); - //Blockly.bindEventWithChecks_(workspace.svgGroup_,"wheel",workspace,function(e){}); - document.getElementById("blocklyDiv").onmousewheel = function (e) { - //console.log(e); - e.preventDefault(); - var hvScroll = e.shiftKey ? "hScroll" : "vScroll"; - var mousewheelOffsetValue = - (20 / 380) * workspace.scrollbar[hvScroll].handleLength_ * 3; - workspace.scrollbar[hvScroll].handlePosition_ += - (e.deltaY || 0) + (e.detail || 0) > 0 ? - mousewheelOffsetValue : - -mousewheelOffsetValue; - workspace.scrollbar[hvScroll].onScroll_(); - // workspace.setScale(workspace.scale); - }; + //Blockly.bindEventWithChecks_(workspace.svgGroup_,"wheel",workspace,function(e){}); + document.getElementById("blocklyDiv").onmousewheel = function (e) { + //console.log(e); + e.preventDefault(); + var hvScroll = e.shiftKey ? "hScroll" : "vScroll"; + var mousewheelOffsetValue = + (20 / 380) * workspace.scrollbar[hvScroll].handleLength_ * 3; + workspace.scrollbar[hvScroll].handlePosition_ += + (e.deltaY || 0) + (e.detail || 0) > 0 + ? mousewheelOffsetValue + : -mousewheelOffsetValue; + workspace.scrollbar[hvScroll].onScroll_(); + // workspace.setScale(workspace.scale); + }; - var doubleClickCheck = [ - [0, "abc"] - ]; + var doubleClickCheck = [[0, "abc"]]; - function omitedcheckUpdateFunction(event) { - if (event.type === "create") { - editor_blockly.addIntoLastUsedType(event.blockId); - } - if (event.type === "ui" && event.element == "click") { - var newClick = [new Date().getTime(), event.blockId]; - var lastClick = doubleClickCheck.shift(); - doubleClickCheck.push(newClick); - if (newClick[0] - lastClick[0] < 500) { - if (newClick[1] === lastClick[1]) { - editor_blockly.doubleClickBlock(newClick[1]); - } - } - } - // Only handle these events - if (["create", "move", "change", "delete"].indexOf(event.type) < 0) - return; - if (editor_blockly.workspace.topBlocks_.length >= 2) { - editor_blockly.setValue("入口方块只能有一个"); - return; - } - var eventType = editor_blockly.entryType; - if (editor_blockly.workspace.topBlocks_.length == 1) { - var blockType = editor_blockly.workspace.topBlocks_[0].type; - if ( - blockType !== eventType + "_m" && - !(editor_blockly.isCommonEntry() && blockType == "common_m") - ) { - editor_blockly.setValue("入口方块类型错误"); - return; - } - } - try { - var code = Blockly.JavaScript.workspaceToCode(workspace).replace( - /\\(i|c|d|e|g|z)/g, - "\\\\$1" - ); - editor_blockly.setValue(code); - } catch (error) { - editor_blockly.setValue(String(error)); - if (error instanceof OmitedError) { - var blockName = error.blockName; - var varName = error.varName; - var block = error.block; - } - // console.log(error); - } - } + function omitedcheckUpdateFunction(event) { + if (event.type === "create") { + editor_blockly.addIntoLastUsedType(event.blockId); + } + if (event.type === "ui" && event.element == "click") { + var newClick = [new Date().getTime(), event.blockId]; + var lastClick = doubleClickCheck.shift(); + doubleClickCheck.push(newClick); + if (newClick[0] - lastClick[0] < 500) { + if (newClick[1] === lastClick[1]) { + editor_blockly.doubleClickBlock(newClick[1]); + } + } + } + // Only handle these events + if (["create", "move", "change", "delete"].indexOf(event.type) < 0) + return; + if (editor_blockly.workspace.topBlocks_.length >= 2) { + editor_blockly.setValue("入口方块只能有一个"); + return; + } + var eventType = editor_blockly.entryType; + if (editor_blockly.workspace.topBlocks_.length == 1) { + var blockType = editor_blockly.workspace.topBlocks_[0].type; + if ( + blockType !== eventType + "_m" && + !(editor_blockly.isCommonEntry() && blockType == "common_m") + ) { + editor_blockly.setValue("入口方块类型错误"); + return; + } + } + try { + var code = Blockly.JavaScript.workspaceToCode(workspace).replace( + /\\(i|c|d|e|g|z)/g, + "\\\\$1" + ); + editor_blockly.setValue(code); + } catch (error) { + editor_blockly.setValue(String(error)); + if (error instanceof OmitedError) { + var blockName = error.blockName; + var varName = error.varName; + var block = error.block; + } + // console.log(error); + } + } - workspace.addChangeListener(omitedcheckUpdateFunction); + workspace.addChangeListener(omitedcheckUpdateFunction); - workspace.addChangeListener(Blockly.Events.disableOrphans); + workspace.addChangeListener(Blockly.Events.disableOrphans); - editor_blockly.workspace = workspace; + editor_blockly.workspace = workspace; - MotaActionFunctions.workspace = function () { - return editor_blockly.workspace; - }; + MotaActionFunctions.workspace = function () { + return editor_blockly.workspace; + }; - // 因为在editor_blockly.parse里已经HTML转义过一次了,所以这里要覆盖掉以避免在注释中出现<等 - MotaActionFunctions.xmlText = function ( - ruleName, - inputs, - isShadow, - comment, - collapsed, - disabled - ) { - var rule = MotaActionBlocks[ruleName]; - var blocktext = isShadow ? "shadow" : "block"; - var xmlText = []; - xmlText.push( - "<" + - blocktext + - ' type="' + - ruleName + - '"' + - (collapsed ? ' collapsed="true"' : "") + - (disabled ? ' disabled="true"' : "") + - ">" - ); - if (!inputs) inputs = []; - for (var ii = 0, inputType; - (inputType = rule.argsType[ii]); ii++) { - var input = inputs[ii]; - var _input = ""; - var noinput = input === null || input === undefined; - if ( - noinput && - inputType === "field" && - MotaActionBlocks[rule.argsGrammarName[ii]].type !== - "field_dropdown" - ) - continue; - if (noinput && inputType === "field") { - noinput = false; - input = rule.fieldDefault(rule.args[ii]); - } - if (noinput) input = ""; - if ( - inputType === "field" && - MotaActionBlocks[rule.argsGrammarName[ii]].type === - "field_checkbox" - ) - input = input ? "TRUE" : "FALSE"; - if (inputType !== "field") { - var subList = false; - var subrulename = rule.argsGrammarName[ii]; - var subrule = MotaActionBlocks[subrulename]; - if (subrule instanceof Array) { - subrulename = subrule[subrule.length - 1]; - subrule = MotaActionBlocks[subrulename]; - subList = true; - } - _input = subrule.xmlText([], true); - if (noinput && !subList && !isShadow) { - //无输入的默认行为是: 如果语句块的备选方块只有一个,直接代入方块 - input = subrule.xmlText(); - } - } - xmlText.push("<" + inputType + ' name="' + rule.args[ii] + '">'); - xmlText.push(_input + input); - xmlText.push(""); - } - if (comment) { - xmlText.push(""); - xmlText.push(comment); - xmlText.push(""); - } - var next = inputs[rule.args.length]; - if (next) { - //next - xmlText.push(""); - xmlText.push(next); - xmlText.push(""); - } - xmlText.push(""); - return xmlText.join(""); - }; - })(); + // 因为在editor_blockly.parse里已经HTML转义过一次了,所以这里要覆盖掉以避免在注释中出现<等 + MotaActionFunctions.xmlText = function ( + ruleName, + inputs, + isShadow, + comment, + collapsed, + disabled + ) { + var rule = MotaActionBlocks[ruleName]; + var blocktext = isShadow ? "shadow" : "block"; + var xmlText = []; + xmlText.push( + "<" + + blocktext + + ' type="' + + ruleName + + '"' + + (collapsed ? ' collapsed="true"' : "") + + (disabled ? ' disabled="true"' : "") + + ">" + ); + if (!inputs) inputs = []; + for (var ii = 0, inputType; (inputType = rule.argsType[ii]); ii++) { + var input = inputs[ii]; + var _input = ""; + var noinput = input === null || input === undefined; + if ( + noinput && + inputType === "field" && + MotaActionBlocks[rule.argsGrammarName[ii]].type !== + "field_dropdown" + ) + continue; + if (noinput && inputType === "field") { + noinput = false; + input = rule.fieldDefault(rule.args[ii]); + } + if (noinput) input = ""; + if ( + inputType === "field" && + MotaActionBlocks[rule.argsGrammarName[ii]].type === + "field_checkbox" + ) + input = input ? "TRUE" : "FALSE"; + if (inputType !== "field") { + var subList = false; + var subrulename = rule.argsGrammarName[ii]; + var subrule = MotaActionBlocks[subrulename]; + if (subrule instanceof Array) { + subrulename = subrule[subrule.length - 1]; + subrule = MotaActionBlocks[subrulename]; + subList = true; + } + _input = subrule.xmlText([], true); + if (noinput && !subList && !isShadow) { + //无输入的默认行为是: 如果语句块的备选方块只有一个,直接代入方块 + input = subrule.xmlText(); + } + } + xmlText.push("<" + inputType + ' name="' + rule.args[ii] + '">'); + xmlText.push(_input + input); + xmlText.push(""); + } + if (comment) { + xmlText.push(""); + xmlText.push(comment); + xmlText.push(""); + } + var next = inputs[rule.args.length]; + if (next) { + //next + xmlText.push(""); + xmlText.push(next); + xmlText.push(""); + } + xmlText.push(""); + return xmlText.join(""); + }; + })(); - // end mark sfergsvae - } - .toString() - .split("// start mark sfergsvae")[1] - .split("// end mark sfergsvae")[0]; - } -}, + // end mark sfergsvae + } + .toString() + .split("// start mark sfergsvae")[1] + .split("// end mark sfergsvae")[0]; + } + }, "夹击激光动画": function () { function createCanvas(name, zIndex) { if (!name) return; @@ -12631,81 +13083,81 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = }; }, "瞬移轨迹": function () { - // 在此增加新插件 - function popMove() { - var ctx = core.getContextByName("popMove"); - if (!ctx) - ctx = core.createCanvas( - "popMove", - 0, - 0, - core.__PIXELS__, - core.__PIXELS__, - 71 - ); - ctx.canvas.classList.add("gameCanvas", "anti-aliasing"); - core.clearMap(ctx); - if (core.status.replay.speed <= 3 && !flags.stopPop) { - var list = core.status.popMove || []; - var count = 0; - list.forEach(function (one) { - // 由frame计算出dy + // 在此增加新插件 + function popMove() { + var ctx = core.getContextByName("popMove"); + if (!ctx) + ctx = core.createCanvas( + "popMove", + 0, + 0, + core.__PIXELS__, + core.__PIXELS__, + 71 + ); + ctx.canvas.classList.add("gameCanvas", "anti-aliasing"); + core.clearMap(ctx); + if (core.status.replay.speed <= 3 && !flags.stopPop) { + var list = core.status.popMove || []; + var count = 0; + list.forEach(function (one) { + // 由frame计算出dy - one.frame++; - // 绘制 + one.frame++; + // 绘制 - if (one.frame >= 0) core.setAlpha(ctx, 1 - one.frame / 30); - else core.setAlpha(ctx, 1); + if (one.frame >= 0) core.setAlpha(ctx, 1 - one.frame / 30); + else core.setAlpha(ctx, 1); - var length = Math.sqrt( - Math.pow(one.px2 - one.px, 2) + Math.pow(one.py2 - one.py, 2) - ); - //console.log(length) - var li = length / 16; - var lx = (one.px2 - one.px) / li; - var ly = (one.py2 - one.py) / li; - for (var i = 0; i < li; i += 1) { - core.setAlpha(ctx, (1 - one.frame / 30) * ((i / li) * 0.8 + 0.2)); - core.drawLine( - "popMove", - one.px + i * lx, - one.py + i * ly, - one.px + (i + 0.5) * lx, - one.py + (i + 0.5) * ly, - "#E1E1E1", - 6 - ); - if (i == 0) - core.strokeCircle("popMove", one.px, one.py, 6, "#E1E1E1", 3); - } - core.strokeCircle("popMove", one.px2, one.py2, 6, "#E1E1E1", 3); - core.strokeCircle( - "popMove", - one.px2, - one.py2, - 6 + (16 * one.frame) / 30, - "#E1E1E1", - 6 * (1 - one.frame / 30) - ); - //core.drawLine('popMove', one.px, one.py, one.px2, one.py2, '#E1E1E1', 6); + var length = Math.sqrt( + Math.pow(one.px2 - one.px, 2) + Math.pow(one.py2 - one.py, 2) + ); + //console.log(length) + var li = length / 16; + var lx = (one.px2 - one.px) / li; + var ly = (one.py2 - one.py) / li; + for (var i = 0; i < li; i += 1) { + core.setAlpha(ctx, (1 - one.frame / 30) * ((i / li) * 0.8 + 0.2)); + core.drawLine( + "popMove", + one.px + i * lx, + one.py + i * ly, + one.px + (i + 0.5) * lx, + one.py + (i + 0.5) * ly, + "#E1E1E1", + 6 + ); + if (i == 0) + core.strokeCircle("popMove", one.px, one.py, 6, "#E1E1E1", 3); + } + core.strokeCircle("popMove", one.px2, one.py2, 6, "#E1E1E1", 3); + core.strokeCircle( + "popMove", + one.px2, + one.py2, + 6 + (16 * one.frame) / 30, + "#E1E1E1", + 6 * (1 - one.frame / 30) + ); + //core.drawLine('popMove', one.px, one.py, one.px2, one.py2, '#E1E1E1', 6); - if (one.frame >= 30) count++; - }); - if (count > 0) list.splice(0, count); - } - } + if (one.frame >= 30) count++; + }); + if (count > 0) list.splice(0, count); + } + } - if (!main.replayChecking) { - core.registerAnimationFrame("popMove", true, popMove); - } - this.addPopMove = function (px, py, px2, py2, frame) { - var data = { px: px, py: py, px2: px2, py2: py2, frame: frame || 0 }; - if (core.status.replay.speed <= 3) { - if (!core.status.popMove) core.status.popMove = [data]; - else core.status.popMove.push(data); - } - }; -}, + if (!main.replayChecking) { + core.registerAnimationFrame("popMove", true, popMove); + } + this.addPopMove = function (px, py, px2, py2, frame) { + var data = { px: px, py: py, px2: px2, py2: py2, frame: frame || 0 }; + if (core.status.replay.speed <= 3) { + if (!core.status.popMove) core.status.popMove = [data]; + else core.status.popMove.push(data); + } + }; + }, "墓碑(编辑器)": function () { // 在此增加新插件 if (main.mode != "editor") return; // 编辑器模式下使用 @@ -13221,1633 +13673,1636 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = }; }, "楼传": function () { - // 在此增加新插件 + // 在此增加新插件 - core.canMoveFloor = function () { - let canmove = false; - core.status.thisMap.blocks.forEach((block) => { - if ( - !block.disable && - (block.event.id == "upFloor" || block.event.id == "downFloor") - ) { - let automaticRoute = core.automaticRoute(block.x, block.y); - if (!core.flags.flyNearStair || automaticRoute.length > 0) { - let loc = automaticRoute.pop(); - loc = automaticRoute.pop(); - if (core.canMoveDirectly(loc?.x, loc?.y) >= 0 || !loc) { - canmove = true; - } - } - } - }); - return canmove; - }; - ui.prototype._drawViewMaps_drawHint = function () { - core.playSound("打开界面"); - }; + core.canMoveFloor = function () { + let canmove = false; + core.status.thisMap.blocks.forEach((block) => { + if ( + !block.disable && + (block.event.id == "upFloor" || block.event.id == "downFloor") + ) { + let automaticRoute = core.automaticRoute(block.x, block.y); + if (!core.flags.flyNearStair || automaticRoute.length > 0) { + let loc = automaticRoute.pop(); + loc = automaticRoute.pop(); + if (core.canMoveDirectly(loc?.x, loc?.y) >= 0 || !loc) { + canmove = true; + } + } + } + }); + return canmove; + }; + ui.prototype._drawViewMaps_drawHint = function () { + core.playSound("打开界面"); + }; - ////// 绘制浏览地图界面 ////// - ui.prototype._drawViewMaps = function (index, x, y) { - core.lockControl(); + ////// 绘制浏览地图界面 ////// + ui.prototype._drawViewMaps = function (index, x, y) { + core.lockControl(); - core.clearMap("data"); - core.status.event.id = "viewMaps"; - this.clearUI(); - //console.log(index) - if (index == null) index = core.floorIds.indexOf(core.status.floorId); - core.animateFrame.tip = null; - core.status.checkBlock.cache = {}; - let data = this._drawViewMaps_buildData(index, x, y); - core.drawWindowSkin("winskin1.webp", "ui", 0, 0, 416, 416); - let page = core.status.event.data.index; - let floorId = core.status.event.data.floorId; - core.ui.statusBar._update_map(floorId); - const bfs = core.plugin.bfsSearch(floorId, 1, true); - const mapdir = bfs.mapdir[floorId]; - core.setTextAlign("ui", "center"); - let size = (core.__PIXELS__ * 3) / 4; //312 - const areas = core.getFlag("areas"); + core.clearMap("data"); + core.status.event.id = "viewMaps"; + this.clearUI(); + //console.log(index) + if (index == null) index = core.floorIds.indexOf(core.status.floorId); + core.animateFrame.tip = null; + core.status.checkBlock.cache = {}; + let data = this._drawViewMaps_buildData(index, x, y); + core.drawWindowSkin("winskin1.webp", "ui", 0, 0, 416, 416); + let page = core.status.event.data.index; + let floorId = core.status.event.data.floorId; + core.ui.statusBar._update_map(floorId); + const bfs = core.plugin.bfsSearch(floorId, 1, true); + const mapdir = bfs.mapdir[floorId]; + core.setTextAlign("ui", "center"); + let size = (core.__PIXELS__ * 3) / 4; //312 + const areas = core.getFlag("areas"); - let i = areas.findIndex((v) => v.maps.includes(floorId)); - core.fillRoundRect("ui", 15 - 2, 15 - 2, 35 + 4, 35 + 4, 4, "#444444"); - core.strokeRoundRect( - "ui", - 15 - 4, - 15 - 4, - 35 + 8, - 35 + 8, - 4, - "#444444", - 1 - ); - core.fillBoldText1( - "ui", - "当前", - 13 + 20, - 17 + 20, - "#FFFFFF", - "#000000", - 2, - this._buildFont(18, true) - ); + let i = areas.findIndex((v) => v.maps.includes(floorId)); + core.fillRoundRect("ui", 15 - 2, 15 - 2, 35 + 4, 35 + 4, 4, "#444444"); + core.strokeRoundRect( + "ui", + 15 - 4, + 15 - 4, + 35 + 8, + 35 + 8, + 4, + "#444444", + 1 + ); + core.fillBoldText1( + "ui", + "当前", + 13 + 20, + 17 + 20, + "#FFFFFF", + "#000000", + 2, + this._buildFont(18, true) + ); - core.fillRoundRect( - "ui", - 15 - 2, - 15 - 2 + 35 + 8 + size + 8 - 54, - 35 + 4, - 35 + 4, - 4, - "#444444" - ); - core.strokeRoundRect( - "ui", - 15 - 4, - 15 - 4 + 35 + 8 + size + 8 - 54, - 35 + 8, - 35 + 8, - 4, - "#444444", - 1 - ); - if ( - !core.status.maps[core.floorIds[page]].canFlyTo || - !core.hasVisitedFloor(core.floorIds[page]) - ) { - core.fillBoldText1( - "ui", - "预览", - 13 + 20, - 17 + 20 + 35 + 8 + size + 8 - 54, - "#909090", - "#000000", - 2, - this._buildFont(18, true) - ); - } else { - core.fillBoldText1( - "ui", - "传送", - 13 + 20, - 17 + 20 + 35 + 8 + size + 8 - 54, - "#909090", - "#000000", - 2, - this._buildFont(18, true) - ); - } - core.fillRoundRect( - "ui", - 15 - 4 + size - 2 + 45, - 15 - 2 + size - 4 + 45, - 35 + 4, - 35 + 4, - 4, - "#444444" - ); - core.strokeRoundRect( - "ui", - 15 - 4 + size - 4 + 45, - 15 - 4 + size - 4 + 45, - 35 + 8, - 35 + 8, - 4, - "#444444", - 1 - ); - core.fillBoldText1( - "ui", - "离开", - 15 - 4 + size - 4 + 45 + 22, - 15 - 4 + size - 4 + 45 + 26, - "#FFFFFF", - "#000000", - 2, - this._buildFont(18, true) - ); + core.fillRoundRect( + "ui", + 15 - 2, + 15 - 2 + 35 + 8 + size + 8 - 54, + 35 + 4, + 35 + 4, + 4, + "#444444" + ); + core.strokeRoundRect( + "ui", + 15 - 4, + 15 - 4 + 35 + 8 + size + 8 - 54, + 35 + 8, + 35 + 8, + 4, + "#444444", + 1 + ); + if ( + !core.status.maps[core.floorIds[page]].canFlyTo || + !core.hasVisitedFloor(core.floorIds[page]) + ) { + core.fillBoldText1( + "ui", + "预览", + 13 + 20, + 17 + 20 + 35 + 8 + size + 8 - 54, + "#909090", + "#000000", + 2, + this._buildFont(18, true) + ); + } else { + core.fillBoldText1( + "ui", + "传送", + 13 + 20, + 17 + 20 + 35 + 8 + size + 8 - 54, + "#909090", + "#000000", + 2, + this._buildFont(18, true) + ); + } + core.fillRoundRect( + "ui", + 15 - 4 + size - 2 + 45, + 15 - 2 + size - 4 + 45, + 35 + 4, + 35 + 4, + 4, + "#444444" + ); + core.strokeRoundRect( + "ui", + 15 - 4 + size - 4 + 45, + 15 - 4 + size - 4 + 45, + 35 + 8, + 35 + 8, + 4, + "#444444", + 1 + ); + core.fillBoldText1( + "ui", + "离开", + 15 - 4 + size - 4 + 45 + 22, + 15 - 4 + size - 4 + 45 + 26, + "#FFFFFF", + "#000000", + 2, + this._buildFont(18, true) + ); - core.fillRoundRect( - "ui", - 15 + 44 - 2, - 15 - 2, - size + 4 - 58, - 35 + 4, - 4, - "#444444" - ); - core.strokeRoundRect( - "ui", - 15 + 44 - 4, - 15 - 4, - size + 8 - 58, - 35 + 8, - 4, - "#444444", - 1 - ); - if (mapdir.includes("up")) { - core.fillBoldText1( - "ui", - "北▲", - 30 + 145 + 10, - 17 + 20, - "#FFFFFF", - "#000000", - 2, - this._buildFont(18, true) - ); - } else { - core.fillBoldText1( - "ui", - "北▲", - 30 + 145 + 10, - 17 + 20, - "#909090", - "#000000", - 2, - this._buildFont(18, true) - ); - } + core.fillRoundRect( + "ui", + 15 + 44 - 2, + 15 - 2, + size + 4 - 58, + 35 + 4, + 4, + "#444444" + ); + core.strokeRoundRect( + "ui", + 15 + 44 - 4, + 15 - 4, + size + 8 - 58, + 35 + 8, + 4, + "#444444", + 1 + ); + if (mapdir.includes("up")) { + core.fillBoldText1( + "ui", + "北▲", + 30 + 145 + 10, + 17 + 20, + "#FFFFFF", + "#000000", + 2, + this._buildFont(18, true) + ); + } else { + core.fillBoldText1( + "ui", + "北▲", + 30 + 145 + 10, + 17 + 20, + "#909090", + "#000000", + 2, + this._buildFont(18, true) + ); + } - core.fillRoundRect( - "ui", - 15 - 2, - 59 - 2, - 35 + 4, - size + 4 - 58, - 4, - "#444444" - ); - core.strokeRoundRect( - "ui", - 15 - 4, - 59 - 4, - 35 + 8, - size + 8 - 58, - 4, - "#444444", - 1 - ); - if (mapdir.includes("left")) { - core.fillBoldText1( - "ui", - "西", - 15 + 17, - 25 + 150, - "#FFFFFF", - "#000000", - 2, - this._buildFont(18, true) - ); - core.fillBoldText1( - "ui", - "◀", - 15 + 17, - 45 + 150, - "#FFFFFF", - "#000000", - 2, - this._buildFont(18, true) - ); - } else { - core.fillBoldText1( - "ui", - "西", - 15 + 17, - 25 + 150, - "#909090", - "#000000", - 2, - this._buildFont(18, true) - ); - core.fillBoldText1( - "ui", - "◀", - 15 + 17, - 45 + 150, - "#909090", - "#000000", - 2, - this._buildFont(18, true) - ); - } - core.fillRoundRect( - "ui", - 15 + 44 - 2, - 15 - 2 + size - 4, - size + 4 - 58, - 35 + 4, - 4, - "#444444" - ); - core.strokeRoundRect( - "ui", - 15 + 44 - 4, - 15 - 4 + size - 4, - size + 8 - 58, - 35 + 8, - 4, - "#444444", - 1 - ); - if (mapdir.includes("down")) { - core.fillBoldText1( - "ui", - "南▼", - 30 + 145 + 10, - 17 + 20 + size - 4, - "#FFFFFF", - "#000000", - 2, - this._buildFont(18, true) - ); - } else { - core.fillBoldText1( - "ui", - "南▼", - 30 + 145 + 10, - 17 + 20 + size - 4, - "#909090", - "#000000", - 2, - this._buildFont(18, true) - ); - } + core.fillRoundRect( + "ui", + 15 - 2, + 59 - 2, + 35 + 4, + size + 4 - 58, + 4, + "#444444" + ); + core.strokeRoundRect( + "ui", + 15 - 4, + 59 - 4, + 35 + 8, + size + 8 - 58, + 4, + "#444444", + 1 + ); + if (mapdir.includes("left")) { + core.fillBoldText1( + "ui", + "西", + 15 + 17, + 25 + 150, + "#FFFFFF", + "#000000", + 2, + this._buildFont(18, true) + ); + core.fillBoldText1( + "ui", + "◀", + 15 + 17, + 45 + 150, + "#FFFFFF", + "#000000", + 2, + this._buildFont(18, true) + ); + } else { + core.fillBoldText1( + "ui", + "西", + 15 + 17, + 25 + 150, + "#909090", + "#000000", + 2, + this._buildFont(18, true) + ); + core.fillBoldText1( + "ui", + "◀", + 15 + 17, + 45 + 150, + "#909090", + "#000000", + 2, + this._buildFont(18, true) + ); + } + core.fillRoundRect( + "ui", + 15 + 44 - 2, + 15 - 2 + size - 4, + size + 4 - 58, + 35 + 4, + 4, + "#444444" + ); + core.strokeRoundRect( + "ui", + 15 + 44 - 4, + 15 - 4 + size - 4, + size + 8 - 58, + 35 + 8, + 4, + "#444444", + 1 + ); + if (mapdir.includes("down")) { + core.fillBoldText1( + "ui", + "南▼", + 30 + 145 + 10, + 17 + 20 + size - 4, + "#FFFFFF", + "#000000", + 2, + this._buildFont(18, true) + ); + } else { + core.fillBoldText1( + "ui", + "南▼", + 30 + 145 + 10, + 17 + 20 + size - 4, + "#909090", + "#000000", + 2, + this._buildFont(18, true) + ); + } - core.fillRoundRect( - "ui", - 15 - 2 + size - 4, - 59 - 2, - 35 + 4, - size + 4 - 58, - 4, - "#444444" - ); - core.strokeRoundRect( - "ui", - 15 - 4 + size - 4, - 59 - 4, - 35 + 8, - size + 8 - 58, - 4, - "#444444", - 1 - ); - if (mapdir.includes("right")) { - core.fillBoldText1( - "ui", - "东", - 15 + 17 + size - 4, - 25 + 150, - "#FFFFFF", - "#000000", - 2, - this._buildFont(18, true) - ); - core.fillBoldText1( - "ui", - "▶", - 15 + 17 + size - 4, - 45 + 150, - "#FFFFFF", - "#000000", - 2, - this._buildFont(18, true) - ); - } else { - core.fillBoldText1( - "ui", - "东", - 15 + 17 + size - 4, - 25 + 150, - "#909090", - "#000000", - 2, - this._buildFont(18, true) - ); - core.fillBoldText1( - "ui", - "▶", - 15 + 17 + size - 4, - 45 + 150, - "#909090", - "#000000", - 2, - this._buildFont(18, true) - ); - } - core.fillRoundRect( - "ui", - 60 - 2, - 60 - 2, - size - 58 + 4, - size - 58 + 4, - 4, - "#444444" - ); - core.strokeRoundRect( - "ui", - 60 - 4, - 60 - 4, - size - 58 + 8, - size - 58 + 8, - 4, - "#444444", - 1 - ); - core.drawThumbnail(floorId, null, { - damage: data.damage, - ctx: "ui", - x: 58, - y: 58, - size: 0.62, - all: data.all, - }); - if ( - !core.status.maps[core.floorIds[page]].canFlyTo || - !core.hasVisitedFloor(core.floorIds[page]) - ) { - /*core.fillRect("ui", 58, + core.fillRoundRect( + "ui", + 15 - 2 + size - 4, + 59 - 2, + 35 + 4, + size + 4 - 58, + 4, + "#444444" + ); + core.strokeRoundRect( + "ui", + 15 - 4 + size - 4, + 59 - 4, + 35 + 8, + size + 8 - 58, + 4, + "#444444", + 1 + ); + if (mapdir.includes("right")) { + core.fillBoldText1( + "ui", + "东", + 15 + 17 + size - 4, + 25 + 150, + "#FFFFFF", + "#000000", + 2, + this._buildFont(18, true) + ); + core.fillBoldText1( + "ui", + "▶", + 15 + 17 + size - 4, + 45 + 150, + "#FFFFFF", + "#000000", + 2, + this._buildFont(18, true) + ); + } else { + core.fillBoldText1( + "ui", + "东", + 15 + 17 + size - 4, + 25 + 150, + "#909090", + "#000000", + 2, + this._buildFont(18, true) + ); + core.fillBoldText1( + "ui", + "▶", + 15 + 17 + size - 4, + 45 + 150, + "#909090", + "#000000", + 2, + this._buildFont(18, true) + ); + } + core.fillRoundRect( + "ui", + 60 - 2, + 60 - 2, + size - 58 + 4, + size - 58 + 4, + 4, + "#444444" + ); + core.strokeRoundRect( + "ui", + 60 - 4, + 60 - 4, + size - 58 + 8, + size - 58 + 8, + 4, + "#444444", + 1 + ); + core.drawThumbnail(floorId, null, { + damage: data.damage, + ctx: "ui", + x: 58, + y: 58, + size: 0.62, + all: data.all, + }); + if ( + !core.status.maps[core.floorIds[page]].canFlyTo || + !core.hasVisitedFloor(core.floorIds[page]) + ) { + /*core.fillRect("ui", 58, 58, size - 50, size - 50, "rgba(0,0,0,0.5)")*/ - core.getContextByName("ui").globalAlpha = 0.7; + core.getContextByName("ui").globalAlpha = 0.7; - core.drawImage( - "ui", - "miwu.webp", - 0, - 0, - size, - size, - 58, - 58, - size - 50, - size - 50 - ); - core.getContextByName("ui").globalAlpha = 1; - /*core.fillText("ui", '?', 188, + core.drawImage( + "ui", + "miwu.webp", + 0, + 0, + size, + size, + 58, + 58, + size - 50, + size - 50 + ); + core.getContextByName("ui").globalAlpha = 1; + /*core.fillText("ui", '?', 188, 278, "rgba(255,255,255,0.2)", this._buildFont(250, true))*/ - } - core.fillRoundRect( - "ui", - 15 + 44 - 2, - 60 - 2 + size - 4, - size + 4 - 58, - 35 + 4, - 4, - "#444444" - ); - core.strokeRoundRect( - "ui", - 15 + 44 - 4, - 60 - 4 + size - 4, - size + 8 - 58, - 35 + 8, - 4, - "#444444", - 1 - ); - core.fillBoldText1( - "ui", - core.status.maps[floorId].areas, - 30 + 145 + 10, - 17 + 65 + size - 4, - "#FFFFFF", - "#000000", - 2, - this._buildFont(18, true) - ); - core.fillRoundRect( - "ui", - 15 - 2, - 60 - 2 + size - 4, - 35 + 4, - 35 + 4, - 4, - "#444444" - ); - core.strokeRoundRect( - "ui", - 15 - 4, - 60 - 4 + size - 4, - 35 + 8, - 35 + 8, - 4, - "#444444", - 1 - ); - if (i === 0) { - core.fillBoldText1( - "ui", - "◀", - 30, - 17 + 65 + size - 4, - "#909090", - "#000000", - 2, - this._buildFont(18, true) - ); - } else { - core.fillBoldText1( - "ui", - "◀", - 30, - 17 + 65 + size - 4, - "#FFFFFF", - "#000000", - 2, - this._buildFont(18, true) - ); - } - core.fillRoundRect( - "ui", - 15 - 2 + size - 4, - 60 - 2 + size - 4, - 35 + 4, - 35 + 4, - 4, - "#444444" - ); - core.strokeRoundRect( - "ui", - 15 - 4 + size - 4, - 60 - 4 + size - 4, - 35 + 8, - 35 + 8, - 4, - "#444444", - 1 - ); - if (i === areas.length - 1) { - core.fillBoldText1( - "ui", - "▶", - 30 + 300 + 10, - 17 + 65 + size - 4, - "#909090", - "#000000", - 2, - this._buildFont(18, true) - ); - } else { - core.fillBoldText1( - "ui", - "▶", - 30 + 300 + 10, - 17 + 65 + size - 4, - "#FFFFFF", - "#000000", - 2, - this._buildFont(18, true) - ); - } - - core.fillRoundRect( - "ui", - 15 - 2 + size - 4, - 15 - 2, - 80 + 4, - 35 + 4, - 4, - "#444444" - ); - core.strokeRoundRect( - "ui", - 15 - 4 + size - 4, - 15 - 4, - 80 + 8, - 35 + 8, - 4, - "#444444", - 1 - ); - if (mapdir.includes("upFloor")) { - core.fillBoldText1( - "ui", - "上楼", - 30 + 320 + 10, - 17 + 20, - "#FFFFFF", - "#000000", - 2, - this._buildFont(18, true) - ); - } else { - core.fillBoldText1( - "ui", - "上楼", - 30 + 320 + 10, - 17 + 20, - "#909090", - "#000000", - 2, - this._buildFont(18, true) - ); - } - core.fillRoundRect( - "ui", - 15 - 2 + size - 4, - 15 - 2 + size - 4, - 80 + 4, - 35 + 4, - 4, - "#444444" - ); - core.strokeRoundRect( - "ui", - 15 - 4 + size - 4, - 15 - 4 + size - 4, - 80 + 8, - 35 + 8, - 4, - "#444444", - 1 - ); - if (mapdir.includes("downFloor")) { - core.fillBoldText1( - "ui", - "下楼", - 30 + 320 + 10, - 17 + 20 + size - 4, - "#FFFFFF", - "#000000", - 2, - this._buildFont(18, true) - ); - } else { - core.fillBoldText1( - "ui", - "下楼", - 30 + 320 + 10, - 17 + 20 + size - 4, - "#909090", - "#000000", - 2, - this._buildFont(18, true) - ); - } - - core.fillRoundRect( - "ui", - 15 - 2 + size - 4 + 35 + 8, - 59 - 2, - 37 + 4, - (size - 58) / 2 + 4, - 4, - "#444444" - ); - core.strokeRoundRect( - "ui", - 15 - 4 + size - 4 + 35 + 8, - 59 - 4, - 37 + 8, - (size - 58) / 2 + 8, - 4, - "#444444", - 1 - ); - const title = core.status.maps[floorId].title; - //const length = title.length - fillTextVertical( - "ui", - title, - 15 - 4 + size - 4 + 45, - 85, - core.hasVisitedFloor(floorId) ? "#FFFFFF" : "#444444", - "#000000", - 18 - ); - //const uictx = main.dom.gameCanvas.ui.getContext('2d') - core.fillRoundRect( - "ui", - 15 - 2 + size - 4 + 35 + 8, - 59 - 2 + (size - 58) / 2 + 8, - 37 + 4, - 119 + 4, - 4, - "#444444" - ); - core.strokeRoundRect( - "ui", - 15 - 4 + size - 4 + 35 + 8, - 59 - 4 + (size - 58) / 2 + 8, - 37 + 8, - 119 + 8, - 4, - "#444444", - 1 - ); - if (core.getFlag("showEnemy")) { - fillTextVertical( - "ui", - "关闭漏怪检测", - 15 - 4 + size - 4 + 45, - 220, - "#FFFFFF", - "#000000", - 18 - ); - } else { - fillTextVertical( - "ui", - "开启漏怪检测", - 15 - 4 + size - 4 + 45, - 220, - "#FFFFFF", - "#000000", - 18 - ); - } - - //uictx.fillTextVertical(title, 15 - 4 + size - 4 + 35 + 29, 25 + 150) - //fillTextVertical('ui', title, 15 - 4 + size - 4 + 35 + 29, 25 + 150, '#FFFFFF', this._buildFont(18, true)) - }; - - function fillTextVertical(name, text, x, y, style, boldstyle, fontsize) { - //竖向文字绘制 - - const ctx = core.ui.getContextByName(name); - if (!ctx) return; - const canvas = document.createElement("canvas"); - const context = canvas.getContext("2d"); - fontsize *= 3; - const length = text.length; - canvas.width = fontsize * 2; - canvas.height = fontsize * length * 2; - if (style) context.fillStyle = core.arrayToRGBA(style); - if (boldstyle) context.strokeStyle = core.arrayToRGBA(boldstyle); - context.lineWidth = 2; - if (fontsize) context.font = core.ui._buildFont(fontsize, true); - let arrText = text.split(""); - - let arrWidth = arrText.map(function (letter) { - return context.measureText(letter).width; - }); - - let align = context.textAlign; - - let baseline = context.textBaseline; - let sx = fontsize, - sy = fontsize * length; - if (align == "left") { - sx = sx + Math.max.apply(null, arrWidth) / 2; - } else if (align == "right") { - sx = sx - Math.max.apply(null, arrWidth) / 2; - } - - if ( - baseline == "bottom" || - baseline == "alphabetic" || - baseline == "ideographic" - ) { - sy = sy - arrWidth[0] / 2; - } else if (baseline == "top" || baseline == "hanging") { - sy = sy + arrWidth[0] / 2; - } - - context.textAlign = "center"; - - context.textBaseline = "middle"; - context.lineWidth = 6; - - // 开始逐字绘制 - - arrText.forEach(function (letter, index) { - // 确定下一个字符的纵坐标位置 - - context.strokeText(letter, sx, sy); - context.fillText(letter, sx, sy); - // 旋转坐标系还原成初始态 - - context.setTransform(1, 0, 0, 1, 0, 0); - - // 确定下一个字符的纵坐标位置 - - var letterWidth = 54; - - sy = sy + letterWidth; - }); - - // 水平垂直对齐方式还原 - - context.textAlign = align; - - context.textBaseline = baseline; - - //绘制到目标位置 - ctx.drawImage( - canvas, - x, - y - (fontsize / 3) * length, - canvas.width / 3, - canvas.height / 3 - ); - } - - ////// 点击楼层传送器时的打开操作 ////// - events.prototype.useFly = function (fromUserAction) { - if (!core.isPlaying()) return; - if (!core.status.maps[core.status.floorId].canFlyFrom) { - core.drawTip(core.material.items["fly"].name + "好像失效了", "fly"); - return; - } - // 从“浏览地图”页面:尝试直接传送到该层 - if (core.status.event.id == "viewMaps") { - if (!core.hasItem("fly")) { - core.playSound("操作失败"); - core.drawTip("你没有" + core.material.items["fly"].name, "fly"); - } else if ( - core.flags.flyNearStair && - !core.nearStair() && - !flags.canMoveFloor - ) { - core.playSound("操作失败"); - core.drawTip( - "无法到达楼梯边使用" + core.material.items["fly"].name, - "fly" - ); - } else { - core.flyTo(core.status.event.data.floorId); - core.updateStatusBar(); - } - return; - } - - if (!this._checkStatus("fly", fromUserAction, true)) return; - //if (core.flags.flyNearStair && !core.nearStair()) - - if ( - (core.flags.flyNearStair && !core.nearStair()) || - !flags.canMoveFloor - ) { - core.playSound("操作失败"); - core.drawTip( - "无法到达楼梯边使用" + core.material.items["fly"].name, - "fly" - ); - core.unlockControl(); - core.status.event.data = null; - core.status.event.id = null; - return; - } - if (!core.canUseItem("fly")) { - core.playSound("操作失败"); - core.drawTip(core.material.items["fly"].name + "好像失效了", "fly"); - core.unlockControl(); - core.status.event.data = null; - core.status.event.id = null; - return; - } - core.playSound("打开界面"); - core.useItem("fly", true); - core.updateStatusBar(); - return; - }; - ////// 系统菜单栏界面时的点击操作 ////// - actions.prototype._clickSettings = function (x, y) { - if (this._out(x)) return; - var choices = core.status.event.ui.choices; - var topIndex = this._getChoicesTopIndex(choices.length); - if (y >= topIndex && y < topIndex + choices.length) { - var selection = y - topIndex; - core.status.event.selection = selection; - switch (selection) { - case 0: - core.status.event.selection = 0; - core.playSound("确定"); - core.ui._drawSwitchs(); - break; - case 1: - // core.playSound('确定'); - core.ui._drawKeyBoard(); - break; - case 2: - // core.playSound('确定'); - core.clearUI(); - core.useItem("fly"); - break; - case 3: - core.status.event.selection = 0; - core.playSound("确定"); - core.ui._drawNotes(); - break; - case 4: - core.status.event.selection = 0; - core.playSound("确定"); - core.ui._drawSyncSave(); - break; - case 5: - core.status.event.selection = 0; - core.playSound("确定"); - core.ui._drawGameInfo(); - break; - case 6: - return core.confirmRestart(); - case 7: - core.playSound("取消"); - core.ui.closePanel(); - break; - } - } - return; - }; - ////// 查看地图界面时的点击操作 ////// - actions.prototype._clickViewMaps = function (x, y, px, py) { - if (core.status.event.data == null) { - core.ui._drawViewMaps(core.floorIds.indexOf(core.status.floorId)); - return; - } - let now = core.floorIds.indexOf(core.status.floorId); - let index = core.status.event.data.index; - let cx = core.status.event.data.x, - cy = core.status.event.data.y; - let floorId = core.floorIds[index], - mw = core.floors[floorId].width, - mh = core.floors[floorId].height; - let perpx = core.__PIXELS__ / 5, - cornerpx = (perpx * 3) / 4; - const bfs = core.plugin.bfsSearch(floorId, 1, true); - const mapdir = bfs.mapdir[floorId]; - const res = bfs.res; - const formto = {}; - for (let from in res) { - const to = res[from]; - const [fromfloorId, fromsx, fromsy, dir] = from.split("_"); - const [tofloorId, tosx, tosy] = to.split("_"); - if (!formto[fromfloorId]) formto[fromfloorId] = {}; - if (!formto[fromfloorId][dir]) formto[fromfloorId][dir] = tofloorId; - } - const areas = core.getFlag("areas"); - let i = areas.findIndex((v) => v.maps.includes(floorId)); - - if (px >= 11 && px <= 54 && py >= 11 && py <= 54) { - core.ui._drawViewMaps(core.floorIds.indexOf(core.status.floorId)); - } else if (px >= 362 && px <= 407 && py >= 191 && py <= 318) { - flags.showEnemy = !flags.showEnemy; - core.ui._drawViewMaps(index); - } else if (px >= 364 && px <= 407 && py >= 364 && py <= 407) { - core.clearMap("data"); - core.playSound("取消"); - core.ui.closePanel(); - core.getItemDetail(); - core.redrawMap(); - core.updateStatusBar(); - core.ui.statusBar._update_map(); - return; - } else if (px >= 55 && px <= 317 && py >= 11 && py <= 54) { - if (mapdir.includes("up")) - core.ui._drawViewMaps(core.floorIds.indexOf(formto[floorId].up)); - } else if (px >= 55 && px <= 317 && py >= 319 && py <= 362) { - if (mapdir.includes("down")) - core.ui._drawViewMaps(core.floorIds.indexOf(formto[floorId].down)); - } else if (px >= 11 && px <= 54 && py >= 55 && py <= 317) { - if (mapdir.includes("left")) - core.ui._drawViewMaps(core.floorIds.indexOf(formto[floorId].left)); - } else if (px >= 319 && px <= 362 && py >= 55 && py <= 317) { - if (mapdir.includes("right")) - core.ui._drawViewMaps(core.floorIds.indexOf(formto[floorId].right)); - } else if (px >= 319 && px <= 407 && py >= 11 && py <= 54) { - if (mapdir.includes("upFloor")) - core.ui._drawViewMaps(core.floorIds.indexOf(formto[floorId].upFloor)); - } else if (px >= 319 && px <= 407 && py >= 319 && py <= 362) { - if (mapdir.includes("downFloor")) - core.ui._drawViewMaps( - core.floorIds.indexOf(formto[floorId].downFloor) - ); - } else if ( - px >= 55 && - px <= 317 && - py >= 55 && - py <= 317 && - core.isPlaying() - ) { - core.useFly(false); - return; - } else if (px >= 11 && px <= 54 && py >= 364 && py <= 407) { - if (i > 0) { - i -= 1; - core.ui._drawViewMaps(core.floorIds.indexOf(areas[i].maps[0])); - } - } else if (px >= 319 && px <= 362 && py >= 364 && py <= 407) { - if (i < areas.length - 1) { - i += 1; - core.ui._drawViewMaps(core.floorIds.indexOf(areas[i].maps[0])); - } - } - }; - const replayAction_fly = function (action) { - //楼层传送的录像操作 - if (action.indexOf("fly:") != 0) return false; - var floorId = action.substring(4); - var toIndex = core.floorIds.indexOf(floorId); - if ( - !core.canUseItem("fly") || - (core.flags.flyNearStair && !core.nearStair() && !flags.canMoveFloor) - ) - return false; - core.ui._drawViewMaps(toIndex); - if (core.status.replay.speed == 24) { - if (!core.flyTo(floorId, core.replay)) - core.control._replay_error(action); - return true; - } - setTimeout(function () { - if (!core.flyTo(floorId, core.replay)) - core.control._replay_error(action); - }, core.control.__replay_getTimeout()); - return true; - }; - core.registerReplayAction("fly", replayAction_fly); - ////// 查看地图界面时,放开某个键的操作 ////// - - actions.prototype._keyUpViewMaps = function (keycode) { - if (core.status.event.data == null) { - core.ui._drawViewMaps(core.floorIds.indexOf(core.status.floorId)); - return; - } - var floorId = core.floorIds[core.status.event.data.index]; - - if (keycode == 27 || keycode == 71) { - core.clearMap("data"); - core.playSound("取消"); - core.ui.closePanel(); - core.getItemDetail(); - core.redrawMap(); - core.ui.statusBar._update_map(); - core.updateStatusBar(); - return; - } - - if (keycode == 86) { - core.status.event.data.damage = !core.status.event.data.damage; - core.playSound("光标移动"); - core.ui._drawViewMaps(core.status.event.data); - return; - } - if (keycode == 66 || keycode == 88) { - if (core.isReplaying()) { - core.control._replay_book(); - } else { - core.openBook(false); - } - return; - } - if ( - (keycode == 13 || keycode == 32 || keycode == 67) && - !core.isReplaying() - ) { - core.useFly(false); - return; - } - return; - }; - actions.prototype._keyDownViewMaps = function (keycode) { - if (core.status.event.data == null) return; - - var floorId = core.floorIds[core.status.event.data.index], - mh = core.floors[floorId].height; - - if (keycode == 39) this._clickViewMaps(9, 1, 330, 250); - if (keycode == 37) this._clickViewMaps(9, 8, 25, 200); - if (keycode == 40) this._clickViewMaps(9, 6, 250, 330); - if (keycode == 38) this._clickViewMaps(9, 3, 200, 25); - if (keycode == 34) this._clickViewMaps(9, 3, 350, 330); - if (keycode == 33) this._clickViewMaps(9, 3, 350, 25); - return; - }; - - actions.prototype._sys_onmousewheel = function (direct) { - // 向下滚动是 -1 ,向上是 1 - - if (this._checkReplaying()) { - // 滚轮控制速度 - if (direct == 1) core.speedUpReplay(); - if (direct == -1) core.speedDownReplay(); - return; - } - - // 楼层飞行器 - if (core.status.lockControl && core.status.event.id == "fly") { - if (direct == 1) core.ui.drawFly(this._getNextFlyFloor(1)); - if (direct == -1) core.ui.drawFly(this._getNextFlyFloor(-1)); - return; - } - - // 怪物手册 - if (core.status.lockControl && core.status.event.id == "book") { - var pageinfo = core.ui._drawBook_pageinfo(); - if (direct == 1) - core.ui.drawBook(core.status.event.data - pageinfo.per_page); - if (direct == -1) - core.ui.drawBook(core.status.event.data + pageinfo.per_page); - return; - } - - // 存读档 - if ( - core.status.lockControl && - (core.status.event.id == "save" || core.status.event.id == "load") - ) { - var index = - core.status.event.data.page * 10 + core.status.event.data.offset; - if (direct == 1) core.ui._drawSLPanel(index - 10); - if (direct == -1) core.ui._drawSLPanel(index + 10); - return; - } - - // 浏览地图 - if (core.status.lockControl && core.status.event.id == "viewMaps") { - let floorId = core.floorIds[core.status.event.data.index]; - if (!flags.__visited__[floorId]) floorId = core.status.floorId; - const visit = Object.keys(flags.__visited__); - let index = visit.indexOf(floorId); - if (direct == 1) { - if (index > 0) - core.ui._drawViewMaps(core.floorIds.indexOf(visit[index - 1])); - } - if (direct == -1) { - if (index < visit.length - 1) - core.ui._drawViewMaps(core.floorIds.indexOf(visit[index + 1])); - } - return; - } - - // wait事件 - if ( - core.status.lockControl && - core.status.event.id == "action" && - core.status.event.data.type == "wait" - ) { - var timeout = - Math.max(0, core.status.event.timeout - new Date().getTime()) || 0; - core.setFlag("type", 0); - var keycode = direct == 1 ? 33 : 34; - core.setFlag("keycode", keycode); - core.setFlag("timeout", timeout); - var executed = core.events.__action_wait_afterGet( - core.status.event.data.current - ); - if (executed || !core.status.event.data.current.forceChild) { - core.status.route.push("input:" + (1e8 * timeout + keycode)); - clearTimeout(core.status.event.interval); - delete core.status.event.timeout; - core.doAction(); - } - return; - } - }; - core.registerAction( - "onmousewheel", - "_sys_onmousewheel", - actions.prototype._sys_onmousewheel, - 0 - ); -}, - "CG回廊": function () { - // 在此增加新插件 - const CGUI = document.createElement("canvas"); //CGui画布设置 - CGUI.style.position = "absolute"; - CGUI.style.zIndex = 300; - CGUI.style.display = "none"; - CGUI.id = "CGUI"; - main.dom.gameGroup.insertAdjacentElement("afterend", CGUI); - CGUI.style.top = "50%"; - CGUI.style.left = "50%"; - CGUI.style.transform = "translate(-50%,-50%)"; - const ctx = CGUI.getContext("2d"); - main.dom.CGUI = CGUI; - let page = 0; //初始页面 - let show = false; //展示状态 - CGUI.onclick = function (e) { - try { - e.preventDefault(); - if (core.isPlaying()) return false; - const left = core.dom.gameGroup.offsetLeft; - const top = core.dom.gameGroup.offsetTop; - const px = Math.floor((e.clientX - left) / core.domStyle.scale), - py = Math.floor((e.clientY - top) / core.domStyle.scale); - core.ui.CG.onclick(px * 3, py * 3); - } catch (ee) { - main.log(ee); } + core.fillRoundRect( + "ui", + 15 + 44 - 2, + 60 - 2 + size - 4, + size + 4 - 58, + 35 + 4, + 4, + "#444444" + ); + core.strokeRoundRect( + "ui", + 15 + 44 - 4, + 60 - 4 + size - 4, + size + 8 - 58, + 35 + 8, + 4, + "#444444", + 1 + ); + core.fillBoldText1( + "ui", + core.status.maps[floorId].areas, + 30 + 145 + 10, + 17 + 65 + size - 4, + "#FFFFFF", + "#000000", + 2, + this._buildFont(18, true) + ); + core.fillRoundRect( + "ui", + 15 - 2, + 60 - 2 + size - 4, + 35 + 4, + 35 + 4, + 4, + "#444444" + ); + core.strokeRoundRect( + "ui", + 15 - 4, + 60 - 4 + size - 4, + 35 + 8, + 35 + 8, + 4, + "#444444", + 1 + ); + if (i === 0) { + core.fillBoldText1( + "ui", + "◀", + 30, + 17 + 65 + size - 4, + "#909090", + "#000000", + 2, + this._buildFont(18, true) + ); + } else { + core.fillBoldText1( + "ui", + "◀", + 30, + 17 + 65 + size - 4, + "#FFFFFF", + "#000000", + 2, + this._buildFont(18, true) + ); + } + core.fillRoundRect( + "ui", + 15 - 2 + size - 4, + 60 - 2 + size - 4, + 35 + 4, + 35 + 4, + 4, + "#444444" + ); + core.strokeRoundRect( + "ui", + 15 - 4 + size - 4, + 60 - 4 + size - 4, + 35 + 8, + 35 + 8, + 4, + "#444444", + 1 + ); + if (i === areas.length - 1) { + core.fillBoldText1( + "ui", + "▶", + 30 + 300 + 10, + 17 + 65 + size - 4, + "#909090", + "#000000", + 2, + this._buildFont(18, true) + ); + } else { + core.fillBoldText1( + "ui", + "▶", + 30 + 300 + 10, + 17 + 65 + size - 4, + "#FFFFFF", + "#000000", + 2, + this._buildFont(18, true) + ); + } + + core.fillRoundRect( + "ui", + 15 - 2 + size - 4, + 15 - 2, + 80 + 4, + 35 + 4, + 4, + "#444444" + ); + core.strokeRoundRect( + "ui", + 15 - 4 + size - 4, + 15 - 4, + 80 + 8, + 35 + 8, + 4, + "#444444", + 1 + ); + if (mapdir.includes("upFloor")) { + core.fillBoldText1( + "ui", + "上楼", + 30 + 320 + 10, + 17 + 20, + "#FFFFFF", + "#000000", + 2, + this._buildFont(18, true) + ); + } else { + core.fillBoldText1( + "ui", + "上楼", + 30 + 320 + 10, + 17 + 20, + "#909090", + "#000000", + 2, + this._buildFont(18, true) + ); + } + core.fillRoundRect( + "ui", + 15 - 2 + size - 4, + 15 - 2 + size - 4, + 80 + 4, + 35 + 4, + 4, + "#444444" + ); + core.strokeRoundRect( + "ui", + 15 - 4 + size - 4, + 15 - 4 + size - 4, + 80 + 8, + 35 + 8, + 4, + "#444444", + 1 + ); + if (mapdir.includes("downFloor")) { + core.fillBoldText1( + "ui", + "下楼", + 30 + 320 + 10, + 17 + 20 + size - 4, + "#FFFFFF", + "#000000", + 2, + this._buildFont(18, true) + ); + } else { + core.fillBoldText1( + "ui", + "下楼", + 30 + 320 + 10, + 17 + 20 + size - 4, + "#909090", + "#000000", + 2, + this._buildFont(18, true) + ); + } + + core.fillRoundRect( + "ui", + 15 - 2 + size - 4 + 35 + 8, + 59 - 2, + 37 + 4, + (size - 58) / 2 + 4, + 4, + "#444444" + ); + core.strokeRoundRect( + "ui", + 15 - 4 + size - 4 + 35 + 8, + 59 - 4, + 37 + 8, + (size - 58) / 2 + 8, + 4, + "#444444", + 1 + ); + const title = core.status.maps[floorId].title; + //const length = title.length + fillTextVertical( + "ui", + title, + 15 - 4 + size - 4 + 45, + 85, + core.hasVisitedFloor(floorId) ? "#FFFFFF" : "#444444", + "#000000", + 18 + ); + //const uictx = main.dom.gameCanvas.ui.getContext('2d') + core.fillRoundRect( + "ui", + 15 - 2 + size - 4 + 35 + 8, + 59 - 2 + (size - 58) / 2 + 8, + 37 + 4, + 119 + 4, + 4, + "#444444" + ); + core.strokeRoundRect( + "ui", + 15 - 4 + size - 4 + 35 + 8, + 59 - 4 + (size - 58) / 2 + 8, + 37 + 8, + 119 + 8, + 4, + "#444444", + 1 + ); + if (core.getFlag("showEnemy")) { + fillTextVertical( + "ui", + "关闭漏怪检测", + 15 - 4 + size - 4 + 45, + 220, + "#FFFFFF", + "#000000", + 18 + ); + } else { + fillTextVertical( + "ui", + "开启漏怪检测", + 15 - 4 + size - 4 + 45, + 220, + "#FFFFFF", + "#000000", + 18 + ); + } + + //uictx.fillTextVertical(title, 15 - 4 + size - 4 + 35 + 29, 25 + 150) + //fillTextVertical('ui', title, 15 - 4 + size - 4 + 35 + 29, 25 + 150, '#FFFFFF', this._buildFont(18, true)) }; - class CG { - constructor() { - this.cgs; - //cg列表 - this.UIMx = [ - //空位用‘none’填充,当前ui3*2 - [ - ["eve_010102.webp", "eve_010203.webp", "eve_010304.webp"], - ["eve_010501.webp", "eve_010601.webp", "eve_010701.webp"], - ], - [ - ["eve_010801.webp", "eve_010902.webp", "eve_011001.webp"], - ["eve_011101.webp", "eve_011202.webp", "eve_011302.webp"], - ], - [ - ["eve_011402.webp", "eve_020102.webp", "eve_020201.webp"], - ["eve_020301.webp", "eve_020401.webp", "eve_020501.webp"], - ], - [ - ["eve_020605.webp", "eve_020701.webp", "eve_020801.webp"], - ["eve_030101.webp", "eve_030206.webp", "eve_030302.webp"], - ], - [ - ["eve_030508.webp", "eve_030601.webp", "eve_030801.webp"], - ["eve_030901.webp", "eve_031002.webp", "eve_031101.webp"], - ], - [ - ["eve_040201.webp", "eve_040401.webp", "eve_040501.webp"], - ["eve_040601.webp", "eve_040702.webp", "eve_040801.webp"], - ], - [ - ["eve_050101.webp", "eve_050201.webp", "eve_050401.webp"], - ["eve_050501.webp", "eve_050601.webp", "eve_050704.webp"], - ], - [ - ["eve_050801.webp", "eve_070101.webp", "bg_1511.webp"], - ["bg_1521.webp", "bg_2011.webp", "bg_2521.webp"], - ], - [ - ["bg_3042.webp", "bg_3551.webp", "bg_3571.webp"], - ["bg_3721.webp", "bg_5033.webp", "bg_5044.webp"], - ], - ]; + function fillTextVertical(name, text, x, y, style, boldstyle, fontsize) { + //竖向文字绘制 + + const ctx = core.ui.getContextByName(name); + if (!ctx) return; + const canvas = document.createElement("canvas"); + const context = canvas.getContext("2d"); + fontsize *= 3; + const length = text.length; + canvas.width = fontsize * 2; + canvas.height = fontsize * length * 2; + if (style) context.fillStyle = core.arrayToRGBA(style); + if (boldstyle) context.strokeStyle = core.arrayToRGBA(boldstyle); + context.lineWidth = 2; + if (fontsize) context.font = core.ui._buildFont(fontsize, true); + let arrText = text.split(""); + + let arrWidth = arrText.map(function (letter) { + return context.measureText(letter).width; + }); + + let align = context.textAlign; + + let baseline = context.textBaseline; + let sx = fontsize, + sy = fontsize * length; + if (align == "left") { + sx = sx + Math.max.apply(null, arrWidth) / 2; + } else if (align == "right") { + sx = sx - Math.max.apply(null, arrWidth) / 2; } - //更新 - update() { - this.background(); - this.drawUI(); + if ( + baseline == "bottom" || + baseline == "alphabetic" || + baseline == "ideographic" + ) { + sy = sy - arrWidth[0] / 2; + } else if (baseline == "top" || baseline == "hanging") { + sy = sy + arrWidth[0] / 2; } - background() { - //画布大小设置 - if (core.domStyle.isVertical) { - CGUI.width = 1248; - CGUI.height = 2028; - } else { - CGUI.width = 2028; - CGUI.height = 1248; - } - core.setTextAlign(ctx, "center"); - } - onclick(px, py) { - //点击 - if (show) { - show = !show; - core.clearMap(ctx); - this.update(); - return; - } - const makeBox = ([x, y], [w, h]) => { - return [ - [x, y], - [x + w, y + h], - ]; - }; - const inRect = ([x, y], [[sx, sy], [dx, dy]]) => { - return sx <= x && x <= dx && sy <= y && y <= dy; - }; - const pos = [px, py]; - const backbox = makeBox([15, 35], [210, 90]); - if (inRect(pos, backbox)) { - //离开按钮是一致的,其余的记区分横竖屏 - CGUI.style.display = "none"; - core.clearMap(ctx); - core.restart(); - return; - } - if (core.domStyle.isVertical) { - //竖屏 - const pageupbox = makeBox([200, 1830], [200, 100]); - const pagedownbox = makeBox([900, 1830], [200, 100]); + context.textAlign = "center"; - const imagebox0 = makeBox([50, 200], [560, 420]); - const imagebox1 = makeBox([50, 750], [560, 420]); - const imagebox2 = makeBox([50, 1300], [560, 420]); + context.textBaseline = "middle"; + context.lineWidth = 6; - const imagebox3 = makeBox([650, 200], [560, 420]); - const imagebox4 = makeBox([650, 750], [560, 420]); - const imagebox5 = makeBox([650, 1300], [560, 420]); - if (inRect(pos, pagedownbox)) { - //2代表当前最大页数-1 - if (page < this.UIMx.length - 1) { - page++; - core.clearMap(ctx); - this.update(); - } - } else if (inRect(pos, pageupbox)) { - if (page > 0) { - page--; - core.clearMap(ctx); - this.update(); - } - } else if (inRect(pos, imagebox0)) { - if (this.cgs.includes(this.UIMx[page][0][0])) { - const img = core.material.images.images[this.UIMx[page][0][0]]; - if (img) { - ctx.save(); //保存设置 - ctx.translate(1248, 0); //重新定位右上角为基准 - ctx.rotate(Math.PI / 2); //旋转90度 - ctx.drawImage(img, 0, 0, 2028, 1248); - ctx.restore(); //重置画布设置 - show = !show; - } - } - } else if (inRect(pos, imagebox1)) { - if (this.cgs.includes(this.UIMx[page][0][1])) { - const img = core.material.images.images[this.UIMx[page][0][1]]; - if (img) { - ctx.save(); //保存设置 - ctx.translate(1248, 0); //重新定位右上角为基准 - ctx.rotate(Math.PI / 2); //旋转90度 - ctx.drawImage(img, 0, 0, 2028, 1248); - ctx.restore(); //重置画布设置 - show = !show; - } - } - } else if (inRect(pos, imagebox2)) { - if (this.cgs.includes(this.UIMx[page][0][2])) { - const img = core.material.images.images[this.UIMx[page][0][2]]; - if (img) { - ctx.save(); //保存设置 - ctx.translate(1248, 0); //重新定位右上角为基准 - ctx.rotate(Math.PI / 2); //旋转90度 - ctx.drawImage(img, 0, 0, 2028, 1248); - ctx.restore(); //重置画布设置 - show = !show; - } - } - } else if (inRect(pos, imagebox3)) { - if (this.cgs.includes(this.UIMx[page][1][0])) { - const img = core.material.images.images[this.UIMx[page][1][0]]; - if (img) { - ctx.save(); //保存设置 - ctx.translate(1248, 0); //重新定位右上角为基准 - ctx.rotate(Math.PI / 2); //旋转90度 - ctx.drawImage(img, 0, 0, 2028, 1248); - ctx.restore(); //重置画布设置 - show = !show; - } - } - } else if (inRect(pos, imagebox4)) { - if (this.cgs.includes(this.UIMx[page][1][1])) { - const img = core.material.images.images[this.UIMx[page][1][1]]; - if (img) { - ctx.save(); //保存设置 - ctx.translate(1248, 0); //重新定位右上角为基准 - ctx.rotate(Math.PI / 2); //旋转90度 - ctx.drawImage(img, 0, 0, 2028, 1248); - ctx.restore(); //重置画布设置 - show = !show; - } - } - } else if (inRect(pos, imagebox5)) { - if (this.cgs.includes(this.UIMx[page][1][2])) { - const img = core.material.images.images[this.UIMx[page][1][2]]; - if (img) { - ctx.save(); //保存设置 - ctx.translate(1248, 0); //重新定位右上角为基准 - ctx.rotate(Math.PI / 2); //旋转90度 - ctx.drawImage(img, 0, 0, 2028, 1248); - ctx.restore(); //重置画布设置 - show = !show; - } - } - } - } else { - const pageupbox = makeBox([200, 1110], [200, 100]); - const pagedownbox = makeBox([1600, 1110], [200, 100]); - const imagebox0 = makeBox([75, 150], [600, 450]); - const imagebox1 = makeBox([725, 150], [600, 450]); - const imagebox2 = makeBox([1300, 150], [600, 450]); - const imagebox3 = makeBox([75, 650], [600, 450]); - const imagebox4 = makeBox([725, 650], [600, 450]); - const imagebox5 = makeBox([1375, 650], [600, 450]); - if (inRect(pos, pagedownbox)) { - if (page < this.UIMx.length - 1) { - page++; - core.clearMap(ctx); - this.update(); - } - } else if (inRect(pos, pageupbox)) { - if (page > 0) { - page--; - core.clearMap(ctx); - this.update(); - } - } else if (inRect(pos, imagebox0)) { - if (this.cgs.includes(this.UIMx[page][0][0])) { - const img = core.material.images.images[this.UIMx[page][0][0]]; - if (img) { - ctx.drawImage(img, 0, 0, 2028, 1248); - show = !show; - } - } - } else if (inRect(pos, imagebox1)) { - if (this.cgs.includes(this.UIMx[page][0][1])) { - const img = core.material.images.images[this.UIMx[page][0][1]]; - if (img) { - ctx.drawImage(img, 0, 0, 2028, 1248); - show = !show; - } - } - } else if (inRect(pos, imagebox2)) { - if (this.cgs.includes(this.UIMx[page][0][2])) { - const img = core.material.images.images[this.UIMx[page][0][2]]; - if (img) { - ctx.drawImage(img, 0, 0, 2028, 1248); - show = !show; - } - } - } else if (inRect(pos, imagebox3)) { - if (this.cgs.includes(this.UIMx[page][1][0])) { - const img = core.material.images.images[this.UIMx[page][1][0]]; - if (img) { - ctx.drawImage(img, 0, 0, 2028, 1248); - show = !show; - } - } - } else if (inRect(pos, imagebox4)) { - if (this.cgs.includes(this.UIMx[page][1][1])) { - const img = core.material.images.images[this.UIMx[page][1][1]]; - if (img) { - ctx.drawImage(img, 0, 0, 2028, 1248); - show = !show; - } - } - } else if (inRect(pos, imagebox5)) { - if (this.cgs.includes(this.UIMx[page][1][2])) { - const img = core.material.images.images[this.UIMx[page][1][2]]; - if (img) { - ctx.drawImage(img, 0, 0, 2028, 1248); - show = !show; - } - } - } - } - } - drawUI() { - //绘制页面 - core.clearMap(CGUI); - const bgVertical = core.material.images.images["bg_2010.webp"]; //竖屏背景 - const bg = core.material.images.images["bg_5043.webp"]; //横屏背景 + // 开始逐字绘制 - if (core.domStyle.isVertical) { - //竖屏 + arrText.forEach(function (letter, index) { + // 确定下一个字符的纵坐标位置 - core.fillRect(ctx, 0, 0, 1248, 2028, "#000000"); //黑色背景 - ctx.globalAlpha = 0.5; //透明度 - if (bgVertical) - ctx.drawImage(bgVertical, 0, 0, 1280, 1500, 0, 0, 1248, 2028); //绘制半透明背景图片 - ctx.globalAlpha = 1; //恢复为不透明 + context.strokeText(letter, sx, sy); + context.fillText(letter, sx, sy); + // 旋转坐标系还原成初始态 - core.setTextAlign(ctx, "center"); - core.fillBoldText1( - ctx, - "◀离开", - 100, - 110, - "#FFFFFF", - "#000000", - 6, - core.ui._buildFont(66, true) - ); + context.setTransform(1, 0, 0, 1, 0, 0); - core.fillBoldText1( - ctx, - "上一页", - 300, - 1900, - page === 0 ? "#444444" : "#FFFFFF", - "#000000", - 6, - core.ui._buildFont(66, true) - ); + // 确定下一个字符的纵坐标位置 - core.fillBoldText1( - ctx, - page + 1 + "/" + this.UIMx.length, - 650, - 1900, - "#FFFFFF", - "#000000", - 6, - core.ui._buildFont(66, true) - ); - core.fillBoldText1( - ctx, - "下一页", - 1000, - 1900, - page === this.UIMx.length - 1 ? "#444444" : "#FFFFFF", - "#000000", - 6, - core.ui._buildFont(66, true) - ); - // 添加向上翻页和向下翻页的按钮 + var letterWidth = 54; - // 添加3*2个4:3的画框,及图片 - for (let i = 0; i < 3; i++) { - for (let j = 0; j < 2; j++) { - const img = core.material.images.images[this.UIMx[page][j][i]]; - core.strokeRect( - ctx, - 50 + j * 600, - 200 + i * 550, - 560, - 420, - "#444444", - 5 - ); - if (this.cgs.includes(this.UIMx[page][j][i])) { - if (img) - ctx.drawImage( - img, - 50 + j * 600 + 15, - 200 + i * 550 + 15, - 560 - 30, - 420 - 30 - ); - } else { - ctx.fillStyle = "#000000"; - ctx.fillRect( - 50 + j * 600 + 15, - 200 + i * 550 + 15, - 560 - 30, - 420 - 30 - ); - const img = core.material.images.images["LOGO.webp"]; - if (img) - ctx.drawImage( - img, - 50 + j * 600 + 15, - 200 + i * 550 + 15, - 560 - 30, - 420 - 30 - ); - } - } - } - } else { - //横屏 - core.fillRect(ctx, 0, 0, 2028, 1248, "#000000"); //黑色背景 - ctx.globalAlpha = 0.5; //透明度 - if (bg) ctx.drawImage(bg, 0, 0, 1280, 720, 0, 0, 2028, 1248); //绘制半透明背景图片 - ctx.globalAlpha = 1; //恢复为不透明 + sy = sy + letterWidth; + }); - core.setTextAlign(ctx, "center"); - core.fillBoldText1( - ctx, - "◀离开", - 110, - 100, - "#FFFFFF", - "#000000", - 6, - core.ui._buildFont(66, true) - ); + // 水平垂直对齐方式还原 - // 添加向上翻页和向下翻页的按钮 - core.fillBoldText1( - ctx, - "上一页", - 300, - 1180, - page === 0 ? "#444444" : "#FFFFFF", - "#000000", - 6, - core.ui._buildFont(66, true) - ); + context.textAlign = align; - core.fillBoldText1( - ctx, - page + 1 + "/" + this.UIMx.length, - 1000, - 1180, - "#FFFFFF", - "#000000", - 6, - core.ui._buildFont(66, true) - ); - core.fillBoldText1( - ctx, - "下一页", - 1700, - 1180, - page === this.UIMx.length - 1 ? "#444444" : "#FFFFFF", - "#000000", - 6, - core.ui._buildFont(66, true) - ); + context.textBaseline = baseline; - // 添加3*2个4:3的画框 - for (let i = 0; i < 2; i++) { - for (let j = 0; j < 3; j++) { - core.strokeRect( - ctx, - 75 + j * 650, - 150 + i * 500, - 600, - 450, - "#444444", - 2 - ); - if (this.cgs.includes(this.UIMx[page][i][j])) { - const img = core.material.images.images[this.UIMx[page][i][j]]; - if (img) - ctx.drawImage( - img, - 75 + j * 650 + 15, - 150 + i * 500 + 15, - 600 - 30, - 450 - 30 - ); - } else { - ctx.fillStyle = "#000000"; - ctx.fillRect( - 75 + j * 650 + 15, - 150 + i * 500 + 15, - 600 - 30, - 450 - 30 - ); - const img = core.material.images.images["LOGO.webp"]; - if (img) - ctx.drawImage( - img, - 75 + j * 650 + 15, - 150 + i * 500 + 15, - 600 - 30, - 450 - 30 - ); - } - } - } - } - } + //绘制到目标位置 + ctx.drawImage( + canvas, + x, + y - (fontsize / 3) * length, + canvas.width / 3, + canvas.height / 3 + ); } - this.setcgs = function (img) { - const a = core.getLocalStorage("cgs", []); - if (img) { - if (!a.includes(img)) a.push(img); - core.setLocalStorage("cgs", a); - } else core.setLocalStorage("cgs"); + + ////// 点击楼层传送器时的打开操作 ////// + events.prototype.useFly = function (fromUserAction) { + if (!core.isPlaying()) return; + if (!core.status.maps[core.status.floorId].canFlyFrom) { + core.drawTip(core.material.items["fly"].name + "好像失效了", "fly"); + return; + } + // 从“浏览地图”页面:尝试直接传送到该层 + if (core.status.event.id == "viewMaps") { + if (!core.hasItem("fly")) { + core.playSound("操作失败"); + core.drawTip("你没有" + core.material.items["fly"].name, "fly"); + } else if ( + core.flags.flyNearStair && + !core.nearStair() && + !flags.canMoveFloor + ) { + core.playSound("操作失败"); + core.drawTip( + "无法到达楼梯边使用" + core.material.items["fly"].name, + "fly" + ); + } else { + core.flyTo(core.status.event.data.floorId); + core.updateStatusBar(); + } + return; + } + + if (!this._checkStatus("fly", fromUserAction, true)) return; + //if (core.flags.flyNearStair && !core.nearStair()) + + if ( + (core.flags.flyNearStair && !core.nearStair()) || + !flags.canMoveFloor + ) { + core.playSound("操作失败"); + core.drawTip( + "无法到达楼梯边使用" + core.material.items["fly"].name, + "fly" + ); + core.unlockControl(); + core.status.event.data = null; + core.status.event.id = null; + return; + } + if (!core.canUseItem("fly")) { + core.playSound("操作失败"); + core.drawTip(core.material.items["fly"].name + "好像失效了", "fly"); + core.unlockControl(); + core.status.event.data = null; + core.status.event.id = null; + return; + } + core.playSound("打开界面"); + core.useItem("fly", true); + core.updateStatusBar(); + return; }; - core.ui.CG = new CG(); - main.dom.CGMode.onclick = function () { - //点击开始页面的CG MODE进入cg回廊 - main.core.control.checkBgm(); - page = 0; - main.core.ui.CG.cgs = core.getLocalStorage("cgs", []); - CGUI.style.display = "block"; - main.core.ui.CG.update(); + ////// 系统菜单栏界面时的点击操作 ////// + actions.prototype._clickSettings = function (x, y) { + if (this._out(x)) return; + var choices = core.status.event.ui.choices; + var topIndex = this._getChoicesTopIndex(choices.length); + if (y >= topIndex && y < topIndex + choices.length) { + var selection = y - topIndex; + core.status.event.selection = selection; + switch (selection) { + case 0: + core.status.event.selection = 0; + core.playSound("确定"); + core.ui._drawSwitchs(); + break; + case 1: + // core.playSound('确定'); + core.ui._drawKeyBoard(); + break; + case 2: + // core.playSound('确定'); + core.clearUI(); + core.useItem("fly"); + break; + case 3: + core.status.event.selection = 0; + core.playSound("确定"); + core.ui._drawNotes(); + break; + case 4: + core.status.event.selection = 0; + core.playSound("确定"); + core.ui._drawSyncSave(); + break; + case 5: + core.status.event.selection = 0; + core.playSound("确定"); + core.ui._drawGameInfo(); + break; + case 6: + return core.confirmRestart(); + case 7: + core.playSound("取消"); + core.ui.closePanel(); + break; + } + } + return; }; + ////// 查看地图界面时的点击操作 ////// + actions.prototype._clickViewMaps = function (x, y, px, py) { + if (core.status.event.data == null) { + core.ui._drawViewMaps(core.floorIds.indexOf(core.status.floorId)); + return; + } + let now = core.floorIds.indexOf(core.status.floorId); + let index = core.status.event.data.index; + let cx = core.status.event.data.x, + cy = core.status.event.data.y; + let floorId = core.floorIds[index], + mw = core.floors[floorId].width, + mh = core.floors[floorId].height; + let perpx = core.__PIXELS__ / 5, + cornerpx = (perpx * 3) / 4; + const bfs = core.plugin.bfsSearch(floorId, 1, true); + const mapdir = bfs.mapdir[floorId]; + const res = bfs.res; + const formto = {}; + for (let from in res) { + const to = res[from]; + const [fromfloorId, fromsx, fromsy, dir] = from.split("_"); + const [tofloorId, tosx, tosy] = to.split("_"); + if (!formto[fromfloorId]) formto[fromfloorId] = {}; + if (!formto[fromfloorId][dir]) formto[fromfloorId][dir] = tofloorId; + } + const areas = core.getFlag("areas"); + let i = areas.findIndex((v) => v.maps.includes(floorId)); + + if (px >= 11 && px <= 54 && py >= 11 && py <= 54) { + core.ui._drawViewMaps(core.floorIds.indexOf(core.status.floorId)); + } else if (px >= 362 && px <= 407 && py >= 191 && py <= 318) { + flags.showEnemy = !flags.showEnemy; + core.ui._drawViewMaps(index); + } else if (px >= 364 && px <= 407 && py >= 364 && py <= 407) { + core.clearMap("data"); + core.playSound("取消"); + core.ui.closePanel(); + core.getItemDetail(); + core.redrawMap(); + core.updateStatusBar(); + core.ui.statusBar._update_map(); + return; + } else if (px >= 55 && px <= 317 && py >= 11 && py <= 54) { + if (mapdir.includes("up")) + core.ui._drawViewMaps(core.floorIds.indexOf(formto[floorId].up)); + } else if (px >= 55 && px <= 317 && py >= 319 && py <= 362) { + if (mapdir.includes("down")) + core.ui._drawViewMaps(core.floorIds.indexOf(formto[floorId].down)); + } else if (px >= 11 && px <= 54 && py >= 55 && py <= 317) { + if (mapdir.includes("left")) + core.ui._drawViewMaps(core.floorIds.indexOf(formto[floorId].left)); + } else if (px >= 319 && px <= 362 && py >= 55 && py <= 317) { + if (mapdir.includes("right")) + core.ui._drawViewMaps(core.floorIds.indexOf(formto[floorId].right)); + } else if (px >= 319 && px <= 407 && py >= 11 && py <= 54) { + if (mapdir.includes("upFloor")) + core.ui._drawViewMaps(core.floorIds.indexOf(formto[floorId].upFloor)); + } else if (px >= 319 && px <= 407 && py >= 319 && py <= 362) { + if (mapdir.includes("downFloor")) + core.ui._drawViewMaps( + core.floorIds.indexOf(formto[floorId].downFloor) + ); + } else if ( + px >= 55 && + px <= 317 && + py >= 55 && + py <= 317 && + core.isPlaying() + ) { + core.useFly(false); + return; + } else if (px >= 11 && px <= 54 && py >= 364 && py <= 407) { + if (i > 0) { + i -= 1; + core.ui._drawViewMaps(core.floorIds.indexOf(areas[i].maps[0])); + } + } else if (px >= 319 && px <= 362 && py >= 364 && py <= 407) { + if (i < areas.length - 1) { + i += 1; + core.ui._drawViewMaps(core.floorIds.indexOf(areas[i].maps[0])); + } + } + }; + const replayAction_fly = function (action) { + //楼层传送的录像操作 + if (action.indexOf("fly:") != 0) return false; + var floorId = action.substring(4); + var toIndex = core.floorIds.indexOf(floorId); + if ( + !core.canUseItem("fly") || + (core.flags.flyNearStair && !core.nearStair() && !flags.canMoveFloor) + ) + return false; + core.ui._drawViewMaps(toIndex); + if (core.status.replay.speed == 24) { + if (!core.flyTo(floorId, core.replay)) + core.control._replay_error(action); + return true; + } + setTimeout(function () { + if (!core.flyTo(floorId, core.replay)) + core.control._replay_error(action); + }, core.control.__replay_getTimeout()); + return true; + }; + core.registerReplayAction("fly", replayAction_fly); + ////// 查看地图界面时,放开某个键的操作 ////// + + actions.prototype._keyUpViewMaps = function (keycode) { + if (core.status.event.data == null) { + core.ui._drawViewMaps(core.floorIds.indexOf(core.status.floorId)); + return; + } + var floorId = core.floorIds[core.status.event.data.index]; + + if (keycode == 27 || keycode == 71) { + core.clearMap("data"); + core.playSound("取消"); + core.ui.closePanel(); + core.getItemDetail(); + core.redrawMap(); + core.ui.statusBar._update_map(); + core.updateStatusBar(); + return; + } + + if (keycode == 86) { + core.status.event.data.damage = !core.status.event.data.damage; + core.playSound("光标移动"); + core.ui._drawViewMaps(core.status.event.data); + return; + } + if (keycode == 66 || keycode == 88) { + if (core.isReplaying()) { + core.control._replay_book(); + } else { + core.openBook(false); + } + return; + } + if ( + (keycode == 13 || keycode == 32 || keycode == 67) && + !core.isReplaying() + ) { + core.useFly(false); + return; + } + return; + }; + actions.prototype._keyDownViewMaps = function (keycode) { + if (core.status.event.data == null) return; + + var floorId = core.floorIds[core.status.event.data.index], + mh = core.floors[floorId].height; + + if (keycode == 39) this._clickViewMaps(9, 1, 330, 250); + if (keycode == 37) this._clickViewMaps(9, 8, 25, 200); + if (keycode == 40) this._clickViewMaps(9, 6, 250, 330); + if (keycode == 38) this._clickViewMaps(9, 3, 200, 25); + if (keycode == 34) this._clickViewMaps(9, 3, 350, 330); + if (keycode == 33) this._clickViewMaps(9, 3, 350, 25); + return; + }; + + actions.prototype._sys_onmousewheel = function (direct) { + // 向下滚动是 -1 ,向上是 1 + + if (this._checkReplaying()) { + // 滚轮控制速度 + if (direct == 1) core.speedUpReplay(); + if (direct == -1) core.speedDownReplay(); + return; + } + + // 楼层飞行器 + if (core.status.lockControl && core.status.event.id == "fly") { + if (direct == 1) core.ui.drawFly(this._getNextFlyFloor(1)); + if (direct == -1) core.ui.drawFly(this._getNextFlyFloor(-1)); + return; + } + + // 怪物手册 + if (core.status.lockControl && core.status.event.id == "book") { + var pageinfo = core.ui._drawBook_pageinfo(); + if (direct == 1) + core.ui.drawBook(core.status.event.data - pageinfo.per_page); + if (direct == -1) + core.ui.drawBook(core.status.event.data + pageinfo.per_page); + return; + } + + // 存读档 + if ( + core.status.lockControl && + (core.status.event.id == "save" || core.status.event.id == "load") + ) { + var index = + core.status.event.data.page * 10 + core.status.event.data.offset; + if (direct == 1) core.ui._drawSLPanel(index - 10); + if (direct == -1) core.ui._drawSLPanel(index + 10); + return; + } + + // 浏览地图 + if (core.status.lockControl && core.status.event.id == "viewMaps") { + let floorId = core.floorIds[core.status.event.data.index]; + if (!flags.__visited__[floorId]) floorId = core.status.floorId; + const visit = Object.keys(flags.__visited__); + let index = visit.indexOf(floorId); + if (direct == 1) { + if (index > 0) + core.ui._drawViewMaps(core.floorIds.indexOf(visit[index - 1])); + } + if (direct == -1) { + if (index < visit.length - 1) + core.ui._drawViewMaps(core.floorIds.indexOf(visit[index + 1])); + } + return; + } + + // wait事件 + if ( + core.status.lockControl && + core.status.event.id == "action" && + core.status.event.data.type == "wait" + ) { + var timeout = + Math.max(0, core.status.event.timeout - new Date().getTime()) || 0; + core.setFlag("type", 0); + var keycode = direct == 1 ? 33 : 34; + core.setFlag("keycode", keycode); + core.setFlag("timeout", timeout); + var executed = core.events.__action_wait_afterGet( + core.status.event.data.current + ); + if (executed || !core.status.event.data.current.forceChild) { + core.status.route.push("input:" + (1e8 * timeout + keycode)); + clearTimeout(core.status.event.interval); + delete core.status.event.timeout; + core.doAction(); + } + return; + } + }; + core.registerAction( + "onmousewheel", + "_sys_onmousewheel", + actions.prototype._sys_onmousewheel, + 0 + ); }, + "CG回廊": function () { + // 在此增加新插件 + const CGUI = document.createElement("canvas"); //CGui画布设置 + CGUI.style.position = "absolute"; + CGUI.style.zIndex = 300; + CGUI.style.display = "none"; + CGUI.id = "CGUI"; + main.dom.gameGroup.insertAdjacentElement("afterend", CGUI); + CGUI.style.top = "50%"; + CGUI.style.left = "50%"; + CGUI.style.transform = "translate(-50%,-50%)"; + const ctx = CGUI.getContext("2d"); + main.dom.CGUI = CGUI; + let page = 0; //初始页面 + let show = false; //展示状态 + CGUI.onclick = function (e) { + try { + e.preventDefault(); + if (core.isPlaying()) return false; + const left = core.dom.gameGroup.offsetLeft; + const top = core.dom.gameGroup.offsetTop; + const px = Math.floor((e.clientX - left) / core.domStyle.scale), + py = Math.floor((e.clientY - top) / core.domStyle.scale); + core.ui.CG.onclick(px * 3, py * 3); + } catch (ee) { + main.log(ee); + } + }; + + class CG { + constructor() { + this.cgs; + //cg列表 + this.UIMx = [ + //空位用‘none’填充,当前ui3*2 + [ + ["eve_010102.webp", "eve_010203.webp", "eve_010304.webp"], + ["eve_010501.webp", "eve_010601.webp", "eve_010701.webp"], + ], + [ + ["eve_010801.webp", "eve_010902.webp", "eve_011001.webp"], + ["eve_011101.webp", "eve_011202.webp", "eve_011302.webp"], + ], + [ + ["eve_011402.webp", "eve_020102.webp", "eve_020201.webp"], + ["eve_020301.webp", "eve_020401.webp", "eve_020501.webp"], + ], + [ + ["eve_020605.webp", "eve_020701.webp", "eve_020801.webp"], + ["eve_030101.webp", "eve_030206.webp", "eve_030302.webp"], + ], + [ + ["eve_030508.webp", "eve_030601.webp", "eve_030801.webp"], + ["eve_030901.webp", "eve_031002.webp", "eve_031101.webp"], + ], + [ + ["eve_040201.webp", "eve_040401.webp", "eve_040501.webp"], + ["eve_040601.webp", "eve_040702.webp", "eve_040801.webp"], + ], + [ + ["eve_050101.webp", "eve_050201.webp", "eve_050401.webp"], + ["eve_050501.webp", "eve_050601.webp", "eve_050704.webp"], + ], + [ + ["eve_050801.webp", "eve_070101.webp", "bg_1511.webp"], + ["bg_1521.webp", "bg_2011.webp", "bg_2521.webp"], + ], + [ + ["bg_3042.webp", "bg_3551.webp", "bg_3571.webp"], + ["bg_3721.webp", "bg_5033.webp", "bg_5044.webp"], + ], + ]; + } + + //更新 + update() { + this.background(); + this.drawUI(); + } + background() { + //画布大小设置 + if (core.domStyle.isVertical) { + CGUI.width = 1248; + CGUI.height = 2028; + } else { + CGUI.width = 2028; + CGUI.height = 1248; + } + core.setTextAlign(ctx, "center"); + } + onclick(px, py) { + //点击 + + if (show) { + show = !show; + core.clearMap(ctx); + this.update(); + return; + } + const makeBox = ([x, y], [w, h]) => { + return [ + [x, y], + [x + w, y + h], + ]; + }; + const inRect = ([x, y], [ + [sx, sy], + [dx, dy] + ]) => { + return sx <= x && x <= dx && sy <= y && y <= dy; + }; + const pos = [px, py]; + const backbox = makeBox([15, 35], [210, 90]); + if (inRect(pos, backbox)) { + //离开按钮是一致的,其余的记区分横竖屏 + CGUI.style.display = "none"; + core.clearMap(ctx); + core.restart(); + return; + } + if (core.domStyle.isVertical) { + //竖屏 + const pageupbox = makeBox([200, 1830], [200, 100]); + const pagedownbox = makeBox([900, 1830], [200, 100]); + + const imagebox0 = makeBox([50, 200], [560, 420]); + const imagebox1 = makeBox([50, 750], [560, 420]); + const imagebox2 = makeBox([50, 1300], [560, 420]); + + const imagebox3 = makeBox([650, 200], [560, 420]); + const imagebox4 = makeBox([650, 750], [560, 420]); + const imagebox5 = makeBox([650, 1300], [560, 420]); + if (inRect(pos, pagedownbox)) { + //2代表当前最大页数-1 + if (page < this.UIMx.length - 1) { + page++; + core.clearMap(ctx); + this.update(); + } + } else if (inRect(pos, pageupbox)) { + if (page > 0) { + page--; + core.clearMap(ctx); + this.update(); + } + } else if (inRect(pos, imagebox0)) { + if (this.cgs.includes(this.UIMx[page][0][0])) { + const img = core.material.images.images[this.UIMx[page][0][0]]; + if (img) { + ctx.save(); //保存设置 + ctx.translate(1248, 0); //重新定位右上角为基准 + ctx.rotate(Math.PI / 2); //旋转90度 + ctx.drawImage(img, 0, 0, 2028, 1248); + ctx.restore(); //重置画布设置 + show = !show; + } + } + } else if (inRect(pos, imagebox1)) { + if (this.cgs.includes(this.UIMx[page][0][1])) { + const img = core.material.images.images[this.UIMx[page][0][1]]; + if (img) { + ctx.save(); //保存设置 + ctx.translate(1248, 0); //重新定位右上角为基准 + ctx.rotate(Math.PI / 2); //旋转90度 + ctx.drawImage(img, 0, 0, 2028, 1248); + ctx.restore(); //重置画布设置 + show = !show; + } + } + } else if (inRect(pos, imagebox2)) { + if (this.cgs.includes(this.UIMx[page][0][2])) { + const img = core.material.images.images[this.UIMx[page][0][2]]; + if (img) { + ctx.save(); //保存设置 + ctx.translate(1248, 0); //重新定位右上角为基准 + ctx.rotate(Math.PI / 2); //旋转90度 + ctx.drawImage(img, 0, 0, 2028, 1248); + ctx.restore(); //重置画布设置 + show = !show; + } + } + } else if (inRect(pos, imagebox3)) { + if (this.cgs.includes(this.UIMx[page][1][0])) { + const img = core.material.images.images[this.UIMx[page][1][0]]; + if (img) { + ctx.save(); //保存设置 + ctx.translate(1248, 0); //重新定位右上角为基准 + ctx.rotate(Math.PI / 2); //旋转90度 + ctx.drawImage(img, 0, 0, 2028, 1248); + ctx.restore(); //重置画布设置 + show = !show; + } + } + } else if (inRect(pos, imagebox4)) { + if (this.cgs.includes(this.UIMx[page][1][1])) { + const img = core.material.images.images[this.UIMx[page][1][1]]; + if (img) { + ctx.save(); //保存设置 + ctx.translate(1248, 0); //重新定位右上角为基准 + ctx.rotate(Math.PI / 2); //旋转90度 + ctx.drawImage(img, 0, 0, 2028, 1248); + ctx.restore(); //重置画布设置 + show = !show; + } + } + } else if (inRect(pos, imagebox5)) { + if (this.cgs.includes(this.UIMx[page][1][2])) { + const img = core.material.images.images[this.UIMx[page][1][2]]; + if (img) { + ctx.save(); //保存设置 + ctx.translate(1248, 0); //重新定位右上角为基准 + ctx.rotate(Math.PI / 2); //旋转90度 + ctx.drawImage(img, 0, 0, 2028, 1248); + ctx.restore(); //重置画布设置 + show = !show; + } + } + } + } else { + const pageupbox = makeBox([200, 1110], [200, 100]); + const pagedownbox = makeBox([1600, 1110], [200, 100]); + const imagebox0 = makeBox([75, 150], [600, 450]); + const imagebox1 = makeBox([725, 150], [600, 450]); + const imagebox2 = makeBox([1300, 150], [600, 450]); + const imagebox3 = makeBox([75, 650], [600, 450]); + const imagebox4 = makeBox([725, 650], [600, 450]); + const imagebox5 = makeBox([1375, 650], [600, 450]); + if (inRect(pos, pagedownbox)) { + if (page < this.UIMx.length - 1) { + page++; + core.clearMap(ctx); + this.update(); + } + } else if (inRect(pos, pageupbox)) { + if (page > 0) { + page--; + core.clearMap(ctx); + this.update(); + } + } else if (inRect(pos, imagebox0)) { + if (this.cgs.includes(this.UIMx[page][0][0])) { + const img = core.material.images.images[this.UIMx[page][0][0]]; + if (img) { + ctx.drawImage(img, 0, 0, 2028, 1248); + show = !show; + } + } + } else if (inRect(pos, imagebox1)) { + if (this.cgs.includes(this.UIMx[page][0][1])) { + const img = core.material.images.images[this.UIMx[page][0][1]]; + if (img) { + ctx.drawImage(img, 0, 0, 2028, 1248); + show = !show; + } + } + } else if (inRect(pos, imagebox2)) { + if (this.cgs.includes(this.UIMx[page][0][2])) { + const img = core.material.images.images[this.UIMx[page][0][2]]; + if (img) { + ctx.drawImage(img, 0, 0, 2028, 1248); + show = !show; + } + } + } else if (inRect(pos, imagebox3)) { + if (this.cgs.includes(this.UIMx[page][1][0])) { + const img = core.material.images.images[this.UIMx[page][1][0]]; + if (img) { + ctx.drawImage(img, 0, 0, 2028, 1248); + show = !show; + } + } + } else if (inRect(pos, imagebox4)) { + if (this.cgs.includes(this.UIMx[page][1][1])) { + const img = core.material.images.images[this.UIMx[page][1][1]]; + if (img) { + ctx.drawImage(img, 0, 0, 2028, 1248); + show = !show; + } + } + } else if (inRect(pos, imagebox5)) { + if (this.cgs.includes(this.UIMx[page][1][2])) { + const img = core.material.images.images[this.UIMx[page][1][2]]; + if (img) { + ctx.drawImage(img, 0, 0, 2028, 1248); + show = !show; + } + } + } + } + } + drawUI() { + //绘制页面 + core.clearMap(CGUI); + const bgVertical = core.material.images.images["bg_2010.webp"]; //竖屏背景 + const bg = core.material.images.images["bg_5043.webp"]; //横屏背景 + + if (core.domStyle.isVertical) { + //竖屏 + + core.fillRect(ctx, 0, 0, 1248, 2028, "#000000"); //黑色背景 + ctx.globalAlpha = 0.5; //透明度 + if (bgVertical) + ctx.drawImage(bgVertical, 0, 0, 1280, 1500, 0, 0, 1248, 2028); //绘制半透明背景图片 + ctx.globalAlpha = 1; //恢复为不透明 + + core.setTextAlign(ctx, "center"); + core.fillBoldText1( + ctx, + "◀离开", + 100, + 110, + "#FFFFFF", + "#000000", + 6, + core.ui._buildFont(66, true) + ); + + core.fillBoldText1( + ctx, + "上一页", + 300, + 1900, + page === 0 ? "#444444" : "#FFFFFF", + "#000000", + 6, + core.ui._buildFont(66, true) + ); + + core.fillBoldText1( + ctx, + page + 1 + "/" + this.UIMx.length, + 650, + 1900, + "#FFFFFF", + "#000000", + 6, + core.ui._buildFont(66, true) + ); + core.fillBoldText1( + ctx, + "下一页", + 1000, + 1900, + page === this.UIMx.length - 1 ? "#444444" : "#FFFFFF", + "#000000", + 6, + core.ui._buildFont(66, true) + ); + // 添加向上翻页和向下翻页的按钮 + + // 添加3*2个4:3的画框,及图片 + for (let i = 0; i < 3; i++) { + for (let j = 0; j < 2; j++) { + const img = core.material.images.images[this.UIMx[page][j][i]]; + core.strokeRect( + ctx, + 50 + j * 600, + 200 + i * 550, + 560, + 420, + "#444444", + 5 + ); + if (this.cgs.includes(this.UIMx[page][j][i])) { + if (img) + ctx.drawImage( + img, + 50 + j * 600 + 15, + 200 + i * 550 + 15, + 560 - 30, + 420 - 30 + ); + } else { + ctx.fillStyle = "#000000"; + ctx.fillRect( + 50 + j * 600 + 15, + 200 + i * 550 + 15, + 560 - 30, + 420 - 30 + ); + const img = core.material.images.images["LOGO.webp"]; + if (img) + ctx.drawImage( + img, + 50 + j * 600 + 15, + 200 + i * 550 + 15, + 560 - 30, + 420 - 30 + ); + } + } + } + } else { + //横屏 + core.fillRect(ctx, 0, 0, 2028, 1248, "#000000"); //黑色背景 + ctx.globalAlpha = 0.5; //透明度 + if (bg) ctx.drawImage(bg, 0, 0, 1280, 720, 0, 0, 2028, 1248); //绘制半透明背景图片 + ctx.globalAlpha = 1; //恢复为不透明 + + core.setTextAlign(ctx, "center"); + core.fillBoldText1( + ctx, + "◀离开", + 110, + 100, + "#FFFFFF", + "#000000", + 6, + core.ui._buildFont(66, true) + ); + + // 添加向上翻页和向下翻页的按钮 + core.fillBoldText1( + ctx, + "上一页", + 300, + 1180, + page === 0 ? "#444444" : "#FFFFFF", + "#000000", + 6, + core.ui._buildFont(66, true) + ); + + core.fillBoldText1( + ctx, + page + 1 + "/" + this.UIMx.length, + 1000, + 1180, + "#FFFFFF", + "#000000", + 6, + core.ui._buildFont(66, true) + ); + core.fillBoldText1( + ctx, + "下一页", + 1700, + 1180, + page === this.UIMx.length - 1 ? "#444444" : "#FFFFFF", + "#000000", + 6, + core.ui._buildFont(66, true) + ); + + // 添加3*2个4:3的画框 + for (let i = 0; i < 2; i++) { + for (let j = 0; j < 3; j++) { + core.strokeRect( + ctx, + 75 + j * 650, + 150 + i * 500, + 600, + 450, + "#444444", + 2 + ); + if (this.cgs.includes(this.UIMx[page][i][j])) { + const img = core.material.images.images[this.UIMx[page][i][j]]; + if (img) + ctx.drawImage( + img, + 75 + j * 650 + 15, + 150 + i * 500 + 15, + 600 - 30, + 450 - 30 + ); + } else { + ctx.fillStyle = "#000000"; + ctx.fillRect( + 75 + j * 650 + 15, + 150 + i * 500 + 15, + 600 - 30, + 450 - 30 + ); + const img = core.material.images.images["LOGO.webp"]; + if (img) + ctx.drawImage( + img, + 75 + j * 650 + 15, + 150 + i * 500 + 15, + 600 - 30, + 450 - 30 + ); + } + } + } + } + } + } + this.setcgs = function (img) { + const a = core.getLocalStorage("cgs", []); + if (img) { + if (!a.includes(img)) a.push(img); + core.setLocalStorage("cgs", a); + } else core.setLocalStorage("cgs"); + }; + core.ui.CG = new CG(); + main.dom.CGMode.onclick = function () { + //点击开始页面的CG MODE进入cg回廊 + main.core.control.checkBgm(); + page = 0; + main.core.ui.CG.cgs = core.getLocalStorage("cgs", []); + CGUI.style.display = "block"; + main.core.ui.CG.update(); + }; +}, "光标设置": function () { // 在此增加新插件 this.changeMouse = function ( @@ -15109,196 +15564,197 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = }; }, "滑动转场": function () { - // 在此增加新插件 - const defaultChange = { - left: "leftPortal", // 左箭头 - up: "upPortal", // 上箭头 - right: "rightPortal", // 右箭头 - down: "downPortal", // 下箭头 - upFloor: "upFloor", // 上楼 - downFloor: "downFloor", // 下楼 - }; - const dirData = { - //方向坐标 - up: [-1, 0], - down: [1, 0], - left: [0, -1], - right: [0, 1], - upFloor: [0, 0], - downFloor: [0, 0], - }; - let allChangeEntries = Object.entries(defaultChange); - const move = document.createElement("canvas"); - const speed = 12; - let modedata = 0; + // 在此增加新插件 + const defaultChange = { + left: "leftPortal", // 左箭头 + up: "upPortal", // 上箭头 + right: "rightPortal", // 右箭头 + down: "downPortal", // 下箭头 + upFloor: "upFloor", // 上楼 + downFloor: "downFloor", // 下楼 + }; + const dirData = { + //方向坐标 + up: [-1, 0], + down: [1, 0], + left: [0, -1], + right: [0, 1], + upFloor: [0, 0], + downFloor: [0, 0], + }; + let allChangeEntries = Object.entries(defaultChange); + const move = document.createElement("canvas"); + const speed = 12; + let modedata = 0; - move.width = 1248; - move.height = 1248; + move.width = 1248; + move.height = 1248; - const ctx = move.getContext("2d"); + const ctx = move.getContext("2d"); - events.prototype.changeFloor = function ( - floorId, - stair, - heroLoc, - time, - callback - ) { - let block = core.getBlock(hero.loc.x, hero.loc.y); - var info = this._changeFloor_getInfo(floorId, stair, heroLoc, time); + events.prototype.changeFloor = function ( + floorId, + stair, + heroLoc, + time, + callback + ) { + let block = core.getBlock(hero.loc.x, hero.loc.y); + var info = this._changeFloor_getInfo(floorId, stair, heroLoc, time); - if (info == null) { - if (callback) callback(); - return; - } - floorId = info.floorId; - info.locked = core.status.lockControl; + if (info == null) { + if (callback) callback(); + return; + } + floorId = info.floorId; + info.locked = core.status.lockControl; - core.dom.floorNameLabel.innerText = core.status.maps[floorId].title; - core.lockControl(); - core.stopAutomaticRoute(); - core.clearContinueAutomaticRoute(); - core.status.replay.animate = true; - clearInterval(core.interval.onDownInterval); - delete core.animateFrame.tip - core.interval.onDownInterval = "tmp"; + core.dom.floorNameLabel.innerText = core.status.maps[floorId].title; + core.lockControl(); + core.stopAutomaticRoute(); + core.clearContinueAutomaticRoute(); + core.status.replay.animate = true; + clearInterval(core.interval.onDownInterval); + delete core.animateFrame.tip; + core.interval.onDownInterval = "tmp"; - this._changeFloor_beforeChange(info, block, callback); - }; - events.prototype._changeFloor_beforeChange = function ( - info, - block, - callback - ) { - this._changeFloor_playSound(); - if ( - block && - block?.event && - !main.replayChecking && - !core.isReplaying() && !core.getFlag("__isFlying__", false) - ) { - const dirEntries = allChangeEntries.find( - (v) => v[1] === block.event.id - ); - if (block?.event?.trigger === "changeFloor" && dirEntries) { - const toFloorId = block.event.data.floorId; - const dir = dirEntries[0]; + this._changeFloor_beforeChange(info, block, callback); + }; + events.prototype._changeFloor_beforeChange = function ( + info, + block, + callback + ) { + this._changeFloor_playSound(); + if ( + block && + block?.event && + !main.replayChecking && + !core.isReplaying() && + !core.getFlag("__isFlying__", false) + ) { + const dirEntries = allChangeEntries.find( + (v) => v[1] === block.event.id + ); + if (block?.event?.trigger === "changeFloor" && dirEntries) { + const toFloorId = block.event.data.floorId; + const dir = dirEntries[0]; - const data = core.ui._drawViewMaps_buildData( - core.floorIds.indexOf(core.status.floorId) - ); - const dataTo = core.ui._drawViewMaps_buildData( - core.floorIds.indexOf(toFloorId) - ); - const v = dirData[dir][1], // 水平数值 - h = dirData[dir][0]; //竖直数值 - ctx.clearRect(0, 0, 1248, 1248); - core.drawThumbnail(core.status.floorId, null, { - damage: data.damage, - ctx: ctx, - x: 416, - y: 416, - size: 1, - all: data.all, - }); - if (dir !== "upFloor" && dir !== "downFloor") { - core.drawThumbnail(toFloorId, null, { - damage: dataTo.damage, - ctx: ctx, - x: 416 + 416 * v, - y: 416 + 416 * h, - size: 1, - all: dataTo.all, - }); + const data = core.ui._drawViewMaps_buildData( + core.floorIds.indexOf(core.status.floorId) + ); + const dataTo = core.ui._drawViewMaps_buildData( + core.floorIds.indexOf(toFloorId) + ); + const v = dirData[dir][1], // 水平数值 + h = dirData[dir][0]; //竖直数值 + ctx.clearRect(0, 0, 1248, 1248); + core.drawThumbnail(core.status.floorId, null, { + damage: data.damage, + ctx: ctx, + x: 416, + y: 416, + size: 1, + all: data.all, + }); + if (dir !== "upFloor" && dir !== "downFloor") { + core.drawThumbnail(toFloorId, null, { + damage: dataTo.damage, + ctx: ctx, + x: 416 + 416 * v, + y: 416 + 416 * h, + size: 1, + all: dataTo.all, + }); - var _run = function () { - var cb = function () { - modedata = 0; - core.clearUI(); - core.clearMap("data"); - core.events._changeFloor_changing(info, callback); - }; + var _run = function () { + var cb = function () { + modedata = 0; + core.clearUI(); + core.clearMap("data"); + core.events._changeFloor_changing(info, callback); + }; - var animate = window.setInterval( - function () { - if (modedata >= 416) { - delete core.animateFrame.asyncId[animate]; - clearInterval(animate); - cb(); - } else { - core.clearUI(); - core.clearMap("data"); + var animate = window.setInterval( + function () { + if (modedata >= 416) { + delete core.animateFrame.asyncId[animate]; + clearInterval(animate); + cb(); + } else { + core.clearUI(); + core.clearMap("data"); - core.canvas.data.drawImage( - move, - 416 + modedata * v, - 416 + modedata * h, - 416, - 416, - 0, - 0, - 416, - 416 - ); - let status = "leftFoot"; + core.canvas.data.drawImage( + move, + 416 + modedata * v, + 416 + modedata * h, + 416, + 416, + 0, + 0, + 416, + 416 + ); + let status = "leftFoot"; - if (modedata > 208) { - status = "rightFoot"; - } - const img = core.material.images.hero; - const heroIconArr = core.material.icons.hero; - const width = core.material.icons.hero.width || 32; - const height = core.material.icons.hero.height; - const heroIcon = heroIconArr[dir]; + if (modedata > 208) { + status = "rightFoot"; + } + const img = core.material.images.hero; + const heroIconArr = core.material.icons.hero; + const width = core.material.icons.hero.width || 32; + const height = core.material.icons.hero.height; + const heroIcon = heroIconArr[dir]; - core.canvas.data.drawImage( - img, - (heroIcon[status] % 4) * width, - heroIcon.loc * height, - width, - height, - core.status.hero.loc.x * 32 - - core.bigmap.offsetX - - (modedata - (modedata * 32) / 416) * v, - core.status.hero.loc.y * 32 - - 16 - - (modedata - (modedata * 32) / 416) * h, - width, - height - ); - modedata += speed; - clearInterval(animate); - delete core.animateFrame.asyncId[animate]; - _run(); - } - }, - core.status.replay.speed == 24 ? - 1 : - 10 / core.status.replay.speed - ); + core.canvas.data.drawImage( + img, + (heroIcon[status] % 4) * width, + heroIcon.loc * height, + width, + height, + core.status.hero.loc.x * 32 - + core.bigmap.offsetX - + (modedata - (modedata * 32) / 416) * v, + core.status.hero.loc.y * 32 - + 16 - + (modedata - (modedata * 32) / 416) * h, + width, + height + ); + modedata += speed; + clearInterval(animate); + delete core.animateFrame.asyncId[animate]; + _run(); + } + }, + core.status.replay.speed == 24 + ? 1 + : 10 / core.status.replay.speed + ); - core.animateFrame.lastAsyncId = animate; - core.animateFrame.asyncId[animate] = cb; - }; - _run(); - return; - } - } - } - // 需要 setTimeout 执行,不然会出错 - window.setTimeout(function () { - if (info.time == 0) core.events._changeFloor_changing(info, callback); - else - core.showWithAnimate( - core.dom.floorMsgGroup, - info.time / 2, - function () { - core.events._changeFloor_changing(info, callback); - } - ); - }, 25); - }; -}, + core.animateFrame.lastAsyncId = animate; + core.animateFrame.asyncId[animate] = cb; + }; + _run(); + return; + } + } + } + // 需要 setTimeout 执行,不然会出错 + window.setTimeout(function () { + if (info.time == 0) core.events._changeFloor_changing(info, callback); + else + core.showWithAnimate( + core.dom.floorMsgGroup, + info.time / 2, + function () { + core.events._changeFloor_changing(info, callback); + } + ); + }, 25); + }; + }, "剧情cg": function () { // 在此增加新插件 // 在此增加新插件 @@ -15460,7 +15916,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = class cgText { constructor() { - this.nobg = false + this.nobg = false; //绘制需要的变量 this.image = ""; this.head = { name: "face_050445.webp", px: -300 }; @@ -16225,489 +16681,491 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = core.ui.cgText = new cgText(); }, "旁白": function () { - // 在此增加新插件 - const over = document.createElement("canvas"); //over画布设置 - over.style.position = "absolute"; - over.style.zIndex = 310; - over.style.display = "none"; - over.id = "over"; - main.dom.gameGroup.insertAdjacentElement("afterend", over); - over.style.top = "50%"; - over.style.left = "50%"; - over.style.transform = "translate(-50%,-50%)"; - const ctx = over.getContext("2d"); - main.dom.over = over; + // 在此增加新插件 + const over = document.createElement("canvas"); //over画布设置 + over.style.position = "absolute"; + over.style.zIndex = 310; + over.style.display = "none"; + over.id = "over"; + main.dom.gameGroup.insertAdjacentElement("afterend", over); + over.style.top = "50%"; + over.style.left = "50%"; + over.style.transform = "translate(-50%,-50%)"; + const ctx = over.getContext("2d"); + main.dom.over = over; - this.over = function ( - image, - memory, - time = 100, - hidetime = 30, - sound = "", - textColor = "#FFFFFF", - boldColor = "#000000", - font = "bold 48px Verdana", - text = "" - ) { - if (!core.isPlaying()) { - return core.doAction(); - } - const img = core.material.images.images?.[image]; - over.style.display = "block"; - let frame = 0; - let sod = 0; - let now = 0; - core.registerAnimationFrame("over", true, (timestamp) => { - if (timestamp - now > 1000 / 60) { - now = timestamp; - core.clearMap(ctx); - if (core.domStyle.isVertical) { - ctx.canvas.width = 416 * 3; - ctx.canvas.height = 676 * 3; - ctx.save(); //保存设置 - ctx.translate(416 * 3, 0); //重新定位右上角为基准 - ctx.rotate(Math.PI / 2); //旋转90度 - } else { - ctx.canvas.width = 676 * 3; - ctx.canvas.height = 416 * 3; - } - ctx.globalAlpha = 1; - if (img) { - //绘制背景 - if (memory) ctx.filter = "sepia(50%)"; - ctx.drawImage(img, 0, 0, 676 * 3, 416 * 3); - ctx.filter = "none"; - } else { - core.fillRect(ctx, 0, 0, 676 * 3, 416 * 3); - } - frame++; - // 绘制 - if (frame <= hidetime) - core.setAlpha(ctx, 1 - (hidetime - frame) / hidetime); - if (frame > hidetime && frame <= hidetime + time) ctx.globalAlpha = 1; - if (frame > hidetime + time && frame <= hidetime * 2 + time) - core.setAlpha(ctx, 1 - (frame - hidetime - time) / hidetime); - const lisen = - sound && core.sounds[sound] && core.musicStatus.soundStatus; - if (frame == hidetime && lisen) { - sod = core.playSound(sound); - } - if (frame > hidetime * 2 + time) { - core.unregisterAnimationFrame("over"); - ctx.restore(); - over.style.display = "none"; - core.stopSound(sod); - core.doAction(); - return; - } + this.over = function ( + image, + memory, + time = 100, + hidetime = 30, + sound = "", + textColor = "#FFFFFF", + boldColor = "#000000", + font = "bold 48px Verdana", + text = "" + ) { + if (!core.isPlaying()) { + return core.doAction(); + } + const img = core.material.images.images?.[image]; + over.style.display = "block"; + let frame = 0; + let sod = 0; + let now = 0; + core.registerAnimationFrame("over", true, (timestamp) => { + if (timestamp - now > 1000 / 60) { + now = timestamp; + core.clearMap(ctx); + if (core.domStyle.isVertical) { + ctx.canvas.width = 416 * 3; + ctx.canvas.height = 676 * 3; + ctx.save(); //保存设置 + ctx.translate(416 * 3, 0); //重新定位右上角为基准 + ctx.rotate(Math.PI / 2); //旋转90度 + } else { + ctx.canvas.width = 676 * 3; + ctx.canvas.height = 416 * 3; + } + ctx.globalAlpha = 1; + if (img) { + //绘制背景 + if (memory) ctx.filter = "sepia(50%)"; + ctx.drawImage(img, 0, 0, 676 * 3, 416 * 3); + ctx.filter = "none"; + } else { + core.fillRect(ctx, 0, 0, 676 * 3, 416 * 3); + } + frame++; + // 绘制 + if (frame <= hidetime) + core.setAlpha(ctx, 1 - (hidetime - frame) / hidetime); + if (frame > hidetime && frame <= hidetime + time) ctx.globalAlpha = 1; + if (frame > hidetime + time && frame <= hidetime * 2 + time) + core.setAlpha(ctx, 1 - (frame - hidetime - time) / hidetime); + const lisen = + sound && core.sounds[sound] && core.musicStatus.soundStatus; + if (frame == hidetime && lisen) { + sod = core.playSound(sound); + } + if (frame > hidetime * 2 + time) { + core.unregisterAnimationFrame("over"); + ctx.restore(); + over.style.display = "none"; + core.stopSound(sod); + core.doAction(); + return; + } - core.setTextAlign(ctx, "center"); - core.fillBoldText1( - ctx, - text, - 1014, - 624, - textColor, - boldColor, - 6, - font - ); + core.setTextAlign(ctx, "center"); + core.fillBoldText1( + ctx, + text, + 1014, + 624, + textColor, + boldColor, + 6, + font + ); - ctx.restore(); - } - }); - }; + ctx.restore(); + } + }); + }; - this.overlist = function ( - image, - memory, - hidetime = 30, - list = [{ - text: "", - sound: "", - time: 50, - textColor: "#FFFFFF", - boldColor: "#000000", - font: "bold 48px Verdana", - frame: 0, - }, ] - ) { - if (!core.isPlaying()) { - return core.doAction(); - } - const img = core.material.images.images?.[image]; - over.style.display = "block"; - let sod = 0; - let i = 0; - let now = 0; - core.registerAnimationFrame("overlist", true, (timestamp) => { - if (timestamp - now > 1000 / 60) { - now = timestamp; - core.clearMap(ctx); - if (core.domStyle.isVertical) { - ctx.canvas.width = 416 * 3; - ctx.canvas.height = 676 * 3; - ctx.save(); //保存设置 - ctx.translate(416 * 3, 0); //重新定位右上角为基准 - ctx.rotate(Math.PI / 2); //旋转90度 - } else { - ctx.canvas.width = 676 * 3; - ctx.canvas.height = 416 * 3; - } - ctx.globalAlpha = 1; - if (img) { - //绘制背景 - if (memory) ctx.filter = "sepia(50%)"; - ctx.drawImage(img, 0, 0, 676 * 3, 416 * 3); - ctx.filter = "none"; - } else { - core.fillRect(ctx, 0, 0, 676 * 3, 416 * 3); - } - const a = list[i]; - const b = list[i - 1]; - const c = list[i - 2]; - const d = list[i - 3]; - let ay = 624, - by = 624, - cy = 624, - dy = 624; - if (i === 0 && !list[1]) { - core.over( - image, - memory, - a.time, - hidetime, - a.sound, - a.textColor, - a.boldColor, - a.font, - a.text - ); - } else { - const numa = - parseInt(a?.font?.match(/\s*[\d.-]+[a-zA-Z%]*\s*/)?.[0].trim()) || - 48; - const numb = - parseInt(b?.font?.match(/\s*[\d.-]+[a-zA-Z%]*\s*/)?.[0].trim()) || - 48; - const numc = - parseInt(c?.font?.match(/\s*[\d.-]+[a-zA-Z%]*\s*/)?.[0].trim()) || - 48; - const numd = - parseInt(d?.font?.match(/\s*[\d.-]+[a-zA-Z%]*\s*/)?.[0].trim()) || - 48; + this.overlist = function ( + image, + memory, + hidetime = 30, + list = [ + { + text: "", + sound: "", + time: 50, + textColor: "#FFFFFF", + boldColor: "#000000", + font: "bold 48px Verdana", + frame: 0, + }, + ] + ) { + if (!core.isPlaying()) { + return core.doAction(); + } + const img = core.material.images.images?.[image]; + over.style.display = "block"; + let sod = 0; + let i = 0; + let now = 0; + core.registerAnimationFrame("overlist", true, (timestamp) => { + if (timestamp - now > 1000 / 60) { + now = timestamp; + core.clearMap(ctx); + if (core.domStyle.isVertical) { + ctx.canvas.width = 416 * 3; + ctx.canvas.height = 676 * 3; + ctx.save(); //保存设置 + ctx.translate(416 * 3, 0); //重新定位右上角为基准 + ctx.rotate(Math.PI / 2); //旋转90度 + } else { + ctx.canvas.width = 676 * 3; + ctx.canvas.height = 416 * 3; + } + ctx.globalAlpha = 1; + if (img) { + //绘制背景 + if (memory) ctx.filter = "sepia(50%)"; + ctx.drawImage(img, 0, 0, 676 * 3, 416 * 3); + ctx.filter = "none"; + } else { + core.fillRect(ctx, 0, 0, 676 * 3, 416 * 3); + } + const a = list[i]; + const b = list[i - 1]; + const c = list[i - 2]; + const d = list[i - 3]; + let ay = 624, + by = 624, + cy = 624, + dy = 624; + if (i === 0 && !list[1]) { + core.over( + image, + memory, + a.time, + hidetime, + a.sound, + a.textColor, + a.boldColor, + a.font, + a.text + ); + } else { + const numa = + parseInt(a?.font?.match(/\s*[\d.-]+[a-zA-Z%]*\s*/)?.[0].trim()) || + 48; + const numb = + parseInt(b?.font?.match(/\s*[\d.-]+[a-zA-Z%]*\s*/)?.[0].trim()) || + 48; + const numc = + parseInt(c?.font?.match(/\s*[\d.-]+[a-zA-Z%]*\s*/)?.[0].trim()) || + 48; + const numd = + parseInt(d?.font?.match(/\s*[\d.-]+[a-zA-Z%]*\s*/)?.[0].trim()) || + 48; - // 绘制 - if (a) { - if (a.frame < hidetime / 2) { - a.frame++; - core.setAlpha(ctx, 1 - (hidetime - a.frame) / hidetime); - ay += ((numa * (hidetime - a.frame)) / hidetime) * 3; - core.setTextAlign(ctx, "center"); - core.fillBoldText1( - ctx, - a.text, - 1014, - ay, - a.textColor, - a.boldColor, - 6, - a.font - ); - } - if (a.frame === hidetime / 2) { - core.setAlpha(ctx, 1 - (hidetime - a.frame) / hidetime); - ay = 624 + ((numa * (hidetime - a.frame)) / hidetime) * 3; - core.setTextAlign(ctx, "center"); + // 绘制 + if (a) { + if (a.frame < hidetime / 2) { + a.frame++; + core.setAlpha(ctx, 1 - (hidetime - a.frame) / hidetime); + ay += ((numa * (hidetime - a.frame)) / hidetime) * 3; + core.setTextAlign(ctx, "center"); + core.fillBoldText1( + ctx, + a.text, + 1014, + ay, + a.textColor, + a.boldColor, + 6, + a.font + ); + } + if (a.frame === hidetime / 2) { + core.setAlpha(ctx, 1 - (hidetime - a.frame) / hidetime); + ay = 624 + ((numa * (hidetime - a.frame)) / hidetime) * 3; + core.setTextAlign(ctx, "center"); - core.fillBoldText1( - ctx, - a.text, - 1014, - ay, - a.textColor, - a.boldColor, - 6, - a.font - ); - if (!b) { - a.frame++; - i++; - } - } - } - if (b) { - if (b.frame > hidetime / 2 && b.frame <= hidetime) { - b.frame++; - core.setAlpha(ctx, 1 - (hidetime - b.frame) / hidetime); - by += ((numb * (hidetime - b.frame)) / hidetime) * 3; - core.setTextAlign(ctx, "center"); - core.fillBoldText1( - ctx, - b.text, - 1014, - by, - b.textColor, - b.boldColor, - 6, - b.font - ); + core.fillBoldText1( + ctx, + a.text, + 1014, + ay, + a.textColor, + a.boldColor, + 6, + a.font + ); + if (!b) { + a.frame++; + i++; + } + } + } + if (b) { + if (b.frame > hidetime / 2 && b.frame <= hidetime) { + b.frame++; + core.setAlpha(ctx, 1 - (hidetime - b.frame) / hidetime); + by += ((numb * (hidetime - b.frame)) / hidetime) * 3; + core.setTextAlign(ctx, "center"); + core.fillBoldText1( + ctx, + b.text, + 1014, + by, + b.textColor, + b.boldColor, + 6, + b.font + ); - core.stopSound(sod); - } - const lisenb = - b.sound && core.sounds[b.sound] && core.musicStatus.soundStatus; - if (b.frame && lisenb) { - sod = core.playSound(sound); - } - if (b.frame > hidetime && b.frame < hidetime + b.time) { - b.frame++; - ctx.globalAlpha = 1; - core.setTextAlign(ctx, "center"); - core.fillBoldText1( - ctx, - b.text, - 1014, - by, - b.textColor, - b.boldColor, - 6, - b.font - ); - } + core.stopSound(sod); + } + const lisenb = + b.sound && core.sounds[b.sound] && core.musicStatus.soundStatus; + if (b.frame && lisenb) { + sod = core.playSound(sound); + } + if (b.frame > hidetime && b.frame < hidetime + b.time) { + b.frame++; + ctx.globalAlpha = 1; + core.setTextAlign(ctx, "center"); + core.fillBoldText1( + ctx, + b.text, + 1014, + by, + b.textColor, + b.boldColor, + 6, + b.font + ); + } - if (b.frame == hidetime + b.time) { - ctx.globalAlpha = 1; - core.setTextAlign(ctx, "center"); - core.fillBoldText1( - ctx, - b.text, - 1014, - by, - b.textColor, - b.boldColor, - 6, - b.font - ); - if (a) a.frame++; - if (b) b.frame++; - if (c) c.frame++; - i++; - } - } - if (c) { - if ( - c.frame > hidetime + c.time && - c.frame < (hidetime * 3) / 2 + c.time - ) { - c.frame++; - core.setAlpha( - ctx, - 1 - (c.frame - hidetime - c.time) / hidetime - ); - cy -= ((numc * (c.frame - hidetime - c.time)) / hidetime) * 3; - core.setTextAlign(ctx, "center"); - core.fillBoldText1( - ctx, - c.text, - 1014, - cy, - c.textColor, - c.boldColor, - 6, - c.font - ); - } - if (c.frame === (hidetime * 3) / 2 + c.time) { - core.setAlpha( - ctx, - 1 - (c.frame - hidetime - c.time) / hidetime - ); - cy = - 624 - ((numc * (c.frame - hidetime - c.time)) / hidetime) * 3; - core.setTextAlign(ctx, "center"); - core.fillBoldText1( - ctx, - c.text, - 1014, - cy, - c.textColor, - c.boldColor, - 6, - c.font - ); - if (!b) { - c.frame++; - i++; - } - } - } - if (d) { - if ( - d.frame > (hidetime * 3) / 2 + d.time && - d.frame < hidetime * 2 + d.time - ) { - d.frame++; - core.setAlpha( - ctx, - 1 - (d.frame - hidetime - d.time) / hidetime - ); - dy -= ((numd * (d.frame - hidetime - d.time)) / hidetime) * 3; - core.setTextAlign(ctx, "center"); - core.fillBoldText1( - ctx, - d.text, - 1014, - dy, - d.textColor, - d.boldColor, - 6, - d.font - ); - } - if (d.frame == hidetime * 2 + d.time && !c) { - core.unregisterAnimationFrame("overlist"); - ctx.restore(); - over.style.display = "none"; - core.stopSound(sod); - core.doAction(); - return; - } - } - } - ctx.restore(); - } - }); - }; + if (b.frame == hidetime + b.time) { + ctx.globalAlpha = 1; + core.setTextAlign(ctx, "center"); + core.fillBoldText1( + ctx, + b.text, + 1014, + by, + b.textColor, + b.boldColor, + 6, + b.font + ); + if (a) a.frame++; + if (b) b.frame++; + if (c) c.frame++; + i++; + } + } + if (c) { + if ( + c.frame > hidetime + c.time && + c.frame < (hidetime * 3) / 2 + c.time + ) { + c.frame++; + core.setAlpha( + ctx, + 1 - (c.frame - hidetime - c.time) / hidetime + ); + cy -= ((numc * (c.frame - hidetime - c.time)) / hidetime) * 3; + core.setTextAlign(ctx, "center"); + core.fillBoldText1( + ctx, + c.text, + 1014, + cy, + c.textColor, + c.boldColor, + 6, + c.font + ); + } + if (c.frame === (hidetime * 3) / 2 + c.time) { + core.setAlpha( + ctx, + 1 - (c.frame - hidetime - c.time) / hidetime + ); + cy = + 624 - ((numc * (c.frame - hidetime - c.time)) / hidetime) * 3; + core.setTextAlign(ctx, "center"); + core.fillBoldText1( + ctx, + c.text, + 1014, + cy, + c.textColor, + c.boldColor, + 6, + c.font + ); + if (!b) { + c.frame++; + i++; + } + } + } + if (d) { + if ( + d.frame > (hidetime * 3) / 2 + d.time && + d.frame < hidetime * 2 + d.time + ) { + d.frame++; + core.setAlpha( + ctx, + 1 - (d.frame - hidetime - d.time) / hidetime + ); + dy -= ((numd * (d.frame - hidetime - d.time)) / hidetime) * 3; + core.setTextAlign(ctx, "center"); + core.fillBoldText1( + ctx, + d.text, + 1014, + dy, + d.textColor, + d.boldColor, + 6, + d.font + ); + } + if (d.frame == hidetime * 2 + d.time && !c) { + core.unregisterAnimationFrame("overlist"); + ctx.restore(); + over.style.display = "none"; + core.stopSound(sod); + core.doAction(); + return; + } + } + } + ctx.restore(); + } + }); + }; - this.changebg = function (img1, memory1, img2, memory2, time, style) { - let globalAlpha1 = 0; - let globalAlpha2 = time; - img1 = core.material.images.images?.[img1]; - img2 = core.material.images.images?.[img2]; - over.style.display = "block"; - let now = 0; - switch (style) { - case "引入": - core.registerAnimationFrame("bgin", true, (timestamp) => { - if (timestamp - now > 1000 / 60) { - now = timestamp; - core.clearMap(ctx); - if (core.domStyle.isVertical) { - ctx.canvas.width = 1248; - ctx.canvas.height = 676 * 3; - ctx.save(); //保存设置 - ctx.translate(1248, 0); //重新定位右上角为基准 - ctx.rotate(Math.PI / 2); //旋转90度 - } else { - ctx.canvas.width = 676 * 3; - ctx.canvas.height = 1248; - } - ctx.globalAlpha = globalAlpha1 / time; - if (img2) { - //绘制背景 - if (memory2) ctx.filter = "sepia(50%)"; - ctx.drawImage(img2, 0, 0, 676 * 3, 1248); - ctx.filter = "none"; - } else { - core.fillRect(ctx, 0, 0, 676 * 3, 1248); - } - globalAlpha1++; - ctx.restore(); - if (globalAlpha1 >= time) { - core.unregisterAnimationFrame("bgin"); - over.style.display = "none"; - core.doAction(); - } - } - }); + this.changebg = function (img1, memory1, img2, memory2, time, style) { + let globalAlpha1 = 0; + let globalAlpha2 = time; + img1 = core.material.images.images?.[img1]; + img2 = core.material.images.images?.[img2]; + over.style.display = "block"; + let now = 0; + switch (style) { + case "引入": + core.registerAnimationFrame("bgin", true, (timestamp) => { + if (timestamp - now > 1000 / 60) { + now = timestamp; + core.clearMap(ctx); + if (core.domStyle.isVertical) { + ctx.canvas.width = 1248; + ctx.canvas.height = 676 * 3; + ctx.save(); //保存设置 + ctx.translate(1248, 0); //重新定位右上角为基准 + ctx.rotate(Math.PI / 2); //旋转90度 + } else { + ctx.canvas.width = 676 * 3; + ctx.canvas.height = 1248; + } + ctx.globalAlpha = globalAlpha1 / time; + if (img2) { + //绘制背景 + if (memory2) ctx.filter = "sepia(50%)"; + ctx.drawImage(img2, 0, 0, 676 * 3, 1248); + ctx.filter = "none"; + } else { + core.fillRect(ctx, 0, 0, 676 * 3, 1248); + } + globalAlpha1++; + ctx.restore(); + if (globalAlpha1 >= time) { + core.unregisterAnimationFrame("bgin"); + over.style.display = "none"; + core.doAction(); + } + } + }); - break; - case "引出": - core.registerAnimationFrame("bgout", true, (timestamp) => { - if (timestamp - now > 1000 / 60) { - now = timestamp; - core.clearMap(ctx); - if (core.domStyle.isVertical) { - ctx.canvas.width = 1248; - ctx.canvas.height = 676 * 3; - ctx.save(); //保存设置 - ctx.translate(1248, 0); //重新定位右上角为基准 - ctx.rotate(Math.PI / 2); //旋转90度 - } else { - ctx.canvas.width = 676 * 3; - ctx.canvas.height = 1248; - } - ctx.globalAlpha = globalAlpha2 / time; - if (img1) { - //绘制背景 - if (memory1) ctx.filter = "sepia(50%)"; - ctx.drawImage(img1, 0, 0, 676 * 3, 1248); - ctx.filter = "none"; - } else { - core.fillRect(ctx, 0, 0, 676 * 3, 1248); - } - globalAlpha2--; - ctx.restore(); - if (globalAlpha2 <= 0) { - core.unregisterAnimationFrame("bgout"); - over.style.display = "none"; - core.doAction(); - } - } - }); + break; + case "引出": + core.registerAnimationFrame("bgout", true, (timestamp) => { + if (timestamp - now > 1000 / 60) { + now = timestamp; + core.clearMap(ctx); + if (core.domStyle.isVertical) { + ctx.canvas.width = 1248; + ctx.canvas.height = 676 * 3; + ctx.save(); //保存设置 + ctx.translate(1248, 0); //重新定位右上角为基准 + ctx.rotate(Math.PI / 2); //旋转90度 + } else { + ctx.canvas.width = 676 * 3; + ctx.canvas.height = 1248; + } + ctx.globalAlpha = globalAlpha2 / time; + if (img1) { + //绘制背景 + if (memory1) ctx.filter = "sepia(50%)"; + ctx.drawImage(img1, 0, 0, 676 * 3, 1248); + ctx.filter = "none"; + } else { + core.fillRect(ctx, 0, 0, 676 * 3, 1248); + } + globalAlpha2--; + ctx.restore(); + if (globalAlpha2 <= 0) { + core.unregisterAnimationFrame("bgout"); + over.style.display = "none"; + core.doAction(); + } + } + }); - break; - case "场景切换": - core.registerAnimationFrame("changebg", true, (timestamp) => { - if (timestamp - now > 1000 / 60) { - now = timestamp; - core.clearMap(ctx); - if (core.domStyle.isVertical) { - ctx.canvas.width = 1248; - ctx.canvas.height = 676 * 3; - ctx.save(); //保存设置 - ctx.translate(1248, 0); //重新定位右上角为基准 - ctx.rotate(Math.PI / 2); //旋转90度 - } else { - ctx.canvas.width = 676 * 3; - ctx.canvas.height = 1248; - } - ctx.globalAlpha = 1; - core.fillRect(ctx, 0, 0, 676 * 3, 1248); - ctx.globalAlpha = globalAlpha2 / time; - if (img1) { - //绘制背景 - if (memory1) ctx.filter = "sepia(50%)"; - ctx.drawImage(img1, 0, 0, 676 * 3, 1248); - ctx.filter = "none"; - } else { - core.fillRect(ctx, 0, 0, 676 * 3, 1248); - } - ctx.globalAlpha = globalAlpha1 / time; - if (img2) { - //绘制背景 - if (memory2) ctx.filter = "sepia(50%)"; - ctx.drawImage(img2, 0, 0, 676 * 3, 1248); - ctx.filter = "none"; - } else { - core.fillRect(ctx, 0, 0, 676 * 3, 1248); - } - globalAlpha2--; - globalAlpha1++; - ctx.restore(); - if (globalAlpha2 <= 0 || globalAlpha1 >= time) { - core.unregisterAnimationFrame("changebg"); - over.style.display = "none"; - core.doAction(); - } - } - }); + break; + case "场景切换": + core.registerAnimationFrame("changebg", true, (timestamp) => { + if (timestamp - now > 1000 / 60) { + now = timestamp; + core.clearMap(ctx); + if (core.domStyle.isVertical) { + ctx.canvas.width = 1248; + ctx.canvas.height = 676 * 3; + ctx.save(); //保存设置 + ctx.translate(1248, 0); //重新定位右上角为基准 + ctx.rotate(Math.PI / 2); //旋转90度 + } else { + ctx.canvas.width = 676 * 3; + ctx.canvas.height = 1248; + } + ctx.globalAlpha = 1; + core.fillRect(ctx, 0, 0, 676 * 3, 1248); + ctx.globalAlpha = globalAlpha2 / time; + if (img1) { + //绘制背景 + if (memory1) ctx.filter = "sepia(50%)"; + ctx.drawImage(img1, 0, 0, 676 * 3, 1248); + ctx.filter = "none"; + } else { + core.fillRect(ctx, 0, 0, 676 * 3, 1248); + } + ctx.globalAlpha = globalAlpha1 / time; + if (img2) { + //绘制背景 + if (memory2) ctx.filter = "sepia(50%)"; + ctx.drawImage(img2, 0, 0, 676 * 3, 1248); + ctx.filter = "none"; + } else { + core.fillRect(ctx, 0, 0, 676 * 3, 1248); + } + globalAlpha2--; + globalAlpha1++; + ctx.restore(); + if (globalAlpha2 <= 0 || globalAlpha1 >= time) { + core.unregisterAnimationFrame("changebg"); + over.style.display = "none"; + core.doAction(); + } + } + }); - break; - } - }; -}, + break; + } + }; + }, "回合制boss战": function () { // 在此增加新插件 const boss = document.createElement("canvas"); //boss战画布设置 @@ -16810,11 +17268,10 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = boss8.style.transform = "translate(-50%,-50%)"; const ctx8 = boss8.getContext("2d"); main.dom.boss8 = boss8; - const { imagelighter } = core.plugin.utils + const { imagelighter } = core.plugin.utils; function getClick() { - - return new Promise(resolve => { + return new Promise((resolve) => { function handleBossClick(e) { try { e.preventDefault(); @@ -16825,59 +17282,162 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = const px = Math.floor((e.clientX - left) / core.domStyle.scale), py = Math.floor((e.clientY - top) / core.domStyle.scale); - let x, y; if (core.domStyle.isVertical) { x = py * 3; y = 1248 - px * 3; - } else { x = px * 3; y = py * 3; } core.ui.boss.click(x, y); - if (x > 1050 && x < 1450 && y > 250 && y < 390 && !core.ui.boss.show && core.ui.boss.hasEnemy()) { + if ( + x > 1050 && + x < 1450 && + y > 250 && + y < 390 && + !core.ui.boss.show && + core.ui.boss.hasEnemy() + ) { // 移除事件监听器 - boss.removeEventListener('click', handleBossClick); - resolve("普通攻击") //有小怪时点击普通攻击 + boss.removeEventListener("click", handleBossClick); + resolve("普通攻击"); //有小怪时点击普通攻击 return; // 退出函数 } - if (x > 850 && x < 1250 && y > 250 && y < 390 && !core.ui.boss.show && !core.ui.boss.hasEnemy()) { + if ( + x > 850 && + x < 1250 && + y > 250 && + y < 390 && + !core.ui.boss.show && + !core.ui.boss.hasEnemy() + ) { // 移除事件监听器 - boss.removeEventListener('click', handleBossClick); - resolve("普通攻击") //无小怪时点击普通攻击 + boss.removeEventListener("click", handleBossClick); + resolve("普通攻击"); //无小怪时点击普通攻击 return; // 退出函数 } } catch (ee) { main.log(ee); } } - boss.addEventListener('click', handleBossClick); - }) + boss.addEventListener("click", handleBossClick); + }); } - const { sleep } = core.plugin.utils + const { sleep } = core.plugin.utils; class Boss { constructor() { //绘制需要的变量 - this.enemyfarme = 0 + this.enemyfarme = 0; this.bg = "bg_3512.webp"; - this.heroImage = "tati_310101.webp" - this.hero = { id: "hero", name: "凯伊姆", hp: 1000, atk: 150, def: 100, spell: 100, speed: 10, mdef: 10 } - this.boss = { name: "菲奥奈", id: "angel", image: "tati_050143.webp", hp: 1000, atk: 200, def: 100, speed: 10, mdef: 10, skill: ['普通攻击', '重斩'], index: 0 } - this.enemy = [] - this.enemy = [ - { name: "小蝙蝠", id: "bat", image: "tati_020125a.webp", hp: 1000, atk: 100, def: 20, speed: 10, mdef: 10, skill: ['普通攻击', '重斩'], index: 0 }, - { name: "红蝙蝠", id: "redBat", image: "tati_050301.webp", hp: 1000, atk: 100, def: 120, speed: 10, mdef: 10, skill: ['普通攻击', '重斩'], index: 0 }, - { name: "大蝙蝠", id: "bigBat", image: "tati_120101.webp", hp: 1000, atk: 100, def: 100, speed: 10, mdef: 10, skill: ['普通攻击', '重斩'], index: 0 }, - { name: "绿色史莱姆", id: "greenSlime", image: "tati_340115.webp", hp: 1000, atk: 100, def: 100, speed: 10, mdef: 10, skill: ['普通攻击', '重斩'], index: 0 }, - { name: "红色史莱姆", id: "redSlime", image: "tati_430101.webp", hp: 1000, atk: 100, def: 100, speed: 10, mdef: 10, skill: ['普通攻击', '重斩'], index: 0 }, - { name: "黑色史莱姆", id: "blackSlime", image: "tati_440101.webp", hp: 1000, atk: 100, def: 100, speed: 10, mdef: 10, skill: ['普通攻击', '重斩'], index: 0 }, - ] - this.selection = "boss" - this.herobuff = [{ id: 'sword1', count: 1 }, { id: 'fly', count: 30 }] - this.bossbuff = [{ id: 'fly', count: 2 }, { id: 'book', count: 12, hp: 100 }] + this.heroImage = "tati_310101.webp"; + this.hero = { + id: "hero", + name: "凯伊姆", + hp: 1000, + atk: 150, + def: 100, + spell: 100, + speed: 10, + mdef: 10, + }; + this.boss = { + name: "菲奥奈", + id: "angel", + image: "tati_050143.webp", + hp: 1000, + atk: 200, + def: 100, + speed: 10, + mdef: 10, + skill: ["普通攻击", "重斩"], + index: 0, + }; + this.enemy = []; + this.enemy = [{ + name: "小蝙蝠", + id: "bat", + image: "tati_020125a.webp", + hp: 1000, + atk: 100, + def: 20, + speed: 10, + mdef: 10, + skill: ["普通攻击", "重斩"], + index: 0, + }, + { + name: "红蝙蝠", + id: "redBat", + image: "tati_050301.webp", + hp: 1000, + atk: 100, + def: 120, + speed: 10, + mdef: 10, + skill: ["普通攻击", "重斩"], + index: 0, + }, + { + name: "大蝙蝠", + id: "bigBat", + image: "tati_120101.webp", + hp: 1000, + atk: 100, + def: 100, + speed: 10, + mdef: 10, + skill: ["普通攻击", "重斩"], + index: 0, + }, + { + name: "绿色史莱姆", + id: "greenSlime", + image: "tati_340115.webp", + hp: 1000, + atk: 100, + def: 100, + speed: 10, + mdef: 10, + skill: ["普通攻击", "重斩"], + index: 0, + }, + { + name: "红色史莱姆", + id: "redSlime", + image: "tati_430101.webp", + hp: 1000, + atk: 100, + def: 100, + speed: 10, + mdef: 10, + skill: ["普通攻击", "重斩"], + index: 0, + }, + { + name: "黑色史莱姆", + id: "blackSlime", + image: "tati_440101.webp", + hp: 1000, + atk: 100, + def: 100, + speed: 10, + mdef: 10, + skill: ["普通攻击", "重斩"], + index: 0, + }, + ]; + this.selection = "boss"; + this.herobuff = [ + { id: "sword1", count: 1 }, + { id: "fly", count: 30 }, + ]; + this.bossbuff = [ + { id: "fly", count: 2 }, + { id: "book", count: 12, hp: 100 }, + ]; this.enemybuff = [ [], [], @@ -16885,49 +17445,55 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = [], [], [] - ] - this.skills = { //技能列表,便于调用(可通过this.skills[name]调用) - "菲奥奈": ['普通攻击', '重斩'] - } - this.skillShow = { //技能说明 - "普通攻击": "常规攻击形式,伤害为自身攻击-对手防御" - } + ]; + this.skills = { + //技能列表,便于调用(可通过this.skills[name]调用) + 菲奥奈: ["普通攻击", "重斩"], + }; + this.skillShow = { + //技能说明 + 普通攻击: "常规攻击形式,伤害为自身攻击-对手防御", + }; this.turn = 0; this.playingAnimate = new Set(); - this.playerTurn = false - this.show = false + this.playerTurn = false; + this.show = false; } - buffshow(a) { //buff说明(均未实装,之后改为实际需要的buff) - let text = "" + buffshow(a) { + //buff说明(均未实装,之后改为实际需要的buff) + let text = ""; switch (a.id) { case "sword1": - text = `\r[rgb(30,66,30)]剑气:\r造成伤害提升\r[red]${10*a.count}%\r` + text = `\r[rgb(30,66,30)]剑气:\r造成伤害提升\r[red]${ + 10 * a.count + }%\r`; break; case "fly": - text = `羽翼守护:接下来\r[gold]${a.count}回合\r不受速度差值影响` + text = `羽翼守护:接下来\r[gold]${a.count}回合\r不受速度差值影响`; break; case "book": - text = `恢复之书:接下来\r[#000033]${a.count}回合\r,每回合行动时回复\r[green]${a.hp}\r点生命` + text = `恢复之书:接下来\r[#000033]${a.count}回合\r,每回合行动时回复\r[green]${a.hp}\r点生命`; break; - } - return text + return text; } shake(hero) { let time = 0, farme = 0; - const xlist = [Math.random() * 40 + 10, Math.random() * -40 - 10, 0] - return new Promise(resolve => { + const xlist = [Math.random() * 40 + 10, Math.random() * -40 - 10, 0]; + return new Promise((resolve) => { core.registerAnimationFrame("shake", true, (temptime) => { if (temptime - time > 1000 / 60) { - time = temptime + time = temptime; - const x = xlist[Math.floor(farme / 5) % 3] + const x = xlist[Math.floor(farme / 5) % 3]; if (hero) { - const img = imagelighter(core.material.images.images[this.heroImage]) - core.clearMap(ctx2) + const img = imagelighter( + core.material.images.images[this.heroImage] + ); + core.clearMap(ctx2); if (core.domStyle.isVertical) { ctx2.canvas.width = 1248; ctx2.canvas.height = 2028; @@ -16939,10 +17505,10 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ctx2.canvas.height = 1248; } - core.drawImage(ctx2, img, x, 168, 750, 1080) + core.drawImage(ctx2, img, x, 168, 750, 1080); ctx2.restore(); } else { - core.clearMap(ctx3) + core.clearMap(ctx3); if (core.domStyle.isVertical) { ctx3.canvas.width = 1248; ctx3.canvas.height = 2028; @@ -16954,27 +17520,32 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ctx3.canvas.height = 1248; } if (this.selection === "boss" || this.selection === "") { - const img = imagelighter(core.material.images.images[this.boss.image]) - core.drawImage(ctx3, img, 1400 + x, 168, 750, 1080) + const img = imagelighter( + core.material.images.images[this.boss.image] + ); + core.drawImage(ctx3, img, 1400 + x, 168, 750, 1080); } else { - const img = imagelighter(core.material.images.images[this.enemy[this.selection].image]) - core.drawImage(ctx3, img, 1400 + x, 168, 750, 1080) + const img = imagelighter( + core.material.images.images[ + this.enemy[this.selection].image + ] + ); + core.drawImage(ctx3, img, 1400 + x, 168, 750, 1080); } ctx3.restore(); } - farme++ + farme++; if (farme > 30) { - core.unregisterAnimationFrame("shake") + core.unregisterAnimationFrame("shake"); - this.drawhero() - this.drawboss() - resolve() + this.drawhero(); + this.drawboss(); + resolve(); } - } - }) - }) + }); + }); } popDamage(damage, onhero) { if (core.domStyle.isVertical) { @@ -16987,93 +17558,105 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ctx.canvas.width = 2028; ctx.canvas.height = 1248; } - let color = "#FFFFFF" + let color = "#FFFFFF"; if (typeof damage === "number") { - color = damage < 0 ? '#22FF44' : 'lightcoral' + color = damage < 0 ? "#22FF44" : "lightcoral"; } let farme = 0, time = 0; - let posx = onhero ? 300 : 1800 - const speed = 9 - return new Promise(resolve => { + let posx = onhero ? 300 : 1800; + const speed = 9; + return new Promise((resolve) => { core.registerAnimationFrame("popDamageonboss", true, (temptime) => { if (temptime - time > 1000 / 60) { - time = temptime - core.clearMap(ctx) - core.setTextAlign(ctx, "center") - core.fillBoldText1(ctx, damage, posx, 800 - speed * farme, color, "#000000", 6, "bold 72px Arial") - farme++ + time = temptime; + core.clearMap(ctx); + core.setTextAlign(ctx, "center"); + core.fillBoldText1( + ctx, + damage, + posx, + 800 - speed * farme, + color, + "#000000", + 6, + "bold 72px Arial" + ); + farme++; ctx2.restore(); if (farme > 30) { - core.unregisterAnimationFrame("popDamageonboss") + core.unregisterAnimationFrame("popDamageonboss"); - core.clearMap(ctx) - resolve() + core.clearMap(ctx); + resolve(); } } - }) - }) + }); + }); } - async skill(sk, a, b) { //a为发起方属性,sk为技能名 - let damage = 0 - switch (sk) { //所有技能效果及动画写在这里 - + async skill(sk, a, b) { + //a为发起方属性,sk为技能名 + let damage = 0; + switch ( + sk //所有技能效果及动画写在这里 + ) { case "普通攻击": - damage = Math.max(a.atk - b.def, 0) //基础伤害 - damage = Math.floor(damage * a.speed / b.speed) //速度比值伤害加成 - b.hp -= damage //承受伤害 - if (b.id === "hero") core.status.hero.statistics.battleDamage += damage; //数据统计记录伤害 - if (damage === 0) damage = "抵抗" + damage = Math.max(a.atk - b.def, 0); //基础伤害 + damage = Math.floor((damage * a.speed) / b.speed); //速度比值伤害加成 + b.hp -= damage; //承受伤害 + if (b.id === "hero") + core.status.hero.statistics.battleDamage += damage; //数据统计记录伤害 + if (damage === 0) damage = "抵抗"; - switch (a.id) { //根据id选取不同的特效 + switch ( + a.id //根据id选取不同的特效 + ) { case "hero": - this.popDamage(damage, false) - if (damage > 0 && typeof damage !== "string") this.shake(false) - await this.playanimate("sword", 1800, 800) - break + this.popDamage(damage, false); + if (damage > 0 && typeof damage !== "string") this.shake(false); + await this.playanimate("sword", 1800, 800); + break; case "angel": - this.popDamage(damage, true) - if (damage > 0 && typeof damage !== "string") this.shake(true) - await this.playanimate("sword", 350, 800) //播放动画sword + this.popDamage(damage, true); + if (damage > 0 && typeof damage !== "string") this.shake(true); + await this.playanimate("sword", 350, 800); //播放动画sword break; case "bat": - this.popDamage(damage, true) - if (damage > 0 && typeof damage !== "string") this.shake(true) - await this.playanimate("sword", 350, 800) //播放动画sword + this.popDamage(damage, true); + if (damage > 0 && typeof damage !== "string") this.shake(true); + await this.playanimate("sword", 350, 800); //播放动画sword break; case "redBat": - this.popDamage(damage, true) - if (damage > 0 && typeof damage !== "string") this.shake(true) - await this.playanimate("Fire01", 350, 800) //播放动画Fire01 + this.popDamage(damage, true); + if (damage > 0 && typeof damage !== "string") this.shake(true); + await this.playanimate("Fire01", 350, 800); //播放动画Fire01 break; case "bigBat": - this.popDamage(damage, true) - if (damage > 0 && typeof damage !== "string") this.shake(true) - await this.playanimate("Fire02", 350, 800) //播放动画Fire02 + this.popDamage(damage, true); + if (damage > 0 && typeof damage !== "string") this.shake(true); + await this.playanimate("Fire02", 350, 800); //播放动画Fire02 break; case "greenSlime": - this.popDamage(damage, true) - if (damage > 0 && typeof damage !== "string") this.shake(true) - await this.playanimate("005-Attack03", 350, 800) //播放动画005-Attack03 + this.popDamage(damage, true); + if (damage > 0 && typeof damage !== "string") this.shake(true); + await this.playanimate("005-Attack03", 350, 800); //播放动画005-Attack03 break; case "redSlime": - this.popDamage(damage, true) - if (damage > 0 && typeof damage !== "string") this.shake(true) - await this.playanimate("012-Heal01", 350, 800) //播放动画012-Heal01 + this.popDamage(damage, true); + if (damage > 0 && typeof damage !== "string") this.shake(true); + await this.playanimate("012-Heal01", 350, 800); //播放动画012-Heal01 break; case "blackSlime": - this.popDamage(damage, true) - if (damage > 0 && typeof damage !== "string") this.shake(true) - await this.playanimate("sword", 350, 800) //播放动画sword + this.popDamage(damage, true); + if (damage > 0 && typeof damage !== "string") this.shake(true); + await this.playanimate("sword", 350, 800); //播放动画sword break; - } break; //下面写其余技能 - } - await sleep(500) //等待1000ms + await sleep(500); //等待1000ms } click(px, py) { @@ -17091,41 +17674,50 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = return sx <= x && x <= dx && sy <= y && y <= dy; }; const pos = [px, py]; - if (main.replayChecking || core.isReplaying()) return + if (main.replayChecking || core.isReplaying()) return; const enemyStatusBox = makeBox([50, 50], [1900, 200]), heroStatusBox = makeBox([600, 920], [900, 300]), bossBox = makeBox([800, 300], [100, 150]), enemyBox = makeBox([700, 500], [300, 300]), imageBox = makeBox([1500, 250], [550, 1000]); - if (this.show) { //清除展示画面 - this.show = !this.show - core.clearMap(ctx8) + if (this.show) { + //清除展示画面 + this.show = !this.show; + core.clearMap(ctx8); } else { - if (inRect(pos, enemyStatusBox) && this.selection !== "" && this.selection !== "boss" && this.hasEnemy()) { //绘制怪物详情 - this.show = !this.show - this.moreShow(this.selection) - - } else if (inRect(pos, enemyStatusBox) && (!this.hasEnemy() || this.selection === "boss")) { //绘制boss详情 - this.show = !this.show - this.moreShow("boss") - - } else if (inRect(pos, heroStatusBox)) { //绘制勇士详情 - this.show = !this.show - this.moreShow("hero") - - } else if (inRect(pos, bossBox) && this.hasEnemy()) { //切换selection为boss - this.selection = 'boss' - this.update() - - } else if (inRect(pos, enemyBox) && this.hasEnemy()) { //切换selection为enemy - const symbol = Math.floor((px - 700) / 100) + Math.floor((py - 500) / 150) * 3 + if ( + inRect(pos, enemyStatusBox) && + this.selection !== "" && + this.selection !== "boss" && + this.hasEnemy() + ) { + //绘制怪物详情 + this.show = !this.show; + this.moreShow(this.selection); + } else if ( + inRect(pos, enemyStatusBox) && + (!this.hasEnemy() || this.selection === "boss") + ) { + //绘制boss详情 + this.show = !this.show; + this.moreShow("boss"); + } else if (inRect(pos, heroStatusBox)) { + //绘制勇士详情 + this.show = !this.show; + this.moreShow("hero"); + } else if (inRect(pos, bossBox) && this.hasEnemy()) { + //切换selection为boss + this.selection = "boss"; + this.update(); + } else if (inRect(pos, enemyBox) && this.hasEnemy()) { + //切换selection为enemy + const symbol = + Math.floor((px - 700) / 100) + Math.floor((py - 500) / 150) * 3; if (this.enemy[symbol] && this.enemy[symbol].hp > 0) { - this.selection = symbol - this.update() - + this.selection = symbol; + this.update(); } - } } } @@ -17140,21 +17732,59 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ctx7.canvas.width = 2028; ctx7.canvas.height = 1248; } - boss7.style.display = "block" - core.clearMap(ctx7) + boss7.style.display = "block"; + core.clearMap(ctx7); if (this.hasEnemy()) { - core.drawWindowSkin("winskin.webp", ctx7, 1050, 250, 400, 660, null, null, null, 3) - core.fillBoldText1(ctx7, "普通攻击", 1120, 350, "#FFFFFF", "#000000", 6, "bold 64px Verdana") - core.drawLine(ctx7, 1050, 390, 1450, 390, "#FFFFFF", 6) + core.drawWindowSkin( + "winskin.webp", + ctx7, + 1050, + 250, + 400, + 660, + null, + null, + null, + 3 + ); + core.fillBoldText1( + ctx7, + "普通攻击", + 1120, + 350, + "#FFFFFF", + "#000000", + 6, + "bold 64px Verdana" + ); + core.drawLine(ctx7, 1050, 390, 1450, 390, "#FFFFFF", 6); } else { - core.drawWindowSkin("winskin.webp", ctx7, 850, 250, 400, 660, null, null, null, 3) - core.fillBoldText1(ctx7, "普通攻击", 920, 350, "#FFFFFF", "#000000", 6, "bold 64px Verdana") - core.drawLine(ctx7, 850, 390, 1250, 390, "#FFFFFF", 6) + core.drawWindowSkin( + "winskin.webp", + ctx7, + 850, + 250, + 400, + 660, + null, + null, + null, + 3 + ); + core.fillBoldText1( + ctx7, + "普通攻击", + 920, + 350, + "#FFFFFF", + "#000000", + 6, + "bold 64px Verdana" + ); + core.drawLine(ctx7, 850, 390, 1250, 390, "#FFFFFF", 6); } - } moreShow(select) { - if (core.domStyle.isVertical) { ctx8.canvas.width = 1248; ctx8.canvas.height = 2028; @@ -17165,20 +17795,49 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ctx8.canvas.width = 2028; ctx8.canvas.height = 1248; } - core.clearMap(ctx8) - core.fillRect(ctx8, 100, 100, 1800, 1000, "rgba(0,0,0,0.7)") - core.drawWindowSkin("winskin.webp", ctx8, 100, 100, 1800, 1000, null, null, null, 3) - let posy = 200 + core.clearMap(ctx8); + core.fillRect(ctx8, 100, 100, 1800, 1000, "rgba(0,0,0,0.7)"); + core.drawWindowSkin( + "winskin.webp", + ctx8, + 100, + 100, + 1800, + 1000, + null, + null, + null, + 3 + ); + let posy = 200; switch (select) { case "hero": //勇士技能/buff - core.fillBoldText1(ctx8, this.hero.name, 1000, posy, "#FFFFFF", "#000000", 6, "bold 48px Verdana") - posy += 100 + core.fillBoldText1( + ctx8, + this.hero.name, + 1000, + posy, + "#FFFFFF", + "#000000", + 6, + "bold 48px Verdana" + ); + posy += 100; if (this.herobuff.length === 0) { - core.fillBoldText1(ctx8, "当前无特殊状态", 200, posy, "#FFFFFF", "#000000", 6, "bold 48px Verdana") - posy += 100 + core.fillBoldText1( + ctx8, + "当前无特殊状态", + 200, + posy, + "#FFFFFF", + "#000000", + 6, + "bold 48px Verdana" + ); + posy += 100; } else { - this.herobuff.forEach(v => { + this.herobuff.forEach((v) => { core.drawTextContent(ctx8, this.buffshow(v), { left: 200, top: posy, @@ -17190,23 +17849,59 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = font: "Verdana", maxWidth: 1600, }); - posy += 100 - }) + posy += 100; + }); } - posy += 50 - core.fillBoldText1(ctx8, "技能说明", 1000, posy, "#FFFFFF", "#000000", 6, "bold 48px Verdana") - posy += 100 - core.fillBoldText1(ctx8, "普通攻击:" + this.skillShow["普通攻击"], 200, posy, "#FFFFFF", "#000000", 6, "bold 48px Verdana") + posy += 50; + core.fillBoldText1( + ctx8, + "技能说明", + 1000, + posy, + "#FFFFFF", + "#000000", + 6, + "bold 48px Verdana" + ); + posy += 100; + core.fillBoldText1( + ctx8, + "普通攻击:" + this.skillShow["普通攻击"], + 200, + posy, + "#FFFFFF", + "#000000", + 6, + "bold 48px Verdana" + ); break; case "boss": - core.fillBoldText1(ctx8, this.boss.name, 1000, posy, "#FFFFFF", "#000000", 6, "bold 48px Verdana") - posy += 100 + core.fillBoldText1( + ctx8, + this.boss.name, + 1000, + posy, + "#FFFFFF", + "#000000", + 6, + "bold 48px Verdana" + ); + posy += 100; //boss技能/buff if (this.bossbuff.length === 0) { - core.fillBoldText1(ctx8, "当前无特殊状态", 200, posy, "#FFFFFF", "#000000", 6, "bold 48px Verdana") - posy += 100 + core.fillBoldText1( + ctx8, + "当前无特殊状态", + 200, + posy, + "#FFFFFF", + "#000000", + 6, + "bold 48px Verdana" + ); + posy += 100; } else { - this.bossbuff.forEach(v => { + this.bossbuff.forEach((v) => { core.drawTextContent(ctx8, this.buffshow(v), { left: 200, top: posy, @@ -17218,24 +17913,61 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = font: "Verdana", maxWidth: 1600, }); - posy += 100 - }) + posy += 100; + }); } - posy += 50 - core.fillBoldText1(ctx8, "当前技能", 1000, posy, "#FFFFFF", "#000000", 6, "bold 48px Verdana") - posy += 100 - core.fillBoldText1(ctx8, this.boss.skill[this.boss.index] + this.skillShow[this.boss.skill[this.boss.index]], 200, posy, "#FFFFFF", "#000000", 6, "bold 48px Verdana") + posy += 50; + core.fillBoldText1( + ctx8, + "当前技能", + 1000, + posy, + "#FFFFFF", + "#000000", + 6, + "bold 48px Verdana" + ); + posy += 100; + core.fillBoldText1( + ctx8, + this.boss.skill[this.boss.index] + + this.skillShow[this.boss.skill[this.boss.index]], + 200, + posy, + "#FFFFFF", + "#000000", + 6, + "bold 48px Verdana" + ); break; default: - const enemy = this.enemy[select] - const enemybuff = this.enemybuff[select] - core.fillBoldText1(ctx8, enemy.name, 1000, posy, "#FFFFFF", "#000000", 6, "bold 48px Verdana") - posy += 100 + const enemy = this.enemy[select]; + const enemybuff = this.enemybuff[select]; + core.fillBoldText1( + ctx8, + enemy.name, + 1000, + posy, + "#FFFFFF", + "#000000", + 6, + "bold 48px Verdana" + ); + posy += 100; if (enemybuff.length === 0) { - core.fillBoldText1(ctx8, "当前无特殊状态", 200, posy, "#FFFFFF", "#000000", 6, "bold 48px Verdana") - posy += 100 + core.fillBoldText1( + ctx8, + "当前无特殊状态", + 200, + posy, + "#FFFFFF", + "#000000", + 6, + "bold 48px Verdana" + ); + posy += 100; } else { - enemybuff.forEach(v => { + enemybuff.forEach((v) => { core.drawTextContent(ctx8, this.buffshow(v), { left: 200, top: posy, @@ -17247,110 +17979,140 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = font: "Verdana", maxWidth: 1600, }); - posy += 100 - }) + posy += 100; + }); } - posy += 50 - core.fillBoldText1(ctx8, "当前技能", 1000, posy, "#FFFFFF", "#000000", 6, "bold 48px Verdana") - posy += 100 - core.fillBoldText1(ctx8, enemy.skill[enemy.index] + this.skillShow[enemy.skill[enemy.index]], 200, posy, "#FFFFFF", "#000000", 6, "bold 48px Verdana") + posy += 50; + core.fillBoldText1( + ctx8, + "当前技能", + 1000, + posy, + "#FFFFFF", + "#000000", + 6, + "bold 48px Verdana" + ); + posy += 100; + core.fillBoldText1( + ctx8, + enemy.skill[enemy.index] + + this.skillShow[enemy.skill[enemy.index]], + 200, + posy, + "#FFFFFF", + "#000000", + 6, + "bold 48px Verdana" + ); break; } - ctx8.restore() + ctx8.restore(); } hasEnemy() { let enemy = false; - this.enemy.forEach(v => { if (v.hp > 0) enemy = true }) - return enemy + this.enemy.forEach((v) => { + if (v.hp > 0) enemy = true; + }); + return enemy; } async bossStart() { - boss.style.display = "block" - this.selection = "boss" - this.playerturn = false - this.show = false - this.turn = 0 - core.lockControl() - await this.blackBg() - this.moveboss() - await this.movehero() - await this.moveStatus() - this.update() - this.fight() + boss.style.display = "block"; + this.selection = "boss"; + this.playerturn = false; + this.show = false; + this.turn = 0; + core.lockControl(); + await this.blackBg(); + this.moveboss(); + await this.movehero(); + await this.moveStatus(); + this.update(); + this.fight(); } async bossEnd() { - hero.hp = this.hero.hp - this.selection = "boss" - await this.close() + hero.hp = this.hero.hp; + this.selection = "boss"; + await this.close(); - core.unlockControl() - core.updateStatusBar() + core.unlockControl(); + core.updateStatusBar(); if (hero.hp <= 0) { - hero.hp = 0 + hero.hp = 0; core.events.lose("BOSS战失败"); } } async fight() { - await this.drawturn() - const fightList = [] - fightList.push(['hero', this.hero.speed]) - if (this.boss.hp > 0) fightList.push(["boss", this.boss.speed]) + await this.drawturn(); + const fightList = []; + fightList.push(["hero", this.hero.speed]); + if (this.boss.hp > 0) fightList.push(["boss", this.boss.speed]); this.enemy.forEach((v, i) => { - if (v.id && v.hp > 0) fightList.push([i, v.speed]) - }) - fightList.sort((a, b) => b[1] - a[1]) + if (v.id && v.hp > 0) fightList.push([i, v.speed]); + }); + fightList.sort((a, b) => b[1] - a[1]); let damage; for (const v of fightList) { switch (v[0]) { - case 'hero': - this.drawchoose() - const skill = await getClick() - let select = this.boss - if (this.selection !== "" && this.selection !== "boss") select = this.enemy[this.selection] - this.skill(skill, this.hero, select) + case "hero": + this.drawchoose(); + const skill = await getClick(); + let select = this.boss; + if (this.selection !== "" && this.selection !== "boss") + select = this.enemy[this.selection]; + this.skill(skill, this.hero, select); - core.clearMap(ctx7) + core.clearMap(ctx7); break; - case 'boss': + case "boss": if (this.boss.hp > 0) { - this.selection = "boss" - this.update() - await sleep(500) //等待500ms + this.selection = "boss"; + this.update(); + await sleep(500); //等待500ms //这里写boss技能的效果 - this.skill(this.boss.skill[this.boss.index], this.boss, this.hero) + this.skill( + this.boss.skill[this.boss.index], + this.boss, + this.hero + ); - this.boss.index++ - if (this.boss.index >= this.boss.skill.length) this.boss.index = 0 + this.boss.index++; + if (this.boss.index >= this.boss.skill.length) + this.boss.index = 0; } break; default: const enemy = this.enemy[v[0]]; if (enemy.hp > 0) { - this.selection = v[0] - this.update() - await sleep(500) //等待500ms - this.skill(enemy.skill[enemy.index], enemy, this.hero) - enemy.index++ - if (enemy.index >= enemy.skill.length) enemy.index = 0 + this.selection = v[0]; + this.update(); + await sleep(500); //等待500ms + this.skill(enemy.skill[enemy.index], enemy, this.hero); + enemy.index++; + if (enemy.index >= enemy.skill.length) enemy.index = 0; } break; - } - await sleep(1000) - this.selection = "" - this.update() - - + await sleep(1000); + this.selection = ""; + this.update(); } let end = true; if (this.boss.hp > 0) end = false; - this.enemy.forEach(v => { if (v.hp > 0) end = false }) + this.enemy.forEach((v) => { + if (v.hp > 0) end = false; + }); - if (this.hero.hp <= 0) end = true - if (end) { this.bossEnd() } else { this.fight() } + if (this.hero.hp <= 0) end = true; + if (end) { + this.bossEnd(); + } else { + this.fight(); + } } drawturn() { - boss8.style.display = "block" - this.turn += 1 + boss8.style.display = "block"; + this.turn += 1; let time = 0, frame = 0, frame2 = 0, @@ -17359,9 +18121,9 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = return new Promise((resolve) => { core.registerAnimationFrame("drawturn", true, (temptime) => { if (temptime - time > 1000 / 60) { - time = temptime - frame += 1 * right - core.clearMap(ctx) + time = temptime; + frame += 1 * right; + core.clearMap(ctx); if (core.domStyle.isVertical) { ctx.canvas.width = 1248; ctx.canvas.height = 2028; @@ -17373,47 +18135,53 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ctx.canvas.height = 1248; } - core.fillRect(ctx, 0, 624 - once * frame, 2028, once * frame * 2, 'rgba(0,0,0,0.7)') - core.setTextAlign(ctx, "center") + core.fillRect( + ctx, + 0, + 624 - once * frame, + 2028, + once * frame * 2, + "rgba(0,0,0,0.7)" + ); + core.setTextAlign(ctx, "center"); core.fillBoldText1( ctx, - 'ROUND ' + this.turn, + "ROUND " + this.turn, 1014, 624, "#FFFFFF", "#000000", 6, core.ui._buildFont(frame * 5, true) - ) + ); if (1014 - once * frame * 7 <= 0) { - frame -= 1 - frame2++ - - if (frame2 > 30) right = -1 + frame -= 1; + frame2++; + if (frame2 > 30) right = -1; } if (frame < 0) { - core.clearMap(ctx) - core.unregisterAnimationFrame("drawturn") - resolve() + core.clearMap(ctx); + core.unregisterAnimationFrame("drawturn"); + resolve(); } } - }) - }) + }); + }); } drawenemy() { let block, time = 0; - boss5.style.display = 'block' - core.registerAnimationFrame('enemyanimate', true, (temptime) => { + boss5.style.display = "block"; + core.registerAnimationFrame("enemyanimate", true, (temptime) => { if (temptime - time > 1000 / 60) { - time = temptime - this.enemyfarme += 1 + time = temptime; + this.enemyfarme += 1; let animate = Math.floor(this.enemyfarme / 30), posx = 700, posy = 500; - core.clearMap(ctx5) + core.clearMap(ctx5); if (core.domStyle.isVertical) { ctx5.canvas.width = 1248; ctx5.canvas.height = 2028; @@ -17426,10 +18194,21 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = } if (this.hasEnemy()) { - - core.drawWindowSkin("winskin.webp", ctx5, 650, 250, 400, 660, null, null, null, 3) - if (this.selection === "boss") core.strokeRect(ctx5, 800, 300, 100, 150, "yellow", 6) - const bossBlock = core.getBlockInfo(this.boss.id) + core.drawWindowSkin( + "winskin.webp", + ctx5, + 650, + 250, + 400, + 660, + null, + null, + null, + 3 + ); + if (this.selection === "boss") + core.strokeRect(ctx5, 800, 300, 100, 150, "yellow", 6); + const bossBlock = core.getBlockInfo(this.boss.id); core.drawImage( ctx5, bossBlock.image, @@ -17456,14 +18235,14 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ); for (let i = 0; i < this.enemy.length; i++) { if (this.enemy[i].id && this.enemy[i].hp > 0) { - block = core.getBlockInfo(this.enemy[i].id) + block = core.getBlockInfo(this.enemy[i].id); } else { - posx += 100 + posx += 100; if (i === 2) { - posx = 700 - posy += 150 + posx = 700; + posy += 150; } - continue + continue; } if (block.cls === "enemys") { @@ -17479,7 +18258,8 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = 96, 96 ); - if (this.selection === i) core.strokeRect(ctx5, posx, posy, 100, 100, "yellow", 6) + if (this.selection === i) + core.strokeRect(ctx5, posx, posy, 100, 100, "yellow", 6); } else { core.drawImage( ctx5, @@ -17493,23 +18273,24 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = 96, 144 ); - if (this.selection === i) core.strokeRect(ctx5, posx, posy, 100, 150, "yellow", 6) + if (this.selection === i) + core.strokeRect(ctx5, posx, posy, 100, 150, "yellow", 6); } - posx += 100 + posx += 100; if (i === 2) { - posx = 700 - posy += 150 + posx = 700; + posy += 150; } } } ctx5.restore(); } - }) + }); } drawhero() { - core.clearMap(ctx2) + core.clearMap(ctx2); if (core.domStyle.isVertical) { ctx2.canvas.width = 1248; ctx2.canvas.height = 2028; @@ -17520,19 +18301,19 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ctx2.canvas.width = 2028; ctx2.canvas.height = 1248; } - core.drawImage(ctx2, this.heroImage, 0, 168, 750, 1080) + core.drawImage(ctx2, this.heroImage, 0, 168, 750, 1080); ctx2.restore(); } movehero() { - boss2.style.display = "block" - core.clearMap(ctx2) + boss2.style.display = "block"; + core.clearMap(ctx2); let time = 0, px = -200; return new Promise((resolve) => { core.registerAnimationFrame("moveheroImage", true, (temptime) => { if (temptime - time > 1000 / 60) { - time = temptime - core.clearMap(ctx2) + time = temptime; + core.clearMap(ctx2); if (core.domStyle.isVertical) { ctx2.canvas.width = 1248; ctx2.canvas.height = 2028; @@ -17543,30 +18324,30 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ctx2.canvas.width = 2028; ctx2.canvas.height = 1248; } - core.drawImage(ctx2, this.heroImage, px, 168, 750, 1080) - px += 10 + core.drawImage(ctx2, this.heroImage, px, 168, 750, 1080); + px += 10; ctx2.restore(); if (px >= 0) { - core.unregisterAnimationFrame("moveheroImage") - this.drawhero() - resolve() - + core.unregisterAnimationFrame("moveheroImage"); + this.drawhero(); + resolve(); } } - }) - }) + }); + }); } update() { - core.drawImage(ctx1, this.bg, 0, 0, 2028, 1248) - this.drawboss() - this.drawhero() - this.drawStatus() - let dodraw = false + core.drawImage(ctx1, this.bg, 0, 0, 2028, 1248); + this.drawboss(); + this.drawhero(); + this.drawStatus(); + let dodraw = false; for (let i = 0; i < this.enemy.length; i++) { - if (this.enemy[i].id && this.enemy[i].hp > 0) { dodraw = true } + if (this.enemy[i].id && this.enemy[i].hp > 0) { + dodraw = true; + } } - if (dodraw === true) this.drawenemy() - + if (dodraw === true) this.drawenemy(); } playanimate(name, x, y, scalex = 10, scaley = 10) { const one = { @@ -17575,18 +18356,16 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = y: y, scalex: scalex, scaley: scaley, - farme: 0 - - } - let time = 0 - boss6.style.display = "block" + farme: 0, + }; + let time = 0; + boss6.style.display = "block"; return new Promise((resolve) => { core.registerAnimationFrame("animateboss", true, (timestamp) => { if (timestamp - time > 1000 / 60) { time = timestamp; core.clearMap(ctx6); - const data = flags["animate_" + one.name]; if (core.domStyle.isVertical) { ctx6.canvas.width = 1248; @@ -17600,9 +18379,8 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = } if (!data) { - - core.unregisterAnimationFrame("animateboss") - resolve() + core.unregisterAnimationFrame("animateboss"); + resolve(); } else { data.imageList.forEach(function (image) { if ( @@ -17634,12 +18412,14 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = (afterfarme - beforefarme || 1), cw = (image.cw ?? img.width) + - (((image.acw ?? img.width) - (image.cw ?? img.width)) * + (((image.acw ?? img.width) - + (image.cw ?? img.width)) * (one.farme - beforefarme)) / (afterfarme - beforefarme || 1), ch = (image.ch ?? img.height) + - (((image.acw ?? img.height) - (image.cw ?? img.height)) * + (((image.acw ?? img.height) - + (image.cw ?? img.height)) * (one.farme - beforefarme)) / (afterfarme - beforefarme || 1), x = @@ -17659,18 +18439,19 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = (afterfarme - beforefarme || 1), h = (image.h ?? one.height) + - (((image.aw ?? one.height) - (image.w ?? one.height)) * + (((image.aw ?? one.height) - + (image.w ?? one.height)) * (one.farme - beforefarme)) / (afterfarme - beforefarme || 1), angle = (Math.PI * ((image.image.angle ?? 0) + - (((image.aangle ?? 0) - (image.image.angle ?? 0)) * + (((image.aangle ?? 0) - + (image.image.angle ?? 0)) * (one.farme - beforefarme)) / (afterfarme - beforefarme || 1))) / 180; - core.drawImage( ctx6, img, @@ -17685,7 +18466,6 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = angle ); } - } }); data.soundList.forEach(function (sound) { @@ -17701,20 +18481,18 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = one.farme++; ctx6.restore(); if (one.farme > data.allFarme) { - core.clearMap(ctx6) - core.unregisterAnimationFrame("animateboss") - resolve() + core.clearMap(ctx6); + core.unregisterAnimationFrame("animateboss"); + resolve(); } } } }); - - }) - + }); } drawboss() { - core.clearMap(ctx3) + core.clearMap(ctx3); if (core.domStyle.isVertical) { ctx3.canvas.width = 1248; ctx3.canvas.height = 2028; @@ -17726,23 +18504,30 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ctx3.canvas.height = 1248; } if (this.selection === "boss" || this.selection === "") { - core.drawImage(ctx3, this.boss.image, 1400, 168, 750, 1080) + core.drawImage(ctx3, this.boss.image, 1400, 168, 750, 1080); } else { - core.drawImage(ctx3, this.enemy[this.selection].image, 1400, 168, 750, 1080) + core.drawImage( + ctx3, + this.enemy[this.selection].image, + 1400, + 168, + 750, + 1080 + ); } ctx3.restore(); } moveboss() { - boss3.style.display = "block" - core.clearMap(ctx3) + boss3.style.display = "block"; + core.clearMap(ctx3); let time = 0, px = 1600; return new Promise((resolve) => { core.registerAnimationFrame("movebossImage", true, (temptime) => { if (temptime - time > 1000 / 60) { - time = temptime - core.clearMap(ctx3) + time = temptime; + core.clearMap(ctx3); if (core.domStyle.isVertical) { ctx3.canvas.width = 1248; ctx3.canvas.height = 2028; @@ -17753,22 +18538,20 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ctx3.canvas.width = 2028; ctx3.canvas.height = 1248; } - core.drawImage(ctx3, this.boss.image, px, 168, 750, 1080) - px -= 10 + core.drawImage(ctx3, this.boss.image, px, 168, 750, 1080); + px -= 10; ctx3.restore(); if (px <= 1400) { - core.unregisterAnimationFrame("movebossImage") - this.drawboss() - resolve() - + core.unregisterAnimationFrame("movebossImage"); + this.drawboss(); + resolve(); } } - }) - }) + }); + }); } drawStatus() { - - core.clearMap(ctx4) + core.clearMap(ctx4); if (core.domStyle.isVertical) { ctx4.canvas.width = 1248; ctx4.canvas.height = 2028; @@ -17779,7 +18562,18 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ctx4.canvas.width = 2028; ctx4.canvas.height = 1248; } - core.drawWindowSkin("winskin.webp", ctx4, 600, 920, 900, 300, null, null, null, 3) + core.drawWindowSkin( + "winskin.webp", + ctx4, + 600, + 920, + 900, + 300, + null, + null, + null, + 3 + ); core.fillBoldText1( ctx4, hero.name, @@ -17802,7 +18596,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ); core.fillBoldText1( ctx4, - '生命 ' + this.hero.hp, + "生命 " + this.hero.hp, 630, 1070, "#FFFFFF", @@ -17812,7 +18606,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ); core.fillBoldText1( ctx4, - '攻击 ' + this.hero.atk, + "攻击 " + this.hero.atk, 630, 1120, "#FFFFFF", @@ -17822,7 +18616,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ); core.fillBoldText1( ctx4, - '防御 ' + this.hero.def, + "防御 " + this.hero.def, 630, 1170, "#FFFFFF", @@ -17832,7 +18626,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ); core.fillBoldText1( ctx4, - '法强 ' + this.hero.spell, + "法强 " + this.hero.spell, 1080, 1070, "#FFFFFF", @@ -17842,7 +18636,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ); core.fillBoldText1( ctx4, - '法抗 ' + this.hero.mdef + "%", + "法抗 " + this.hero.mdef + "%", 1080, 1120, "#FFFFFF", @@ -17852,7 +18646,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ); core.fillBoldText1( ctx4, - '速度 ' + this.hero.speed, + "速度 " + this.hero.speed, 1080, 1170, "#FFFFFF", @@ -17860,12 +18654,11 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = 6, core.ui._buildFont(44, true) ); - let posx = 980 - this.herobuff.forEach(v => { + let posx = 980; + this.herobuff.forEach((v) => { if (v) { - - core.drawIcon(ctx4, v.id, posx, 950, 64, 64) - core.setTextAlign(ctx4, "right") + core.drawIcon(ctx4, v.id, posx, 950, 64, 64); + core.setTextAlign(ctx4, "right"); core.fillBoldText1( ctx4, v.count, @@ -17876,13 +18669,24 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = 6, core.ui._buildFont(24, true) ); - core.setTextAlign(ctx4, "left") - posx += 80 + core.setTextAlign(ctx4, "left"); + posx += 80; } - }) + }); if (this.selection === "boss" || !this.hasEnemy()) { - core.drawWindowSkin("winskin.webp", ctx4, 50, 50, 1900, 200, null, null, null, 3) + core.drawWindowSkin( + "winskin.webp", + ctx4, + 50, + 50, + 1900, + 200, + null, + null, + null, + 3 + ); core.fillBoldText1( ctx4, this.boss.name, @@ -17913,7 +18717,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = 6, core.ui._buildFont(44, true) ); - const bosstext = this.boss.skill[this.boss.index] + const bosstext = this.boss.skill[this.boss.index]; core.fillBoldText1( ctx4, bosstext, @@ -17973,14 +18777,12 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = "#000000", 6, core.ui._buildFont(44, true) - ); - let posx = 600 - this.bossbuff.forEach(v => { + let posx = 600; + this.bossbuff.forEach((v) => { if (v) { - - core.drawIcon(ctx4, v.id, posx, 80, 64, 64) - core.setTextAlign(ctx4, "right") + core.drawIcon(ctx4, v.id, posx, 80, 64, 64); + core.setTextAlign(ctx4, "right"); core.fillBoldText1( ctx4, v.count, @@ -17991,12 +18793,23 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = 6, core.ui._buildFont(24, true) ); - core.setTextAlign(ctx4, "left") - posx += 80 + core.setTextAlign(ctx4, "left"); + posx += 80; } - }) + }); } else if (this.selection === "") {} else { - core.drawWindowSkin("winskin.webp", ctx4, 50, 50, 1900, 200, null, null, null, 3) + core.drawWindowSkin( + "winskin.webp", + ctx4, + 50, + 50, + 1900, + 200, + null, + null, + null, + 3 + ); core.fillBoldText1( ctx4, this.enemy[this.selection].name, @@ -18027,7 +18840,8 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = 6, core.ui._buildFont(44, true) ); - const enemytext = this.enemy[this.selection].skill[this.enemy[this.selection].index] + const enemytext = + this.enemy[this.selection].skill[this.enemy[this.selection].index]; core.fillBoldText1( ctx4, enemytext, @@ -18087,14 +18901,12 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = "#000000", 6, core.ui._buildFont(44, true) - ); - let posx = 600 - this.enemybuff[this.selection].forEach(v => { + let posx = 600; + this.enemybuff[this.selection].forEach((v) => { if (v) { - - core.drawIcon(ctx4, v.id, posx, 80, 64, 64) - core.setTextAlign(ctx4, "right") + core.drawIcon(ctx4, v.id, posx, 80, 64, 64); + core.setTextAlign(ctx4, "right"); core.fillBoldText1( ctx4, v.count, @@ -18105,22 +18917,22 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = 6, core.ui._buildFont(24, true) ); - core.setTextAlign(ctx4, "left") - posx += 80 + core.setTextAlign(ctx4, "left"); + posx += 80; } - }) + }); } ctx4.restore(); } moveStatus() { - boss4.style.display = "block" + boss4.style.display = "block"; let time = 0, posy = 400; return new Promise((resolve) => { core.registerAnimationFrame("moveStatus", true, (temptime) => { if (temptime - time > 1000 / 60) { - time = temptime - core.clearMap(ctx4) + time = temptime; + core.clearMap(ctx4); if (core.domStyle.isVertical) { ctx4.canvas.width = 1248; ctx4.canvas.height = 2028; @@ -18131,7 +18943,18 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ctx4.canvas.width = 2028; ctx4.canvas.height = 1248; } - core.drawWindowSkin("winskin.webp", ctx4, 600, 920 + posy, 900, 300, null, null, null, 3) + core.drawWindowSkin( + "winskin.webp", + ctx4, + 600, + 920 + posy, + 900, + 300, + null, + null, + null, + 3 + ); core.fillBoldText1( ctx4, hero.name, @@ -18154,7 +18977,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ); core.fillBoldText1( ctx4, - '生命 ' + this.hero.hp, + "生命 " + this.hero.hp, 630, 1070 + posy, "#FFFFFF", @@ -18164,7 +18987,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ); core.fillBoldText1( ctx4, - '攻击 ' + this.hero.atk, + "攻击 " + this.hero.atk, 630, 1120 + posy, "#FFFFFF", @@ -18174,7 +18997,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ); core.fillBoldText1( ctx4, - '防御 ' + this.hero.def, + "防御 " + this.hero.def, 630, 1170 + posy, "#FFFFFF", @@ -18184,7 +19007,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ); core.fillBoldText1( ctx4, - '法强 ' + this.hero.spell, + "法强 " + this.hero.spell, 1080, 1070 + posy, "#FFFFFF", @@ -18194,7 +19017,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ); core.fillBoldText1( ctx4, - '法抗 ' + this.hero.mdef + "%", + "法抗 " + this.hero.mdef + "%", 1080, 1120 + posy, "#FFFFFF", @@ -18204,7 +19027,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ); core.fillBoldText1( ctx4, - '速度 ' + this.hero.speed, + "速度 " + this.hero.speed, 1080, 1170 + posy, "#FFFFFF", @@ -18212,12 +19035,11 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = 6, core.ui._buildFont(44, true) ); - let posx = 980 - this.herobuff.forEach(v => { + let posx = 980; + this.herobuff.forEach((v) => { if (v) { - - core.drawIcon(ctx4, v.id, posx, 950 + posy, 64, 64) - core.setTextAlign(ctx4, "right") + core.drawIcon(ctx4, v.id, posx, 950 + posy, 64, 64); + core.setTextAlign(ctx4, "right"); core.fillBoldText1( ctx4, v.count, @@ -18228,12 +19050,23 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = 6, core.ui._buildFont(24, true) ); - core.setTextAlign(ctx4, "left") - posx += 80 + core.setTextAlign(ctx4, "left"); + posx += 80; } - }) + }); if (this.selection === "boss") { - core.drawWindowSkin("winskin.webp", ctx4, 50, 50 - posy / 2, 1900, 200, null, null, null, 3) + core.drawWindowSkin( + "winskin.webp", + ctx4, + 50, + 50 - posy / 2, + 1900, + 200, + null, + null, + null, + 3 + ); core.fillBoldText1( ctx4, this.boss.name, @@ -18303,14 +19136,12 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = "#000000", 6, core.ui._buildFont(44, true) - ); - let posx = 600 - this.bossbuff.forEach(v => { + let posx = 600; + this.bossbuff.forEach((v) => { if (v) { - - core.drawIcon(ctx4, v.id, posx, 80 - posy / 2, 64, 64) - core.setTextAlign(ctx4, "right") + core.drawIcon(ctx4, v.id, posx, 80 - posy / 2, 64, 64); + core.setTextAlign(ctx4, "right"); core.fillBoldText1( ctx4, v.count, @@ -18321,12 +19152,23 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = 6, core.ui._buildFont(24, true) ); - core.setTextAlign(ctx4, "left") - posx += 80 + core.setTextAlign(ctx4, "left"); + posx += 80; } - }) + }); } else if (this.selection === "") {} else { - core.drawWindowSkin("winskin.webp", ctx4, 50, 50 - posy / 2, 1900, 200, null, null, null, 3) + core.drawWindowSkin( + "winskin.webp", + ctx4, + 50, + 50 - posy / 2, + 1900, + 200, + null, + null, + null, + 3 + ); core.fillBoldText1( ctx4, this.enemy[this.selection].name, @@ -18396,14 +19238,12 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = "#000000", 6, core.ui._buildFont(44, true) - ); - let posx = 600 - this.enemybuff[this.selection].forEach(v => { + let posx = 600; + this.enemybuff[this.selection].forEach((v) => { if (v) { - - core.drawIcon(ctx4, v.id, posx, 80 - posy / 2, 64, 64) - core.setTextAlign(ctx4, "right") + core.drawIcon(ctx4, v.id, posx, 80 - posy / 2, 64, 64); + core.setTextAlign(ctx4, "right"); core.fillBoldText1( ctx4, v.count, @@ -18414,30 +19254,30 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = 6, core.ui._buildFont(24, true) ); - core.setTextAlign(ctx4, "left") - posx += 80 + core.setTextAlign(ctx4, "left"); + posx += 80; } - }) + }); } ctx4.restore(); - posy -= 10 + posy -= 10; if (posy <= 0) { - core.unregisterAnimationFrame("moveStatus") - this.drawStatus() - resolve() + core.unregisterAnimationFrame("moveStatus"); + this.drawStatus(); + resolve(); } } - }) - }) + }); + }); } close() { let globalAlpha = 0, - time = 0 + time = 0; return new Promise((resolve) => { core.registerAnimationFrame("closeblack", true, (temptime) => { if (temptime - time > 1000 / 60) { - time = temptime - core.clearMap(ctx) + time = temptime; + core.clearMap(ctx); if (core.domStyle.isVertical) { ctx.canvas.width = 1248; ctx.canvas.height = 2028; @@ -18449,30 +19289,29 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ctx.canvas.height = 1248; } - ctx.globalAlpha = globalAlpha; core.fillRect(ctx, 0, 0, 2028, 1248); - globalAlpha += 1 / 30 + globalAlpha += 1 / 30; ctx.restore(); if (globalAlpha > 1) { - time = 0 - globalAlpha = 1 - core.unregisterAnimationFrame("closeblack") - core.unregisterAnimationFrame('enemyanimate') - boss1.style.display = 'none' - boss2.style.display = 'none' - boss3.style.display = 'none' - boss4.style.display = 'none' - boss5.style.display = 'none' - boss6.style.display = 'none' - boss7.style.display = 'none' - boss8.style.display = 'none' + time = 0; + globalAlpha = 1; + core.unregisterAnimationFrame("closeblack"); + core.unregisterAnimationFrame("enemyanimate"); + boss1.style.display = "none"; + boss2.style.display = "none"; + boss3.style.display = "none"; + boss4.style.display = "none"; + boss5.style.display = "none"; + boss6.style.display = "none"; + boss7.style.display = "none"; + boss8.style.display = "none"; core.registerAnimationFrame("closeblack2", true, (temptime) => { if (temptime - time > 1000 / 60) { - time = temptime - core.clearMap(ctx) + time = temptime; + core.clearMap(ctx); if (core.domStyle.isVertical) { ctx.canvas.width = 1248; ctx.canvas.height = 2028; @@ -18483,35 +19322,35 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ctx.canvas.width = 2028; ctx.canvas.height = 1248; } - ctx.globalAlpha = globalAlpha + ctx.globalAlpha = globalAlpha; core.fillRect(ctx, 0, 0, 2028, 1248, "#000000"); ctx.restore(); - globalAlpha -= 1 / 30 + globalAlpha -= 1 / 30; if (globalAlpha < 0) { - core.unregisterAnimationFrame("closeblack2") + core.unregisterAnimationFrame("closeblack2"); - boss.style.display = 'none' + boss.style.display = "none"; - resolve() + resolve(); } } - }) + }); } } - }) - }) + }); + }); } blackBg() { let globalAlpha = 0, time = 0, img = core.material.images.images[this.bg]; - boss1.style.display = 'block' + boss1.style.display = "block"; return new Promise((resolve) => { core.registerAnimationFrame("bossblack", true, (temptime) => { if (temptime - time > 1000 / 60) { - time = temptime - core.clearMap(ctx1) + time = temptime; + core.clearMap(ctx1); if (core.domStyle.isVertical) { ctx1.canvas.width = 1248; ctx1.canvas.height = 2028; @@ -18523,20 +19362,19 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ctx1.canvas.height = 1248; } - ctx1.globalAlpha = globalAlpha; core.fillRect(ctx1, 0, 0, 2028, 1248); - globalAlpha += 1 / 30 + globalAlpha += 1 / 30; ctx1.restore(); if (globalAlpha > 1) { - time = 0 - globalAlpha = 0 - core.unregisterAnimationFrame("bossblack") + time = 0; + globalAlpha = 0; + core.unregisterAnimationFrame("bossblack"); core.registerAnimationFrame("bossBg", true, (temptime) => { if (temptime - time > 1000 / 60) { - time = temptime - core.clearMap(ctx1) + time = temptime; + core.clearMap(ctx1); if (core.domStyle.isVertical) { ctx1.canvas.width = 1248; ctx1.canvas.height = 2028; @@ -18548,28 +19386,25 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ctx1.canvas.height = 1248; } - ctx1.globalAlpha = 1 + ctx1.globalAlpha = 1; core.fillRect(ctx1, 0, 0, 2028, 1248); - ctx1.globalAlpha = globalAlpha + ctx1.globalAlpha = globalAlpha; if (img) ctx1.drawImage(img, 0, 0, 2028, 1248); ctx1.restore(); - globalAlpha += 1 / 30 + globalAlpha += 1 / 30; if (globalAlpha > 1) { - core.unregisterAnimationFrame("bossBg") - resolve() + core.unregisterAnimationFrame("bossBg"); + resolve(); } } - }) + }); } } - }) - }) + }); + }); } } - core.ui.boss = new Boss() - - - + core.ui.boss = new Boss(); }, "剧情视频引用": function () { // 在此增加新插件 @@ -18755,127 +19590,127 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = }; }, "帧动画/图片叠拼": function () { - // 在此增加新插件 - this.animationDrawable = function ( - allFarme, - color, - globalAlpha, - imageList, - soundList - ) { - if (!core.isPlaying()) { - return core.doAction(); - } - const over = main.dom.over; - const ctx = over.getContext("2d"); - over.style.display = "block"; + // 在此增加新插件 + this.animationDrawable = function ( + allFarme, + color, + globalAlpha, + imageList, + soundList + ) { + if (!core.isPlaying()) { + return core.doAction(); + } + const over = main.dom.over; + const ctx = over.getContext("2d"); + over.style.display = "block"; - let farme = 0; - let now = 0; - core.registerAnimationFrame( - "animationDrawable", - true, - function (timestamp) { - if (timestamp - now > 1000 / 60) { - now = timestamp; - if (core.domStyle.isVertical) { - over.width = 1248; - over.height = 2028; - ctx.save(); //保存设置 - ctx.translate(1248, 0); //重新定位右上角为基准 - ctx.rotate(Math.PI / 2); //旋转90度 - } else { - over.width = 2028; - over.height = 1248; - } + let farme = 0; + let now = 0; + core.registerAnimationFrame( + "animationDrawable", + true, + function (timestamp) { + if (timestamp - now > 1000 / 60) { + now = timestamp; + if (core.domStyle.isVertical) { + over.width = 1248; + over.height = 2028; + ctx.save(); //保存设置 + ctx.translate(1248, 0); //重新定位右上角为基准 + ctx.rotate(Math.PI / 2); //旋转90度 + } else { + over.width = 2028; + over.height = 1248; + } - ctx.globalAlpha = (globalAlpha ?? 100) / 100; - core.fillRect(ctx, 0, 0, 2028, 1248, color); + ctx.globalAlpha = (globalAlpha ?? 100) / 100; + core.fillRect(ctx, 0, 0, 2028, 1248, color); - imageList.forEach(function (one) { - if ( - farme >= (one.beforefarme ?? 0) && - farme <= (one.afterfarme ?? allFarme) - ) { - const img = core.material.images.images?.[one.image]; - if (img) { - const gla = one.globalAlpha ?? 100; - const agla = one.aglobalAlpha ?? gla, - beforefarme = one.beforefarme ?? 0; - const afterfarme = one.afterfarme ?? allFarme; + imageList.forEach(function (one) { + if ( + farme >= (one.beforefarme ?? 0) && + farme <= (one.afterfarme ?? allFarme) + ) { + const img = core.material.images.images?.[one.image]; + if (img) { + const gla = one.globalAlpha ?? 100; + const agla = one.aglobalAlpha ?? gla, + beforefarme = one.beforefarme ?? 0; + const afterfarme = one.afterfarme ?? allFarme; - ctx.globalAlpha = - (gla + - ((agla - gla) * (farme - beforefarme)) / - (afterfarme - beforefarme || 1)) / - 100; + ctx.globalAlpha = + (gla + + ((agla - gla) * (farme - beforefarme)) / + (afterfarme - beforefarme || 1)) / + 100; - const cx = - (one.cx ?? 0) + - (((one.acx ?? 0) - (one.cx ?? 0)) * - (farme - beforefarme)) / - (afterfarme - beforefarme || 1), - cy = - (one.cy ?? 0) + - (((one.acy ?? 0) - (one.cy ?? 0)) * - (farme - beforefarme)) / - (afterfarme - beforefarme || 1), - cw = - (one.cw ?? img.width) + - (((one.acw ?? img.width) - (one.cw ?? img.width)) * - (farme - beforefarme)) / - (afterfarme - beforefarme || 1), - ch = - (one.ch ?? img.height) + - (((one.acw ?? img.height) - (one.cw ?? img.height)) * - (farme - beforefarme)) / - (afterfarme - beforefarme || 1), - x = - (one.x ?? 0) + - (((one.ax ?? 0) - (one.x ?? 0)) * (farme - beforefarme)) / - (afterfarme - beforefarme || 1), - y = - (one.y ?? 0) + - (((one.ay ?? 0) - (one.y ?? 0)) * (farme - beforefarme)) / - (afterfarme - beforefarme || 1), - w = - (one.w ?? 2028) + - (((one.aw ?? 2028) - (one.w ?? 2028)) * - (farme - beforefarme)) / - (afterfarme - beforefarme || 1), - h = - (one.h ?? 1248) + - (((one.aw ?? 1248) - (one.w ?? 1248)) * - (farme - beforefarme)) / - (afterfarme - beforefarme || 1); - ctx.drawImage(img, cx, cy, cw, ch, x, y, w, h); - } - } - }); - soundList.forEach(function (one) { - const lisen = - one.sound && - core.sounds[one.sound] && - core.musicStatus.soundStatus; - if (farme == one.startfarme && lisen) { - if (one.stopbefore) core.stopSound(); - core.playSound(one.sound); - } - }); - farme++; - ctx.globalAlpha = 1; - ctx.restore(); + const cx = + (one.cx ?? 0) + + (((one.acx ?? 0) - (one.cx ?? 0)) * + (farme - beforefarme)) / + (afterfarme - beforefarme || 1), + cy = + (one.cy ?? 0) + + (((one.acy ?? 0) - (one.cy ?? 0)) * + (farme - beforefarme)) / + (afterfarme - beforefarme || 1), + cw = + (one.cw ?? img.width) + + (((one.acw ?? img.width) - (one.cw ?? img.width)) * + (farme - beforefarme)) / + (afterfarme - beforefarme || 1), + ch = + (one.ch ?? img.height) + + (((one.acw ?? img.height) - (one.cw ?? img.height)) * + (farme - beforefarme)) / + (afterfarme - beforefarme || 1), + x = + (one.x ?? 0) + + (((one.ax ?? 0) - (one.x ?? 0)) * (farme - beforefarme)) / + (afterfarme - beforefarme || 1), + y = + (one.y ?? 0) + + (((one.ay ?? 0) - (one.y ?? 0)) * (farme - beforefarme)) / + (afterfarme - beforefarme || 1), + w = + (one.w ?? 2028) + + (((one.aw ?? 2028) - (one.w ?? 2028)) * + (farme - beforefarme)) / + (afterfarme - beforefarme || 1), + h = + (one.h ?? 1248) + + (((one.aw ?? 1248) - (one.w ?? 1248)) * + (farme - beforefarme)) / + (afterfarme - beforefarme || 1); + ctx.drawImage(img, cx, cy, cw, ch, x, y, w, h); + } + } + }); + soundList.forEach(function (one) { + const lisen = + one.sound && + core.sounds[one.sound] && + core.musicStatus.soundStatus; + if (farme == one.startfarme && lisen) { + if (one.stopbefore) core.stopSound(); + core.playSound(one.sound); + } + }); + farme++; + ctx.globalAlpha = 1; + ctx.restore(); - if (farme > allFarme) { - core.unregisterAnimationFrame("animationDrawable"); - over.style.display = "none"; - core.doAction(); - } - } - } - ); - }; -}, + if (farme > allFarme) { + core.unregisterAnimationFrame("animationDrawable"); + over.style.display = "none"; + core.doAction(); + } + } + } + ); + }; + }, "musicMode": function () { // 在此增加新插件 const music = document.createElement("canvas"); @@ -20091,547 +20926,551 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = }; }, "帧动画特效(游戏界面)": function () { - // 在此增加新插件 - const animate2 = document.createElement("canvas"); //画布设置 - animate2.style.zIndex = 91; - animate2.id = "animate2"; - animate2.classList.add("gameCanvas", "anti-aliasing"); - animate2.style.display = "block"; - animate2.width = 416; - animate2.height = 416; - animate2.style.width = core.__PIXELS__ * core.domStyle.scale + "px"; - animate2.style.height = core.__PIXELS__ * core.domStyle.scale + "px"; - main.dom.animate2 = animate2; - const anctx = animate2.getContext("2d"); + // 在此增加新插件 + const animate2 = document.createElement("canvas"); //画布设置 + animate2.style.zIndex = 91; + animate2.id = "animate2"; + animate2.classList.add("gameCanvas", "anti-aliasing"); + animate2.style.display = "block"; + animate2.width = 416; + animate2.height = 416; + animate2.style.width = core.__PIXELS__ * core.domStyle.scale + "px"; + animate2.style.height = core.__PIXELS__ * core.domStyle.scale + "px"; + main.dom.animate2 = animate2; + const anctx = animate2.getContext("2d"); - main.dom.gameDraw.appendChild(animate2); + main.dom.gameDraw.appendChild(animate2); - core.plugin.playing = new Set(); + core.plugin.playing = new Set(); - this.setanimate = function ( - name, - px, - py, - width, - height, - allFarme, - imageList, - soundList - ) { - const data = { - px: px, - py: py, - width: width, - height: height, - allFarme: allFarme, - imageList: imageList, - soundList: soundList, - }; - core.setFlag("animate_" + name, data); - }; - this.deleteanimate = function (name) { - core.setFlag("animate_" + name); - }; - let thistime = 0; - this.playanimate = function (name, x, y, hero, scalex, scaley, callback) { - const data = { - name: name, - x: x, - y: y, - hero: hero, - scalex: scalex, - scaley: scaley, - farme: 0, - callback, - }; + this.setanimate = function ( + name, + px, + py, + width, + height, + allFarme, + imageList, + soundList + ) { + const data = { + px: px, + py: py, + width: width, + height: height, + allFarme: allFarme, + imageList: imageList, + soundList: soundList, + }; + core.setFlag("animate_" + name, data); + }; + this.deleteanimate = function (name) { + core.setFlag("animate_" + name); + }; + let thistime = 0; + this.playanimate = function (name, x, y, hero, scalex, scaley, callback) { + const data = { + name: name, + x: x, + y: y, + hero: hero, + scalex: scalex, + scaley: scaley, + farme: 0, + callback, + }; - core.plugin.playing.add(data); - }; - core.registerAnimationFrame("animateonmap", true, function (timestamp) { - if (timestamp - thistime > 1000 / 30) { - thistime = timestamp; - core.clearMap(anctx); - core.plugin.playing.forEach((one) => { - const data = flags["animate_" + one.name]; - if (!data) { - core.plugin.playing.delete(one); - } else { - data.imageList.forEach(function (image) { - if ( - one.farme >= (image.beforefarme ?? 0) && - one.farme <= (image.afterfarme ?? data.allFarme) - ) { - const img = core.material.images.images?.[image.image]; - if (img) { - const gla = image.globalAlpha ?? 100; - const agla = image.aglobalAlpha ?? gla, - beforefarme = image.beforefarme ?? 0; - const afterfarme = image.afterfarme ?? data.allFarme; + core.plugin.playing.add(data); + }; + core.registerAnimationFrame("animateonmap", true, function (timestamp) { + if (timestamp - thistime > 1000 / 30) { + thistime = timestamp; + core.clearMap(anctx); + core.plugin.playing.forEach((one) => { + const data = flags["animate_" + one.name]; + if (!data) { + core.plugin.playing.delete(one); + } else { + data.imageList.forEach(function (image) { + if ( + one.farme >= (image.beforefarme ?? 0) && + one.farme <= (image.afterfarme ?? data.allFarme) + ) { + const img = core.material.images.images?.[image.image]; + if (img) { + const gla = image.globalAlpha ?? 100; + const agla = image.aglobalAlpha ?? gla, + beforefarme = image.beforefarme ?? 0; + const afterfarme = image.afterfarme ?? data.allFarme; - anctx.globalAlpha = - (gla + - ((agla - gla) * (one.farme - beforefarme)) / - (afterfarme - beforefarme || 1)) / - 100; + anctx.globalAlpha = + (gla + + ((agla - gla) * (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1)) / + 100; - const cx = - (image.cx ?? 0) + - (((image.acx ?? 0) - (image.cx ?? 0)) * - (one.farme - beforefarme)) / - (afterfarme - beforefarme || 1), - cy = - (image.cy ?? 0) + - (((image.acy ?? 0) - (image.cy ?? 0)) * - (one.farme - beforefarme)) / - (afterfarme - beforefarme || 1), - cw = - (image.cw ?? img.width) + - (((image.acw ?? img.width) - (image.cw ?? img.width)) * - (one.farme - beforefarme)) / - (afterfarme - beforefarme || 1), - ch = - (image.ch ?? img.height) + - (((image.acw ?? img.height) - (image.cw ?? img.height)) * - (one.farme - beforefarme)) / - (afterfarme - beforefarme || 1), - x = - (image.x ?? 0) + - (((image.ax ?? 0) - (image.x ?? 0)) * - (one.farme - beforefarme)) / - (afterfarme - beforefarme || 1), - y = - (image.y ?? 0) + - (((image.ay ?? 0) - (image.y ?? 0)) * - (one.farme - beforefarme)) / - (afterfarme - beforefarme || 1), - w = - (image.w ?? one.width) + - (((image.aw ?? one.width) - (image.w ?? one.width)) * - (one.farme - beforefarme)) / - (afterfarme - beforefarme || 1), - h = - (image.h ?? one.height) + - (((image.aw ?? one.height) - (image.w ?? one.height)) * - (one.farme - beforefarme)) / - (afterfarme - beforefarme || 1), - angle = - (Math.PI * - ((image.image.angle ?? 0) + - (((image.aangle ?? 0) - (image.image.angle ?? 0)) * - (one.farme - beforefarme)) / - (afterfarme - beforefarme || 1))) / - 180; + const cx = + (image.cx ?? 0) + + (((image.acx ?? 0) - (image.cx ?? 0)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + cy = + (image.cy ?? 0) + + (((image.acy ?? 0) - (image.cy ?? 0)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + cw = + (image.cw ?? img.width) + + (((image.acw ?? img.width) - (image.cw ?? img.width)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + ch = + (image.ch ?? img.height) + + (((image.acw ?? img.height) - (image.cw ?? img.height)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + x = + (image.x ?? 0) + + (((image.ax ?? 0) - (image.x ?? 0)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + y = + (image.y ?? 0) + + (((image.ay ?? 0) - (image.y ?? 0)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + w = + (image.w ?? one.width) + + (((image.aw ?? one.width) - (image.w ?? one.width)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + h = + (image.h ?? one.height) + + (((image.aw ?? one.height) - (image.w ?? one.height)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + angle = + (Math.PI * + ((image.image.angle ?? 0) + + (((image.aangle ?? 0) - (image.image.angle ?? 0)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1))) / + 180; - if (one.hero) { - let sx, sy; - if (core.status.heroMoving < 0) { - sx = 0; - sy = 0; - } else { - sx = - core.utils.scan[core.status.hero.loc.direction].x * - 4 * - core.status.heroMoving; - sy = - core.utils.scan[core.status.hero.loc.direction].y * - 4 * - core.status.heroMoving; - } - const herox = core.status.hero.loc.x * 32 + 16 + sx; - const heroy = core.status.hero.loc.y * 32 + 16 + sy; - core.drawImage( - anctx, - img, - cx, - cy, - cw, - ch, - herox + (x - data.px) * one.scalex, - heroy + (y - data.py) * one.scaley, - w * one.scalex, - h * one.scaley, - angle - ); - } else { - core.drawImage( - anctx, - img, - cx, - cy, - cw, - ch, - one.x + (x - data.px) * one.scalex, - one.y + (y - data.py) * one.scaley, - w * one.scalex, - h * one.scaley, - angle - ); - } - } - } - }); - data.soundList.forEach(function (sound) { - const lisen = - sound.sound && - core.sounds[sound.sound] && - core.musicStatus.soundStatus; - if (one.farme == sound.startfarme && lisen) { - if (sound.stopbefore) core.stopSound(); - core.playSound(sound.sound); - } - }); - one.farme++; - if (one.farme > data.allFarme) { - core.plugin.playing.delete(one); - if (one.callback) { - one.callback(); - } - } - } - }); - } - }); -}, + if (one.hero) { + let sx, sy; + if (core.status.heroMoving < 0) { + sx = 0; + sy = 0; + } else { + sx = + core.utils.scan[core.status.hero.loc.direction].x * + 4 * + core.status.heroMoving; + sy = + core.utils.scan[core.status.hero.loc.direction].y * + 4 * + core.status.heroMoving; + } + const herox = core.status.hero.loc.x * 32 + 16 + sx; + const heroy = core.status.hero.loc.y * 32 + 16 + sy; + core.drawImage( + anctx, + img, + cx, + cy, + cw, + ch, + herox + (x - data.px) * one.scalex, + heroy + (y - data.py) * one.scaley, + w * one.scalex, + h * one.scaley, + angle + ); + } else { + core.drawImage( + anctx, + img, + cx, + cy, + cw, + ch, + one.x + (x - data.px) * one.scalex, + one.y + (y - data.py) * one.scaley, + w * one.scalex, + h * one.scaley, + angle + ); + } + } + } + }); + data.soundList.forEach(function (sound) { + const lisen = + sound.sound && + core.sounds[sound.sound] && + core.musicStatus.soundStatus; + if (one.farme == sound.startfarme && lisen) { + if (sound.stopbefore) core.stopSound(); + core.playSound(sound.sound); + } + }); + one.farme++; + if (one.farme > data.allFarme) { + core.plugin.playing.delete(one); + if (one.callback) { + one.callback(); + } + } + } + }); + } + }); + }, "intro&loop": function () { - // 在此增加新插件 - this.introAndLoop = function (intro, time, loop) { - core.playBgm(intro); - setTimeout(() => { - core.playBgm(loop); - }, time * 1000); - }; -}, + // 在此增加新插件 + this.introAndLoop = function (intro, time, loop) { + core.playBgm(intro); + setTimeout(() => { + core.playBgm(loop); + }, time * 1000); + }; + }, "开局选项悬停": function () { - // 在此增加新插件 + // 在此增加新插件 - main.dom.playGame.addEventListener("mouseenter", () => { - core.dom.playGame.style.backgroundColor = "#808080"; - }); - main.dom.playGame.addEventListener("mouseleave", () => { - core.dom.playGame.style.backgroundColor = "transparent"; - }); - main.dom.playGame.addEventListener("touchmove", () => { - core.dom.playGame.style.backgroundColor = "#808080"; - }); - main.dom.playGame.addEventListener("touchend", () => { - core.dom.playGame.style.backgroundColor = "transparent"; - }); - main.dom.playGame.addEventListener("touchcancel", () => { - core.dom.playGame.style.backgroundColor = "transparent"; - }); + main.dom.playGame.addEventListener("mouseenter", () => { + core.dom.playGame.style.backgroundColor = "#808080"; + }); + main.dom.playGame.addEventListener("mouseleave", () => { + core.dom.playGame.style.backgroundColor = "transparent"; + }); + main.dom.playGame.addEventListener("touchmove", () => { + core.dom.playGame.style.backgroundColor = "#808080"; + }); + main.dom.playGame.addEventListener("touchend", () => { + core.dom.playGame.style.backgroundColor = "transparent"; + }); + main.dom.playGame.addEventListener("touchcancel", () => { + core.dom.playGame.style.backgroundColor = "transparent"; + }); - main.dom.loadGame.addEventListener("mouseenter", () => { - core.dom.loadGame.style.backgroundColor = "#808080"; - }); - main.dom.loadGame.addEventListener("mouseleave", () => { - core.dom.loadGame.style.backgroundColor = "transparent"; - }); - main.dom.loadGame.addEventListener("touchmove", () => { - core.dom.loadGame.style.backgroundColor = "#808080"; - }); - main.dom.loadGame.addEventListener("touchend", () => { - core.dom.loadGame.style.backgroundColor = "transparent"; - }); - main.dom.loadGame.addEventListener("touchcancel", () => { - core.dom.loadGame.style.backgroundColor = "transparent"; - }); + main.dom.loadGame.addEventListener("mouseenter", () => { + core.dom.loadGame.style.backgroundColor = "#808080"; + }); + main.dom.loadGame.addEventListener("mouseleave", () => { + core.dom.loadGame.style.backgroundColor = "transparent"; + }); + main.dom.loadGame.addEventListener("touchmove", () => { + core.dom.loadGame.style.backgroundColor = "#808080"; + }); + main.dom.loadGame.addEventListener("touchend", () => { + core.dom.loadGame.style.backgroundColor = "transparent"; + }); + main.dom.loadGame.addEventListener("touchcancel", () => { + core.dom.loadGame.style.backgroundColor = "transparent"; + }); - main.dom.CGMode.addEventListener("mouseenter", () => { - core.dom.CGMode.style.backgroundColor = "#808080"; - }); - main.dom.CGMode.addEventListener("mouseleave", () => { - core.dom.CGMode.style.backgroundColor = "transparent"; - }); - main.dom.CGMode.addEventListener("touchmove", () => { - core.dom.CGMode.style.backgroundColor = "#808080"; - }); - main.dom.CGMode.addEventListener("touchend", () => { - core.dom.CGMode.style.backgroundColor = "transparent"; - }); - main.dom.CGMode.addEventListener("touchcancel", () => { - core.dom.CGMode.style.backgroundColor = "transparent"; - }); + main.dom.CGMode.addEventListener("mouseenter", () => { + core.dom.CGMode.style.backgroundColor = "#808080"; + }); + main.dom.CGMode.addEventListener("mouseleave", () => { + core.dom.CGMode.style.backgroundColor = "transparent"; + }); + main.dom.CGMode.addEventListener("touchmove", () => { + core.dom.CGMode.style.backgroundColor = "#808080"; + }); + main.dom.CGMode.addEventListener("touchend", () => { + core.dom.CGMode.style.backgroundColor = "transparent"; + }); + main.dom.CGMode.addEventListener("touchcancel", () => { + core.dom.CGMode.style.backgroundColor = "transparent"; + }); - main.dom.musicMode.addEventListener("mouseenter", () => { - core.dom.musicMode.style.backgroundColor = "#808080"; - }); - main.dom.musicMode.addEventListener("mouseleave", () => { - core.dom.musicMode.style.backgroundColor = "transparent"; - }); - main.dom.musicMode.addEventListener("touchmove", () => { - core.dom.musicMode.style.backgroundColor = "#808080"; - }); - main.dom.musicMode.addEventListener("touchend", () => { - core.dom.musicMode.style.backgroundColor = "transparent"; - }); - main.dom.musicMode.addEventListener("touchcancel", () => { - core.dom.musicMode.style.backgroundColor = "transparent"; - }); + main.dom.musicMode.addEventListener("mouseenter", () => { + core.dom.musicMode.style.backgroundColor = "#808080"; + }); + main.dom.musicMode.addEventListener("mouseleave", () => { + core.dom.musicMode.style.backgroundColor = "transparent"; + }); + main.dom.musicMode.addEventListener("touchmove", () => { + core.dom.musicMode.style.backgroundColor = "#808080"; + }); + main.dom.musicMode.addEventListener("touchend", () => { + core.dom.musicMode.style.backgroundColor = "transparent"; + }); + main.dom.musicMode.addEventListener("touchcancel", () => { + core.dom.musicMode.style.backgroundColor = "transparent"; + }); - main.dom.replayGame.addEventListener("mouseenter", () => { - core.dom.replayGame.style.backgroundColor = "#808080"; - }); - main.dom.replayGame.addEventListener("mouseleave", () => { - core.dom.replayGame.style.backgroundColor = "transparent"; - }); - main.dom.replayGame.addEventListener("touchmove", () => { - core.dom.replayGame.style.backgroundColor = "#808080"; - }); - main.dom.replayGame.addEventListener("touchend", () => { - core.dom.replayGame.style.backgroundColor = "transparent"; - }); - main.dom.replayGame.addEventListener("touchcancel", () => { - core.dom.replayGame.style.backgroundColor = "transparent"; - }); -}, + main.dom.replayGame.addEventListener("mouseenter", () => { + core.dom.replayGame.style.backgroundColor = "#808080"; + }); + main.dom.replayGame.addEventListener("mouseleave", () => { + core.dom.replayGame.style.backgroundColor = "transparent"; + }); + main.dom.replayGame.addEventListener("touchmove", () => { + core.dom.replayGame.style.backgroundColor = "#808080"; + }); + main.dom.replayGame.addEventListener("touchend", () => { + core.dom.replayGame.style.backgroundColor = "transparent"; + }); + main.dom.replayGame.addEventListener("touchcancel", () => { + core.dom.replayGame.style.backgroundColor = "transparent"; + }); + }, "天气叠加": function () { - //使用方法:使用core.setWeather(天气,等级)来增加天气,使用core.setWeather()来清空天气 - // 天气叠加功能 - ////// 更改天气效果 ////// - control.prototype.setWeather = function (type, level) { - // 非雨雪 - if (type == null) { - Object.keys(core.control.weathers).forEach(function (one) { - core.deleteCanvas("weather" + one); - }); - core.animateFrame.weather.type = []; - core.animateFrame.weather.nodes = {}; - core.animateFrame.weather.level = {}; - core.animateFrame.weather.time = {}; - return; - } - if (!core.animateFrame.weather.level || level == null) - core.animateFrame.weather.level = {}; - if (!core.animateFrame.weather.type) core.animateFrame.weather.type = []; - level = core.clamp(parseInt(level) || 5, 1, 10); - // 当前天气:则忽略 - if ( - core.animateFrame.weather.type.includes(type) && - level == core.animateFrame.weather.level[type] - ) - return; - if (core.animateFrame.weather.nodes[type]) return; - // 计算当前的宽高 - core.createCanvas( - "weather" + type, - 0, - 0, - core.__PIXELS__, - core.__PIXELS__, - 80 - ); - core.animateFrame.weather.type.push(type); - core.animateFrame.weather.level[type] = level; - this._setWeather_createNodes(type, level); - }; - control.prototype._setWeather_createNodes = function (type, level) { - var number = - level * - parseInt( - (20 * core.bigmap.width * core.bigmap.height) / - (core.__SIZE__ * core.__SIZE__) - ); - if (!core.animateFrame.weather.nodes[type]) - core.animateFrame.weather.nodes[type] = []; - switch (type) { - case "rain": - for (var a = 0; a < number; a++) { - core.animateFrame.weather.nodes.rain.push({ - x: Math.random() * core.bigmap.width * 32, - y: Math.random() * core.bigmap.height * 32, - l: Math.random() * 2.5, - xs: -4 + Math.random() * 4 + 2, - ys: Math.random() * 10 + 10, - }); - } - break; - case "snow": - for (var a = 0; a < number; a++) { - core.animateFrame.weather.nodes.snow.push({ - x: Math.random() * core.bigmap.width * 32, - y: Math.random() * core.bigmap.height * 32, - r: Math.random() * 5 + 1, - d: Math.random() * Math.min(level, 200), - }); - } - break; - case "fog": - if (core.animateFrame.weather.fog) { - core.animateFrame.weather.nodes[type] = [{ - level: number, - x: 0, - y: -core.__PIXELS__ / 2, - dx: -Math.random() * 1.5, - dy: Math.random(), - delta: 0.001, - }, ]; - } - break; - case "cloud": - if (core.animateFrame.weather.cloud) { - core.animateFrame.weather.nodes[type] = [{ - level: number, - x: 0, - y: -core.__PIXELS__ / 2, - dx: -Math.random() * 1.5, - dy: Math.random(), - delta: 0.001, - }, ]; - } - break; - case "sun": - if (core.animateFrame.weather.sun) { - // 直接绘制 - core.clearMap("weather" + type); - core.setAlpha("weather" + type, level / 10); - core.drawImage( - "weather" + type, - core.animateFrame.weather.sun, - 0, - 0, - core.animateFrame.weather.sun.width, - core.animateFrame.weather.sun.height, - 0, - 0, - core.__PIXELS__, - core.__PIXELS__ - ); - core.setAlpha("weather" + type, 1); - } - break; - } - }; - core.registerAnimationFrame("weather", true, function (timestamp) { - var weather = core.animateFrame.weather; - if (!weather.type) return; - weather.type.forEach(function (one) { - if ( - timestamp - weather.time[one] <= 30 || - !core.dymCanvas["weather" + one] - ) - return; - core.control["_animationFrame_weather_" + one](); - weather.time[one] = timestamp; - }); - }); - // 雨 - control.prototype._animationFrame_weather_rain = function () { - var ctx = core.dymCanvas.weatherrain, - ox = core.bigmap.offsetX, - oy = core.bigmap.offsetY; - core.clearMap("weatherrain"); - ctx.strokeStyle = "rgba(174,194,224,0.8)"; - ctx.lineWidth = 1; - ctx.lineCap = "round"; - core.animateFrame.weather.nodes.rain.forEach(function (p) { - ctx.beginPath(); - ctx.moveTo(p.x - ox, p.y - oy); - ctx.lineTo(p.x + p.l * p.xs - ox, p.y + p.l * p.ys - oy); - ctx.stroke(); - p.x += p.xs; - p.y += p.ys; - if (p.x > core.bigmap.width * 32 || p.y > core.bigmap.height * 32) { - p.x = Math.random() * core.bigmap.width * 32; - p.y = -10; - } - }); - ctx.fill(); - }; - // 雪 - control.prototype._animationFrame_weather_snow = function () { - var ctx = core.dymCanvas.weathersnow, - ox = core.bigmap.offsetX, - oy = core.bigmap.offsetY; - core.clearMap("weathersnow"); - ctx.fillStyle = "rgba(255, 255, 255, 0.8)"; - ctx.beginPath(); - if (!core.animateFrame.weather.data) core.animateFrame.weather.data = {}; - core.animateFrame.weather.data.snow = - core.animateFrame.weather.data.snow || 0; - core.animateFrame.weather.data.snow += 0.01; - var angle = core.animateFrame.weather.data.snow; - core.animateFrame.weather.nodes.snow.forEach(function (p) { - ctx.moveTo(p.x - ox, p.y - oy); - ctx.arc(p.x - ox, p.y - oy, p.r, 0, Math.PI * 2, true); - // update - p.x += Math.sin(angle) * core.animateFrame.weather.level.snow; - p.y += Math.cos(angle + p.d) + 1 + p.r / 2; - if ( - p.x > core.bigmap.width * 32 + 5 || - p.x < -5 || - p.y > core.bigmap.height * 32 - ) { - if (Math.random() > 1 / 3) { - p.x = Math.random() * core.bigmap.width * 32; - p.y = -10; - } else { - if (Math.sin(angle) > 0) p.x = -5; - else p.x = core.bigmap.width * 32 + 5; - p.y = Math.random() * core.bigmap.height * 32; - } - } - }); - ctx.fill(); - }; - // 图片天气 - control.prototype.__animateFrame_weather_image = function (image, type) { - if (!image) return; - var node = core.animateFrame.weather.nodes[type][0]; - core.setAlpha("weather" + type, node.level / 500); - var wind = 1.5; - var width = image.width, - height = image.height; - node.x += node.dx * wind; - node.y += (2 * node.dy - 1) * wind; - if (node.x + 3 * width <= core.__PIXELS__) { - node.x += 4 * width; - while (node.x > 0) node.x -= width; - } - node.dy += node.delta; - if (node.dy >= 1) { - node.delta = -0.001; - } else if (node.dy <= 0) { - node.delta = 0.001; - } - if (node.y + 3 * height <= core.__PIXELS__) { - node.y += 4 * height; - while (node.y > 0) node.y -= height; - } else if (node.y >= 0) { - node.y -= height; - } - for (var i = 0; i < 3; ++i) { - for (var j = 0; j < 3; ++j) { - if ( - node.x + (i + 1) * width <= 0 || - node.x + i * width >= core.__PIXELS__ || - node.y + (j + 1) * height <= 0 || - node.y + j * height >= core.__PIXELS__ - ) - continue; - core.drawImage( - "weather" + type, - image, - node.x + i * width, - node.y + j * height - ); - } - } - core.setAlpha("weather" + type, 1); - }; - // 雾 - control.prototype._animationFrame_weather_fog = function () { - core.clearMap("weatherfog"); - this.__animateFrame_weather_image(core.animateFrame.weather.fog, "fog"); - }; - // 云 - control.prototype._animationFrame_weather_cloud = function () { - core.clearMap("weathercloud"); - this.__animateFrame_weather_image( - core.animateFrame.weather.cloud, - "cloud" - ); - }; -}, + //使用方法:使用core.setWeather(天气,等级)来增加天气,使用core.setWeather()来清空天气 + // 天气叠加功能 + ////// 更改天气效果 ////// + control.prototype.setWeather = function (type, level) { + // 非雨雪 + if (type == null) { + Object.keys(core.control.weathers).forEach(function (one) { + core.deleteCanvas("weather" + one); + }); + core.animateFrame.weather.type = []; + core.animateFrame.weather.nodes = {}; + core.animateFrame.weather.level = {}; + core.animateFrame.weather.time = {}; + return; + } + if (!core.animateFrame.weather.level || level == null) + core.animateFrame.weather.level = {}; + if (!core.animateFrame.weather.type) core.animateFrame.weather.type = []; + level = core.clamp(parseInt(level) || 5, 1, 10); + // 当前天气:则忽略 + if ( + core.animateFrame.weather.type.includes(type) && + level == core.animateFrame.weather.level[type] + ) + return; + if (core.animateFrame.weather.nodes[type]) return; + // 计算当前的宽高 + core.createCanvas( + "weather" + type, + 0, + 0, + core.__PIXELS__, + core.__PIXELS__, + 80 + ); + core.animateFrame.weather.type.push(type); + core.animateFrame.weather.level[type] = level; + this._setWeather_createNodes(type, level); + }; + control.prototype._setWeather_createNodes = function (type, level) { + var number = + level * + parseInt( + (20 * core.bigmap.width * core.bigmap.height) / + (core.__SIZE__ * core.__SIZE__) + ); + if (!core.animateFrame.weather.nodes[type]) + core.animateFrame.weather.nodes[type] = []; + switch (type) { + case "rain": + for (var a = 0; a < number; a++) { + core.animateFrame.weather.nodes.rain.push({ + x: Math.random() * core.bigmap.width * 32, + y: Math.random() * core.bigmap.height * 32, + l: Math.random() * 2.5, + xs: -4 + Math.random() * 4 + 2, + ys: Math.random() * 10 + 10, + }); + } + break; + case "snow": + for (var a = 0; a < number; a++) { + core.animateFrame.weather.nodes.snow.push({ + x: Math.random() * core.bigmap.width * 32, + y: Math.random() * core.bigmap.height * 32, + r: Math.random() * 5 + 1, + d: Math.random() * Math.min(level, 200), + }); + } + break; + case "fog": + if (core.animateFrame.weather.fog) { + core.animateFrame.weather.nodes[type] = [ + { + level: number, + x: 0, + y: -core.__PIXELS__ / 2, + dx: -Math.random() * 1.5, + dy: Math.random(), + delta: 0.001, + }, + ]; + } + break; + case "cloud": + if (core.animateFrame.weather.cloud) { + core.animateFrame.weather.nodes[type] = [ + { + level: number, + x: 0, + y: -core.__PIXELS__ / 2, + dx: -Math.random() * 1.5, + dy: Math.random(), + delta: 0.001, + }, + ]; + } + break; + case "sun": + if (core.animateFrame.weather.sun) { + // 直接绘制 + core.clearMap("weather" + type); + core.setAlpha("weather" + type, level / 10); + core.drawImage( + "weather" + type, + core.animateFrame.weather.sun, + 0, + 0, + core.animateFrame.weather.sun.width, + core.animateFrame.weather.sun.height, + 0, + 0, + core.__PIXELS__, + core.__PIXELS__ + ); + core.setAlpha("weather" + type, 1); + } + break; + } + }; + core.registerAnimationFrame("weather", true, function (timestamp) { + var weather = core.animateFrame.weather; + if (!weather.type) return; + weather.type.forEach(function (one) { + if ( + timestamp - weather.time[one] <= 30 || + !core.dymCanvas["weather" + one] + ) + return; + core.control["_animationFrame_weather_" + one](); + weather.time[one] = timestamp; + }); + }); + // 雨 + control.prototype._animationFrame_weather_rain = function () { + var ctx = core.dymCanvas.weatherrain, + ox = core.bigmap.offsetX, + oy = core.bigmap.offsetY; + core.clearMap("weatherrain"); + ctx.strokeStyle = "rgba(174,194,224,0.8)"; + ctx.lineWidth = 1; + ctx.lineCap = "round"; + core.animateFrame.weather.nodes.rain.forEach(function (p) { + ctx.beginPath(); + ctx.moveTo(p.x - ox, p.y - oy); + ctx.lineTo(p.x + p.l * p.xs - ox, p.y + p.l * p.ys - oy); + ctx.stroke(); + p.x += p.xs; + p.y += p.ys; + if (p.x > core.bigmap.width * 32 || p.y > core.bigmap.height * 32) { + p.x = Math.random() * core.bigmap.width * 32; + p.y = -10; + } + }); + ctx.fill(); + }; + // 雪 + control.prototype._animationFrame_weather_snow = function () { + var ctx = core.dymCanvas.weathersnow, + ox = core.bigmap.offsetX, + oy = core.bigmap.offsetY; + core.clearMap("weathersnow"); + ctx.fillStyle = "rgba(255, 255, 255, 0.8)"; + ctx.beginPath(); + if (!core.animateFrame.weather.data) core.animateFrame.weather.data = {}; + core.animateFrame.weather.data.snow = + core.animateFrame.weather.data.snow || 0; + core.animateFrame.weather.data.snow += 0.01; + var angle = core.animateFrame.weather.data.snow; + core.animateFrame.weather.nodes.snow.forEach(function (p) { + ctx.moveTo(p.x - ox, p.y - oy); + ctx.arc(p.x - ox, p.y - oy, p.r, 0, Math.PI * 2, true); + // update + p.x += Math.sin(angle) * core.animateFrame.weather.level.snow; + p.y += Math.cos(angle + p.d) + 1 + p.r / 2; + if ( + p.x > core.bigmap.width * 32 + 5 || + p.x < -5 || + p.y > core.bigmap.height * 32 + ) { + if (Math.random() > 1 / 3) { + p.x = Math.random() * core.bigmap.width * 32; + p.y = -10; + } else { + if (Math.sin(angle) > 0) p.x = -5; + else p.x = core.bigmap.width * 32 + 5; + p.y = Math.random() * core.bigmap.height * 32; + } + } + }); + ctx.fill(); + }; + // 图片天气 + control.prototype.__animateFrame_weather_image = function (image, type) { + if (!image) return; + var node = core.animateFrame.weather.nodes[type][0]; + core.setAlpha("weather" + type, node.level / 500); + var wind = 1.5; + var width = image.width, + height = image.height; + node.x += node.dx * wind; + node.y += (2 * node.dy - 1) * wind; + if (node.x + 3 * width <= core.__PIXELS__) { + node.x += 4 * width; + while (node.x > 0) node.x -= width; + } + node.dy += node.delta; + if (node.dy >= 1) { + node.delta = -0.001; + } else if (node.dy <= 0) { + node.delta = 0.001; + } + if (node.y + 3 * height <= core.__PIXELS__) { + node.y += 4 * height; + while (node.y > 0) node.y -= height; + } else if (node.y >= 0) { + node.y -= height; + } + for (var i = 0; i < 3; ++i) { + for (var j = 0; j < 3; ++j) { + if ( + node.x + (i + 1) * width <= 0 || + node.x + i * width >= core.__PIXELS__ || + node.y + (j + 1) * height <= 0 || + node.y + j * height >= core.__PIXELS__ + ) + continue; + core.drawImage( + "weather" + type, + image, + node.x + i * width, + node.y + j * height + ); + } + } + core.setAlpha("weather" + type, 1); + }; + // 雾 + control.prototype._animationFrame_weather_fog = function () { + core.clearMap("weatherfog"); + this.__animateFrame_weather_image(core.animateFrame.weather.fog, "fog"); + }; + // 云 + control.prototype._animationFrame_weather_cloud = function () { + core.clearMap("weathercloud"); + this.__animateFrame_weather_image( + core.animateFrame.weather.cloud, + "cloud" + ); + }; + }, "回合战斗动画": function () { // 在此增加新插件 const animateAttack = document.createElement("canvas"); //画布设置 @@ -20645,10 +21484,10 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = animateAttack.style.height = core.__PIXELS__ * core.domStyle.scale + "px"; main.dom.animateAttack = animateAttack; const ctx = animateAttack.getContext("2d"); - core.plugin.playingattack = new Set() - const ctx6 = main.dom.animate2.getContext('2d') - let easy = false - const { imagelighter } = core.plugin.utils + core.plugin.playingattack = new Set(); + const ctx6 = main.dom.animate2.getContext("2d"); + let easy = false; + const { imagelighter } = core.plugin.utils; function playanimate(name, x, y, scalex = 1, scaley = 1) { const data = { @@ -20657,15 +21496,14 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = y: y, scalex: scalex, scaley: scaley, - farme: 0 - - } - core.plugin.playingattack.add(data) + farme: 0, + }; + core.plugin.playingattack.add(data); } function playinganimate() { - let time = 0 - if (core.plugin.playingattack.size === 0) return Promise.resolve() + let time = 0; + if (core.plugin.playingattack.size === 0) return Promise.resolve(); return new Promise((resolve) => { core.registerAnimationFrame("animateenemyattack", true, (timestamp) => { if (timestamp - time > 1000 / 60) { @@ -20678,8 +21516,8 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = if (!data) { core.plugin.playingattack.delete(one); if (core.plugin.playingattack.size === 0) { - core.unregisterAnimationFrame("animateenemyattack") - resolve() + core.unregisterAnimationFrame("animateenemyattack"); + resolve(); } } else { data.imageList.forEach(function (image) { @@ -20712,12 +21550,14 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = (afterfarme - beforefarme || 1), cw = (image.cw ?? img.width) + - (((image.acw ?? img.width) - (image.cw ?? img.width)) * + (((image.acw ?? img.width) - + (image.cw ?? img.width)) * (one.farme - beforefarme)) / (afterfarme - beforefarme || 1), ch = (image.ch ?? img.height) + - (((image.acw ?? img.height) - (image.cw ?? img.height)) * + (((image.acw ?? img.height) - + (image.cw ?? img.height)) * (one.farme - beforefarme)) / (afterfarme - beforefarme || 1), x = @@ -20737,18 +21577,19 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = (afterfarme - beforefarme || 1), h = (image.h ?? one.height) + - (((image.aw ?? one.height) - (image.w ?? one.height)) * + (((image.aw ?? one.height) - + (image.w ?? one.height)) * (one.farme - beforefarme)) / (afterfarme - beforefarme || 1), angle = (Math.PI * ((image.image.angle ?? 0) + - (((image.aangle ?? 0) - (image.image.angle ?? 0)) * + (((image.aangle ?? 0) - + (image.image.angle ?? 0)) * (one.farme - beforefarme)) / (afterfarme - beforefarme || 1))) / 180; - core.drawImage( ctx6, img, @@ -20763,7 +21604,6 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = angle ); } - } }); data.soundList.forEach(function (sound) { @@ -20779,25 +21619,22 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = one.farme++; ctx6.restore(); if (one.farme > data.allFarme) { - core.clearMap(ctx6) - core.plugin.playingattack.delete(one) + core.clearMap(ctx6); + core.plugin.playingattack.delete(one); if (core.plugin.playingattack.size === 0) { - core.unregisterAnimationFrame("animateenemyattack") - resolve() + core.unregisterAnimationFrame("animateenemyattack"); + resolve(); } } } - }) + }); } }); - - }) - + }); } - main.dom.gameDraw.appendChild(animateAttack); - const { lcm, gcd } = core.plugin.utils + const { lcm, gcd } = core.plugin.utils; function animateOnAttack(name, onenemy) { if (onenemy) { @@ -20823,15 +21660,15 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = core.lockControl(); core.clearMap(ctx); core.status.event.id = "attackAnimate"; - let turn = 0 + let turn = 0; enemyInfo.id = enemyId; enemyInfo.cls = core.getClsFromId(enemyId); enemyInfo.name = core.material.enemys[enemyId].name; - if (oneTurn < 120) oneTurn *= Math.round(120 / oneTurn) + if (oneTurn < 120) oneTurn *= Math.round(120 / oneTurn); let time = 0, farme = 0; - return new Promise(res => { + return new Promise((res) => { core.plugin.battle_onclick = function (x, y, px, py) { const makeBox = ([x, y], [w, h]) => { return [ @@ -20851,17 +21688,20 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = uneasybox = makeBox([265, 330], [65, 20]), uneasyclosebox = makeBox([290, 350], [40, 20]); if (inRect(pos, easybox) && easy) { - easy = false + easy = false; } else if (inRect(pos, uneasybox) && !easy) { - easy = true - } else if ((inRect(pos, easyclosebox) && easy) || (inRect(pos, uneasyclosebox) && !easy)) { - core.status.event.id = '' - core.unregisterAnimationFrame("attackAnimate") - core.clearMap(ctx) - core.closePanel() - res() + easy = true; + } else if ( + (inRect(pos, easyclosebox) && easy) || + (inRect(pos, uneasyclosebox) && !easy) + ) { + core.status.event.id = ""; + core.unregisterAnimationFrame("attackAnimate"); + core.clearMap(ctx); + core.closePanel(); + res(); } - } + }; async function drawAttackAnimate( heroInfo, oneTurn, @@ -20872,11 +21712,10 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = heroDiffList, enemyDiffList, heroanimateList, - enemyanimateList, - + enemyanimateList ) { - core.lockControl() - core.status.event.id = 'battle' + core.lockControl(); + core.status.event.id = "battle"; let attack = false; if (heroInfo.isAttack) attack = true; @@ -20927,9 +21766,16 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = "bold 18px Verdana" ); - core.strokeRect(ctx, 112, 159, 32, 48, "rgba(255,255,255,1)", 1); - let img = attack && (heroDiffList[turn].hp < 0) ? imagelighter(core.material.images.images["hero.webp"]) : attack && (heroDiffList[turn].hp > 0) ? imagelighter(core.material.images.images["hero.webp"], 'rgba(0, 255, 0, 0.5)') : core.material.images.images["hero.webp"] + let img = + attack && heroDiffList[turn].hp < 0 ? + imagelighter(core.material.images.images["hero.webp"]) : + attack && heroDiffList[turn].hp > 0 ? + imagelighter( + core.material.images.images["hero.webp"], + "rgba(0, 255, 0, 0.5)" + ) : + core.material.images.images["hero.webp"]; core.drawImage( ctx, img, @@ -20957,7 +21803,15 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = core.setTextAlign(ctx, "right"); if (enemyInfo.cls === "enemys") { core.strokeRect(ctx, 272, 175, 32, 32, "rgba(255,255,255,1)", 1); - let img = attack && (enemyDiffList[turn].hp < 0) ? imagelighter(core.getBlockInfo(enemyInfo.id).image) : attack && (enemyDiffList[turn].hp > 0) ? imagelighter(core.getBlockInfo(enemyInfo.id).image, 'rgba(0, 255, 0, 0.5)') : core.getBlockInfo(enemyInfo.id).image + let img = + attack && enemyDiffList[turn].hp < 0 ? + imagelighter(core.getBlockInfo(enemyInfo.id).image) : + attack && enemyDiffList[turn].hp > 0 ? + imagelighter( + core.getBlockInfo(enemyInfo.id).image, + "rgba(0, 255, 0, 0.5)" + ) : + core.getBlockInfo(enemyInfo.id).image; core.drawImage( ctx, img, @@ -20972,7 +21826,15 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ); } else { core.strokeRect(ctx, 272, 159, 32, 48, "rgba(255,255,255,1)", 1); - let img = attack && (enemyDiffList[turn].hp < 0) ? imagelighter(core.getBlockInfo(enemyInfo.id).image) : attack && (enemyDiffList[turn].hp > 0) ? imagelighter(core.getBlockInfo(enemyInfo.id).image, 'rgba(0, 255, 0, 0.5)') : core.getBlockInfo(enemyInfo.id).image + let img = + attack && enemyDiffList[turn].hp < 0 ? + imagelighter(core.getBlockInfo(enemyInfo.id).image) : + attack && enemyDiffList[turn].hp > 0 ? + imagelighter( + core.getBlockInfo(enemyInfo.id).image, + "rgba(0, 255, 0, 0.5)" + ) : + core.getBlockInfo(enemyInfo.id).image; core.drawImage( ctx, img, @@ -21027,7 +21889,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ); if (!attack && !onattack) enemyInfo.now += enemyInfo.speed / onegcd; - let enemynow = Math.min(100 + enemyInfo.now / oneTurn * 215, 315); + let enemynow = Math.min(100 + (enemyInfo.now / oneTurn) * 215, 315); ctx.fillStyle = "#FFFFFF"; ctx.beginPath(); ctx.moveTo(enemynow, 120); @@ -21066,7 +21928,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = core.drawLine(ctx, 100, 125, 315, 125, "#FFFFFF", 5); equipInfo.forEach(function (v) { if (!attack && !onattack) v.now += v.speed / onegcd; - let vnow = Math.min(100 + v.now / oneTurn * 215, 315); + let vnow = Math.min(100 + (v.now / oneTurn) * 215, 315); ctx.beginPath(); ctx.moveTo(vnow, 120); ctx.lineTo(vnow + 5, 110); @@ -21078,7 +21940,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = core.drawIcon(ctx, v.id, vnow - 16, 54, 32, 32); }); if (!attack && !onattack) heroInfo.now += hero.speed / onegcd; - let heronow = Math.min(100 + heroInfo.now / oneTurn * 215, 315); + let heronow = Math.min(100 + (heroInfo.now / oneTurn) * 215, 315); ctx.beginPath(); ctx.moveTo(heronow, 120); ctx.lineTo(heronow + 5, 110); @@ -21086,7 +21948,18 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ctx.closePath(); ctx.fill(); - core.drawImage(ctx, "hero.webp", 0, 0, 32, 48, heronow - 16, 58, 32, 48); + core.drawImage( + ctx, + "hero.webp", + 0, + 0, + 32, + 48, + heronow - 16, + 58, + 32, + 48 + ); } else { core.fillRect(ctx, 64, 52, 288, 320, "rgba(0,0,0,0.5)"); core.strokeRect(ctx, 64, 52, 288, 320, "rgba(255,255,255,0.5)", 4); @@ -21148,8 +22021,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ); core.fillBoldText( ctx, - "法攻 " + - core.formatBigNumber(heroInfo.matk), + "法攻 " + core.formatBigNumber(heroInfo.matk), 90, 305, "#FFFFFF", @@ -21158,8 +22030,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ); core.fillBoldText( ctx, - "护盾 " + - core.formatBigNumber(heroInfo.mhp), + "护盾 " + core.formatBigNumber(heroInfo.mhp), 90, 325, "#FFFFFF", @@ -21186,7 +22057,15 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ); core.strokeRect(ctx, 112, 159, 32, 48, "rgba(255,255,255,1)", 1); - let img = attack && (heroDiffList[turn].hp < 0) ? imagelighter(core.material.images.images["hero.webp"]) : attack && (heroDiffList[turn].hp > 0) ? imagelighter(core.material.images.images["hero.webp"], 'rgba(0, 255, 0, 0.5)') : core.material.images.images["hero.webp"] + let img = + attack && heroDiffList[turn].hp < 0 ? + imagelighter(core.material.images.images["hero.webp"]) : + attack && heroDiffList[turn].hp > 0 ? + imagelighter( + core.material.images.images["hero.webp"], + "rgba(0, 255, 0, 0.5)" + ) : + core.material.images.images["hero.webp"]; core.drawImage( ctx, img, @@ -21214,7 +22093,15 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = core.setTextAlign(ctx, "right"); if (enemyInfo.cls === "enemys") { core.strokeRect(ctx, 272, 175, 32, 32, "rgba(255,255,255,1)", 1); - let img = attack && (enemyDiffList[turn].hp < 0) ? imagelighter(core.getBlockInfo(enemyInfo.id).image) : attack && (enemyDiffList[turn].hp > 0) ? imagelighter(core.getBlockInfo(enemyInfo.id).image, 'rgba(0, 255, 0, 0.5)') : core.getBlockInfo(enemyInfo.id).image + let img = + attack && enemyDiffList[turn].hp < 0 ? + imagelighter(core.getBlockInfo(enemyInfo.id).image) : + attack && enemyDiffList[turn].hp > 0 ? + imagelighter( + core.getBlockInfo(enemyInfo.id).image, + "rgba(0, 255, 0, 0.5)" + ) : + core.getBlockInfo(enemyInfo.id).image; core.drawImage( ctx, img, @@ -21229,7 +22116,15 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ); } else { core.strokeRect(ctx, 272, 159, 32, 48, "rgba(255,255,255,1)", 1); - let img = attack && (enemyDiffList[turn].hp < 0) ? imagelighter(core.getBlockInfo(enemyInfo.id).image) : attack && (enemyDiffList[turn].hp > 0) ? imagelighter(core.getBlockInfo(enemyInfo.id).image, 'rgba(0, 255, 0, 0.5)') : core.getBlockInfo(enemyInfo.id).image + let img = + attack && enemyDiffList[turn].hp < 0 ? + imagelighter(core.getBlockInfo(enemyInfo.id).image) : + attack && enemyDiffList[turn].hp > 0 ? + imagelighter( + core.getBlockInfo(enemyInfo.id).image, + "rgba(0, 255, 0, 0.5)" + ) : + core.getBlockInfo(enemyInfo.id).image; core.drawImage( ctx, img, @@ -21278,7 +22173,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ); core.fillBoldText( ctx, - (enemyInfo.spell ?? 0) + " 法qi强", + (enemyInfo.spell ?? 0) + " 法强", 330, 285, "#FFFFFF", @@ -21342,7 +22237,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ); if (!attack && !onattack) enemyInfo.now += enemyInfo.speed / onegcd; - let enemynow = Math.min(100 + enemyInfo.now / oneTurn * 215, 315); + let enemynow = Math.min(100 + (enemyInfo.now / oneTurn) * 215, 315); ctx.fillStyle = "#FFFFFF"; ctx.beginPath(); ctx.moveTo(enemynow, 120); @@ -21381,7 +22276,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = core.drawLine(ctx, 100, 125, 315, 125, "#FFFFFF", 5); equipInfo.forEach(function (v) { if (!attack && !onattack) v.now += v.speed / onegcd; - let vnow = Math.min(100 + v.now / oneTurn * 215, 315); + let vnow = Math.min(100 + (v.now / oneTurn) * 215, 315); ctx.beginPath(); ctx.moveTo(vnow, 120); ctx.lineTo(vnow + 5, 110); @@ -21393,7 +22288,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = core.drawIcon(ctx, v.id, vnow - 16, 54, 32, 32); }); if (!attack && !onattack) heroInfo.now += hero.speed / onegcd; - let heronow = Math.min(100 + heroInfo.now / oneTurn * 215, 315); + let heronow = Math.min(100 + (heroInfo.now / oneTurn) * 215, 315); ctx.beginPath(); ctx.moveTo(heronow, 120); ctx.lineTo(heronow + 5, 110); @@ -21401,36 +22296,43 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ctx.closePath(); ctx.fill(); - core.drawImage(ctx, "hero.webp", 0, 0, 32, 48, heronow - 16, 58, 32, 48); + core.drawImage( + ctx, + "hero.webp", + 0, + 0, + 32, + 48, + heronow - 16, + 58, + 32, + 48 + ); } - let nowattacking = false + let nowattacking = false; if (heroInfo.now >= oneTurn && !heroInfo.isAttack) { - heroInfo.onattack = false + heroInfo.onattack = false; heroInfo.isAttack = true; - nowattacking = true - + nowattacking = true; } if (enemyInfo.now >= oneTurn && !enemyInfo.isAttack) { - enemyInfo.onattack = false + enemyInfo.onattack = false; enemyInfo.isAttack = true; - nowattacking = true - + nowattacking = true; } - const equipanimate = [] - equipInfo.forEach(v => { + const equipanimate = []; + equipInfo.forEach((v) => { if (v.now >= oneTurn && !v.isAttack) { v.isAttack = true; - v.onattack = false - nowattacking = true - equipanimate.push(v) - + v.onattack = false; + nowattacking = true; + equipanimate.push(v); } }); if (!attack && nowattacking) { - - let herodamage = enemyDiffList[turn].hp - if (herodamage > 0) herodamage = '+' + herodamage - let text = herodamage === 0 ? "抵抗" : herodamage + let herodamage = enemyDiffList[turn].hp; + if (herodamage > 0) herodamage = "+" + herodamage; + let text = herodamage === 0 ? "抵抗" : herodamage; Dove.MorePerform.ShowDamagePop.PopDamage( ctx, // 默认画布名称 @@ -21438,83 +22340,89 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = 160, // 英雄位置 y text, // 伤害值 18, // 默认字体大小 - "Arial", //默认字体 - typeof text === 'string' && text.startsWith('+') ? '#22FF44' : typeof text === 'string' ? "#FFFFFF" : null, // 默认颜色 - text === '抵抗' ? "#000000" : null, // 默认描边颜色 + "Arial", //默认字体 + typeof text === "string" && text.startsWith("+") ? + "#22FF44" : + typeof text === "string" ? + "#FFFFFF" : + null, // 默认颜色 + text === "抵抗" ? "#000000" : null, // 默认描边颜色 0, // 默认水平速度 -1, // 默认垂直速度 0, // 默认重力 90 // 默认显示时长(帧数) ); for (const v in enemyDiffList[turn]) { - enemyInfo[v] += enemyDiffList[turn][v] + enemyInfo[v] += enemyDiffList[turn][v]; } - enemyanimateList[turn].forEach(v => animateOnAttack(v, true)) - let enemydamage = heroDiffList[turn].hp - if (enemydamage > 0) enemydamage = '+' + enemydamage - text = enemydamage === 0 ? "抵抗" : enemydamage + enemyanimateList[turn].forEach((v) => animateOnAttack(v, true)); + let enemydamage = heroDiffList[turn].hp; + if (enemydamage > 0) enemydamage = "+" + enemydamage; + text = enemydamage === 0 ? "抵抗" : enemydamage; Dove.MorePerform.ShowDamagePop.PopDamage( ctx, // 默认画布名称 110, // 英雄位置 x 160, // 英雄位置 y text, // 伤害值 18, // 默认字体大小 - "Arial", //默认字体 - typeof text === 'string' && text.startsWith('+') ? '#22FF44' : typeof text === 'string' ? "#FFFFFF" : null, // 默认颜色 - text === '抵抗' ? "#000000" : null, // 默认描边颜色 + "Arial", //默认字体 + typeof text === "string" && text.startsWith("+") ? + "#22FF44" : + typeof text === "string" ? + "#FFFFFF" : + null, // 默认颜色 + text === "抵抗" ? "#000000" : null, // 默认描边颜色 0, // 默认水平速度 -1, // 默认垂直速度 0, // 默认重力 90 // 默认显示时长(帧数) ); for (const v in heroDiffList[turn]) { - heroInfo[v] += heroDiffList[turn][v] + heroInfo[v] += heroDiffList[turn][v]; } - heroanimateList[turn].forEach(v => animateOnAttack(v, false)) + heroanimateList[turn].forEach((v) => animateOnAttack(v, false)); - if (enemyDiffList[turn] < 0) enemyInfo.inAttack = true - if (heroDiffList[turn] < 0) heroInfo.inAttack = true - if (heroInfo.hp < 0) heroInfo.hp = 0 - if (enemyInfo.hp < 0) enemyInfo.hp = 0 - await Promise.all([await playinganimate(), - new Promise(resolve => { + if (enemyDiffList[turn] < 0) enemyInfo.inAttack = true; + if (heroDiffList[turn] < 0) heroInfo.inAttack = true; + if (heroInfo.hp < 0) heroInfo.hp = 0; + if (enemyInfo.hp < 0) enemyInfo.hp = 0; + await Promise.all([ + await playinganimate(), + new Promise((resolve) => { if (heroInfo.isAttack) { heroInfo.now = 0; heroInfo.isAttack = false; } - resolve() + resolve(); }), - new Promise(resolve => { + new Promise((resolve) => { if (enemyInfo.isAttack) { enemyInfo.now = 0; enemyInfo.isAttack = false; } - resolve() + resolve(); }), - new Promise(resolve => { + new Promise((resolve) => { if (equipanimate.length > 0) { - equipanimate.forEach(v => { + equipanimate.forEach((v) => { v.now = 0; v.isAttack = false; - }) + }); } - resolve() + resolve(); }), - new Promise(resolve => { - turn++ - resolve() - }) - ]) - - + new Promise((resolve) => { + turn++; + resolve(); + }), + ]); if (heroInfo.hp <= 0 || enemyInfo.hp <= 0) { - core.status.event.id = '' - core.unregisterAnimationFrame("attackAnimate") - core.clearMap(ctx) - core.closePanel() - res() - + core.status.event.id = ""; + core.unregisterAnimationFrame("attackAnimate"); + core.clearMap(ctx); + core.closePanel(); + res(); } } } @@ -21534,926 +22442,1372 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = enemyanimateList ); - farme++; } }); - }) - } + }); + }; }, "剧情内容": function () { - // 每项为一个数组,第一项是名字,第二项是对话内容,第三项为音频文件名(没有则不需要第三项) - // 回放只会在同一个this下回放,进入剧情前请以事件块声明进入哪个剧情数组 - this.chapter0 = [ - ["", "这些天,街道不曾下雨。"], - ["", "所以,那浸湿地面的,定是那些女孩们流落的鲜血无疑。"], - ["", "我蹲在充斥着铁锈味般恶臭的小巷中,悠闲地如是想着。"], - ["", "扑哧。"], - ["", "耳旁再次响起象征着某个女孩子死去的声音。"], - ["", "再一次——"], - ["", "再一次。"], - ["", "女子们被肢解成单纯的肉块。"], - ["", "我任由流下的血浸满全身,屏住自己的呼吸。"], - ["", "祈求自己能拥有从猎人手中逃脱的幸运。"], - ["", "扑哧。"], - ["", "直到刚才,我们还坐在去往娼馆的马车的路上。"], - ["", "而在这之中的某些人,已经不在这个世上了。"], - ["", "不,应该把“某些”换成“几乎所有”才更为恰当吧。"], - ["", "恐怕,不久之后我也会变成小巷中血腥的装饰品。"], - ["", "我是为了得到这种死法,才辛苦苟活至今的吗?"], - ["", "来个人告诉我啊——"], - ["", "谁都好。"], - ["", "来人啊!!"], - ["少女", "「呃······!?」", "aiy010000010.opus"], //小动物01 - ["", "漆黑的物体充斥了我的整个视野"], - ["", "我很快意识到,那是只很大的脚。"], - ["", "必须要出声求救。"], - ["", "可是,耳中却只能听到自己的牙关不停交战的声音。"], - ["", "我是如此的无助。"], - ["", "逃跑也好,道歉也罢。"], - ["", "就连抬头看一眼将要杀掉我的人的面孔都做不到。"], - ["少女", "「······被杀」", "aiy010000020.opus"], //小动物02 - ["", "会被杀。"], - ["", "会被杀!!"], - ["", "来自内心深处的冰冷预感,渐渐地在体内蔓延开来。"], - ["少女", "「不,不要······」", "aiy010000030.opus"], //小动物03 - ["", "浮游都市,《诺瓦斯·艾蒂尔》。"], - ["", "《特别受灾地区》——"], - ["", "通称,《牢狱》"], - ["", "是被险峻的峭壁环绕,与世隔绝的,都市的最底部。"], - ["年轻人", "「放开我!」", "aiy710000010.opus"], //龙套1-01 - ["年轻人", "「我只是在帮那个女人而已!」", "aiy710000020.opus"], //龙套1-02 - ["年轻人", "「你们没听到吗!?」", "aiy710000030.opus"], //龙套1-03 - ["年轻人", "「她是被受骗才会被卖到娼馆来的」", "aiy710000040.opus"], //龙套1-04 - [ - "年轻人", - "「用肮脏的手段把钱借给她父母的,就是你们这些家伙吧!?」", - "aiy710000050.opus", - ], //龙套1-05 - ["年轻人", "「给我说些什么啊」", "aiy710000060.opus"], //龙套1-06 - ["凯伊姆", "「这些话等到了娼馆再说吧」", "aiy310000010.opus"], //男主01 - ["凯伊姆", "「我来抓你,只是受雇于人而已」", "aiy310000020.opus"], //男主02 - ["", "我走进娼馆《莉莉乌姆》的接待室。"], - ["", "正在桌旁整理账簿的奥兹停下手头的工作,抬起头向我看来。"], - ["奥兹", "「这不是凯伊姆先生吗,辛苦了」", "aiy350000010.opus"], //金锁高官01 - ["奥兹", "「委托已经完成了吗?」", "aiy350000020.opus"], //金锁高官02 - ["凯伊姆", "「啊啊,是这家伙没错吧」", "aiy310000030.opus"], //男主03 - ["", "奥兹用只要接触到就能杀人般的眼神在男人脸上搜过。"], - ["奥兹", "「没错,就是这个人」", "aiy350000030.opus"], //金锁高官03 - ["凯伊姆", "「是么」", "aiy310000040.opus"], //男主04 - ["年轻人", "「你,你们要对我做什么」", "aiy710000070.opus"], //龙套1-07 - ["奥兹", "「······」", "aiy350000040.opus"], //金锁高官04 - ["", "奥兹用一个眼神,就让男人闭上了嘴。"], - ["", "然后,向我这边转过身来。"], - ["奥兹", "「抱歉啊,总是麻烦你去做这些无聊的事」", "aiy350000050.opus"], //金锁高官05 - ["奥兹", "「都怪我们这边的年轻人太没用」", "aiy350000060.opus"], //金锁高官06 - ["凯伊姆", "「客套话就免了」", "aiy310000050.opus"], //男主05 - ["奥兹", "「这还真是失礼了」", "aiy350000070.opus"], //金锁高官07 - ["奥兹", "「喂,来个人」", "aiy350000080.opus"], //金锁高官08 - ["光头男人", "「是」", "aiy820000010.opus"], //龙套2-01 - ["奥兹", "「凯伊姆先生做完工作回来了」", "aiy350000090.opus"], //金锁高官09 - ["光头男人", "「是,是,那个······」", "aiy820000020.opus"], //龙套2-02 - ["奥兹", "「我是要你拿些酒来,这个蠢材!」", "aiy350000100.opus"], //金锁高官10 - ["", "喀!"], - ["", "奥兹扔出的烟灰缸砸中了手下的额头。"], - ["", "鲜血四溅。"], - ["凯伊姆", "「不用这么麻烦」", "aiy310000060.opus"], //男主06 - ["凯伊姆", "「我接下来要去《菲诺列塔》」", "aiy310000070.opus"], //男主07 - ["奥兹", "「喔唷」", "aiy350000110.opus"], //金锁高官11 - [ - "奥兹", - "「既然如此,我就不留您在这里喝难饮的劣质酒了」", - "aiy350000120.opus", - ], //金锁高官12 - ["", "奥兹斜眼看着正捂住额头呻吟的手下,轻描淡写地说道。"], - ["凯伊姆", "「用这些钱去买药」", "aiy310000080.opus"], //男主08 - ["", "我将几枚铜钱仍在那个手下的身前。"], - ["奥兹", "「凯伊姆先生,不用对他们这么好」", "aiy350000130.opus"], //金锁高官13 - ["凯伊姆", "「无妨」", "aiy310000090.opus"], //男主09 - ["凯伊姆", "「话说回来,那个要落跑的女人呢?」", "aiy310000100.opus"], //男主10 - [ - "奥兹", - "「我把她交给那些年轻人了,现在应该正在体会人生的严苛吧」", - "aiy350000140.opus", - ], //金锁高官14 - [ - "奥兹", - "「正好,趁此机会凯伊姆先生也来享受一番如何?」", - "aiy350000150.opus", - ], //金锁高官15 - ["年轻人", "「你,你们这些家伙,要对她做什么!?」", "aiy710000080.opus"], //龙套1-08 - ["", "咣!"], - ["", "奥兹给了他一拳。"], - ["", "一击即倒。"], - ["", "喀,咚,咯!"], - ["", "奥兹毫不留情地向男人的脸上踩去。"], - ["年轻人", "「咕······呃咳······」", "aiy710000090.opus"], //龙套1-09 - ["", "折断的牙齿伴着血泡被吐出。"], - ["", "这份白色在鲜红色的液体中格外显眼。"], - [ - "年轻人", - "「你们以为做出这种事······卫兵会坐视不理吗······」", - "aiy710000100.opus", - ], //龙套1-10 - ["奥兹", "「啊啊,不会坐视不理的」", "aiy350000160.opus"], //金锁高官16 - [ - "奥兹", - "「应该会拿出你的钱包,和我们商量如何瓜分吧」", - "aiy350000170.opus", - ], //金锁高官17 - ["年轻人", "「那,那种事······」", "aiy710000110.opus"], //龙套1-11 - ["", "这在牢狱是理所当然的事。"], - ["奥兹", "「怎么,头一回来牢狱么?」", "aiy350000180.opus"], //金锁高官18 - ["", "男人点了点头。"], - [ - "奥兹", - "「为了被骗的女人而来到牢狱,真是个规矩人啊」", - "aiy350000190.opus", - ], //金锁高官19 - ["奥兹", "「······前提是,被骗的人不是你」", "aiy350000200.opus"], //金锁高官20 - ["年轻人", "「你说······我被骗了?」", "aiy710000120.opus"], //龙套1-12 - ["年轻人", "「那,那是怎么回事!?」", "aiy710000130.opus"], //龙套1-13 - ["奥兹", "「不用急,今天晚上会好好告诉你的」", "aiy350000210.opus"], //金锁高官21 - ["", "奥兹抓起男人的脸。"], - ["", "为引诱客人的怜悯之心而装纯,是娼妇的惯用手段。"], - ["", "双亲被骗而借钱,结果作为抵押而将自己卖到这里,这是典型的说法。"], - [ - "", - "如果只是头脑发热而成为常客也就罢了,这次的男人热血过头,居然想出了要带女人私奔的计划。", - ], - [ - "", - "虽然女人半开玩笑地予以拒绝,但不知天高地厚的这家伙还是拉着她逃跑了。", - ], - ["", "不过,想要逃脱追击本来就是不可能的任务。"], - ["", "但即便如此,这种事情还是会一再的出现。"], - ["", "说谎的女人和被骗的男人。"], - ["", "在娼馆街,这是令人看到生厌的日常的风景。"], - ["凯伊姆", "「我要走了」", "aiy310000110.opus"], //男主11 - ["奥兹", "「好的,下次再麻烦您」", "aiy350000220.opus"], //金锁高官22 - ["奥兹", "「之后吉克先生会将谢礼交给您的」", "aiy350000230.opus"], //金锁高官23 - ["凯伊姆", "「啊啊」", "aiy310000120.opus"], //男主12 - ["", "我背向奥兹走出娼馆。"], - ["凯伊姆", "「······?」", "aiy310000130.opus"], //男主13 - ["", "从远方传来微弱的歌声。"], - ["", "是关卡广场的方向。"], - ["", "对了。"], - ["", "今天有觐见圣女的仪式。"], - ["", "当代的圣女伊莲——"], - ["", "俗称《盲眼之圣女》,据说即使在历代的圣女中,人气也是数一数二的。"], - ["", "广场上的人估计相当多吧。"], - ["", "虽然我也想去看看她长什么样,不过要在人潮中挤来挤去就免了。"], - ["", "还是老老实实去菲诺列塔喝烧酒吧。"], - ["", "正当我这样想着的时候,一个身影自小巷的那头走来。"], - ["凯伊姆", "「艾莉斯」", "aiy310000140.opus"], //男主14 - ]; - this.chapter01 = [ - ["艾莉斯", "「啊,凯伊姆」", "aiy020000005.opus"], //医生00.5 - ["艾莉斯", "「正好,我还想要去找你呢」", "aiy020000010.opus"], //医生01 - [ - "艾莉斯", - "「没想到凯伊姆会主动出现······这是命运吗?」", - "aiy020000020.opus", - ], //医生02 - ["凯伊姆", "「显然不是吧」", "aiy310000150.opus"], //男主15 - ["艾莉斯", "「啊,是么」", "aiy020000030.opus"], //医生03 - ["", "艾莉斯挑了挑整齐的双眉,微微地哼了一声。"], - [ - "", - "虽然是个相当引人注目的美人,但她这个将亲切儿子丢入无底深渊的性格,为自己扣了不少的分", - ], - ["", "给人印象最深的,就是那潭水般的双瞳。"], - ["", "在漆黑的瞳孔中,完全看不出感情的波动。"], - ["艾莉斯", "「喜欢我的眼睛吗?」", "aiy020000040.opus"], //医生04 - ["艾莉斯", "「如果想要的话就给你吧?」", "aiy020000050.opus"], //医生05 - ["凯伊姆", "「用不着」", "aiy310000160.opus"], //男主16 - ["艾莉斯", "「阿拉,可惜」", "aiy020000060.opus"], //医生06 - ["凯伊姆", "「那么,找我有什么事」", "aiy310000170.opus"], //男主17 - ["艾莉斯", "「梅尔特的钱好像被偷了」", "aiy020000070.opus"], //医生07 - ["凯伊姆", "「钱被偷了?都几岁了还这么没用」", "aiy310000180.opus"], //男主18 - ["艾莉斯", "「不要对我说啊」", "aiy020000080.opus"], //医生08 - [ - "凯伊姆", - "「那家伙,该不会说要让我去抓那个小偷吧?」", - "aiy310000190.opus", - ], //男主19 - ["艾莉斯", "「就是这样」", "aiy020000090.opus"], //医生09 - ["凯伊姆", "「笨蛋吗」", "aiy310000200.opus"], //男主20 - ["凯伊姆", "「如果是小钱的话,就当做是买个教训吧」", "aiy310000210.opus"], //男主21 - ["艾莉斯", "「说起来,被盗的是这个月的上纳金」", "aiy020000100.opus"], //医生10 - ["凯伊姆", "「你说什么?」", "aiy310000220.opus"], //男主22 - ["艾莉斯", "「用这些钱买教训,也太过奢侈了呢」", "aiy020000110.opus"], //医生11 - ["凯伊姆", "「知道了,我去找」", "aiy310000230.opus"], //男主23 - ["凯伊姆", "「小偷的特征呢」", "aiy310000240.opus"], //男主24 - ["艾莉斯", "「男孩子」", "aiy020000120.opus"], //医生12 - ["艾莉斯", "「······而且,背后有翅膀」", "aiy020000130.opus"], //医生13 - [ - "艾莉斯", - "「虽然姑且是藏在身后,但是仔细观察的话是很明显的」", - "aiy020000140.opus", - ], //医生14 - ["凯伊姆", "「羽化病吗」", "aiy310000250.opus"], //男主25 - [ - "艾莉斯", - "「那些人可是毫不留情的,所以即使是为了那个孩子,也要赶快抓到他」", - "aiy020000150.opus", - ], //医生15 - ["凯伊姆", "「注意到他逃窜的方向了吗?」", "aiy310000260.opus"], //男主26 - ["艾莉斯", "「广场那边」", "aiy020000160.opus"], //医生16 - [ - "艾莉斯", - "「虽然刚才《不蚀金锁》的人去追了,不过多半是······」", - "aiy020000170.opus", - ], //医生17 - ["凯伊姆", "「偏偏还是广场吗」", "aiy310000280.opus"], //男主28 - ["艾莉斯", "「今天是觐见圣女大人的日子」", "aiy020000180.opus"], //医生18 - ["凯伊姆", "「我知道」", "aiy310000290.opus"], //男主29 - ["凯伊姆", "「尽量找找看就好」", "aiy310000300.opus"], //男主30 - ]; - this.chapter02 = [ - ["不蚀金锁成员", "「凯伊姆先生,凯伊姆先生」", "aiy860000010.ogg"], - [ - "不蚀金锁成员", - "「您已经和艾莉斯大夫见过面了吗?」", - "aiy860000020.ogg", - ], - ["凯伊姆", "「啊啊,所以才会追过来的」", "aiy310000310.ogg"], //男主31 - ["凯伊姆", "「看到小偷了吗?」", "aiy310000320.ogg"], //男主32 - [ - "不蚀金锁成员", - "「没有,他向广场那边逃了过去,今天这么拥挤,我们也只能放弃了」", - "aiy860000030.ogg", - ], - [ - "不蚀金锁成员", - "「不过,我也只是刚好在店里所以才追了过去,并不是受人所托」", - "aiy860000040.ogg", - ], - ["不蚀金锁成员", "「我已经准备撤退了」", "aiy860000050.ogg"], - ["不蚀金锁成员", "「凯伊姆先生还要继续追吗?」", "aiy860000060.ogg"], - ["凯伊姆", "「啊啊」", "aiy310000330.ogg"], //男主33 - ["", "做完情报交换之后,我跟男人道别。"], - ["凯伊姆", "「和我想的一样啊······」", "aiy310000340.ogg"], //男主34 - ["", "在牢狱中最大的广场上,聚集着看不到尽头的人群。"], - ["", "就算是来参见圣女祈祷,这人数也太多了点吧。"], - ["", "自然,我也找不到逃跑的孩子。"], - ["", "是混杂到人群中了吧。"], - ["", "如果已经从广场上脱身了的话,就更难发现了。"], - ["", "只好赌他还在这里了。"], - ["", "我先移动到了一个视野良好的地方。"], - ["", "从这里,一眼就可以看到人群的变化。"], - ["", "广场还是沸腾起来。"], - ["", "抬头望去,原来是在天台之上出现了一个人影"], - ["", "但是,与周围的期待不同,现身的是一名中年的神官。"], - ["", "骂声四溢。"], - ["", "神官则是笑着摆正衣领"], - ["神官", "「从现在开始,举行谒见的仪式」", "aiy440000010.ogg"], //神官01 - [ - "神官", - "「在参见那位大人之前,我希望牢狱的诸位再次思考这个《诺瓦斯·艾蒂尔》存在的意义······」", - "aiy440000020.ogg", - ], //神官02 - [ - "神官", - "「初代圣女伊莲大人,便是也难怪这崇高的祈祷之力,令《诺瓦斯·艾蒂尔》浮在空中,拯救了我们的祖先」", - "aiy440000030.ogg", - ], //神官03 - [ - "神官", - "「这之后的几百年来,传承了初代大人力量的历代圣女伊莲大人,让这里留在了空中」", - "aiy440000040.ogg", - ], //神官04 - [ - "神官", - "「这座都市是被圣女大人守护的人类最后的圣域,而我们则是被选召的虔诚的信徒」", - "aiy440000050.ogg", - ], //神官05 - [ - "神官", - "「怀着对圣女的感激祈祷吧,感谢圣女伊莲吧!并献上祈祷!」", - "aiy440000060.ogg", - ], //神官06 - ["圣女", "「不忘感谢与祈祷,神才会拯救我们」", "aiy030000010.ogg"], //圣女01 - ["圣女", "「与我一起,向神虔诚地祈祷吧」", "aiy030000020.ogg"], //圣女02 - ["", "广场上欢声雷动。"], - ["", "圣女没有回应喧嚣的人声,而是静静地合上双眼面向广场。"], - ["", "虽然感觉有些冷淡,但总比像个傻瓜似的笑着向这群人挥手要强。"], - ["", "她掌握着这条街道,还有在这条街上生活的人的命运。"], - ["", "比起揽得人气,她更想要为了街道的继续存在而献出全力。"], - ["", "也是为了不让《大崩落》的惨剧再度发生。"], - ["", "十几年前的那场悲剧。"], - [ - "", - "虽然在我脑海中的记忆已经相当模糊,但哪怕只是稍有触及,不快的感觉都会在胸口蔓延开。", - ], - ["凯伊姆", "「······」", "aiy310000350.ogg"], //男主35 - ["", "这时我才想起,现在不是我在这里看圣女的时候。"], - ["女声", "「——っ!?」", "aiy510000010.ogg"], - ["围观的女人", "「羽,羽化病人!?」", "aiy510000020.ogg"], - ["围观的中年人", "「喂,谁去叫下羽狩」", "aiy720000010.ogg"], - [ - "惊慌的观众", - "「你这家伙不要靠近我,要是传染了可怎么办」", - "aiy730000010.ogg", - ], - ["粗鲁的观众", "「你这小鬼赶快滚开」", "aiy740000010.ogg"], - ["凯伊姆", "「接下来」", "aiy310000360.ogg"], //男主36 - ["圣女", "「发生什么事了?看上去似乎很嘈杂」", "aiy030000030.ogg"], //圣女03 - [ - "随从", - "「似乎是某个人逃跑了······具体的我也不是很清楚」", - "aiy130000010.ogg", - ], //侍从01 - [ - "神官", - "「圣女大人,继续待在天台上可能会出事,请您先回到室内吧」", - "aiy440000070.ogg", - ], //神官07 - [ - "圣女", - "「不用在意我,比起那个,我更关心究竟发生了什么事」", - "aiy030000050.ogg", - ], //圣女05 - ["神官", "「对不起,我真的不知道」", "aiy440000080.ogg"], //神官08 - ["圣女", "「······是吗」", "aiy030000060.ogg"], //圣女06 - ["男", "「恕我僭越,请准许我说明情况」", "aiy320000010.ogg"], //男主他哥01 - ["男", "「在来觐见的人群中出现了《羽化病》的患者」", "aiy320000020.ogg"], //男主他哥02 - ["男", "「围观的人群因而产生了骚动」", "aiy320000030.ogg"], //男主他哥03 - [ - "男", - "「现在,《防疫局》已经派遣了部队。我想不久之后,他们就会安静下来了」", - "aiy320000040.ogg", - ], //男主他哥04 - ["圣女", "「羽化病······」", "aiy030000070.ogg"], //圣女07 - ["男", "「怎么了?」", "aiy320000050.ogg"], //男主他哥05 - ["圣女", "「没什么」", "aiy030000080.ogg"], //圣女08 - ["圣女", "「辛苦了,你的名字是?」", "aiy030000090.ogg"], //圣女09 - [ - "男", - "「属下是在防疫局任职的,鲁基乌斯· 迪斯·米利尤」", - "aiy320000060.ogg", - ], //男主他哥06 - [ - "神官", - "「噢噢,阁下就是鲁基乌斯卿吗,我听说过你的传闻」", - "aiy440000090.ogg", - ], //神官09 - ["神官", "「阁下是在工作上相当出色的人呢」", "aiy440000100.ogg"], //神官10 - ["鲁基乌斯", "「不敢当」", "aiy320000070.ogg"], //男主他哥07 - [ - "鲁基乌斯", - "「话说回来,这次是属下警备工作的失职。让圣女大人见到这不成体统的一面,请您见谅」", - "aiy320000080.ogg", - ], //男主他哥08 - [ - "圣女", - "「即使是目不见物的我,也能感受到聚集于此的民众数量之多。警备工作难以展开也在情理之中」", - "aiy030000100.ogg", - ], //圣女10 - ["鲁基乌斯", "「属下不胜惶恐」", "aiy320000090.ogg"], //男主他哥09 - [ - "鲁基乌斯", - "「接下来属下还要回到工作岗位上,在这里就先告退了」", - "aiy320000100.ogg", - ], //男主他哥10 - ["圣女", "「鲁基乌斯先生」", "aiy030000110.ogg"], //圣女11 - ["鲁基乌斯", "「属下在」", "aiy320000110.ogg"], //男主他哥11 - ["圣女", "「你是怎样看待羽狩的工作的呢?」", "aiy030000120.ogg"], //圣女12 - ["神官", "「圣,圣女大人」", "aiy440000110.ogg"], //神官11 - [ - "鲁基乌斯", - "「防疫局的工作是国王陛下赐予的重要职务。属下非常荣幸能够为这个都市的繁荣尽一份微薄之力」", - "aiy320000120.ogg", - ], //男主他哥12 - ["神官", "「不,不亏是鲁基乌斯卿,相当优秀的想法」", "aiy440000120.ogg"], //神官12 - ["圣女", "「是吗。辛苦你了」", "aiy030000130.ogg"], //圣女13 - ["随从", "「圣女大人······」", "aiy130000020.ogg"], //侍从02 - ["鲁基乌斯", "「······」", "aiy320000135.ogg"], //男主他哥13 - ["鲁基乌斯", "「那么,属下就回岗位去了」", "aiy320000140.ogg"], //男主他哥14 - ]; - this.chapter03 = [ - ["", "从羽化病的少年纷乱的足音中,可以听得出相当的疲劳。"], - ["", "显然,他并没有想到我会捷足先登吧。"], - ["", "少年惶恐地回头看了一眼后,微微露出安心的表情,双手拄在膝盖上。。"], - ["凯伊姆", "「辛苦你了」", "aiy310000370.ogg"], //男主37 - ["羽化病患少年", "「稀!?」", "aiy750000010.ogg"], - ["凯伊姆", "「逃到贫民区是个不错的想法」", "aiy310000380.ogg"], //男主38 - ["羽化病患少年", "「你,你是,羽狩吗?」", "aiy750000020.ogg"], - ["凯伊姆", "「不是」", "aiy310000390.ogg"], //男主39 - [ - "羽化病患少年", - "「什,什么啊······混蛋,不要吓我啊」", - "aiy750000030.ogg", - ], - ["凯伊姆", "「我对令你受惊这件事致以歉意」", "aiy310000400.ogg"], //男主40 - ["凯伊姆", "「作为回报,麻烦你把从店里偷的钱交出来吧」", "aiy310000410.ogg"], //男主41 - ["羽化病患少年", "「钱?你在说什么」", "aiy750000040.ogg"], - ["凯伊姆", "「你要找的腰上的东西,掉在你身后了」", "aiy310000420.ogg"], //男主42 - ["羽化病患少年", "「哎?」", "aiy750000050.ogg"], - ["羽化病患少年", "「呃呀」", "aiy750000060.ogg"], - ["羽化病患少年", "「你······你这混蛋」", "aiy750000070.ogg"], - ["凯伊姆", "「······」", "aiy310000430.ogg"], //男主43 - ["凯伊姆", "「把偷的钱交出来」", "aiy310000440.ogg"], //男主44 - ["羽化病患少年", "「我不知道你在······咕」", "aiy750000080.ogg"], - [ - "羽化病患少年", - "「你,你说是我偷的······有什么证据吗」", - "aiy750000090.ogg", - ], - ["凯伊姆", "「你还挺倔的啊」", "aiy310000450.ogg"], //男主45 - ["凯伊姆", "「不过,给我听好了」", "aiy310000460.ogg"], //男主46 - ["凯伊姆", "「你偷的那些钱,是要上缴给《不蚀金锁》的上纳金」", "aiy310000470.ogg"], //男主47 - ["凯伊姆", "「而且,钱的主人是从前和吉克颇有渊源的女人」", "aiy310000480.ogg"], //男主48 - ["羽化病患少年", "「吉克?」", "aiy750000100.ogg"], - ["凯伊姆", "「他是《不蚀金锁》的主人,这么说你就明白了吧」", "aiy310000490.ogg"], //男主49 - ["羽化病患少年", "「哎?哎?怎么会······」", "aiy750000110.ogg"], - ["凯伊姆", "「再问你一遍,钱在哪里?」", "aiy310000510.ogg"], //男主51 - ["羽化病患少年", "「是,是,是,在我的怀里」", "aiy750000120.ogg"], - ["凯伊姆", "「你没有擅自拿掉一部分吧」", "aiy310000520.ogg"], //男主52 - ["羽化病患少年", "「是,是的」", "aiy7500000130.ogg"], - [ - "羽化病患少年", - "「那,那个,您是《不蚀金锁》的人吗?」", - "aiy750000140.ogg", - ], - ["凯伊姆", "「算是吧」", "aiy310000530.ogg"], //男主53 - [ - "羽化病患少年", - "「我什么都可以做,请您一定要帮帮我」", - "aiy750000150.ogg", - ], - ["凯伊姆", "「抱歉,我并没有兴趣去帮助他人」", "aiy310000540.ogg"], //男主54 - [ - "羽化病患少年", - "「我什么······什么,都会做的······」", - "aiy750000160.ogg", - ], - ["羽化病患少年", "「我一直都是生活在下层的」", "aiy750000170.ogg"], - [ - "羽化病患少年", - "「可是,不知何时染上了羽化病······背后长出了翅膀······」", - "aiy750000180.ogg", - ], - [ - "羽化病患少年", - "「被寄宿工作的店赶了出来,只得流落到牢狱这里」", - "aiy750000190.ogg", - ], - [ - "羽化病患少年", - "「因为独自实在是饿的不行了,所以才会偷这些钱的」", - "aiy750000200.ogg", - ], - [ - "羽化病患少年", - "「我明明没有做任何坏事······为什么······会遇到这种事······」", - "aiy750000210.ogg", - ], - ["凯伊姆", "「谁知道」", "aiy310000550.ogg"], //男主55 - [ - "羽化病患少年", - "「呜······呜呜······接下来,要对我做什么?」", - "aiy750000220.ogg", - ], - ["凯伊姆", "「我要把你带到组织那里」", "aiy310000560.ogg"], //男主56 - ["羽化病患少年", "「怎,怎么这样」", "aiy750000230.ogg"], - ["凯伊姆", "「不过,那样做的前提是你不是羽化病人」", "aiy310000570.ogg"], //男主57 - ["凯伊姆", "「组织也没有笨到把羽化病人招待到家里的程度」", "aiy310000580.ogg"], //男主58 - ["羽化病患少年", "「那么,是要放我逃走吗?」", "aiy750000240.ogg"], - ["凯伊姆", "「我要让你学到教训」", "aiy310000590.ogg"], //男主59 - ["凯伊姆", "「如果换做是组织的制裁,至少要有断条胳膊的觉悟」", "aiy310000600.ogg"], //男主60 - ["凯伊姆", "「你的运气不错」", "aiy310000610.ogg"], //男主61 - ["羽化病患少年", "「唔······啊,是的······」", "aiy750000250.ogg"], - ["凯伊姆", "「滚」", "aiy310000620.ogg"], //男主62 - ["羽化病患少年", "「非常感谢」", "aiy750000260.ogg"], - ["羽化病患少年", "「唔啊!?」", "aiy750000270.ogg"], - ["男", "「到这里就结束了,羽化病人」", "aiy430000010.ogg"], //兰格01 - ["男", "「确认他的翅膀」", "aiy430000020.ogg"], //兰格02 - ["", "趁还没有被卷入麻烦的事情之前,赶快离开这里吧"], - ["羽狩的指挥者", "「那边的那个人」", "aiy430000030.ogg"], //兰格03 - ["凯伊姆", "「······有什么事?」", "aiy310000630.ogg"], //男主63 - ["羽狩的指挥者", "「可以稍微让我问几句话吗」", "aiy430000040.ogg"], //兰格04 - ["凯伊姆", "「······」", "aiy310000640.ogg"], //男主64 - ["凯伊姆", "「啊啊,无妨」", "aiy310000650.ogg"], //男主65 - ["羽狩的指挥者", "「感谢您的合作」", "aiy430000050.ogg"], //兰格05 - ["", "队长殷勤地致以谢礼。"], - ["", "而在他的眼前,少年的衣服已经被他的补下们扯破。"], - ["", "在瘦骨嶙峋的裸露后背上,长有纯白的羽翼。"], - ["红发的羽狩", "「副队长,确认翅膀的持有了」"], - ["羽狩的副队长", "「保护他」", "aiy430000060.ogg"], //兰格06 - ["羽化病患少年", "「不要······请原谅,我······」", "aiy750000280.ogg"], - [ - "羽狩的副队长", - "「我们只是要带你去治愈院治疗羽化病,不是什么应该感到害怕的事情」", - "aiy430000070.ogg", - ], //兰格07 - ["羽化病患少年", "「可是,可是」", "aiy750000290.ogg"], - ["羽狩的副队长", "「没关系的」", "aiy430000080.ogg"], //兰格08 - ["羽化病患少年", "「······哥,哥哥」", "aiy750000300.ogg"], - ["羽狩的副队长", "「你是羽化病人的亲属吗?」", "aiy430000090.ogg"], //兰格09 - ["凯伊姆", "「只是路人而已」", "aiy310000660.ogg"], //男主66 - ["凯伊姆", "「顺带一提,我也没有打算找你们的麻烦」", "aiy310000670.ogg"], //男主67 - [ - "羽狩的副队长", - "「前几天,有个和你说了同样的话的人,在我们背向他的瞬间对我们发动了袭击」", - "aiy430000100.ogg", - ], //兰格10 - ["羽狩的副队长", "「我的一个部下就此永久失去了半截胳膊」", "aiy430000110.ogg"], //兰格11 - ["凯伊姆", "「我表示同情」", "aiy310000680.ogg"], //男主68 - ["凯伊姆", "「我马上就会消失的,这样就没问题了吧?」", "aiy310000690.ogg"], //男主69 - ["羽狩的副队长", "「嘛,不要这么慌张」", "aiy430000120.ogg"], //兰格12 - ["", "副队长看着羽化的少年。"], - ["羽狩的副队长", "「你与这个人是什么关系?没有被他殴打吗?」", "aiy430000130.ogg"], //兰格13 - ["羽化病患少年", "「没,没有」", "aiy750000310.ogg"], - [ - "羽狩的副队长", - "「如何对我们保持合作,你就可以在治愈院得到优先的治疗」", - "aiy430000140.ogg", - ], //兰格14 - ["羽化病患少年", "「······」", "aiy750000320.ogg"], - [ - "羽化病患少年", - "「那个人,是《不蚀金锁》的组织成员······」", - "aiy750000330.ogg", - ], - [ - "羽化病患少年", - "「突然说让我拿出钱来,我刚一拒绝他就打我」", - "aiy750000340.ogg", - ], - ["羽狩的副队长", "「原来如此······」", "aiy430000150.ogg"], //兰格15 - [ - "羽狩的副队长", - "「那位少年说你是《不蚀金锁》的一员,不知此事是否属实?」", - "aiy430000160.ogg", - ], //兰格16 - ["凯伊姆", "「当然不是」", "aiy310000700.ogg"], //男主70 - ["凯伊姆", "「我只是从那里接受工作而已,并不是他们的成员」", "aiy310000710.ogg"], //男主71 - ["羽狩的副队长", "「你的意思是说,少年在说谎吗?」", "aiy430000170.ogg"], //兰格17 - ["凯伊姆", "「啊啊」", "aiy310000720.ogg"], //男主72 - [ - "凯伊姆", - "「如果你们和组织有关系的话,只要问问我是不是那里的成员就能明白事实了吧」", - "aiy310000730.ogg", - ], //男主73 - ["羽狩的副队长", "「就算我去询问,也无法从他们那里得到事实」", "aiy430000180.ogg"], //兰格18 - [ - "羽狩的副队长", - "「《不蚀金锁》的那些人一向都不对我们合作,我对此深感困扰」", - "aiy430000190.ogg", - ], //兰格19 - ["凯伊姆", "「真是辛苦啊」", "aiy310000740.ogg"], //男主74 - ["羽狩的副队长", "「说的是啊」", "aiy430000200.ogg"], //兰格20 - ["羽狩的副队长", "「其实,砍下我部下胳膊的似乎也是组织的成员呢」", "aiy430000210.ogg"], //兰格21 - [ - "羽狩的副队长", - "「无需如此警戒,我只是想在看守所向你咨询一些事情而已」", - "aiy430000220.ogg", - ], //兰格22 - [ - "羽狩的副队长", - "「如果能够知晓牢狱与组织的事情,我们也可以尽可能地对更多的羽化病人进行保护」", - "aiy430000230.ogg", - ], //兰格23 - ["羽狩的副队长", "「那和整条街道的和平也是紧密相关的吧?」", "aiy430000240.ogg"], //兰格24 - ["凯伊姆", "「我知道,你们有逮捕干扰狩猎羽化病人的权力」", "aiy310000750.ogg"], //男主75 - [ - "凯伊姆", - "「但是,我没有对你们做出任何干扰,为什么要对我如此纠缠不休呢」", - "aiy310000760.ogg", - ], //男主76 - ["羽狩的副队长", "「那些话,我们会在看守所对你详细说明的」", "aiy430000250.ogg"], //兰格25 - ["凯伊姆", "「······」", "aiy310000770.ogg"], //男主77 - ["", "在这里起争执的话,就会被羽狩加害。"], - ["", "就算能从这里脱身,今后只要碰面就会产生纠纷也是摆明的事情。"], - ["", "就算逃跑,也没有好的结果。"], - ["", "正当我想要打圆场的时候,刚才的气氛一瞬间产生了转变。"], - ["", "发生了什么事······"], - ["???", "「我认为,那位先生是正确的」", "aiy050000010.ogg"], //菲奥奈01 - ["", "羽狩们一起回头。"], - ["", "而在他们视线的焦点处,"], - ["", "伫立着一位女性。"], - ["", "在端正的容颜下,代表着强烈意志的双眉十分显眼。"], - ["", "身体的柔软与紧紧包裹在其身上的羽狩制服,两者显得十分的不搭配。"], - ["", "我还是第一次看到女性的羽狩。"], - ["羽狩的副队长", "「队长,这是获得《不蚀金锁》情报的好机会」", "aiy430000260.ogg"], //兰格26 - [ - "羽狩的队长", - "「兰格副队长,就算是为了获得情报,也不能做出恫吓的发言啊」", - "aiy050000020.ogg", - ], //菲奥奈02 - ["兰格副队长", "「我并没有打算去恫吓他······」", "aiy430000270.ogg"], //兰格27 - ["羽狩的队长", "「告诉我那个被砍掉胳膊的队员的名字」", "aiy050000030.ogg"], //菲奥奈03 - ["羽狩的队长", "「我会去探望他的」", "aiy050000040.ogg"], //菲奥奈04 - ["兰格副队长", "「那个是······」", "aiy430000280.ogg"], //兰格28 - ["羽狩的队长", "「我知道,你一直在为有所收获而努力工作」", "aiy050000050.ogg"], //菲奥奈05 - ["羽狩的队长", "「但是,正因为我们的工作是为民众提供帮助」", "aiy050000060.ogg"], //菲奥奈06 - ["羽狩的队长", "「所以就更不能损害人与人之间的信赖」", "aiy050000070.ogg"], //菲奥奈07 - ["兰格副队长", "「我会铭记在心」", "aiy430000290.ogg"], //兰格29 - ["羽狩的队长", "「这位先生,我的部下失礼了」", "aiy050000080.ogg"], //菲奥奈08 - ["凯伊姆", "「只要不对我再来一次就好」", "aiy310000780.ogg"], //男主78 - ["羽狩的队长", "「请稍等」", "aiy050000090.ogg"], //菲奥奈09 - ["凯伊姆", "「有什么事?」", "aiy310000790.ogg"], //男主79 - ["羽狩的队长", "「我想确认一件事」", "aiy050000100.ogg"], //菲奥奈10 - ["羽狩的队长", "「你真的不是《不蚀金锁》的成员吗?」", "aiy050000110.ogg"], //菲奥奈11 - ["凯伊姆", "「真的」", "aiy310000800.ogg"], //男主80 - ["凯伊姆", "「如果我说是的话,你有什么打算?」", "aiy310000810.ogg"], //男主81 - ["羽狩的队长", "「我听过传闻,说他们是用依靠暴力而得的钱在生活」", "aiy050000120.ogg"], //菲奥奈12 - ["凯伊姆", "「······这样啊」", "aiy310000820.ogg"], //男主82 - ["凯伊姆", "「如果能有收获就好了啊」", "aiy310000830.ogg"], //男主83 - ]; - this.chapter04 = [ - ["梅尔特", "「欢迎光临」", "aiy120000020.ogg"], //老板娘01,文件序号是以2开始,后续全部加1 - ["梅尔特", "「辛苦了」", "aiy120000030.ogg"], //老板娘02 - ["梅尔特", "「抱歉,又拜托给你了个这么麻烦的工作」", "aiy120000040.ogg"], //老板娘03 - ["凯伊姆", "「没什么,比想象中完成的更容易」", "aiy310000840.ogg"], //男主84 - ["梅尔特", "「那就好」", "aiy120000050.ogg"], //老板娘04 - ["梅尔特", "「这是我的一点谢意」", "aiy120000060.ogg"], //老板娘05 - ["凯伊姆", "「味道有些变化啊」", "aiy310000850.ogg"], //男主85 - ["梅尔特", "「啊,被发现了?」", "aiy120000070.ogg"], //老板娘06 - ["梅尔特", "「最近,没能到手什么好的原料呢」", "aiy120000080.ogg"], //老板娘07 - ["凯伊姆", "「去拜托吉克如何?」", "aiy310000860.ogg"], //男主86 - [ - "梅尔特", - "「话是这么说,但是总不能用店里采购的这种小事去麻烦他吧······」", - "aiy120000090.ogg" - ], //老板娘08 - ["凯伊姆", "「那希望你也不要来麻烦我」", "aiy310000870.ogg"], //男主87 - ["梅尔特", "「那 是 两 码 事」", "aiy120000100.ogg"], //老板娘09 - ["梅尔特", "「再说,凯伊姆是靠着工作来生活的吧」", "aiy120000110.ogg"], //老板娘10 - [ - "梅尔特", - "「而且,自己的钱被偷了这么害羞的事,向凯伊姆以外的其他人都说不出口」", - "aiy120000120.ogg" - ], //老板娘11 - ["凯伊姆", "「反正,也已经传到吉克的耳朵里了」", "aiy310000880.ogg"], //男主88 - ["梅尔特", "「这是面子问题啊,面子问题」", "aiy120000130.ogg"], //老板娘12 - ["凯伊姆", "「嘛,算了」", "aiy310000890.ogg"], //男主89 - ["凯伊姆", "「这样就好了吧?」", "aiy310000900.ogg"], //男主90 - ["梅尔特", "「这是钱包呢」", "aiy120000140.ogg"], //老板娘13 - ["梅尔特", "「嗯,东西没少」", "aiy120000150.ogg"], //老板娘14 - ["梅尔特", "「太好啦—这个月的上纳金,我可全部都放在里面了呢」", "aiy120000160.ogg"], //老板娘15 - ["梅尔特", "「如果没有找到的话,说不定就又会被送到娼馆里了呢」", "aiy120000170.ogg"], //老板娘16 - ["凯伊姆", "「在那边不是来钱更快吗?」", "aiy310000910.ogg"], //男主91 - ["梅尔特", "「阿拉,你是在说我还能有魅力吗?」", "aiy120000180.ogg"], //老板娘17 - ["凯伊姆", "「这是客套话而已」", "aiy310000920.ogg"], //男主92 - ["梅尔特", "「欺负人」", "aiy120000190.ogg"], //老板娘18 - ["梅尔特", "「总而言之,今天帮大忙了」", "aiy120000200.ogg"], //老板娘19 - ["梅尔特", "「谢礼嘛······」", "aiy120000210.ogg"], //老板娘20 - ["凯伊姆", "「就记在账单上吧」", "aiy310000930.ogg"], //男主93 - ["梅尔特", "「了解—盛谢惠顾了哦?」", "aiy120000220.ogg"], //老板娘21 - ["", "喀啷喀啷"], - ["", "门铃响起"], - ["", "喧哗瞬间安静下来。"], - ["", "进来的人是吉克。"], - ["", "是掌控着牢狱的组织之一,《不蚀金锁》的头目。"], - ["", "不仅组织的成员,就连店内一般的客人也对他以注目礼表示敬意。"], - ["吉克", "「各位继续吧」", "aiy340000010.ogg"], //吉克01 - ["", "仿佛停滞的时钟重新转动了一般,店内恢复了热闹的气氛。"], - ["吉克", "「抱歉,今天拜托你去做了无聊的工作」。", "aiy340000020.ogg"], //吉克02 - ["凯伊姆", "「不用介意」", "aiy310000940.ogg"], //男主94 - ["", "吉克轻轻点了点头,在我右边坐了下来"], - ["凯伊姆", "「逃跑的男人怎么样了?」", "aiy310000950.ogg"], //男主95 - ["吉克", "「嗯?已经不在这个世上了」。", "aiy340000030.ogg"], //吉克03 - ["吉克", "「有什么想要知道的事吗?」", "aiy340000040.ogg"], //吉克04 - ["凯伊姆", "「不,没什么」", "aiy310000960.ogg"], //男主96 - ["吉克", "「那个无聊的家伙,完全没有趣味呢」", "aiy340000050.ogg"], //吉克05 - ["吉克", "「真希望他也替我负责清扫的部下也考虑考虑」", "aiy340000060.ogg"], //吉克06 - ["凯伊姆", "「真是灾难啊」", "aiy310000970.ogg"], //男主97 - ["吉克", "「比起那个,我听说了哦。你去追羽化病人了啊」", "aiy340000070.ogg"], //吉克07 - ["凯伊姆", "「消息真灵通」", "aiy310000980.ogg"], //男主98 - ["吉克", "「梅尔特也注意点」", "aiy340000080.ogg"], //吉克08 - ["吉克", "「你丢钱已经不是一回两回了」", "aiy340000090.ogg"], //吉克09 - ["梅尔特", "「好的—我会注意的。」", "aiy120000230.ogg"], //老板娘22 - ["梅尔特", "「吉克还是平常的点单吧」", "aiy120000240.ogg"], //老板娘23 - ["梅尔特", "「凯伊姆要再来一杯吗?」", "aiy120000250.ogg"], //老板娘24 - ["", "我们用眼神点头示意后,梅尔特开始准备起酒来。"], - ["", "悠然地吐出眼圈后,吉克取出一个纸包放在柜台上。"], - ["吉克", "「这是抓捕逃跑男人的报酬」", "aiy340000100.ogg"], //吉克10 - ["凯伊姆", "「下次有什么事再告诉我」", "aiy310000990.ogg"], //男主99 - ["梅尔特", "「来,久等了」", "aiy120000260.ogg"], //老板娘25 - ["凯伊姆", "「话说回来梅尔特,为什么会被那种孩子偷到钱?」", "aiy310001000.ogg"], //男主100 - ["吉克", "「让我猜猜看」", "aiy340000110.ogg"], //吉克11 - ["吉克", "「是那个吧,看某个特立独行的男人入迷了,所以就有了空隙?」", "aiy340000120.ogg"], //吉克12 - ["梅尔特", "「可惜—」", "aiy120000270.ogg"], //老板娘26 - ["梅尔特", "「事实恰恰相反,是那家伙一直在纠缠我」", "aiy120000280.ogg"], //老板娘27 - ["凯伊姆", "「完全把你当成新进的女佣了么」", "aiy310001010.ogg"], //男主101 - ["梅尔特", "「我从前可是很有名的,不会被当成这种下人吧」", "aiy120000290.ogg"], //老板娘28 - ["梅尔特", "「······而且,我没法对对我这么钟情的人发火啊」", "aiy120000300.ogg"], //老板娘29 - ["凯伊姆&吉克", "「你傻啊」", "aiy310001027.ogg"], //男主102.7,吉克13.5 - ["梅尔特", "「异口同声呢,不亏是兄弟」", "aiy120000310.ogg"], //老板娘30 - ["凯伊姆", "「别用这种称呼,怪恶心的」", "aiy310001030.ogg"], //男主103 - ["吉克", "「说得没错」", "aiy340000140.ogg"], //吉克14 - ["吉克", "「······说起来······」", "aiy340000150.ogg"], //吉克15 - ["梅尔特", "「怎么了?」", "aiy120000320.ogg"], //老板娘31 - ["吉克", "「有件事我一直很在意,我和凯伊姆,哪个是哥哥啊?」", "aiy340000160.ogg"], //吉克16 - ["凯伊姆", "「你也说这么无聊的话题」", "aiy310001040.ogg"], //男主104 - ["吉克", "「不,这是很重要的事情」", "aiy340000170.ogg"], //吉克17 - ["吉克", "「梅尔特,事实是怎么样的?」", "aiy340000180.ogg"], //吉克18 - ["梅尔特", "「啊~是怎么样的呢~」", "aiy120000330.ogg"], //老板娘32 - ["梅尔特", "「我忘记了」", "aiy120000340.ogg"], //老板娘33 - ["吉克", "「骗人」", "aiy340000190.ogg"], //吉克19 - ["梅尔特", "「我说真的」", "aiy120000350.ogg"], //老板娘34 - ["梅尔特", "「嘛,如果想起来了的话,就算是卸载艺术上我也会公诸于众的」", "aiy120000360.ogg"], //老板娘35 - ["吉克", "「喔唷」", "aiy340000200.ogg"], //吉克20 - ["吉克", "「那么,我就不能比你先死了啊」", "aiy340000210.ogg"], //吉克21 - ["梅尔特", "「蒙你费心」", "aiy120000370.ogg"], //老板娘36 - ["梅尔特", "「顺带一提,有传言说吃过我们这里的料理后可以长生不老哦?」", "aiy120000380.ogg"], //老板娘37 - ["吉克", "「好,来两份炖菜,记得加腊肠」", "aiy340000220.ogg"], //吉克22 - ["梅尔特", "「多谢惠顾」", "aiy120000390.ogg"], //老板娘38 - ["", "微微一笑后,梅尔特去厨房传达点单。"], - ["凯伊姆", "「吉克······」", "aiy310001050.ogg"], //男主105 - ["吉克", "「啊,不好了」", "aiy340000230.ogg"], //吉克23 - ["凯伊姆", "「话题扯远了」", "aiy310001060.ogg"], //男主106 - ["梅尔特", "「什么话题来着?」", "aiy120000400.ogg"], //老板娘39 - ["凯伊姆", "「关于为什么你的钱会被偷这件事」", "aiy310001070.ogg"], //男主107 - ["凯伊姆", "「丢钱的时候以你来说,应该不会全无察觉吧?」", "aiy310001080.ogg"], //男主108 - ["梅尔特", "「算是吧,被偷的时候确实也想过要抓住他」", "aiy120000410.ogg"], //老板娘40 - ["梅尔特", "「但是,我注意到了那个孩子背后的鼓起呢」", "aiy120000420.ogg"], //老板娘41 - ["凯伊姆", "「所以就不由自主地放他逃跑了?」", "aiy310001090.ogg"], //男主109 - ["吉克", "「就算你想羽化病人施恩,也不会得到任何回报哦」", "aiy340000240.ogg"], //吉克24 - ["梅尔特", "「我知道」", "aiy120000430.ogg"], //老板娘42 - ["梅尔特", "「正因为知道,所以之后才会拜托凯伊姆去将钱取回的」", "aiy120000440.ogg"], //老板娘43 - ["梅尔特", "「可是,呢······」", "aiy120000450.ogg"], //老板娘44 - ["梅尔特", "「果然还是很矛盾呢」", "aiy120000460.ogg"], //老板娘45 - ["梅尔特", "「明明是自己放他逃跑的,之后又拜托别人去抓他」", "aiy120000470.ogg"], //老板娘46 - ["梅尔特", "「但是,在那一刹那······应该说是,突然露出了真心吧」", "aiy120000480.ogg"], //老板娘47 - ["梅尔特", "「真的,只是自我满足而已」", "aiy120000490.ogg"], //老板娘48 - ["凯伊姆", "「对于那个孩子来说不是很幸运么」", "aiy310001100.ogg"], //男主110 - ["凯伊姆", "「在被《不蚀金锁》抓到之前,就被羽狩保护了」", "aiy310001110.ogg"], //男主111 - ["凯伊姆", "「现在应该已经躺在治愈院的床上了」", "aiy310001120.ogg"], //男主112 - ["吉克", "「如果被我们抓到的话,嘛,至少也会断掉一根胳膊吧」", "aiy340000250.ogg"], //吉克25 - ["凯伊姆", "「比起失去胳膊,这不是个很好地结局吗」", "aiy310001130.ogg"], //男主113 - ["吉克", "「多亏梅尔特的一念之善,那个小子的胳膊被救下来了」", "aiy340000260.ogg"], //吉克26 - ["吉克", "「对我来说,不能去管教他稍微有点可惜就是了」", "aiy340000270.ogg"], //吉克27 - ["凯伊姆", "「我姑且是给了他两三拳」", "aiy310001140.ogg"], //男主114 - ["吉克", "「你这不是很善解人意么」", "aiy340000280.ogg"], //吉克28 - ["梅尔特", "「没有帮他的忙啊」", "aiy120000500.ogg"], //老板娘49 - ["凯伊姆", "「你给我用常识考虑考虑」", "aiy310001150.ogg"], //男主115 - ["梅尔特", "「本来,就算羽化病人不被羽狩带走而导致羽化病扩散,在牢狱里死亡的理由也要多少就有多少」", "aiy120000510.ogg"], //老板娘50 - ["梅尔特", "「没事到如今多一个病人,也不会有什么改变的吧」", "aiy120000520.ogg"], //老板娘51 - ["梅尔特", "「那么,那么些羽化病人为什么就不能和我们一起开心地生活呢」", "aiy120000530.ogg"], //老板娘52 - ["吉克", "「像梅尔特这样思考的人少之又少」", "aiy340000290.ogg"], //吉克29 - ["凯伊姆", "「就算早晚都会死去,为了今日的苟活而努力拼搏也是人之常情」", "aiy310001160.ogg"], //男主116 - ["梅尔特", "「我知道」", "aiy120000540.ogg"], //老板娘53 - ["梅尔特", "「别介意,我刚才只是顺口说说」", "aiy120000550.ogg"], //老板娘54 - ["", "喀啷喀啷"], - ["梅尔特", "「辛苦了,艾莉斯」", "aiy120000560.ogg"], //老板娘55 - ["艾莉斯", "「嗯」", "aiy020000190.ogg"], //医生19 - ["", "用不可爱的声音随口回应后,艾莉斯理所当然般地在我左边的座位坐下"], - ["", "梅尔特什么都没有问,就开始准备起茶来"], - ["梅尔特", "「多亏你去帮忙叫凯伊姆了呢」", "aiy120000570.ogg"], //老板娘56 - ["艾莉斯", "「不客气」", "aiy020000200.ogg"], //医生20 - ["艾莉斯", "「我从店里出去以后不久就看到他了,这是我们被命运之绳紧紧相连的证明呢」", "aiy020000210.ogg"], //医生21 - ["凯伊姆", "「那还真是糟糕」", "aiy310001170.ogg"], //男主117 - ["艾莉斯", "「用不着这么害羞的」", "aiy020000220.ogg"], //医生22 - ["凯伊姆", "「用茶堵上你的嘴吧」", "aiy310001180.ogg"], //男主118 - ["艾莉斯", "「好」", "aiy020000230.ogg"], //医生23 - ["梅尔特", "「司空见惯的风景呢」", "aiy120000580.ogg"], //老板娘57 - ["凯伊姆", "「你在那之后去做什么了?」", "aiy310001190.ogg"], //男主119 - ["艾莉斯", "「去莉莉乌姆照顾患病的女孩子了」", "aiy020000240.ogg"], //医生24 - ["艾莉斯", "「好像是毒品上瘾,费了很大劲才止住她的胡闹」", "aiy020000250.ogg"], //医生25 - ["艾莉斯", "「希望你能好好管理下自己店里的娼妇呢」", "aiy020000260.ogg"], //医生26 - ["吉克", "「抱歉啊」", "aiy340000300.ogg"], //吉克30 - ["吉克", "「为表歉意,就让我来给艾莉斯诊疗一下吧」", "aiy340000310.ogg"], //吉克31 - ["艾莉斯", "「去死吧」", "aiy020000270.ogg"], //医生27 - ["梅尔特", "「是什么药?」", "aiy120000590.ogg"], //老板娘58 - ["吉克", "「是最近上市的一种药」", "aiy340000320.ogg"], //吉克32 - ["吉克", "「虽然中毒的可能性很低,但只要中毒便会一发而不可收拾」", "aiy340000330.ogg"], //吉克33 - ["艾莉斯", "「知道了」", "aiy020000280.ogg"], //医生28 - ["吉克", "「虽然我也许没有时间去管教她,不过我还是会注意的」", "aiy340000340.ogg"], //吉克34 - ["艾莉斯", "「毒药的主人是吉克吗?」", "aiy020000290.ogg"], //医生29 - ["吉克", "「《不蚀金锁》不卖药,这是从先代定下的规矩」", "aiy340000350.ogg"], //吉克35 - ["艾莉斯", "「抱歉,开玩笑的」", "aiy020000300.ogg"], //医生30 - ["吉克", "「关于药的出处,这边也会调查的」", "aiy340000360.ogg"], //吉克36 - ["吉克", "「如果有什么传闻的话记得告诉我」", "aiy340000370.ogg"], //吉克37 - ["艾莉斯", "「知道了」", "aiy020000310.ogg"], //医生31 - ["艾莉斯", "「麻药中毒的人真麻烦呢,又不能完全治好」", "aiy020000320.ogg"], //医生32 - ["艾莉斯", "「既然要悄悄的打,那就也悄悄地去死不就好了」", "aiy020000330.ogg"], //医生33 - ["", "喀啷喀啷"], - ["奥兹", "「吉克大人,抱歉打扰你开心的时光」", "aiy350000240.ogg"], //金锁高官24 - ["吉克", "「怎么了」", "aiy340000380.ogg"], //吉克38 - ["奥兹", "「请将耳朵凑过来」", "aiy350000250.ogg"], //金锁高官25 - ["吉克", "「······知道了」", "aiy340000390.ogg"], //吉克39 - ["吉克", "「凯伊姆,一会到娼馆来一趟」", "aiy340000400.ogg"], //吉克40 - ["凯伊姆", "「啊啊」", "aiy310001200.ogg"], //男主120 - ["吉克", "「噢,我都给忘了」", "aiy340000410.ogg"], //吉克41 - ["吉克", "「让这里的大家都开心一下」", "aiy340000420.ogg"], //吉克42 - ["梅尔特", "「收到」", "aiy120000600.ogg"], //老板娘59 - ["吉克", "「我走了」", "aiy340000430.ogg"], //吉克43 - ["奥兹", "「好」", "aiy350000260.ogg"], //金锁高官26 - ["", "梆梆"], - ["梅尔特", "「大家静静,有个好消息」", "aiy120000610.ogg"], //老板娘60 - ["梅尔特", "「今天有个『大人物』要请客哦」", "aiy120000620.ogg"], //老板娘61 - ["艾莉斯", "「吉克还是一如既往的大方」", "aiy020000340.ogg"], //医生34 - ["梅尔特", "「果然,头目就应该像这样呢」", "aiy120000630.ogg"], //老板娘62 - ["凯伊姆", "「他的做法是继承先代的」", "aiy310001210.ogg"], //男主121 - ["梅尔特", "「又来了又来了」", "aiy120000640.ogg"], //老板娘63 - ["梅尔特", "「他想要赶上先代还早了十年呢」", "aiy120000650.ogg"], //老板娘64 - ["凯伊姆", "「有些太严厉了吧」", "aiy310001220.ogg"], //男主122 - ["艾莉斯", "「说起来,吉克有什么事」", "aiy020000350.ogg"], //医生35 - ["梅尔特", "「既然要叫上凯伊姆,再怎么说也不是什么小事吧?」", "aiy120000670.ogg"], //老板娘66 - ["凯伊姆", "「说的也是」", "aiy310001230.ogg"], //男主123 - ["艾莉斯", "「我期待看到你光荣负伤的样子」", "aiy020000360.ogg"], //医生36 - ["凯伊姆", "「不要为人的不幸祈求啊」", "aiy310001240.ogg"], //男主124 - ["梅尔特", "「来,喝完这杯就去加油工作吧」", "aiy120000680.ogg"], //老板娘67 - ["凯伊姆", "「啊啊」", "aiy310001250.ogg"], //男主125 - ["凯伊姆", "「我走了」", "aiy310001260.ogg"], //男主126 - ["艾莉斯", "「加油(受伤)吧」", "aiy020000370.ogg"], //医生37 - ["梅尔特", "「一路走好」", "aiy120000690.ogg"], //老板娘68 - ]; - this.chapter05 = [ - ["", "今晚的娼馆街比平常来得更加热闹"], - ["", "视线中可以看到很多生客。"], - ["莉莎", "「呀——!」", "aiy150000010.ogg"], //三小只C01 - ["莉莎", "「呐,凯伊姆凯伊姆凯伊姆」", "aiy150000020.ogg"], //三小只C02 - ["莉莎", "「我难道没有魅力吗?」", "aiy150000030.ogg"], //三小只C03 - ["凯伊姆", "「突然之间怎么了」", "aiy310001270.ogg"], //男主127 - ["莉莎", "「因为因为因为,明明这么热闹,却只有我没有接到客人」", "aiy150000040.ogg"], //三小只C04 - ["莉莎", "「亏我还对他们说,我会用超绝的技巧让他们舒服得如同化作夜明的流星般呢」", "aiy150000050.ogg"], //三小只C05 - ["凯伊姆", "「那个台词太糟糕了」", "aiy310001280.ogg"], //男主128 - ["莉莎", "「哎—什么啊,这可是我昨天花了一晚上考虑出来的呢」", "aiy150000060.ogg"], //三小只C06 - ["凯伊姆", "「去睡觉,不要用你那空空如也的脑袋去考虑这种无聊事」", "aiy310001290.ogg"], //男主129 - ["莉莎", "「好过分!?」", "aiy150000070.ogg"], //三小只C07 - ["凯伊姆", "「你看看周围,今天有很多新客人吧?」", "aiy310001300.ogg"], //男主130 - ["莉莎", "「嗯~~」", "aiy150000080.ogg"], //三小只C08 - ["莉莎", "「啊,你这么一说还真是」", "aiy150000090.ogg"], //三小只C09 - ["凯伊姆", "「他们心里都很紧张,不可能会被你这种强拉的手法钓上钩吧」", "aiy310001310.ogg"], //男主131 - ["莉莎", "「这样啊,是不想欲仙欲死吗?」", "aiy150000100.ogg"], //三小只C10 - ["凯伊姆", "「不,没有男人不会希望那样的」", "aiy310001320.ogg"], //男主132 - ["凯伊姆", "「不过,强来是不行的。去让他们被温柔地包容着化作流星吧」", "aiy310001330.ogg"], //男主133 - ["莉莎", "「原—来如此」", "aiy150000110.ogg"], //三小只C11 - ["莉莎", "「凯伊姆肯定很有娼妇的才能哦」", "aiy150000120.ogg"], //三小只C12 - ["凯伊姆", "「没有」", "aiy310001340.ogg"], //男主134 - ["凯伊姆", "「好了,你赶紧去赚钱吧」", "aiy310001350.ogg"], //男主135 - ["莉莎", "「收到—」", "aiy150000130.ogg"], //三小只C13 - ["", "莉莎精神满满地回答后,就啪嗒啪嗒地跑开了。"], - ["莉莎", "「呐—那边的大哥哥,和我一起化作星光吧—」", "aiy150000140.ogg"], //三小只C14 - ["", "这家伙"], - ["", "非要用这么麻烦的说法么。"], - ["", "咚"], - ["莉莎", "「呀」", "aiy150000150.ogg"], //三小只C15 - ["大胡子醉汉", "「好疼」", "aiy800000010.ogg"], - ["", "突然,莉莎与一个男人相撞。"], - ["", "虽然男人可以摆出派头,但从那虚浮的脚步可以看出他相当的醉意。"], - ["莉莎", "「好疼疼,对不起」", "aiy150000160.ogg"], //三小只C16 - ["大胡子醉汉", "「这不是道歉就能了事的事吧,大姐—」", "aiy800000020.ogg"], - ["大胡子醉汉", "「哟,穿得相当清凉啊,喂」", "aiy800000030.ogg"], - ["大肚子的醉汉", "「喂—怎么了?」", "aiy810000010.ogg"], - ["大胡子醉汉", "「这位小姐特意往我身上撞呢」", "aiy800000040.ogg"], - ["大肚子的醉汉", "「喂喂喂喂,你是要做什么」", "aiy810000020.ogg"], - ["莉莎", "「呜哎—所以我都说对不起了啊」", "aiy150000170.ogg"], //三小只C17 - ["莉莎", "「对,对了。作为冲撞的补偿,我会给您提供很好的服务的,怎么样?」", "aiy150000180.ogg"], //三小只C18 - ["大胡子醉汉", "「是免费的吧?」", "aiy800000050.ogg"], - ["莉莎", "「那个······这,这姑且也是工作······免费就太」", "aiy150000190.ogg"], //三小只C19 - ["大肚子的醉汉", "「真是的,娼妇就是这种人。钱,钱,钱,完全没有做人的诚意」", "aiy810000030.ogg"], - ["大胡子醉汉", "「好—你这家伙。我给你钱,你现在就在这里给我服务」", "aiy800000060.ogg"], - ["莉莎", "「这,这该怎么说呢,稍微有些过了吧,在这里做很害羞的」", "aiy150000200.ogg"], //三小只C20 - ["大胡子醉汉", "「你除了晃腰以外还有用得着脑子的地方吗?别说这种像个人说的话啊」", "aiy800000070.ogg"], - ["大肚子的醉汉", "「啊啊?这些钱不够吗?」", "aiy810000040.ogg"], - ["大胡子醉汉", "「来,赶快把脚张开让我O,你们最喜欢这种事了吧?」", "aiy800000080.ogg"], - ["莉莎", "「是,是认真的吗······这些人」", "aiy150000210.ogg"], //三小只C21 - ["大肚子的醉汉", "「赶快做」", "aiy810000050.ogg"], - ["莉莎", "「呃······」", "aiy150000220.ogg"], //三小只C22 - ["凯伊姆", "「喂」", "aiy310001360.ogg"], //男主136 - ["大肚子的醉汉", "「啊?」", "aiy810000060.ogg"], - ["凯伊姆", "「即便是娼妇,也有不能出售的东西」", "aiy310001370.ogg"], //男主137 - ["", "喀"], - ["", "我一拳击中男人被酒精染红的脸,"], - ["大胡子醉汉", "「咦」", "aiy800000090.ogg"], - ["", "嘎"], - ["", "再一拳击中另一个人的腹部。"], - ["大肚子的醉汉", "「咕······」", "aiy810000070.ogg"], - ["大胡子醉汉", "「唔······」", "aiy800000100.ogg"], - ["", "两人像两只毛虫般躺在地上蠕动着挣扎"], - ["", "一时半会应该起不来了吧"], - ["莉莎", "「凯伊姆先生,太迟了太迟了太迟了」", "aiy150000230.ogg"], //三小只C23 - ["凯伊姆", "「都是你闯出的祸吧」", "aiy310001380.ogg"], //男主138 - ["莉莎", "「话是,那么说,可是」", "aiy150000240.ogg"], //三小只C24 - ["凯伊姆", "「赶快回莉莉乌姆去」", "aiy310001390.ogg"], //男主139 - ["莉莎", "「唔,嗯。谢了,凯伊姆。再见」", "aiy150000250.ogg"], //三小只C25 - ["", "久留无用"], - ]; - this.chapter06 = [ - ["", "漂浮的紫烟与甜美香醇的空气。"], - - - ]; -}, + // 每项为一个数组,第一项是名字,第二项是对话内容,第三项为音频文件名(没有则不需要第三项) + // 回放只会在同一个this下回放,进入剧情前请以事件块声明进入哪个剧情数组 + this.chapter0 = [ + ["", "这些天,街道不曾下雨。"], + ["", "所以,那浸湿地面的,定是那些女孩们流落的鲜血无疑。"], + ["", "我蹲在充斥着铁锈味般恶臭的小巷中,悠闲地如是想着。"], + ["", "扑哧。"], + ["", "耳旁再次响起象征着某个女孩子死去的声音。"], + ["", "再一次——"], + ["", "再一次。"], + ["", "女子们被肢解成单纯的肉块。"], + ["", "我任由流下的血浸满全身,屏住自己的呼吸。"], + ["", "祈求自己能拥有从猎人手中逃脱的幸运。"], + ["", "扑哧。"], + ["", "直到刚才,我们还坐在去往娼馆的马车的路上。"], + ["", "而在这之中的某些人,已经不在这个世上了。"], + ["", "不,应该把“某些”换成“几乎所有”才更为恰当吧。"], + ["", "恐怕,不久之后我也会变成小巷中血腥的装饰品。"], + ["", "我是为了得到这种死法,才辛苦苟活至今的吗?"], + ["", "来个人告诉我啊——"], + ["", "谁都好。"], + ["", "来人啊!!"], + ["少女", "「呃······!?」", "aiy010000010.opus"], //小动物01 + ["", "漆黑的物体充斥了我的整个视野"], + ["", "我很快意识到,那是只很大的脚。"], + ["", "必须要出声求救。"], + ["", "可是,耳中却只能听到自己的牙关不停交战的声音。"], + ["", "我是如此的无助。"], + ["", "逃跑也好,道歉也罢。"], + ["", "就连抬头看一眼将要杀掉我的人的面孔都做不到。"], + ["少女", "「······被杀」", "aiy010000020.opus"], //小动物02 + ["", "会被杀。"], + ["", "会被杀!!"], + ["", "来自内心深处的冰冷预感,渐渐地在体内蔓延开来。"], + ["少女", "「不,不要······」", "aiy010000030.opus"], //小动物03 + ["", "浮游都市,《诺瓦斯·艾蒂尔》。"], + ["", "《特别受灾地区》——"], + ["", "通称,《牢狱》"], + ["", "是被险峻的峭壁环绕,与世隔绝的,都市的最底部。"], + ["年轻人", "「放开我!」", "aiy710000010.opus"], //龙套1-01 + ["年轻人", "「我只是在帮那个女人而已!」", "aiy710000020.opus"], //龙套1-02 + ["年轻人", "「你们没听到吗!?」", "aiy710000030.opus"], //龙套1-03 + ["年轻人", "「她是被受骗才会被卖到娼馆来的」", "aiy710000040.opus"], //龙套1-04 + [ + "年轻人", + "「用肮脏的手段把钱借给她父母的,就是你们这些家伙吧!?」", + "aiy710000050.opus", + ], //龙套1-05 + ["年轻人", "「给我说些什么啊」", "aiy710000060.opus"], //龙套1-06 + ["凯伊姆", "「这些话等到了娼馆再说吧」", "aiy310000010.opus"], //男主01 + ["凯伊姆", "「我来抓你,只是受雇于人而已」", "aiy310000020.opus"], //男主02 + ["", "我走进娼馆《莉莉乌姆》的接待室。"], + ["", "正在桌旁整理账簿的奥兹停下手头的工作,抬起头向我看来。"], + ["奥兹", "「这不是凯伊姆先生吗,辛苦了」", "aiy350000010.opus"], //金锁高官01 + ["奥兹", "「委托已经完成了吗?」", "aiy350000020.opus"], //金锁高官02 + ["凯伊姆", "「啊啊,是这家伙没错吧」", "aiy310000030.opus"], //男主03 + ["", "奥兹用只要接触到就能杀人般的眼神在男人脸上搜过。"], + ["奥兹", "「没错,就是这个人」", "aiy350000030.opus"], //金锁高官03 + ["凯伊姆", "「是么」", "aiy310000040.opus"], //男主04 + ["年轻人", "「你,你们要对我做什么」", "aiy710000070.opus"], //龙套1-07 + ["奥兹", "「······」", "aiy350000040.opus"], //金锁高官04 + ["", "奥兹用一个眼神,就让男人闭上了嘴。"], + ["", "然后,向我这边转过身来。"], + ["奥兹", "「抱歉啊,总是麻烦你去做这些无聊的事」", "aiy350000050.opus"], //金锁高官05 + ["奥兹", "「都怪我们这边的年轻人太没用」", "aiy350000060.opus"], //金锁高官06 + ["凯伊姆", "「客套话就免了」", "aiy310000050.opus"], //男主05 + ["奥兹", "「这还真是失礼了」", "aiy350000070.opus"], //金锁高官07 + ["奥兹", "「喂,来个人」", "aiy350000080.opus"], //金锁高官08 + ["光头男人", "「是」", "aiy820000010.opus"], //龙套2-01 + ["奥兹", "「凯伊姆先生做完工作回来了」", "aiy350000090.opus"], //金锁高官09 + ["光头男人", "「是,是,那个······」", "aiy820000020.opus"], //龙套2-02 + ["奥兹", "「我是要你拿些酒来,这个蠢材!」", "aiy350000100.opus"], //金锁高官10 + ["", "喀!"], + ["", "奥兹扔出的烟灰缸砸中了手下的额头。"], + ["", "鲜血四溅。"], + ["凯伊姆", "「不用这么麻烦」", "aiy310000060.opus"], //男主06 + ["凯伊姆", "「我接下来要去《菲诺列塔》」", "aiy310000070.opus"], //男主07 + ["奥兹", "「喔唷」", "aiy350000110.opus"], //金锁高官11 + [ + "奥兹", + "「既然如此,我就不留您在这里喝难饮的劣质酒了」", + "aiy350000120.opus", + ], //金锁高官12 + ["", "奥兹斜眼看着正捂住额头呻吟的手下,轻描淡写地说道。"], + ["凯伊姆", "「用这些钱去买药」", "aiy310000080.opus"], //男主08 + ["", "我将几枚铜钱仍在那个手下的身前。"], + ["奥兹", "「凯伊姆先生,不用对他们这么好」", "aiy350000130.opus"], //金锁高官13 + ["凯伊姆", "「无妨」", "aiy310000090.opus"], //男主09 + ["凯伊姆", "「话说回来,那个要落跑的女人呢?」", "aiy310000100.opus"], //男主10 + [ + "奥兹", + "「我把她交给那些年轻人了,现在应该正在体会人生的严苛吧」", + "aiy350000140.opus", + ], //金锁高官14 + [ + "奥兹", + "「正好,趁此机会凯伊姆先生也来享受一番如何?」", + "aiy350000150.opus", + ], //金锁高官15 + ["年轻人", "「你,你们这些家伙,要对她做什么!?」", "aiy710000080.opus"], //龙套1-08 + ["", "咣!"], + ["", "奥兹给了他一拳。"], + ["", "一击即倒。"], + ["", "喀,咚,咯!"], + ["", "奥兹毫不留情地向男人的脸上踩去。"], + ["年轻人", "「咕······呃咳······」", "aiy710000090.opus"], //龙套1-09 + ["", "折断的牙齿伴着血泡被吐出。"], + ["", "这份白色在鲜红色的液体中格外显眼。"], + [ + "年轻人", + "「你们以为做出这种事······卫兵会坐视不理吗······」", + "aiy710000100.opus", + ], //龙套1-10 + ["奥兹", "「啊啊,不会坐视不理的」", "aiy350000160.opus"], //金锁高官16 + [ + "奥兹", + "「应该会拿出你的钱包,和我们商量如何瓜分吧」", + "aiy350000170.opus", + ], //金锁高官17 + ["年轻人", "「那,那种事······」", "aiy710000110.opus"], //龙套1-11 + ["", "这在牢狱是理所当然的事。"], + ["奥兹", "「怎么,头一回来牢狱么?」", "aiy350000180.opus"], //金锁高官18 + ["", "男人点了点头。"], + [ + "奥兹", + "「为了被骗的女人而来到牢狱,真是个规矩人啊」", + "aiy350000190.opus", + ], //金锁高官19 + ["奥兹", "「······前提是,被骗的人不是你」", "aiy350000200.opus"], //金锁高官20 + ["年轻人", "「你说······我被骗了?」", "aiy710000120.opus"], //龙套1-12 + ["年轻人", "「那,那是怎么回事!?」", "aiy710000130.opus"], //龙套1-13 + ["奥兹", "「不用急,今天晚上会好好告诉你的」", "aiy350000210.opus"], //金锁高官21 + ["", "奥兹抓起男人的脸。"], + ["", "为引诱客人的怜悯之心而装纯,是娼妇的惯用手段。"], + ["", "双亲被骗而借钱,结果作为抵押而将自己卖到这里,这是典型的说法。"], + [ + "", + "如果只是头脑发热而成为常客也就罢了,这次的男人热血过头,居然想出了要带女人私奔的计划。", + ], + [ + "", + "虽然女人半开玩笑地予以拒绝,但不知天高地厚的这家伙还是拉着她逃跑了。", + ], + ["", "不过,想要逃脱追击本来就是不可能的任务。"], + ["", "但即便如此,这种事情还是会一再的出现。"], + ["", "说谎的女人和被骗的男人。"], + ["", "在娼馆街,这是令人看到生厌的日常的风景。"], + ["凯伊姆", "「我要走了」", "aiy310000110.opus"], //男主11 + ["奥兹", "「好的,下次再麻烦您」", "aiy350000220.opus"], //金锁高官22 + ["奥兹", "「之后吉克先生会将谢礼交给您的」", "aiy350000230.opus"], //金锁高官23 + ["凯伊姆", "「啊啊」", "aiy310000120.opus"], //男主12 + ["", "我背向奥兹走出娼馆。"], + ["凯伊姆", "「······?」", "aiy310000130.opus"], //男主13 + ["", "从远方传来微弱的歌声。"], + ["", "是关卡广场的方向。"], + ["", "对了。"], + ["", "今天有觐见圣女的仪式。"], + ["", "当代的圣女伊莲——"], + ["", "俗称《盲眼之圣女》,据说即使在历代的圣女中,人气也是数一数二的。"], + ["", "广场上的人估计相当多吧。"], + ["", "虽然我也想去看看她长什么样,不过要在人潮中挤来挤去就免了。"], + ["", "还是老老实实去菲诺列塔喝烧酒吧。"], + ["", "正当我这样想着的时候,一个身影自小巷的那头走来。"], + ["凯伊姆", "「艾莉斯」", "aiy310000140.opus"], //男主14 + ]; + this.chapter01 = [ + ["艾莉斯", "「啊,凯伊姆」", "aiy020000005.opus"], //医生00.5 + ["艾莉斯", "「正好,我还想要去找你呢」", "aiy020000010.opus"], //医生01 + [ + "艾莉斯", + "「没想到凯伊姆会主动出现······这是命运吗?」", + "aiy020000020.opus", + ], //医生02 + ["凯伊姆", "「显然不是吧」", "aiy310000150.opus"], //男主15 + ["艾莉斯", "「啊,是么」", "aiy020000030.opus"], //医生03 + ["", "艾莉斯挑了挑整齐的双眉,微微地哼了一声。"], + [ + "", + "虽然是个相当引人注目的美人,但她这个将亲切儿子丢入无底深渊的性格,为自己扣了不少的分", + ], + ["", "给人印象最深的,就是那潭水般的双瞳。"], + ["", "在漆黑的瞳孔中,完全看不出感情的波动。"], + ["艾莉斯", "「喜欢我的眼睛吗?」", "aiy020000040.opus"], //医生04 + ["艾莉斯", "「如果想要的话就给你吧?」", "aiy020000050.opus"], //医生05 + ["凯伊姆", "「用不着」", "aiy310000160.opus"], //男主16 + ["艾莉斯", "「阿拉,可惜」", "aiy020000060.opus"], //医生06 + ["凯伊姆", "「那么,找我有什么事」", "aiy310000170.opus"], //男主17 + ["艾莉斯", "「梅尔特的钱好像被偷了」", "aiy020000070.opus"], //医生07 + ["凯伊姆", "「钱被偷了?都几岁了还这么没用」", "aiy310000180.opus"], //男主18 + ["艾莉斯", "「不要对我说啊」", "aiy020000080.opus"], //医生08 + [ + "凯伊姆", + "「那家伙,该不会说要让我去抓那个小偷吧?」", + "aiy310000190.opus", + ], //男主19 + ["艾莉斯", "「就是这样」", "aiy020000090.opus"], //医生09 + ["凯伊姆", "「笨蛋吗」", "aiy310000200.opus"], //男主20 + ["凯伊姆", "「如果是小钱的话,就当做是买个教训吧」", "aiy310000210.opus"], //男主21 + ["艾莉斯", "「说起来,被盗的是这个月的上纳金」", "aiy020000100.opus"], //医生10 + ["凯伊姆", "「你说什么?」", "aiy310000220.opus"], //男主22 + ["艾莉斯", "「用这些钱买教训,也太过奢侈了呢」", "aiy020000110.opus"], //医生11 + ["凯伊姆", "「知道了,我去找」", "aiy310000230.opus"], //男主23 + ["凯伊姆", "「小偷的特征呢」", "aiy310000240.opus"], //男主24 + ["艾莉斯", "「男孩子」", "aiy020000120.opus"], //医生12 + ["艾莉斯", "「······而且,背后有翅膀」", "aiy020000130.opus"], //医生13 + [ + "艾莉斯", + "「虽然姑且是藏在身后,但是仔细观察的话是很明显的」", + "aiy020000140.opus", + ], //医生14 + ["凯伊姆", "「羽化病吗」", "aiy310000250.opus"], //男主25 + [ + "艾莉斯", + "「那些人可是毫不留情的,所以即使是为了那个孩子,也要赶快抓到他」", + "aiy020000150.opus", + ], //医生15 + ["凯伊姆", "「注意到他逃窜的方向了吗?」", "aiy310000260.opus"], //男主26 + ["艾莉斯", "「广场那边」", "aiy020000160.opus"], //医生16 + [ + "艾莉斯", + "「虽然刚才《不蚀金锁》的人去追了,不过多半是······」", + "aiy020000170.opus", + ], //医生17 + ["凯伊姆", "「偏偏还是广场吗」", "aiy310000280.opus"], //男主28 + ["艾莉斯", "「今天是觐见圣女大人的日子」", "aiy020000180.opus"], //医生18 + ["凯伊姆", "「我知道」", "aiy310000290.opus"], //男主29 + ["凯伊姆", "「尽量找找看就好」", "aiy310000300.opus"], //男主30 + ]; + this.chapter02 = [ + ["不蚀金锁成员", "「凯伊姆先生,凯伊姆先生」", "aiy860000010.ogg"], + [ + "不蚀金锁成员", + "「您已经和艾莉斯大夫见过面了吗?」", + "aiy860000020.ogg", + ], + ["凯伊姆", "「啊啊,所以才会追过来的」", "aiy310000310.ogg"], //男主31 + ["凯伊姆", "「看到小偷了吗?」", "aiy310000320.ogg"], //男主32 + [ + "不蚀金锁成员", + "「没有,他向广场那边逃了过去,今天这么拥挤,我们也只能放弃了」", + "aiy860000030.ogg", + ], + [ + "不蚀金锁成员", + "「不过,我也只是刚好在店里所以才追了过去,并不是受人所托」", + "aiy860000040.ogg", + ], + ["不蚀金锁成员", "「我已经准备撤退了」", "aiy860000050.ogg"], + ["不蚀金锁成员", "「凯伊姆先生还要继续追吗?」", "aiy860000060.ogg"], + ["凯伊姆", "「啊啊」", "aiy310000330.ogg"], //男主33 + ["", "做完情报交换之后,我跟男人道别。"], + ["凯伊姆", "「和我想的一样啊······」", "aiy310000340.ogg"], //男主34 + ["", "在牢狱中最大的广场上,聚集着看不到尽头的人群。"], + ["", "就算是来参见圣女祈祷,这人数也太多了点吧。"], + ["", "自然,我也找不到逃跑的孩子。"], + ["", "是混杂到人群中了吧。"], + ["", "如果已经从广场上脱身了的话,就更难发现了。"], + ["", "只好赌他还在这里了。"], + ["", "我先移动到了一个视野良好的地方。"], + ["", "从这里,一眼就可以看到人群的变化。"], + ["", "广场还是沸腾起来。"], + ["", "抬头望去,原来是在天台之上出现了一个人影"], + ["", "但是,与周围的期待不同,现身的是一名中年的神官。"], + ["", "骂声四溢。"], + ["", "神官则是笑着摆正衣领"], + ["神官", "「从现在开始,举行谒见的仪式」", "aiy440000010.ogg"], //神官01 + [ + "神官", + "「在参见那位大人之前,我希望牢狱的诸位再次思考这个《诺瓦斯·艾蒂尔》存在的意义······」", + "aiy440000020.ogg", + ], //神官02 + [ + "神官", + "「初代圣女伊莲大人,便是也难怪这崇高的祈祷之力,令《诺瓦斯·艾蒂尔》浮在空中,拯救了我们的祖先」", + "aiy440000030.ogg", + ], //神官03 + [ + "神官", + "「这之后的几百年来,传承了初代大人力量的历代圣女伊莲大人,让这里留在了空中」", + "aiy440000040.ogg", + ], //神官04 + [ + "神官", + "「这座都市是被圣女大人守护的人类最后的圣域,而我们则是被选召的虔诚的信徒」", + "aiy440000050.ogg", + ], //神官05 + [ + "神官", + "「怀着对圣女的感激祈祷吧,感谢圣女伊莲吧!并献上祈祷!」", + "aiy440000060.ogg", + ], //神官06 + ["圣女", "「不忘感谢与祈祷,神才会拯救我们」", "aiy030000010.ogg"], //圣女01 + ["圣女", "「与我一起,向神虔诚地祈祷吧」", "aiy030000020.ogg"], //圣女02 + ["", "广场上欢声雷动。"], + ["", "圣女没有回应喧嚣的人声,而是静静地合上双眼面向广场。"], + ["", "虽然感觉有些冷淡,但总比像个傻瓜似的笑着向这群人挥手要强。"], + ["", "她掌握着这条街道,还有在这条街上生活的人的命运。"], + ["", "比起揽得人气,她更想要为了街道的继续存在而献出全力。"], + ["", "也是为了不让《大崩落》的惨剧再度发生。"], + ["", "十几年前的那场悲剧。"], + [ + "", + "虽然在我脑海中的记忆已经相当模糊,但哪怕只是稍有触及,不快的感觉都会在胸口蔓延开。", + ], + ["凯伊姆", "「······」", "aiy310000350.ogg"], //男主35 + ["", "这时我才想起,现在不是我在这里看圣女的时候。"], + ["女声", "「——っ!?」", "aiy510000010.ogg"], + ["围观的女人", "「羽,羽化病人!?」", "aiy510000020.ogg"], + ["围观的中年人", "「喂,谁去叫下羽狩」", "aiy720000010.ogg"], + [ + "惊慌的观众", + "「你这家伙不要靠近我,要是传染了可怎么办」", + "aiy730000010.ogg", + ], + ["粗鲁的观众", "「你这小鬼赶快滚开」", "aiy740000010.ogg"], + ["凯伊姆", "「接下来」", "aiy310000360.ogg"], //男主36 + ["圣女", "「发生什么事了?看上去似乎很嘈杂」", "aiy030000030.ogg"], //圣女03 + [ + "随从", + "「似乎是某个人逃跑了······具体的我也不是很清楚」", + "aiy130000010.ogg", + ], //侍从01 + [ + "神官", + "「圣女大人,继续待在天台上可能会出事,请您先回到室内吧」", + "aiy440000070.ogg", + ], //神官07 + [ + "圣女", + "「不用在意我,比起那个,我更关心究竟发生了什么事」", + "aiy030000050.ogg", + ], //圣女05 + ["神官", "「对不起,我真的不知道」", "aiy440000080.ogg"], //神官08 + ["圣女", "「······是吗」", "aiy030000060.ogg"], //圣女06 + ["男", "「恕我僭越,请准许我说明情况」", "aiy320000010.ogg"], //男主他哥01 + ["男", "「在来觐见的人群中出现了《羽化病》的患者」", "aiy320000020.ogg"], //男主他哥02 + ["男", "「围观的人群因而产生了骚动」", "aiy320000030.ogg"], //男主他哥03 + [ + "男", + "「现在,《防疫局》已经派遣了部队。我想不久之后,他们就会安静下来了」", + "aiy320000040.ogg", + ], //男主他哥04 + ["圣女", "「羽化病······」", "aiy030000070.ogg"], //圣女07 + ["男", "「怎么了?」", "aiy320000050.ogg"], //男主他哥05 + ["圣女", "「没什么」", "aiy030000080.ogg"], //圣女08 + ["圣女", "「辛苦了,你的名字是?」", "aiy030000090.ogg"], //圣女09 + [ + "男", + "「属下是在防疫局任职的,鲁基乌斯· 迪斯·米利尤」", + "aiy320000060.ogg", + ], //男主他哥06 + [ + "神官", + "「噢噢,阁下就是鲁基乌斯卿吗,我听说过你的传闻」", + "aiy440000090.ogg", + ], //神官09 + ["神官", "「阁下是在工作上相当出色的人呢」", "aiy440000100.ogg"], //神官10 + ["鲁基乌斯", "「不敢当」", "aiy320000070.ogg"], //男主他哥07 + [ + "鲁基乌斯", + "「话说回来,这次是属下警备工作的失职。让圣女大人见到这不成体统的一面,请您见谅」", + "aiy320000080.ogg", + ], //男主他哥08 + [ + "圣女", + "「即使是目不见物的我,也能感受到聚集于此的民众数量之多。警备工作难以展开也在情理之中」", + "aiy030000100.ogg", + ], //圣女10 + ["鲁基乌斯", "「属下不胜惶恐」", "aiy320000090.ogg"], //男主他哥09 + [ + "鲁基乌斯", + "「接下来属下还要回到工作岗位上,在这里就先告退了」", + "aiy320000100.ogg", + ], //男主他哥10 + ["圣女", "「鲁基乌斯先生」", "aiy030000110.ogg"], //圣女11 + ["鲁基乌斯", "「属下在」", "aiy320000110.ogg"], //男主他哥11 + ["圣女", "「你是怎样看待羽狩的工作的呢?」", "aiy030000120.ogg"], //圣女12 + ["神官", "「圣,圣女大人」", "aiy440000110.ogg"], //神官11 + [ + "鲁基乌斯", + "「防疫局的工作是国王陛下赐予的重要职务。属下非常荣幸能够为这个都市的繁荣尽一份微薄之力」", + "aiy320000120.ogg", + ], //男主他哥12 + ["神官", "「不,不亏是鲁基乌斯卿,相当优秀的想法」", "aiy440000120.ogg"], //神官12 + ["圣女", "「是吗。辛苦你了」", "aiy030000130.ogg"], //圣女13 + ["随从", "「圣女大人······」", "aiy130000020.ogg"], //侍从02 + ["鲁基乌斯", "「······」", "aiy320000135.ogg"], //男主他哥13 + ["鲁基乌斯", "「那么,属下就回岗位去了」", "aiy320000140.ogg"], //男主他哥14 + ]; + this.chapter03 = [ + ["", "从羽化病的少年纷乱的足音中,可以听得出相当的疲劳。"], + ["", "显然,他并没有想到我会捷足先登吧。"], + ["", "少年惶恐地回头看了一眼后,微微露出安心的表情,双手拄在膝盖上。。"], + ["凯伊姆", "「辛苦你了」", "aiy310000370.ogg"], //男主37 + ["羽化病患少年", "「稀!?」", "aiy750000010.ogg"], + ["凯伊姆", "「逃到贫民区是个不错的想法」", "aiy310000380.ogg"], //男主38 + ["羽化病患少年", "「你,你是,羽狩吗?」", "aiy750000020.ogg"], + ["凯伊姆", "「不是」", "aiy310000390.ogg"], //男主39 + [ + "羽化病患少年", + "「什,什么啊······混蛋,不要吓我啊」", + "aiy750000030.ogg", + ], + ["凯伊姆", "「我对令你受惊这件事致以歉意」", "aiy310000400.ogg"], //男主40 + [ + "凯伊姆", + "「作为回报,麻烦你把从店里偷的钱交出来吧」", + "aiy310000410.ogg", + ], //男主41 + ["羽化病患少年", "「钱?你在说什么」", "aiy750000040.ogg"], + ["凯伊姆", "「你要找的腰上的东西,掉在你身后了」", "aiy310000420.ogg"], //男主42 + ["羽化病患少年", "「哎?」", "aiy750000050.ogg"], + ["羽化病患少年", "「呃呀」", "aiy750000060.ogg"], + ["羽化病患少年", "「你······你这混蛋」", "aiy750000070.ogg"], + ["凯伊姆", "「······」", "aiy310000430.ogg"], //男主43 + ["凯伊姆", "「把偷的钱交出来」", "aiy310000440.ogg"], //男主44 + ["羽化病患少年", "「我不知道你在······咕」", "aiy750000080.ogg"], + [ + "羽化病患少年", + "「你,你说是我偷的······有什么证据吗」", + "aiy750000090.ogg", + ], + ["凯伊姆", "「你还挺倔的啊」", "aiy310000450.ogg"], //男主45 + ["凯伊姆", "「不过,给我听好了」", "aiy310000460.ogg"], //男主46 + [ + "凯伊姆", + "「你偷的那些钱,是要上缴给《不蚀金锁》的上纳金」", + "aiy310000470.ogg", + ], //男主47 + [ + "凯伊姆", + "「而且,钱的主人是从前和吉克颇有渊源的女人」", + "aiy310000480.ogg", + ], //男主48 + ["羽化病患少年", "「吉克?」", "aiy750000100.ogg"], + [ + "凯伊姆", + "「他是《不蚀金锁》的主人,这么说你就明白了吧」", + "aiy310000490.ogg", + ], //男主49 + ["羽化病患少年", "「哎?哎?怎么会······」", "aiy750000110.ogg"], + ["凯伊姆", "「再问你一遍,钱在哪里?」", "aiy310000510.ogg"], //男主51 + ["羽化病患少年", "「是,是,是,在我的怀里」", "aiy750000120.ogg"], + ["凯伊姆", "「你没有擅自拿掉一部分吧」", "aiy310000520.ogg"], //男主52 + ["羽化病患少年", "「是,是的」", "aiy7500000130.ogg"], + [ + "羽化病患少年", + "「那,那个,您是《不蚀金锁》的人吗?」", + "aiy750000140.ogg", + ], + ["凯伊姆", "「算是吧」", "aiy310000530.ogg"], //男主53 + [ + "羽化病患少年", + "「我什么都可以做,请您一定要帮帮我」", + "aiy750000150.ogg", + ], + ["凯伊姆", "「抱歉,我并没有兴趣去帮助他人」", "aiy310000540.ogg"], //男主54 + [ + "羽化病患少年", + "「我什么······什么,都会做的······」", + "aiy750000160.ogg", + ], + ["羽化病患少年", "「我一直都是生活在下层的」", "aiy750000170.ogg"], + [ + "羽化病患少年", + "「可是,不知何时染上了羽化病······背后长出了翅膀······」", + "aiy750000180.ogg", + ], + [ + "羽化病患少年", + "「被寄宿工作的店赶了出来,只得流落到牢狱这里」", + "aiy750000190.ogg", + ], + [ + "羽化病患少年", + "「因为独自实在是饿的不行了,所以才会偷这些钱的」", + "aiy750000200.ogg", + ], + [ + "羽化病患少年", + "「我明明没有做任何坏事······为什么······会遇到这种事······」", + "aiy750000210.ogg", + ], + ["凯伊姆", "「谁知道」", "aiy310000550.ogg"], //男主55 + [ + "羽化病患少年", + "「呜······呜呜······接下来,要对我做什么?」", + "aiy750000220.ogg", + ], + ["凯伊姆", "「我要把你带到组织那里」", "aiy310000560.ogg"], //男主56 + ["羽化病患少年", "「怎,怎么这样」", "aiy750000230.ogg"], + ["凯伊姆", "「不过,那样做的前提是你不是羽化病人」", "aiy310000570.ogg"], //男主57 + [ + "凯伊姆", + "「组织也没有笨到把羽化病人招待到家里的程度」", + "aiy310000580.ogg", + ], //男主58 + ["羽化病患少年", "「那么,是要放我逃走吗?」", "aiy750000240.ogg"], + ["凯伊姆", "「我要让你学到教训」", "aiy310000590.ogg"], //男主59 + [ + "凯伊姆", + "「如果换做是组织的制裁,至少要有断条胳膊的觉悟」", + "aiy310000600.ogg", + ], //男主60 + ["凯伊姆", "「你的运气不错」", "aiy310000610.ogg"], //男主61 + ["羽化病患少年", "「唔······啊,是的······」", "aiy750000250.ogg"], + ["凯伊姆", "「滚」", "aiy310000620.ogg"], //男主62 + ["羽化病患少年", "「非常感谢」", "aiy750000260.ogg"], + ["羽化病患少年", "「唔啊!?」", "aiy750000270.ogg"], + ["男", "「到这里就结束了,羽化病人」", "aiy430000010.ogg"], //兰格01 + ["男", "「确认他的翅膀」", "aiy430000020.ogg"], //兰格02 + ["", "趁还没有被卷入麻烦的事情之前,赶快离开这里吧"], + ["羽狩的指挥者", "「那边的那个人」", "aiy430000030.ogg"], //兰格03 + ["凯伊姆", "「······有什么事?」", "aiy310000630.ogg"], //男主63 + ["羽狩的指挥者", "「可以稍微让我问几句话吗」", "aiy430000040.ogg"], //兰格04 + ["凯伊姆", "「······」", "aiy310000640.ogg"], //男主64 + ["凯伊姆", "「啊啊,无妨」", "aiy310000650.ogg"], //男主65 + ["羽狩的指挥者", "「感谢您的合作」", "aiy430000050.ogg"], //兰格05 + ["", "队长殷勤地致以谢礼。"], + ["", "而在他的眼前,少年的衣服已经被他的补下们扯破。"], + ["", "在瘦骨嶙峋的裸露后背上,长有纯白的羽翼。"], + ["红发的羽狩", "「副队长,确认翅膀的持有了」"], + ["羽狩的副队长", "「保护他」", "aiy430000060.ogg"], //兰格06 + ["羽化病患少年", "「不要······请原谅,我······」", "aiy750000280.ogg"], + [ + "羽狩的副队长", + "「我们只是要带你去治愈院治疗羽化病,不是什么应该感到害怕的事情」", + "aiy430000070.ogg", + ], //兰格07 + ["羽化病患少年", "「可是,可是」", "aiy750000290.ogg"], + ["羽狩的副队长", "「没关系的」", "aiy430000080.ogg"], //兰格08 + ["羽化病患少年", "「······哥,哥哥」", "aiy750000300.ogg"], + ["羽狩的副队长", "「你是羽化病人的亲属吗?」", "aiy430000090.ogg"], //兰格09 + ["凯伊姆", "「只是路人而已」", "aiy310000660.ogg"], //男主66 + ["凯伊姆", "「顺带一提,我也没有打算找你们的麻烦」", "aiy310000670.ogg"], //男主67 + [ + "羽狩的副队长", + "「前几天,有个和你说了同样的话的人,在我们背向他的瞬间对我们发动了袭击」", + "aiy430000100.ogg", + ], //兰格10 + [ + "羽狩的副队长", + "「我的一个部下就此永久失去了半截胳膊」", + "aiy430000110.ogg", + ], //兰格11 + ["凯伊姆", "「我表示同情」", "aiy310000680.ogg"], //男主68 + [ + "凯伊姆", + "「我马上就会消失的,这样就没问题了吧?」", + "aiy310000690.ogg", + ], //男主69 + ["羽狩的副队长", "「嘛,不要这么慌张」", "aiy430000120.ogg"], //兰格12 + ["", "副队长看着羽化的少年。"], + [ + "羽狩的副队长", + "「你与这个人是什么关系?没有被他殴打吗?」", + "aiy430000130.ogg", + ], //兰格13 + ["羽化病患少年", "「没,没有」", "aiy750000310.ogg"], + [ + "羽狩的副队长", + "「如何对我们保持合作,你就可以在治愈院得到优先的治疗」", + "aiy430000140.ogg", + ], //兰格14 + ["羽化病患少年", "「······」", "aiy750000320.ogg"], + [ + "羽化病患少年", + "「那个人,是《不蚀金锁》的组织成员······」", + "aiy750000330.ogg", + ], + [ + "羽化病患少年", + "「突然说让我拿出钱来,我刚一拒绝他就打我」", + "aiy750000340.ogg", + ], + ["羽狩的副队长", "「原来如此······」", "aiy430000150.ogg"], //兰格15 + [ + "羽狩的副队长", + "「那位少年说你是《不蚀金锁》的一员,不知此事是否属实?」", + "aiy430000160.ogg", + ], //兰格16 + ["凯伊姆", "「当然不是」", "aiy310000700.ogg"], //男主70 + [ + "凯伊姆", + "「我只是从那里接受工作而已,并不是他们的成员」", + "aiy310000710.ogg", + ], //男主71 + ["羽狩的副队长", "「你的意思是说,少年在说谎吗?」", "aiy430000170.ogg"], //兰格17 + ["凯伊姆", "「啊啊」", "aiy310000720.ogg"], //男主72 + [ + "凯伊姆", + "「如果你们和组织有关系的话,只要问问我是不是那里的成员就能明白事实了吧」", + "aiy310000730.ogg", + ], //男主73 + [ + "羽狩的副队长", + "「就算我去询问,也无法从他们那里得到事实」", + "aiy430000180.ogg", + ], //兰格18 + [ + "羽狩的副队长", + "「《不蚀金锁》的那些人一向都不对我们合作,我对此深感困扰」", + "aiy430000190.ogg", + ], //兰格19 + ["凯伊姆", "「真是辛苦啊」", "aiy310000740.ogg"], //男主74 + ["羽狩的副队长", "「说的是啊」", "aiy430000200.ogg"], //兰格20 + [ + "羽狩的副队长", + "「其实,砍下我部下胳膊的似乎也是组织的成员呢」", + "aiy430000210.ogg", + ], //兰格21 + [ + "羽狩的副队长", + "「无需如此警戒,我只是想在看守所向你咨询一些事情而已」", + "aiy430000220.ogg", + ], //兰格22 + [ + "羽狩的副队长", + "「如果能够知晓牢狱与组织的事情,我们也可以尽可能地对更多的羽化病人进行保护」", + "aiy430000230.ogg", + ], //兰格23 + [ + "羽狩的副队长", + "「那和整条街道的和平也是紧密相关的吧?」", + "aiy430000240.ogg", + ], //兰格24 + [ + "凯伊姆", + "「我知道,你们有逮捕干扰狩猎羽化病人的权力」", + "aiy310000750.ogg", + ], //男主75 + [ + "凯伊姆", + "「但是,我没有对你们做出任何干扰,为什么要对我如此纠缠不休呢」", + "aiy310000760.ogg", + ], //男主76 + [ + "羽狩的副队长", + "「那些话,我们会在看守所对你详细说明的」", + "aiy430000250.ogg", + ], //兰格25 + ["凯伊姆", "「······」", "aiy310000770.ogg"], //男主77 + ["", "在这里起争执的话,就会被羽狩加害。"], + ["", "就算能从这里脱身,今后只要碰面就会产生纠纷也是摆明的事情。"], + ["", "就算逃跑,也没有好的结果。"], + ["", "正当我想要打圆场的时候,刚才的气氛一瞬间产生了转变。"], + ["", "发生了什么事······"], + ["???", "「我认为,那位先生是正确的」", "aiy050000010.ogg"], //菲奥奈01 + ["", "羽狩们一起回头。"], + ["", "而在他们视线的焦点处,"], + ["", "伫立着一位女性。"], + ["", "在端正的容颜下,代表着强烈意志的双眉十分显眼。"], + ["", "身体的柔软与紧紧包裹在其身上的羽狩制服,两者显得十分的不搭配。"], + ["", "我还是第一次看到女性的羽狩。"], + [ + "羽狩的副队长", + "「队长,这是获得《不蚀金锁》情报的好机会」", + "aiy430000260.ogg", + ], //兰格26 + [ + "羽狩的队长", + "「兰格副队长,就算是为了获得情报,也不能做出恫吓的发言啊」", + "aiy050000020.ogg", + ], //菲奥奈02 + ["兰格副队长", "「我并没有打算去恫吓他······」", "aiy430000270.ogg"], //兰格27 + [ + "羽狩的队长", + "「告诉我那个被砍掉胳膊的队员的名字」", + "aiy050000030.ogg", + ], //菲奥奈03 + ["羽狩的队长", "「我会去探望他的」", "aiy050000040.ogg"], //菲奥奈04 + ["兰格副队长", "「那个是······」", "aiy430000280.ogg"], //兰格28 + [ + "羽狩的队长", + "「我知道,你一直在为有所收获而努力工作」", + "aiy050000050.ogg", + ], //菲奥奈05 + [ + "羽狩的队长", + "「但是,正因为我们的工作是为民众提供帮助」", + "aiy050000060.ogg", + ], //菲奥奈06 + [ + "羽狩的队长", + "「所以就更不能损害人与人之间的信赖」", + "aiy050000070.ogg", + ], //菲奥奈07 + ["兰格副队长", "「我会铭记在心」", "aiy430000290.ogg"], //兰格29 + ["羽狩的队长", "「这位先生,我的部下失礼了」", "aiy050000080.ogg"], //菲奥奈08 + ["凯伊姆", "「只要不对我再来一次就好」", "aiy310000780.ogg"], //男主78 + ["羽狩的队长", "「请稍等」", "aiy050000090.ogg"], //菲奥奈09 + ["凯伊姆", "「有什么事?」", "aiy310000790.ogg"], //男主79 + ["羽狩的队长", "「我想确认一件事」", "aiy050000100.ogg"], //菲奥奈10 + [ + "羽狩的队长", + "「你真的不是《不蚀金锁》的成员吗?」", + "aiy050000110.ogg", + ], //菲奥奈11 + ["凯伊姆", "「真的」", "aiy310000800.ogg"], //男主80 + ["凯伊姆", "「如果我说是的话,你有什么打算?」", "aiy310000810.ogg"], //男主81 + [ + "羽狩的队长", + "「我听过传闻,说他们是用依靠暴力而得的钱在生活」", + "aiy050000120.ogg", + ], //菲奥奈12 + ["凯伊姆", "「······这样啊」", "aiy310000820.ogg"], //男主82 + ["凯伊姆", "「如果能有收获就好了啊」", "aiy310000830.ogg"], //男主83 + ]; + this.chapter04 = [ + ["梅尔特", "「欢迎光临」", "aiy120000020.ogg"], //老板娘01,文件序号是以2开始,后续全部加1 + ["梅尔特", "「辛苦了」", "aiy120000030.ogg"], //老板娘02 + ["梅尔特", "「抱歉,又拜托给你了个这么麻烦的工作」", "aiy120000040.ogg"], //老板娘03 + ["凯伊姆", "「没什么,比想象中完成的更容易」", "aiy310000840.ogg"], //男主84 + ["梅尔特", "「那就好」", "aiy120000050.ogg"], //老板娘04 + ["梅尔特", "「这是我的一点谢意」", "aiy120000060.ogg"], //老板娘05 + ["凯伊姆", "「味道有些变化啊」", "aiy310000850.ogg"], //男主85 + ["梅尔特", "「啊,被发现了?」", "aiy120000070.ogg"], //老板娘06 + ["梅尔特", "「最近,没能到手什么好的原料呢」", "aiy120000080.ogg"], //老板娘07 + ["凯伊姆", "「去拜托吉克如何?」", "aiy310000860.ogg"], //男主86 + [ + "梅尔特", + "「话是这么说,但是总不能用店里采购的这种小事去麻烦他吧······」", + "aiy120000090.ogg", + ], //老板娘08 + ["凯伊姆", "「那希望你也不要来麻烦我」", "aiy310000870.ogg"], //男主87 + ["梅尔特", "「那 是 两 码 事」", "aiy120000100.ogg"], //老板娘09 + ["梅尔特", "「再说,凯伊姆是靠着工作来生活的吧」", "aiy120000110.ogg"], //老板娘10 + [ + "梅尔特", + "「而且,自己的钱被偷了这么害羞的事,向凯伊姆以外的其他人都说不出口」", + "aiy120000120.ogg", + ], //老板娘11 + ["凯伊姆", "「反正,也已经传到吉克的耳朵里了」", "aiy310000880.ogg"], //男主88 + ["梅尔特", "「这是面子问题啊,面子问题」", "aiy120000130.ogg"], //老板娘12 + ["凯伊姆", "「嘛,算了」", "aiy310000890.ogg"], //男主89 + ["凯伊姆", "「这样就好了吧?」", "aiy310000900.ogg"], //男主90 + ["梅尔特", "「这是钱包呢」", "aiy120000140.ogg"], //老板娘13 + ["梅尔特", "「嗯,东西没少」", "aiy120000150.ogg"], //老板娘14 + [ + "梅尔特", + "「太好啦—这个月的上纳金,我可全部都放在里面了呢」", + "aiy120000160.ogg", + ], //老板娘15 + [ + "梅尔特", + "「如果没有找到的话,说不定就又会被送到娼馆里了呢」", + "aiy120000170.ogg", + ], //老板娘16 + ["凯伊姆", "「在那边不是来钱更快吗?」", "aiy310000910.ogg"], //男主91 + ["梅尔特", "「阿拉,你是在说我还能有魅力吗?」", "aiy120000180.ogg"], //老板娘17 + ["凯伊姆", "「这是客套话而已」", "aiy310000920.ogg"], //男主92 + ["梅尔特", "「欺负人」", "aiy120000190.ogg"], //老板娘18 + ["梅尔特", "「总而言之,今天帮大忙了」", "aiy120000200.ogg"], //老板娘19 + ["梅尔特", "「谢礼嘛······」", "aiy120000210.ogg"], //老板娘20 + ["凯伊姆", "「就记在账单上吧」", "aiy310000930.ogg"], //男主93 + ["梅尔特", "「了解—盛谢惠顾了哦?」", "aiy120000220.ogg"], //老板娘21 + ["", "喀啷喀啷"], + ["", "门铃响起"], + ["", "喧哗瞬间安静下来。"], + ["", "进来的人是吉克。"], + ["", "是掌控着牢狱的组织之一,《不蚀金锁》的头目。"], + ["", "不仅组织的成员,就连店内一般的客人也对他以注目礼表示敬意。"], + ["吉克", "「各位继续吧」", "aiy340000010.ogg"], //吉克01 + ["", "仿佛停滞的时钟重新转动了一般,店内恢复了热闹的气氛。"], + ["吉克", "「抱歉,今天拜托你去做了无聊的工作」。", "aiy340000020.ogg"], //吉克02 + ["凯伊姆", "「不用介意」", "aiy310000940.ogg"], //男主94 + ["", "吉克轻轻点了点头,在我右边坐了下来"], + ["凯伊姆", "「逃跑的男人怎么样了?」", "aiy310000950.ogg"], //男主95 + ["吉克", "「嗯?已经不在这个世上了」。", "aiy340000030.ogg"], //吉克03 + ["吉克", "「有什么想要知道的事吗?」", "aiy340000040.ogg"], //吉克04 + ["凯伊姆", "「不,没什么」", "aiy310000960.ogg"], //男主96 + ["吉克", "「那个无聊的家伙,完全没有趣味呢」", "aiy340000050.ogg"], //吉克05 + [ + "吉克", + "「真希望他也替我负责清扫的部下也考虑考虑」", + "aiy340000060.ogg", + ], //吉克06 + ["凯伊姆", "「真是灾难啊」", "aiy310000970.ogg"], //男主97 + [ + "吉克", + "「比起那个,我听说了哦。你去追羽化病人了啊」", + "aiy340000070.ogg", + ], //吉克07 + ["凯伊姆", "「消息真灵通」", "aiy310000980.ogg"], //男主98 + ["吉克", "「梅尔特也注意点」", "aiy340000080.ogg"], //吉克08 + ["吉克", "「你丢钱已经不是一回两回了」", "aiy340000090.ogg"], //吉克09 + ["梅尔特", "「好的—我会注意的。」", "aiy120000230.ogg"], //老板娘22 + ["梅尔特", "「吉克还是平常的点单吧」", "aiy120000240.ogg"], //老板娘23 + ["梅尔特", "「凯伊姆要再来一杯吗?」", "aiy120000250.ogg"], //老板娘24 + ["", "我们用眼神点头示意后,梅尔特开始准备起酒来。"], + ["", "悠然地吐出眼圈后,吉克取出一个纸包放在柜台上。"], + ["吉克", "「这是抓捕逃跑男人的报酬」", "aiy340000100.ogg"], //吉克10 + ["凯伊姆", "「下次有什么事再告诉我」", "aiy310000990.ogg"], //男主99 + ["梅尔特", "「来,久等了」", "aiy120000260.ogg"], //老板娘25 + [ + "凯伊姆", + "「话说回来梅尔特,为什么会被那种孩子偷到钱?」", + "aiy310001000.ogg", + ], //男主100 + ["吉克", "「让我猜猜看」", "aiy340000110.ogg"], //吉克11 + [ + "吉克", + "「是那个吧,看某个特立独行的男人入迷了,所以就有了空隙?」", + "aiy340000120.ogg", + ], //吉克12 + ["梅尔特", "「可惜—」", "aiy120000270.ogg"], //老板娘26 + ["梅尔特", "「事实恰恰相反,是那家伙一直在纠缠我」", "aiy120000280.ogg"], //老板娘27 + ["凯伊姆", "「完全把你当成新进的女佣了么」", "aiy310001010.ogg"], //男主101 + [ + "梅尔特", + "「我从前可是很有名的,不会被当成这种下人吧」", + "aiy120000290.ogg", + ], //老板娘28 + [ + "梅尔特", + "「······而且,我没法对对我这么钟情的人发火啊」", + "aiy120000300.ogg", + ], //老板娘29 + ["凯伊姆&吉克", "「你傻啊」", "aiy310001027.ogg"], //男主102.7,吉克13.5 + ["梅尔特", "「异口同声呢,不亏是兄弟」", "aiy120000310.ogg"], //老板娘30 + ["凯伊姆", "「别用这种称呼,怪恶心的」", "aiy310001030.ogg"], //男主103 + ["吉克", "「说得没错」", "aiy340000140.ogg"], //吉克14 + ["吉克", "「······说起来······」", "aiy340000150.ogg"], //吉克15 + ["梅尔特", "「怎么了?」", "aiy120000320.ogg"], //老板娘31 + [ + "吉克", + "「有件事我一直很在意,我和凯伊姆,哪个是哥哥啊?」", + "aiy340000160.ogg", + ], //吉克16 + ["凯伊姆", "「你也说这么无聊的话题」", "aiy310001040.ogg"], //男主104 + ["吉克", "「不,这是很重要的事情」", "aiy340000170.ogg"], //吉克17 + ["吉克", "「梅尔特,事实是怎么样的?」", "aiy340000180.ogg"], //吉克18 + ["梅尔特", "「啊~是怎么样的呢~」", "aiy120000330.ogg"], //老板娘32 + ["梅尔特", "「我忘记了」", "aiy120000340.ogg"], //老板娘33 + ["吉克", "「骗人」", "aiy340000190.ogg"], //吉克19 + ["梅尔特", "「我说真的」", "aiy120000350.ogg"], //老板娘34 + [ + "梅尔特", + "「嘛,如果想起来了的话,就算是卸载艺术上我也会公诸于众的」", + "aiy120000360.ogg", + ], //老板娘35 + ["吉克", "「喔唷」", "aiy340000200.ogg"], //吉克20 + ["吉克", "「那么,我就不能比你先死了啊」", "aiy340000210.ogg"], //吉克21 + ["梅尔特", "「蒙你费心」", "aiy120000370.ogg"], //老板娘36 + [ + "梅尔特", + "「顺带一提,有传言说吃过我们这里的料理后可以长生不老哦?」", + "aiy120000380.ogg", + ], //老板娘37 + ["吉克", "「好,来两份炖菜,记得加腊肠」", "aiy340000220.ogg"], //吉克22 + ["梅尔特", "「多谢惠顾」", "aiy120000390.ogg"], //老板娘38 + ["", "微微一笑后,梅尔特去厨房传达点单。"], + ["凯伊姆", "「吉克······」", "aiy310001050.ogg"], //男主105 + ["吉克", "「啊,不好了」", "aiy340000230.ogg"], //吉克23 + ["凯伊姆", "「话题扯远了」", "aiy310001060.ogg"], //男主106 + ["梅尔特", "「什么话题来着?」", "aiy120000400.ogg"], //老板娘39 + ["凯伊姆", "「关于为什么你的钱会被偷这件事」", "aiy310001070.ogg"], //男主107 + [ + "凯伊姆", + "「丢钱的时候以你来说,应该不会全无察觉吧?」", + "aiy310001080.ogg", + ], //男主108 + [ + "梅尔特", + "「算是吧,被偷的时候确实也想过要抓住他」", + "aiy120000410.ogg", + ], //老板娘40 + [ + "梅尔特", + "「但是,我注意到了那个孩子背后的鼓起呢」", + "aiy120000420.ogg", + ], //老板娘41 + ["凯伊姆", "「所以就不由自主地放他逃跑了?」", "aiy310001090.ogg"], //男主109 + [ + "吉克", + "「就算你想羽化病人施恩,也不会得到任何回报哦」", + "aiy340000240.ogg", + ], //吉克24 + ["梅尔特", "「我知道」", "aiy120000430.ogg"], //老板娘42 + [ + "梅尔特", + "「正因为知道,所以之后才会拜托凯伊姆去将钱取回的」", + "aiy120000440.ogg", + ], //老板娘43 + ["梅尔特", "「可是,呢······」", "aiy120000450.ogg"], //老板娘44 + ["梅尔特", "「果然还是很矛盾呢」", "aiy120000460.ogg"], //老板娘45 + [ + "梅尔特", + "「明明是自己放他逃跑的,之后又拜托别人去抓他」", + "aiy120000470.ogg", + ], //老板娘46 + [ + "梅尔特", + "「但是,在那一刹那······应该说是,突然露出了真心吧」", + "aiy120000480.ogg", + ], //老板娘47 + ["梅尔特", "「真的,只是自我满足而已」", "aiy120000490.ogg"], //老板娘48 + ["凯伊姆", "「对于那个孩子来说不是很幸运么」", "aiy310001100.ogg"], //男主110 + [ + "凯伊姆", + "「在被《不蚀金锁》抓到之前,就被羽狩保护了」", + "aiy310001110.ogg", + ], //男主111 + ["凯伊姆", "「现在应该已经躺在治愈院的床上了」", "aiy310001120.ogg"], //男主112 + [ + "吉克", + "「如果被我们抓到的话,嘛,至少也会断掉一根胳膊吧」", + "aiy340000250.ogg", + ], //吉克25 + ["凯伊姆", "「比起失去胳膊,这不是个很好地结局吗」", "aiy310001130.ogg"], //男主113 + [ + "吉克", + "「多亏梅尔特的一念之善,那个小子的胳膊被救下来了」", + "aiy340000260.ogg", + ], //吉克26 + [ + "吉克", + "「对我来说,不能去管教他稍微有点可惜就是了」", + "aiy340000270.ogg", + ], //吉克27 + ["凯伊姆", "「我姑且是给了他两三拳」", "aiy310001140.ogg"], //男主114 + ["吉克", "「你这不是很善解人意么」", "aiy340000280.ogg"], //吉克28 + ["梅尔特", "「没有帮他的忙啊」", "aiy120000500.ogg"], //老板娘49 + ["凯伊姆", "「你给我用常识考虑考虑」", "aiy310001150.ogg"], //男主115 + [ + "梅尔特", + "「本来,就算羽化病人不被羽狩带走而导致羽化病扩散,在牢狱里死亡的理由也要多少就有多少」", + "aiy120000510.ogg", + ], //老板娘50 + [ + "梅尔特", + "「没事到如今多一个病人,也不会有什么改变的吧」", + "aiy120000520.ogg", + ], //老板娘51 + [ + "梅尔特", + "「那么,那么些羽化病人为什么就不能和我们一起开心地生活呢」", + "aiy120000530.ogg", + ], //老板娘52 + ["吉克", "「像梅尔特这样思考的人少之又少」", "aiy340000290.ogg"], //吉克29 + [ + "凯伊姆", + "「就算早晚都会死去,为了今日的苟活而努力拼搏也是人之常情」", + "aiy310001160.ogg", + ], //男主116 + ["梅尔特", "「我知道」", "aiy120000540.ogg"], //老板娘53 + ["梅尔特", "「别介意,我刚才只是顺口说说」", "aiy120000550.ogg"], //老板娘54 + ["", "喀啷喀啷"], + ["梅尔特", "「辛苦了,艾莉斯」", "aiy120000560.ogg"], //老板娘55 + ["艾莉斯", "「嗯」", "aiy020000190.ogg"], //医生19 + ["", "用不可爱的声音随口回应后,艾莉斯理所当然般地在我左边的座位坐下"], + ["", "梅尔特什么都没有问,就开始准备起茶来"], + ["梅尔特", "「多亏你去帮忙叫凯伊姆了呢」", "aiy120000570.ogg"], //老板娘56 + ["艾莉斯", "「不客气」", "aiy020000200.ogg"], //医生20 + [ + "艾莉斯", + "「我从店里出去以后不久就看到他了,这是我们被命运之绳紧紧相连的证明呢」", + "aiy020000210.ogg", + ], //医生21 + ["凯伊姆", "「那还真是糟糕」", "aiy310001170.ogg"], //男主117 + ["艾莉斯", "「用不着这么害羞的」", "aiy020000220.ogg"], //医生22 + ["凯伊姆", "「用茶堵上你的嘴吧」", "aiy310001180.ogg"], //男主118 + ["艾莉斯", "「好」", "aiy020000230.ogg"], //医生23 + ["梅尔特", "「司空见惯的风景呢」", "aiy120000580.ogg"], //老板娘57 + ["凯伊姆", "「你在那之后去做什么了?」", "aiy310001190.ogg"], //男主119 + ["艾莉斯", "「去莉莉乌姆照顾患病的女孩子了」", "aiy020000240.ogg"], //医生24 + [ + "艾莉斯", + "「好像是毒品上瘾,费了很大劲才止住她的胡闹」", + "aiy020000250.ogg", + ], //医生25 + ["艾莉斯", "「希望你能好好管理下自己店里的娼妇呢」", "aiy020000260.ogg"], //医生26 + ["吉克", "「抱歉啊」", "aiy340000300.ogg"], //吉克30 + ["吉克", "「为表歉意,就让我来给艾莉斯诊疗一下吧」", "aiy340000310.ogg"], //吉克31 + ["艾莉斯", "「去死吧」", "aiy020000270.ogg"], //医生27 + ["梅尔特", "「是什么药?」", "aiy120000590.ogg"], //老板娘58 + ["吉克", "「是最近上市的一种药」", "aiy340000320.ogg"], //吉克32 + [ + "吉克", + "「虽然中毒的可能性很低,但只要中毒便会一发而不可收拾」", + "aiy340000330.ogg", + ], //吉克33 + ["艾莉斯", "「知道了」", "aiy020000280.ogg"], //医生28 + [ + "吉克", + "「虽然我也许没有时间去管教她,不过我还是会注意的」", + "aiy340000340.ogg", + ], //吉克34 + ["艾莉斯", "「毒药的主人是吉克吗?」", "aiy020000290.ogg"], //医生29 + [ + "吉克", + "「《不蚀金锁》不卖药,这是从先代定下的规矩」", + "aiy340000350.ogg", + ], //吉克35 + ["艾莉斯", "「抱歉,开玩笑的」", "aiy020000300.ogg"], //医生30 + ["吉克", "「关于药的出处,这边也会调查的」", "aiy340000360.ogg"], //吉克36 + ["吉克", "「如果有什么传闻的话记得告诉我」", "aiy340000370.ogg"], //吉克37 + ["艾莉斯", "「知道了」", "aiy020000310.ogg"], //医生31 + [ + "艾莉斯", + "「麻药中毒的人真麻烦呢,又不能完全治好」", + "aiy020000320.ogg", + ], //医生32 + [ + "艾莉斯", + "「既然要悄悄的打,那就也悄悄地去死不就好了」", + "aiy020000330.ogg", + ], //医生33 + ["", "喀啷喀啷"], + ["奥兹", "「吉克大人,抱歉打扰你开心的时光」", "aiy350000240.ogg"], //金锁高官24 + ["吉克", "「怎么了」", "aiy340000380.ogg"], //吉克38 + ["奥兹", "「请将耳朵凑过来」", "aiy350000250.ogg"], //金锁高官25 + ["吉克", "「······知道了」", "aiy340000390.ogg"], //吉克39 + ["吉克", "「凯伊姆,一会到娼馆来一趟」", "aiy340000400.ogg"], //吉克40 + ["凯伊姆", "「啊啊」", "aiy310001200.ogg"], //男主120 + ["吉克", "「噢,我都给忘了」", "aiy340000410.ogg"], //吉克41 + ["吉克", "「让这里的大家都开心一下」", "aiy340000420.ogg"], //吉克42 + ["梅尔特", "「收到」", "aiy120000600.ogg"], //老板娘59 + ["吉克", "「我走了」", "aiy340000430.ogg"], //吉克43 + ["奥兹", "「好」", "aiy350000260.ogg"], //金锁高官26 + ["", "梆梆"], + ["梅尔特", "「大家静静,有个好消息」", "aiy120000610.ogg"], //老板娘60 + ["梅尔特", "「今天有个『大人物』要请客哦」", "aiy120000620.ogg"], //老板娘61 + ["艾莉斯", "「吉克还是一如既往的大方」", "aiy020000340.ogg"], //医生34 + ["梅尔特", "「果然,头目就应该像这样呢」", "aiy120000630.ogg"], //老板娘62 + ["凯伊姆", "「他的做法是继承先代的」", "aiy310001210.ogg"], //男主121 + ["梅尔特", "「又来了又来了」", "aiy120000640.ogg"], //老板娘63 + ["梅尔特", "「他想要赶上先代还早了十年呢」", "aiy120000650.ogg"], //老板娘64 + ["凯伊姆", "「有些太严厉了吧」", "aiy310001220.ogg"], //男主122 + ["艾莉斯", "「说起来,吉克有什么事」", "aiy020000350.ogg"], //医生35 + [ + "梅尔特", + "「既然要叫上凯伊姆,再怎么说也不是什么小事吧?」", + "aiy120000670.ogg", + ], //老板娘66 + ["凯伊姆", "「说的也是」", "aiy310001230.ogg"], //男主123 + ["艾莉斯", "「我期待看到你光荣负伤的样子」", "aiy020000360.ogg"], //医生36 + ["凯伊姆", "「不要为人的不幸祈求啊」", "aiy310001240.ogg"], //男主124 + ["梅尔特", "「来,喝完这杯就去加油工作吧」", "aiy120000680.ogg"], //老板娘67 + ["凯伊姆", "「啊啊」", "aiy310001250.ogg"], //男主125 + ["凯伊姆", "「我走了」", "aiy310001260.ogg"], //男主126 + ["艾莉斯", "「加油(受伤)吧」", "aiy020000370.ogg"], //医生37 + ["梅尔特", "「一路走好」", "aiy120000690.ogg"], //老板娘68 + ]; + this.chapter05 = [ + ["", "今晚的娼馆街比平常来得更加热闹"], + ["", "视线中可以看到很多生客。"], + ["莉莎", "「呀——!」", "aiy150000010.ogg"], //三小只C01 + ["莉莎", "「呐,凯伊姆凯伊姆凯伊姆」", "aiy150000020.ogg"], //三小只C02 + ["莉莎", "「我难道没有魅力吗?」", "aiy150000030.ogg"], //三小只C03 + ["凯伊姆", "「突然之间怎么了」", "aiy310001270.ogg"], //男主127 + [ + "莉莎", + "「因为因为因为,明明这么热闹,却只有我没有接到客人」", + "aiy150000040.ogg", + ], //三小只C04 + [ + "莉莎", + "「亏我还对他们说,我会用超绝的技巧让他们舒服得如同化作夜明的流星般呢」", + "aiy150000050.ogg", + ], //三小只C05 + ["凯伊姆", "「那个台词太糟糕了」", "aiy310001280.ogg"], //男主128 + [ + "莉莎", + "「哎—什么啊,这可是我昨天花了一晚上考虑出来的呢」", + "aiy150000060.ogg", + ], //三小只C06 + [ + "凯伊姆", + "「去睡觉,不要用你那空空如也的脑袋去考虑这种无聊事」", + "aiy310001290.ogg", + ], //男主129 + ["莉莎", "「好过分!?」", "aiy150000070.ogg"], //三小只C07 + ["凯伊姆", "「你看看周围,今天有很多新客人吧?」", "aiy310001300.ogg"], //男主130 + ["莉莎", "「嗯~~」", "aiy150000080.ogg"], //三小只C08 + ["莉莎", "「啊,你这么一说还真是」", "aiy150000090.ogg"], //三小只C09 + [ + "凯伊姆", + "「他们心里都很紧张,不可能会被你这种强拉的手法钓上钩吧」", + "aiy310001310.ogg", + ], //男主131 + ["莉莎", "「这样啊,是不想欲仙欲死吗?」", "aiy150000100.ogg"], //三小只C10 + ["凯伊姆", "「不,没有男人不会希望那样的」", "aiy310001320.ogg"], //男主132 + [ + "凯伊姆", + "「不过,强来是不行的。去让他们被温柔地包容着化作流星吧」", + "aiy310001330.ogg", + ], //男主133 + ["莉莎", "「原—来如此」", "aiy150000110.ogg"], //三小只C11 + ["莉莎", "「凯伊姆肯定很有娼妇的才能哦」", "aiy150000120.ogg"], //三小只C12 + ["凯伊姆", "「没有」", "aiy310001340.ogg"], //男主134 + ["凯伊姆", "「好了,你赶紧去赚钱吧」", "aiy310001350.ogg"], //男主135 + ["莉莎", "「收到—」", "aiy150000130.ogg"], //三小只C13 + ["", "莉莎精神满满地回答后,就啪嗒啪嗒地跑开了。"], + ["莉莎", "「呐—那边的大哥哥,和我一起化作星光吧—」", "aiy150000140.ogg"], //三小只C14 + ["", "这家伙"], + ["", "非要用这么麻烦的说法么。"], + ["", "咚"], + ["莉莎", "「呀」", "aiy150000150.ogg"], //三小只C15 + ["大胡子醉汉", "「好疼」", "aiy800000010.ogg"], + ["", "突然,莉莎与一个男人相撞。"], + ["", "虽然男人可以摆出派头,但从那虚浮的脚步可以看出他相当的醉意。"], + ["莉莎", "「好疼疼,对不起」", "aiy150000160.ogg"], //三小只C16 + ["大胡子醉汉", "「这不是道歉就能了事的事吧,大姐—」", "aiy800000020.ogg"], + ["大胡子醉汉", "「哟,穿得相当清凉啊,喂」", "aiy800000030.ogg"], + ["大肚子的醉汉", "「喂—怎么了?」", "aiy810000010.ogg"], + ["大胡子醉汉", "「这位小姐特意往我身上撞呢」", "aiy800000040.ogg"], + ["大肚子的醉汉", "「喂喂喂喂,你是要做什么」", "aiy810000020.ogg"], + ["莉莎", "「呜哎—所以我都说对不起了啊」", "aiy150000170.ogg"], //三小只C17 + [ + "莉莎", + "「对,对了。作为冲撞的补偿,我会给您提供很好的服务的,怎么样?」", + "aiy150000180.ogg", + ], //三小只C18 + ["大胡子醉汉", "「是免费的吧?」", "aiy800000050.ogg"], + [ + "莉莎", + "「那个······这,这姑且也是工作······免费就太」", + "aiy150000190.ogg", + ], //三小只C19 + [ + "大肚子的醉汉", + "「真是的,娼妇就是这种人。钱,钱,钱,完全没有做人的诚意」", + "aiy810000030.ogg", + ], + [ + "大胡子醉汉", + "「好—你这家伙。我给你钱,你现在就在这里给我服务」", + "aiy800000060.ogg", + ], + [ + "莉莎", + "「这,这该怎么说呢,稍微有些过了吧,在这里做很害羞的」", + "aiy150000200.ogg", + ], //三小只C20 + [ + "大胡子醉汉", + "「你除了晃腰以外还有用得着脑子的地方吗?别说这种像个人说的话啊」", + "aiy800000070.ogg", + ], + ["大肚子的醉汉", "「啊啊?这些钱不够吗?」", "aiy810000040.ogg"], + [ + "大胡子醉汉", + "「来,赶快把脚张开让我O,你们最喜欢这种事了吧?」", + "aiy800000080.ogg", + ], + ["莉莎", "「是,是认真的吗······这些人」", "aiy150000210.ogg"], //三小只C21 + ["大肚子的醉汉", "「赶快做」", "aiy810000050.ogg"], + ["莉莎", "「呃······」", "aiy150000220.ogg"], //三小只C22 + ["凯伊姆", "「喂」", "aiy310001360.ogg"], //男主136 + ["大肚子的醉汉", "「啊?」", "aiy810000060.ogg"], + ["凯伊姆", "「即便是娼妇,也有不能出售的东西」", "aiy310001370.ogg"], //男主137 + ["", "喀"], + ["", "我一拳击中男人被酒精染红的脸,"], + ["大胡子醉汉", "「咦」", "aiy800000090.ogg"], + ["", "嘎"], + ["", "再一拳击中另一个人的腹部。"], + ["大肚子的醉汉", "「咕······」", "aiy810000070.ogg"], + ["大胡子醉汉", "「唔······」", "aiy800000100.ogg"], + ["", "两人像两只毛虫般躺在地上蠕动着挣扎"], + ["", "一时半会应该起不来了吧"], + ["莉莎", "「凯伊姆先生,太迟了太迟了太迟了」", "aiy150000230.ogg"], //三小只C23 + ["凯伊姆", "「都是你闯出的祸吧」", "aiy310001380.ogg"], //男主138 + ["莉莎", "「话是,那么说,可是」", "aiy150000240.ogg"], //三小只C24 + ["凯伊姆", "「赶快回莉莉乌姆去」", "aiy310001390.ogg"], //男主139 + ["莉莎", "「唔,嗯。谢了,凯伊姆。再见」", "aiy150000250.ogg"], //三小只C25 + ["", "久留无用"], + ]; + this.chapter06 = [["", "漂浮的紫烟与甜美香醇的空气。"]]; + }, "动画及周期装备映射": function () { + // 在此增加新插件 + this.equip = { + //所有回合中的装备及速度 + sword1: { id: "sword1", speed: 10 }, + }; + this.heroanimate = { + //勇士武器对应的动画(key为主手武器ID,value为帧动画名) + sword1: "sword", + }; + this.enemyanimate = { + //怪物对应的动画(key为怪物ID,value为帧动画名) + bat: "sword", + }; + this.equipanimate = { + //勇士周期性装备对应的动画(key为装备Id,value为帧动画名) + shield0: "sword", + }; + }, + "勇士法抗乘算叠加": function () { + // 在此增加新插件 + items.prototype.compareEquipment = function ( + compareEquipId, + beComparedEquipId + ) { + var result = { value: {}, percentage: {} }; + var first = core.material.items[compareEquipId], + second = core.material.items[beComparedEquipId]; + for (var one in result) { + for (var name in core.status.hero) { + if (name === "mdef" && one === "percentage") { + var ans = 1; + if (first?.equip?.[one]?.[name]) + ans *= 1 - (first.equip[one][name] || 0) / 100; + + if (second?.equip?.[one]?.[name]) + ans /= 1 - (second.equip[one][name] || 0) / 100; + + if (ans != 1) result[one][name] = ans; + } else if (name === "mdef" && one === "value") { + var ans = 0; + if (first) ans -= ((first.equip || {})[one] || {})[name] || 0; + if (second) ans += ((second.equip || {})[one] || {})[name] || 0; + if (ans != 0) result[one][name] = ans; + } else { + if (typeof core.status.hero[name] == "number") { + var ans = 0; + if (first) ans += ((first.equip || {})[one] || {})[name] || 0; + if (second) ans -= ((second.equip || {})[one] || {})[name] || 0; + if (ans != 0) result[one][name] = ans; + } + } + } + } + return result; + }; + let a = 1; + items.prototype._loadEquipEffect = function (equipId, unloadEquipId) { + // 比较能力值 + var result = core.compareEquipment(equipId, unloadEquipId); + + for (var name in result.percentage) { + if (name === "mdef") { + a *= result.percentage[name]; + core.setBuff(name, 1 - a); + } else { + core.addBuff(name, result.percentage[name] / 100); + } + } + for (var name in result.value) + core.status.hero[name] += result.value[name]; + }; + }, + "手册(临时)": function () { // 在此增加新插件 - this.equip = { //所有回合中的装备及速度 - "sword1": { id: 'sword1', speed: 10 } + ui.prototype._drawBook_drawContent = function (index, enemy, top, left) { + var width = core._PX_ - left; // 9 : 8 : 8 划分三列 + this._drawBook_drawRow1(index, enemy, top, left, width, top + 20); + this._drawBook_drawRow4(index, enemy, top, left, width, top + 38); + this._drawBook_drawRow2(index, enemy, top, left, width, top + 56); + this._drawBook_drawRow3(index, enemy, top, left, width, top + 74); + this._drawBook_drawRow5(index, enemy, top, left, width, top + 90); } - this.heroanimate = { //勇士武器对应的动画(key为主手武器ID,value为帧动画名) - "sword1": "sword" + ui.prototype._drawBook_drawRow4 = function (index, enemy, top, left, width, position) { + // 绘制第一行 + core.setTextAlign('ui', 'left'); + var b13 = this._buildFont(13, true), + f13 = this._buildFont(13, false); + var col1 = left, + col2 = left + width * 9 / 25, + col3 = left + width * 17 / 25; + core.fillText('ui', core.getStatusLabel('speed'), col1, position, '#DDDDDD', f13); + core.fillText('ui', core.formatBigNumber(enemy.speed || 0), col1 + 30, position, null, b13); + core.fillText('ui', core.getStatusLabel('spell'), col2, position, null, f13); + core.fillText('ui', core.formatBigNumber(enemy.spell || 0), col2 + 30, position, null, b13); + core.fillText('ui', core.getStatusLabel('mdef'), col3, position, null, f13); + core.fillText('ui', core.formatBigNumber(enemy.mdef || 0) + "%", col3 + 30, position, null, b13); } - this.enemyanimate = { //怪物对应的动画(key为怪物ID,value为帧动画名) - "bat": "sword" + ui.prototype._drawBook_drawRow5 = function (index, enemy, top, left, width, position) { + // 绘制第一行 + core.setTextAlign('ui', 'left'); + var b13 = this._buildFont(13, true), + f13 = this._buildFont(13, false); + var col1 = left, + col2 = left + width * 13 / 25; + + core.fillText('ui', "勇士出手次数", col1, position, '#DDDDDD', f13); + core.fillText('ui', core.getDamageInfo(enemy, null) ? core.getDamageInfo(enemy, null).hero_turn : '???', col1 + 80, position, null, b13); + core.fillText('ui', "怪物出手次数", col2, position, null, f13); + core.fillText('ui', core.getDamageInfo(enemy, null) ? core.getDamageInfo(enemy, null).mon_turn : '???', col2 + 80, position, null, b13); + } - this.equipanimate = { //勇士周期性装备对应的动画(key为装备Id,value为帧动画名) - "shield0": "sword" + ui.prototype._drawBook_pageinfo = function () { + var per_page = 4; + var padding_top = 12; // 距离顶端像素 + var per_height = (core._PY_ - 32 - padding_top) / per_page; + return { per_page: per_page, padding_top: padding_top, per_height: per_height }; + } +}, + "新怪物手册": function () { + // 在此增加新插件 + const book = document.createElement("canvas"); //创建怪物手册画布 + book.style.position = "absolute"; + book.style.zIndex = 400; + book.style.display = "none"; + book.id = "book"; + main.dom.gameGroup.insertAdjacentElement("afterend", book); + book.style.top = "50%"; + book.style.left = "50%"; + book.style.transform = "translate(-50%,-50%)"; + const ctx = book.getContext("2d"); + main.dom.book = book + + book.onclick = function (e) { //画布点击监听 + try { + e.preventDefault(); + const left = core.dom.gameGroup.offsetLeft; + const top = core.dom.gameGroup.offsetTop; + const px = Math.floor((e.clientX - left) / core.domStyle.scale), + py = Math.floor((e.clientY - top) / core.domStyle.scale); + + let x, y; + if (core.domStyle.isVertical) { //对竖屏进行坐标转换 + x = py * 3; + y = 1248 - px * 3; + } else { + x = px * 3; + y = py * 3; + } + bookclick(x, y) + } catch (ee) { + main.log(ee); + } } + function bookclick(x, y) { //点击画布(x,y)触发的效果 + const makeBox = ([x, y], [w, h]) => { //创建点击检测区域 + return [ + [x, y], + [x + w, y + h], + ]; + }; + const pos = [x, y]; //创建点击坐标pos + const inRect = ([x, y], [ //检测点击坐标是否在检测区域中 + [sx, sy], + [dx, dy] + ]) => { + return sx <= x && x <= dx && sy <= y && y <= dy; + }; + /** + * 使用范例 + *const backbox = makeBox([15, 35], [210, 90]); + *if(inRect(pos,backbox)){} + */ + } + this.drawBook = function (floorId = core.status.floorId) { + if (core.domStyle.isVertical) { //对竖屏进行绘制坐标变换,只需要考虑横屏绘制,竖屏将自适应转置 + ctx.canvas.width = 1248; + ctx.canvas.height = 2028; + ctx.save(); //保存设置 + ctx.translate(1248, 0); //重新定位右上角为基准 + ctx.rotate(Math.PI / 2); //旋转90度 + } else { + ctx.canvas.width = 2028; + ctx.canvas.height = 1248; + } + //在这里写绘制内容,只写横屏就行 + + ctx.restore(); //恢复变换前的坐标,否则将连续转置 + } } } \ No newline at end of file