diff --git a/_server/MotaAction.g4 b/_server/MotaAction.g4
index c488ffd..eaa641e 100644
--- a/_server/MotaAction.g4
+++ b/_server/MotaAction.g4
@@ -1138,7 +1138,7 @@ return code;
cgtext_s
: '背景' EvalString? '回忆滤镜' Bool? '移除对话框' Bool? '剧情库序列' Int '头像' EvalString?'坐标PX' Number'打字间隔' Int? BGNL? Newline
- '自动等待时长' Int '音频文件(需在全塔属性——使用音效注册)'EvalString? BGNL? Newline
+ '自动等待时长' Int BGNL? Newline
textcgDrawingList+? Newline
@@ -1146,11 +1146,10 @@ cgtext_s
tooltip : cgtext:显示一段包含cg的文字(剧情)
helpUrl : /_docs/#/instruction
allImages : ['EvalString_0','EvalString_1']
-allSounds : ['EvalString_2']
default : ["bg_5043.webp",false,false,0,"face_050445.webp",-300,0,2000,"","这句话显示在对话框内",[{ "name":"tati_050145a.webp" , "px": 100,"filter":false }]]
var head ='{ "name": "'+EvalString_1+'", "px": '+Number_0+' }'
var list=',"bodyList": [\n'+textcgDrawingList_0.slice(0,-1)+'\n]'
-var code = '{"type": "cgtext", "bg":"'+EvalString_0+'","memory":'+Bool_0+',"WindowSkin":'+Bool_1+',"head":'+head+' ,"index":"'+Int_0+'","time":'+Int_1+',"wait":'+Int_2+',"sound":"'+EvalString_2+'"'+list+' },\n';
+var code = '{"type": "cgtext", "bg":"'+EvalString_0+'","memory":'+Bool_0+',"WindowSkin":'+Bool_1+',"head":'+head+' ,"index":"'+Int_0+'","time":'+Int_1+',"wait":'+Int_2+list+' },\n';
return code;
*/;
textcgDrawingList
diff --git a/_server/MotaActionParser.js b/_server/MotaActionParser.js
index 85647da..db8cf0b 100644
--- a/_server/MotaActionParser.js
+++ b/_server/MotaActionParser.js
@@ -574,7 +574,6 @@ MotaActionParser = function () {
data.head.px || -300,
data.time,
data.wait,
- data.sound,
buildcgDrawing(data.bodyList),
this.next,
]);
diff --git a/_server/table/data.comment.js b/_server/table/data.comment.js
index 6698265..358881b 100644
--- a/_server/table/data.comment.js
+++ b/_server/table/data.comment.js
@@ -269,7 +269,7 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = {
"_type": "textarea",
"_data": "法强",
},
- "spelldef": {
+ "mdef": {
"_leaf": true,
"_type": "textarea",
"_data": "法抗百分比",
@@ -280,7 +280,7 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = {
"_data": "100为法强转化为等值魔攻",
"_docs": "魔攻比例"
},
- "mdef": {
+ "mhp": {
"_leaf": true,
"_type": "textarea",
"_data": "100为法强转化为等值护盾",
diff --git a/project/data.js b/project/data.js
index 0920725..cf5aaac 100644
--- a/project/data.js
+++ b/project/data.js
@@ -437,18 +437,21 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
"face_440110.webp",
"green.webp",
"hero.webp",
+ "jianji.webp",
"l.webp",
"lane1.webp",
"light.webp",
"lock.webp",
"lr.webp",
"maba.webp",
+ "miwu.webp",
"null.webp",
"other_0001.webp",
"other_0002.webp",
"other_0003.webp",
"other_0004.webp",
"r.webp",
+ "sound.webp",
"status.webp",
"suiji.webp",
"tati_020101.webp",
@@ -1116,7 +1119,7 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
"atk": 100,
"def": 100,
"mdef": 0,
- "speed": 0,
+ "speed": 10,
"money": 0,
"exp": 0,
"equipment": [],
@@ -1138,7 +1141,8 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
"steps": 0,
"matk": 0,
"spell": 0,
- "spelldef": 0
+ "spelldef": 0,
+ "mhp": 0
},
"startCanvas": [
{
@@ -1494,14 +1498,12 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
],
"startText": [
{
- "type": "setValue",
- "name": "item:book",
- "value": "1"
+ "type": "function",
+ "function": "function(){\ncore.getItem('book',1);core.getItem('fly',1)\n}"
},
{
- "type": "setValue",
- "name": "item:fly",
- "value": "1"
+ "type": "insert",
+ "name": "战斗动画特效注册"
},
{
"type": "insert",
diff --git a/project/enemys.js b/project/enemys.js
index f4da758..8c80082 100644
--- a/project/enemys.js
+++ b/project/enemys.js
@@ -4,7 +4,7 @@ var enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80 =
"redSlime": {"name":"红头怪","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[],"value":10,"magic":false},
"blackSlime": {"name":"青头怪","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
"slimelord": {"name":"怪王","hp":100,"atk":120,"def":0,"money":10,"exp":0,"point":0,"special":[1,9]},
- "bat": {"name":"小蝙蝠","hp":100,"atk":120,"def":0,"money":2,"exp":0,"point":0,"special":[1],"mdef":0,"speed":10},
+ "bat": {"name":"小蝙蝠","hp":100,"atk":120,"def":0,"money":2,"exp":0,"point":0,"special":[1],"mdef":0,"speed":15},
"bigBat": {"name":"大蝙蝠","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
"redBat": {"name":"红蝙蝠","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
"vampire": {"name":"冥灵魔王","hp":888,"atk":888,"def":888,"money":888,"exp":888,"point":0,"special":[6],"n":8},
diff --git a/project/events.js b/project/events.js
index 5c6c1a0..71a864c 100644
--- a/project/events.js
+++ b/project/events.js
@@ -456,7 +456,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "0",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -477,7 +476,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "1",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -498,7 +496,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "2",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -528,7 +525,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "3",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -549,7 +545,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "4",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -570,7 +565,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "5",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -591,7 +585,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "6",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -612,7 +605,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "7",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -633,7 +625,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "8",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -654,7 +645,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "9",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -675,7 +665,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "10",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -705,7 +694,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "11",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -726,7 +714,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "12",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -747,7 +734,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "13",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -768,7 +754,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "14",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -789,7 +774,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "15",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -810,7 +794,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "16",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -831,7 +814,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "17",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -852,7 +834,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "18",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -882,7 +863,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "19",
"time": 30,
"wait": 1000,
- "sound": "aiy010000010.opus",
"bodyList": [
{
"name": "",
@@ -912,7 +892,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "20",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -933,7 +912,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "21",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -963,7 +941,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "22",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -993,7 +970,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "23",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -1014,7 +990,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "24",
"time": 50,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -1044,7 +1019,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "25",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -1065,7 +1039,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "26",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -1086,7 +1059,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "27",
"time": 30,
"wait": 2000,
- "sound": "aiy010000020.opus",
"bodyList": [
{
"name": "",
@@ -1107,7 +1079,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "28",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -1128,7 +1099,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "29",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -1149,7 +1119,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "30",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -1170,7 +1139,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "31",
"time": 30,
"wait": 1000,
- "sound": "aiy010000030.opus",
"bodyList": [
{
"name": "",
@@ -1205,7 +1173,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "32",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -1226,7 +1193,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "33",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -1247,7 +1213,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "34",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -1268,7 +1233,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "35",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -1289,7 +1253,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "36",
"time": 30,
"wait": 1000,
- "sound": "aiy710000010.opus",
"bodyList": [
{
"name": "",
@@ -1310,7 +1273,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "37",
"time": 30,
"wait": 1000,
- "sound": "aiy710000020.opus",
"bodyList": [
{
"name": "",
@@ -1340,7 +1302,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "38",
"time": 30,
"wait": 1000,
- "sound": "aiy710000030.opus",
"bodyList": [
{
"name": "",
@@ -1361,7 +1322,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "39",
"time": 30,
"wait": 1000,
- "sound": "aiy710000040.opus",
"bodyList": [
{
"name": "",
@@ -1382,7 +1342,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "40",
"time": 30,
"wait": 1000,
- "sound": "aiy710000050.opus",
"bodyList": [
{
"name": "",
@@ -1412,7 +1371,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "41",
"time": 30,
"wait": 1000,
- "sound": "aiy710000060.opus",
"bodyList": [
{
"name": "",
@@ -1433,7 +1391,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "42",
"time": 30,
"wait": 1000,
- "sound": "aiy310000010.opus",
"bodyList": [
{
"name": "",
@@ -1454,7 +1411,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "43",
"time": 30,
"wait": 1000,
- "sound": "aiy310000020.opus",
"bodyList": [
{
"name": "",
@@ -1484,7 +1440,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "44",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -1505,7 +1460,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "45",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -1526,7 +1480,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "46",
"time": 30,
"wait": 1000,
- "sound": "aiy350000010.opus",
"bodyList": [
{
"name": "",
@@ -1547,7 +1500,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "47",
"time": 30,
"wait": 1000,
- "sound": "aiy350000020.opus",
"bodyList": [
{
"name": "",
@@ -1568,7 +1520,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "48",
"time": 30,
"wait": 1000,
- "sound": "aiy310000030.opus",
"bodyList": [
{
"name": "",
@@ -1589,7 +1540,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "49",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -1610,7 +1560,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "50",
"time": 30,
"wait": 1000,
- "sound": "aiy350000030.opus",
"bodyList": [
{
"name": "",
@@ -1631,7 +1580,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "51",
"time": 30,
"wait": 1000,
- "sound": "aiy310000040.opus",
"bodyList": [
{
"name": "",
@@ -1652,7 +1600,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "52",
"time": 30,
"wait": 1000,
- "sound": "aiy710000070.opus",
"bodyList": [
{
"name": "",
@@ -1673,7 +1620,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "53",
"time": 30,
"wait": 1000,
- "sound": "aiy350000040.opus",
"bodyList": [
{
"name": "",
@@ -1694,7 +1640,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "54",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -1715,7 +1660,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "55",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -1736,7 +1680,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "56",
"time": 30,
"wait": 1000,
- "sound": "aiy350000050.opus",
"bodyList": [
{
"name": "",
@@ -1757,7 +1700,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "57",
"time": 30,
"wait": 1000,
- "sound": "aiy350000060.opus",
"bodyList": [
{
"name": "",
@@ -1778,7 +1720,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "58",
"time": 30,
"wait": 1000,
- "sound": "aiy310000050.opus",
"bodyList": [
{
"name": "",
@@ -1799,7 +1740,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "59",
"time": 30,
"wait": 1000,
- "sound": "aiy350000070.opus",
"bodyList": [
{
"name": "",
@@ -1820,7 +1760,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "60",
"time": 30,
"wait": 1000,
- "sound": "aiy350000080.opus",
"bodyList": [
{
"name": "",
@@ -1841,7 +1780,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "61",
"time": 30,
"wait": 1000,
- "sound": "aiy820000010.opus",
"bodyList": [
{
"name": "",
@@ -1862,7 +1800,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "62",
"time": 30,
"wait": 1000,
- "sound": "aiy350000090.opus",
"bodyList": [
{
"name": "",
@@ -1883,7 +1820,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "63",
"time": 30,
"wait": 1000,
- "sound": "aiy820000020.opus",
"bodyList": [
{
"name": "",
@@ -1904,7 +1840,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "64",
"time": 30,
"wait": 1000,
- "sound": "aiy350000100.opus",
"bodyList": [
{
"name": "",
@@ -1925,7 +1860,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "65",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -1946,7 +1880,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "66",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -1967,7 +1900,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "67",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -1988,7 +1920,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "68",
"time": 30,
"wait": 1000,
- "sound": "aiy310000060.opus",
"bodyList": [
{
"name": "",
@@ -2009,7 +1940,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "69",
"time": 30,
"wait": 1000,
- "sound": "aiy310000070.opus",
"bodyList": [
{
"name": "",
@@ -2030,7 +1960,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "70",
"time": 30,
"wait": 1000,
- "sound": "aiy350000110.opus",
"bodyList": [
{
"name": "",
@@ -2051,7 +1980,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "71",
"time": 30,
"wait": 1000,
- "sound": "aiy350000120.opus",
"bodyList": [
{
"name": "",
@@ -2072,7 +2000,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "72",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -2093,7 +2020,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "73",
"time": 30,
"wait": 1000,
- "sound": "aiy310000080.opus",
"bodyList": [
{
"name": "",
@@ -2114,7 +2040,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "74",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -2135,7 +2060,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "75",
"time": 30,
"wait": 1000,
- "sound": "aiy350000130.opus",
"bodyList": [
{
"name": "",
@@ -2156,7 +2080,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "76",
"time": 30,
"wait": 1000,
- "sound": "aiy310000090.opus",
"bodyList": [
{
"name": "",
@@ -2177,7 +2100,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "77",
"time": 30,
"wait": 1000,
- "sound": "aiy310000100.opus",
"bodyList": [
{
"name": "",
@@ -2198,7 +2120,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "78",
"time": 30,
"wait": 1000,
- "sound": "aiy350000140.opus",
"bodyList": [
{
"name": "",
@@ -2219,7 +2140,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "79",
"time": 30,
"wait": 1000,
- "sound": "aiy350000150.opus",
"bodyList": [
{
"name": "",
@@ -2240,7 +2160,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "80",
"time": 30,
"wait": 1000,
- "sound": "aiy710000080.opus",
"bodyList": [
{
"name": "",
@@ -2261,7 +2180,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "81",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -2282,7 +2200,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "82",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -2303,7 +2220,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "83",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -2324,7 +2240,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "84",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -2345,7 +2260,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "85",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -2366,7 +2280,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "86",
"time": 30,
"wait": 1000,
- "sound": "aiy710000090.opus",
"bodyList": [
{
"name": "",
@@ -2387,7 +2300,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "87",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -2408,7 +2320,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "88",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -2429,7 +2340,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "89",
"time": 30,
"wait": 1000,
- "sound": "aiy710000100.opus",
"bodyList": [
{
"name": "",
@@ -2450,7 +2360,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "90",
"time": 30,
"wait": 1000,
- "sound": "aiy350000160.opus",
"bodyList": [
{
"name": "",
@@ -2471,7 +2380,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "91",
"time": 30,
"wait": 1000,
- "sound": "aiy350000170.opus",
"bodyList": [
{
"name": "",
@@ -2492,7 +2400,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "92",
"time": 30,
"wait": 1000,
- "sound": "aiy710000110.opus",
"bodyList": [
{
"name": "",
@@ -2513,7 +2420,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "93",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -2534,7 +2440,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "94",
"time": 30,
"wait": 2000,
- "sound": "aiy350000180.opus",
"bodyList": [
{
"name": "",
@@ -2555,7 +2460,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "95",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -2576,7 +2480,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "96",
"time": 30,
"wait": 1000,
- "sound": "aiy350000190.opus",
"bodyList": [
{
"name": "",
@@ -2597,7 +2500,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "97",
"time": 30,
"wait": 1000,
- "sound": "aiy350000200.opus",
"bodyList": [
{
"name": "",
@@ -2618,7 +2520,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "98",
"time": 30,
"wait": 1000,
- "sound": "aiy710000120.opus",
"bodyList": [
{
"name": "",
@@ -2639,7 +2540,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "99",
"time": 30,
"wait": 1000,
- "sound": "aiy710000130.opus",
"bodyList": [
{
"name": "",
@@ -2660,7 +2560,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "100",
"time": 30,
"wait": 1000,
- "sound": "aiy350000210.opus",
"bodyList": [
{
"name": "",
@@ -2681,7 +2580,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "101",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -2702,7 +2600,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "102",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -2723,7 +2620,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "103",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -2744,7 +2640,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "104",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -2765,7 +2660,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "105",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -2786,7 +2680,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "106",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -2807,7 +2700,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "107",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -2828,7 +2720,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "108",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -2849,7 +2740,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "109",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -2870,7 +2760,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "110",
"time": 30,
"wait": 1000,
- "sound": "aiy310000110.opus",
"bodyList": [
{
"name": "",
@@ -2891,7 +2780,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "111",
"time": 30,
"wait": 1000,
- "sound": "aiy350000220.opus",
"bodyList": [
{
"name": "",
@@ -2912,7 +2800,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "112",
"time": 30,
"wait": 1000,
- "sound": "aiy350000230.opus",
"bodyList": [
{
"name": "",
@@ -2933,7 +2820,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "113",
"time": 30,
"wait": 1000,
- "sound": "aiy310000120.opus",
"bodyList": [
{
"name": "",
@@ -2954,7 +2840,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "114",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -2975,7 +2860,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "115",
"time": 30,
"wait": 1000,
- "sound": "aiy310000130.opus",
"bodyList": [
{
"name": "",
@@ -3005,7 +2889,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "116",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -3026,7 +2909,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "117",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -3047,7 +2929,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "118",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -3068,7 +2949,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "119",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -3089,7 +2969,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "120",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -3110,7 +2989,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "121",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -3131,7 +3009,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "122",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -3152,7 +3029,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "123",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -3173,7 +3049,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "124",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -3194,7 +3069,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "125",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -3224,7 +3098,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "126",
"time": 30,
"wait": 1000,
- "sound": "aiy310000140.opus",
"bodyList": [
{
"name": "",
@@ -3273,7 +3146,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "0",
"time": 30,
"wait": 1000,
- "sound": "aiy020000005.opus",
"bodyList": [
{
"name": "",
@@ -3298,7 +3170,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "1",
"time": 30,
"wait": 1000,
- "sound": "aiy020000010.opus",
"bodyList": [
{
"name": "tati_020141.webp",
@@ -3319,7 +3190,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "2",
"time": 30,
"wait": 1000,
- "sound": "aiy020000020.opus",
"bodyList": [
{
"name": "tati_020157.webp",
@@ -3340,7 +3210,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "3",
"time": 30,
"wait": 1000,
- "sound": "aiy310000150.opus",
"bodyList": [
{
"name": "tati_020157.webp",
@@ -3361,7 +3230,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "4",
"time": 30,
"wait": 1000,
- "sound": "aiy020000030.opus",
"bodyList": [
{
"name": "tati_020107.webp",
@@ -3382,7 +3250,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "5",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "tati_020107.webp",
@@ -3403,7 +3270,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "6",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "tati_020107.webp",
@@ -3424,7 +3290,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "7",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "tati_020107.webp",
@@ -3445,7 +3310,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "8",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "tati_020107.webp",
@@ -3466,7 +3330,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "9",
"time": 30,
"wait": 1000,
- "sound": "aiy020000040.opus",
"bodyList": [
{
"name": "tati_020157.webp",
@@ -3487,7 +3350,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "10",
"time": 30,
"wait": 1000,
- "sound": "aiy020000050.opus",
"bodyList": [
{
"name": "tati_020157.webp",
@@ -3508,7 +3370,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "11",
"time": 30,
"wait": 1000,
- "sound": "aiy310000160.opus",
"bodyList": [
{
"name": "tati_020157.webp",
@@ -3529,7 +3390,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "12",
"time": 30,
"wait": 1000,
- "sound": "aiy020000060.opus",
"bodyList": [
{
"name": "tati_020111.webp",
@@ -3550,7 +3410,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "13",
"time": 30,
"wait": 1000,
- "sound": "aiy310000170.opus",
"bodyList": [
{
"name": "tati_020111.webp",
@@ -3571,7 +3430,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "14",
"time": 30,
"wait": 1000,
- "sound": "aiy020000070.opus",
"bodyList": [
{
"name": "tati_020101.webp",
@@ -3592,7 +3450,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "15",
"time": 30,
"wait": 1000,
- "sound": "aiy310000180.opus",
"bodyList": [
{
"name": "tati_020101.webp",
@@ -3613,7 +3470,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "16",
"time": 30,
"wait": 1000,
- "sound": "aiy020000080.opus",
"bodyList": [
{
"name": "tati_020107.webp",
@@ -3634,7 +3490,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "17",
"time": 30,
"wait": 1000,
- "sound": "aiy310000190.opus",
"bodyList": [
{
"name": "tati_020107.webp",
@@ -3655,7 +3510,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "18",
"time": 30,
"wait": 1000,
- "sound": "aiy020000090.opus",
"bodyList": [
{
"name": "tati_020157.webp",
@@ -3676,7 +3530,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "19",
"time": 30,
"wait": 1000,
- "sound": "aiy310000200.opus",
"bodyList": [
{
"name": "tati_020157.webp",
@@ -3697,7 +3550,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "20",
"time": 30,
"wait": 1000,
- "sound": "aiy310000210.opus",
"bodyList": [
{
"name": "tati_020157.webp",
@@ -3718,7 +3570,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "21",
"time": 30,
"wait": 1000,
- "sound": "aiy020000100.opus",
"bodyList": [
{
"name": "tati_020125.webp",
@@ -3739,7 +3590,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "22",
"time": 30,
"wait": 1000,
- "sound": "aiy310000220.opus",
"bodyList": [
{
"name": "tati_020125.webp",
@@ -3760,7 +3610,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "23",
"time": 30,
"wait": 1000,
- "sound": "aiy020000110.opus",
"bodyList": [
{
"name": "tati_020121.webp",
@@ -3781,7 +3630,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "24",
"time": 30,
"wait": 1000,
- "sound": "aiy310000230.opus",
"bodyList": [
{
"name": "tati_020121.webp",
@@ -3802,7 +3650,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "25",
"time": 30,
"wait": 1000,
- "sound": "aiy310000240.opus",
"bodyList": [
{
"name": "tati_020121.webp",
@@ -3823,7 +3670,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "26",
"time": 30,
"wait": 1000,
- "sound": "aiy020000120.opus",
"bodyList": [
{
"name": "tati_020105.webp",
@@ -3844,7 +3690,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "27",
"time": 30,
"wait": 1000,
- "sound": "aiy020000130.opus",
"bodyList": [
{
"name": "tati_020103.webp",
@@ -3865,7 +3710,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "28",
"time": 30,
"wait": 1000,
- "sound": "aiy020000140.opus",
"bodyList": [
{
"name": "tati_020141.webp",
@@ -3886,7 +3730,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "29",
"time": 30,
"wait": 1000,
- "sound": "aiy310000250.opus",
"bodyList": [
{
"name": "tati_020141.webp",
@@ -3907,7 +3750,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "30",
"time": 30,
"wait": 1000,
- "sound": "aiy020000150.opus",
"bodyList": [
{
"name": "tati_020105.webp",
@@ -3928,7 +3770,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "31",
"time": 30,
"wait": 1000,
- "sound": "aiy310000260.opus",
"bodyList": [
{
"name": "tati_020105.webp",
@@ -3949,7 +3790,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "32",
"time": 30,
"wait": 1000,
- "sound": "aiy020000160.opus",
"bodyList": [
{
"name": "tati_020105.webp",
@@ -3970,7 +3810,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "33",
"time": 30,
"wait": 1000,
- "sound": "aiy020000170.opus",
"bodyList": [
{
"name": "tati_020107.webp",
@@ -3991,7 +3830,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "34",
"time": 30,
"wait": 1000,
- "sound": "aiy310000280.opus",
"bodyList": [
{
"name": "tati_020107.webp",
@@ -4012,7 +3850,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "35",
"time": 30,
"wait": 1000,
- "sound": "aiy020000180.opus",
"bodyList": [
{
"name": "tati_020145.webp",
@@ -4033,7 +3870,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "36",
"time": 30,
"wait": 1000,
- "sound": "aiy310000290.opus",
"bodyList": [
{
"name": "tati_020145.webp",
@@ -4054,7 +3890,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "37",
"time": 30,
"wait": 1000,
- "sound": "aiy310000300.opus",
"bodyList": [
{
"name": "tati_020145.webp",
@@ -4099,7 +3934,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "0",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4120,7 +3954,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "1",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4141,7 +3974,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "2",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4162,7 +3994,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "3",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4183,7 +4014,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "4",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4204,7 +4034,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "5",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4225,7 +4054,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "6",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4246,7 +4074,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "7",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4267,7 +4094,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "8",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4288,7 +4114,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "9",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4318,7 +4143,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "10",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4339,7 +4163,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "11",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4360,7 +4183,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "12",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4381,7 +4203,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "13",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4402,7 +4223,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "14",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4423,7 +4243,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "15",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4444,7 +4263,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "16",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4474,7 +4292,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "17",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4495,7 +4312,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "18",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4516,7 +4332,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "19",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4550,7 +4365,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "20",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "tati_440101.webp",
@@ -4571,7 +4385,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "21",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "tati_440101.webp",
@@ -4592,7 +4405,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "22",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "tati_440101.webp",
@@ -4613,7 +4425,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "23",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4634,7 +4445,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "24",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4655,7 +4465,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "25",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4676,7 +4485,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "26",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4697,7 +4505,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "27",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4718,7 +4525,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "28",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4739,7 +4545,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "29",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4786,7 +4591,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "30",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4807,7 +4611,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "31",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4832,7 +4635,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "32",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4853,7 +4655,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "33",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4874,7 +4675,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "34",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4895,7 +4695,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "35",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4916,7 +4715,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "36",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4937,7 +4735,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "37",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4958,7 +4755,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "38",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -4979,7 +4775,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "39",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5000,7 +4795,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "40",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5021,7 +4815,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "41",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5046,7 +4839,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "42",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5076,7 +4868,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "43",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5097,7 +4888,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "44",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5118,7 +4908,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "45",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5139,7 +4928,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "46",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5160,7 +4948,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "47",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5190,7 +4977,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "48",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5211,7 +4997,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "49",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5232,7 +5017,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "50",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5253,7 +5037,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "51",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5274,7 +5057,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "52",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5295,7 +5077,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "53",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5316,7 +5097,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "54",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5337,7 +5117,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "55",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5358,7 +5137,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "56",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5379,7 +5157,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "57",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5400,7 +5177,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "58",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5421,7 +5197,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "59",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5442,7 +5217,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "60",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5463,7 +5237,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "61",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5484,7 +5257,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "62",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5505,7 +5277,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "63",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5526,7 +5297,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "64",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5547,7 +5317,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "65",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5568,7 +5337,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "66",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5589,7 +5357,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "67",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5610,7 +5377,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "68",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5631,7 +5397,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "69",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5652,7 +5417,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "70",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5673,7 +5437,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "71",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5694,7 +5457,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "72",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5715,7 +5477,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "73",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5736,7 +5497,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "74",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5757,7 +5517,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "75",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5778,7 +5537,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "76",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5799,7 +5557,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "77",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5820,7 +5577,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "78",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5841,7 +5597,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"index": "79",
"time": 30,
"wait": 1000,
- "sound": "",
"bodyList": [
{
"name": "",
@@ -5858,10 +5613,6 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"memory2": false,
"time": 30,
"style": "引出"
- },
- {
- "type": "comment",
- "text": "下一场景是追捕羽化病少年...做个标记"
}
],
"chapter03": [
@@ -10883,6 +10634,136 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
}
]
}
+ ],
+ "战斗动画特效注册": [
+ {
+ "type": "setanimate",
+ "name": "sword",
+ "px": 48,
+ "py": 48,
+ "width": 192,
+ "height": 192,
+ "allFarme": 15,
+ "imageList": [
+ {
+ "image": "jianji.webp",
+ "beforefarme": 0,
+ "globalAlpha": 100,
+ "cx": 192,
+ "cy": 2112,
+ "cw": 192,
+ "ch": 192,
+ "x": 0,
+ "y": 0,
+ "w": 96,
+ "h": 96,
+ "afterfarme": 3,
+ "acx": 192,
+ "acy": 2112,
+ "acw": 192,
+ "ach": 192,
+ "ax": 0,
+ "ay": 0,
+ "aw": 96,
+ "ah": 96
+ },
+ {
+ "image": "jianji.webp",
+ "beforefarme": 4,
+ "globalAlpha": 100,
+ "cx": 384,
+ "cy": 2112,
+ "cw": 192,
+ "ch": 192,
+ "x": 0,
+ "y": 0,
+ "w": 96,
+ "h": 96,
+ "afterfarme": 6,
+ "acx": 384,
+ "acy": 2112,
+ "acw": 192,
+ "ach": 192,
+ "ax": 0,
+ "ay": 0,
+ "aw": 96,
+ "ah": 96
+ },
+ {
+ "image": "jianji.webp",
+ "beforefarme": 7,
+ "globalAlpha": 100,
+ "cx": 576,
+ "cy": 2112,
+ "cw": 192,
+ "ch": 192,
+ "x": 0,
+ "y": 0,
+ "w": 96,
+ "h": 96,
+ "afterfarme": 9,
+ "acx": 576,
+ "acy": 2112,
+ "acw": 192,
+ "ach": 192,
+ "ax": 0,
+ "ay": 0,
+ "aw": 96,
+ "ah": 96
+ },
+ {
+ "image": "jianji.webp",
+ "beforefarme": 10,
+ "globalAlpha": 100,
+ "cx": 768,
+ "cy": 2112,
+ "cw": 192,
+ "ch": 192,
+ "x": 0,
+ "y": 0,
+ "w": 96,
+ "h": 96,
+ "afterfarme": 12,
+ "acx": 768,
+ "acy": 2112,
+ "acw": 192,
+ "ach": 192,
+ "ax": 0,
+ "ay": 0,
+ "aw": 96,
+ "ah": 96
+ },
+ {
+ "image": "jianji.webp",
+ "beforefarme": 13,
+ "globalAlpha": 100,
+ "cx": 0,
+ "cy": 2304,
+ "cw": 192,
+ "ch": 192,
+ "x": 0,
+ "y": 0,
+ "w": 96,
+ "h": 96,
+ "afterfarme": 15,
+ "acx": 0,
+ "acy": 2304,
+ "acw": 192,
+ "ach": 192,
+ "ax": 0,
+ "ay": 0,
+ "aw": 96,
+ "ah": 96
+ }
+ ],
+ "soundList": [
+ {
+ "sound": "",
+ "startfarme": 0,
+ "stopbefore": false
+ }
+ ]
+ }
]
},
"CommonEventTemplate": {
diff --git a/project/images/jianji.webp b/project/images/jianji.webp
new file mode 100644
index 0000000..40504a4
Binary files /dev/null and b/project/images/jianji.webp differ
diff --git a/project/images/miwu.webp b/project/images/miwu.webp
new file mode 100644
index 0000000..84e72cc
Binary files /dev/null and b/project/images/miwu.webp differ
diff --git a/project/images/sound.webp b/project/images/sound.webp
new file mode 100644
index 0000000..1fed120
Binary files /dev/null and b/project/images/sound.webp differ
diff --git a/project/plugins.js b/project/plugins.js
index 170978f..27fd1e2 100644
--- a/project/plugins.js
+++ b/project/plugins.js
@@ -207,7 +207,10 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
core.ui.cgText.time = data.time;
core.ui.cgText.wait = data.wait;
core.ui.cgText.WindowSkin = data.WindowSkin;
- core.ui.cgText.sound = data.sound || "";
+ 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();
@@ -2520,1799 +2523,1804 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
})();
},
"statusBar": function () {
- main.dom.floorMsgGroup.style.display = "none";
- main.dom.statusBar.style.display = "none";
- main.dom.toolBar.style.display = "none";
- //所有数据*3是为了实现高清画布
- const GAMEVIEW_WIDTH = 676 * 3; //横屏画面宽度
- const GAMEVIEW_HEIGHT = 416 * 3; //横屏画面高度
+ main.dom.floorMsgGroup.style.display = "none";
+ main.dom.statusBar.style.display = "none";
+ main.dom.toolBar.style.display = "none";
+ //所有数据*3是为了实现高清画布
+ const GAMEVIEW_WIDTH = 676 * 3; //横屏画面宽度
+ const GAMEVIEW_HEIGHT = 416 * 3; //横屏画面高度
- const GAMEVIEW_WIDTH_VERTICAL = 416 * 3; //竖屏画面宽度
- const GAMEVIEW_HEIGHT_VERTICAL = 676 * 3; //竖屏画面高度
+ const GAMEVIEW_WIDTH_VERTICAL = 416 * 3; //竖屏画面宽度
+ const GAMEVIEW_HEIGHT_VERTICAL = 676 * 3; //竖屏画面高度
- const BAR_WIDTH = 130 * 3; //横屏左侧额外距离(即边栏宽度)
- const BAR_HEIGHT_VERTICAL = 130 * 3; //竖屏上侧额外距离(即边栏高度)
- const BORDER_WIDTH = 0; //游戏画面左侧偏移距离
- const BORDER_HEIGHT = 0; //游戏画面上侧偏移距离
+ const BAR_WIDTH = 130 * 3; //横屏左侧额外距离(即边栏宽度)
+ const BAR_HEIGHT_VERTICAL = 130 * 3; //竖屏上侧额外距离(即边栏高度)
+ const BORDER_WIDTH = 0; //游戏画面左侧偏移距离
+ const BORDER_HEIGHT = 0; //游戏画面上侧偏移距离
- const ITEM_BOX_LEFT = 549 * 3; //横屏道具栏左侧距离(右侧边栏需增加BAR_WIDTH+GAMEVIEW_HEIGHT)
- const ITEM_BOX_TOP = 155 * 3; //横屏道具栏上侧距离
- const ITEM_BOX_LEFT_VERTICAL = 160 * 3; //竖屏道具栏左侧距离
- const ITEM_BOX_TOP_VERTICAL = 549 * 3; //竖屏道具栏上侧距离(下侧边栏需增加BAR_HEIGHT_VERTICAL+GAMEVIEW_WIDTH_VERTICAL)
+ const ITEM_BOX_LEFT = 549 * 3; //横屏道具栏左侧距离(右侧边栏需增加BAR_WIDTH+GAMEVIEW_HEIGHT)
+ const ITEM_BOX_TOP = 155 * 3; //横屏道具栏上侧距离
+ const ITEM_BOX_LEFT_VERTICAL = 160 * 3; //竖屏道具栏左侧距离
+ const ITEM_BOX_TOP_VERTICAL = 549 * 3; //竖屏道具栏上侧距离(下侧边栏需增加BAR_HEIGHT_VERTICAL+GAMEVIEW_WIDTH_VERTICAL)
- const EQUIP_BLOCK_LEFT = 549 * 3; //横屏装备栏左侧距离(右侧边栏需增加BAR_WIDTH+GAMEVIEW_HEIGHT)
- const EQUIP_BLOCK_TOP = 10 * 3; //横屏装备栏上侧距离
- const EQUIP_BLOCK_LEFT_VERTICAL = 10 * 3; //竖屏装备栏左侧距离
- const EQUIP_BLOCK_TOP_VERTICAL = 549 * 3; //竖屏装备栏上侧距离(下侧边栏需增加BAR_HEIGHT_VERTICAL+GAMEVIEW_WIDTH_VERTICAL)
+ const EQUIP_BLOCK_LEFT = 549 * 3; //横屏装备栏左侧距离(右侧边栏需增加BAR_WIDTH+GAMEVIEW_HEIGHT)
+ const EQUIP_BLOCK_TOP = 10 * 3; //横屏装备栏上侧距离
+ const EQUIP_BLOCK_LEFT_VERTICAL = 10 * 3; //竖屏装备栏左侧距离
+ const EQUIP_BLOCK_TOP_VERTICAL = 549 * 3; //竖屏装备栏上侧距离(下侧边栏需增加BAR_HEIGHT_VERTICAL+GAMEVIEW_WIDTH_VERTICAL)
- const MAP_BLOCK_LEFT = 551 * 3; //横屏小地图左侧距离(右侧边栏需增加BAR_WIDTH+GAMEVIEW_HEIGHT)
- const MAP_BLOCK_TOP = 0; //横屏小地图上侧距离
- const MAP_BLOCK_LEFT_VERTICAL = 0; //竖屏小地图左侧距离
- const MAP_BLOCK_TOP_VERTICAL = 551 * 3; //竖屏小地图上侧距离(下侧边栏需增加BAR_HEIGHT_VERTICAL+GAMEVIEW_WIDTH_VERTICAL)
+ const MAP_BLOCK_LEFT = 551 * 3; //横屏小地图左侧距离(右侧边栏需增加BAR_WIDTH+GAMEVIEW_HEIGHT)
+ const MAP_BLOCK_TOP = 0; //横屏小地图上侧距离
+ const MAP_BLOCK_LEFT_VERTICAL = 0; //竖屏小地图左侧距离
+ 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_LEFT_VERTICAL = 110 * 3; //竖屏钥匙栏左侧距离
- const KEY_BLOCK_TOP_VERTICAL = EQUIP_BLOCK_TOP_VERTICAL; //竖屏钥匙栏上侧距离(下侧边栏需增加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_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_LEFT_VERTICAL = 113 * 3; //竖屏道具说明左侧距离
- const INFO_BLOCK_TOP_VERTICAL = 8 * 3; //竖屏道具说明上侧距离(下侧边栏需增加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_LEFT_VERTICAL = 113 * 3; //竖屏道具说明左侧距离
+ const INFO_BLOCK_TOP_VERTICAL = 8 * 3; //竖屏道具说明上侧距离(下侧边栏需增加BAR_HEIGHT_VERTICAL+GAMEVIEW_WIDTH_VERTICAL)
- const TOOL_BOX_LEFT = EQUIP_BLOCK_LEFT; //横屏工具栏左侧距离(右侧边栏需增加BAR_WIDTH+GAMEVIEW_HEIGHT)
- const TOOL_BOX_TOP = 348 * 3; //横屏工具栏上侧距离
- const TOOL_BOX_LEFT_VERTICAL = 348 * 3; //竖屏工具栏左侧距离
- const TOOL_BOX_TOP_VERTICAL = 549 * 3; //竖屏工具栏上侧距离(下侧边栏需增加BAR_HEIGHT_VERTICAL+GAMEVIEW_WIDTH_VERTICAL)
+ const TOOL_BOX_LEFT = EQUIP_BLOCK_LEFT; //横屏工具栏左侧距离(右侧边栏需增加BAR_WIDTH+GAMEVIEW_HEIGHT)
+ const TOOL_BOX_TOP = 348 * 3; //横屏工具栏上侧距离
+ const TOOL_BOX_LEFT_VERTICAL = 348 * 3; //竖屏工具栏左侧距离
+ const TOOL_BOX_TOP_VERTICAL = 549 * 3; //竖屏工具栏上侧距离(下侧边栏需增加BAR_HEIGHT_VERTICAL+GAMEVIEW_WIDTH_VERTICAL)
- const TOOL_ICON_OUTER_SIZE = 34 * 3;
+ const TOOL_ICON_OUTER_SIZE = 34 * 3;
- const TEXT_COLOR = "#FFFFFF"; //默认文字颜色
- const globalAlpha = 0.7; //默认底框透明度
- const FORCE_COUNTABLE_ITEMS = ["centerFly"]; //常态显示数量的非永久道具,如果道具不在此数组中,则只有道具多余1时显示数量
+ const TEXT_COLOR = "#FFFFFF"; //默认文字颜色
+ const globalAlpha = 0.7; //默认底框透明度
+ const FORCE_COUNTABLE_ITEMS = ["centerFly"]; //常态显示数量的非永久道具,如果道具不在此数组中,则只有道具多余1时显示数量
- const outerBackground = document.createElement("canvas"); //背景画布设置
- let globalAlphafloor = 0,
- globalAlphafloorStatus = 4;
- outerBackground.style.position = "absolute";
- outerBackground.style.zIndex = 5;
- outerBackground.id = "outerBackground";
- main.dom.outerBackground = outerBackground;
- main.dom.startPanel.insertAdjacentElement("afterend", outerBackground);
+ const outerBackground = document.createElement("canvas"); //背景画布设置
+ let globalAlphafloor = 0,
+ globalAlphafloorStatus = 4;
+ outerBackground.style.position = "absolute";
+ outerBackground.style.zIndex = 5;
+ outerBackground.id = "outerBackground";
+ main.dom.outerBackground = outerBackground;
+ main.dom.startPanel.insertAdjacentElement("afterend", outerBackground);
- const outerUI = document.createElement("canvas"); //额外ui画布设置(状态栏所有绘制、点击都在额外ui上)
- outerUI.style.position = "absolute";
- outerUI.style.zIndex = 165;
- outerUI.id = "outerUI";
+ const outerUI = document.createElement("canvas"); //额外ui画布设置(状态栏所有绘制、点击都在额外ui上)
+ outerUI.style.position = "absolute";
+ outerUI.style.zIndex = 165;
+ outerUI.id = "outerUI";
- main.dom.outerUI = outerUI;
- outerBackground.insertAdjacentElement("afterend", outerUI);
- setTimeout(function () {
- // Should be executed immediately after init()
- main.canvas.outerUI = outerUI.getContext("2d");
- });
- outerUI.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.statusBar.onclick(px * 3, py * 3);
- } catch (ee) {
- main.log(ee);
- }
- };
+ main.dom.outerUI = outerUI;
+ outerBackground.insertAdjacentElement("afterend", outerUI);
+ setTimeout(function () {
+ // Should be executed immediately after init()
+ main.canvas.outerUI = outerUI.getContext("2d");
+ });
+ outerUI.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.statusBar.onclick(px * 3, py * 3);
+ } catch (ee) {
+ main.log(ee);
+ }
+ };
- const _resize_gameGroup = function (obj) {
- //游戏画面自适应调节
- const gameGroup = core.dom.gameGroup;
- gameGroup.style.width = obj.totalWidth + "px";
- gameGroup.style.height = obj.totalHeight + "px";
- gameGroup.style.left = (obj.clientWidth - obj.totalWidth) / 2 + "px";
- gameGroup.style.top = (obj.clientHeight - obj.totalHeight) / 2 + "px";
- //floorMsgGroup为切换楼层中生效,显示时间可通过‘全塔属性’——‘切换楼层时间’或游戏内设置调整
- //显示内容为游戏名/版本号/楼层名
- // floorMsgGroup
- var floorMsgGroup = core.dom.floorMsgGroup;
- var globalAttribute =
- core.status.globalAttribute || core.initStatus.globalAttribute;
- floorMsgGroup.style = globalAttribute.floorChangingStyle;
- floorMsgGroup.style.height = floorMsgGroup.style.width =
- (GAMEVIEW_HEIGHT / 3) * core.domStyle.scale + "px";
- floorMsgGroup.style.fontSize = 16 * core.domStyle.scale + "px";
+ const _resize_gameGroup = function (obj) {
+ //游戏画面自适应调节
+ const gameGroup = core.dom.gameGroup;
+ gameGroup.style.width = obj.totalWidth + "px";
+ gameGroup.style.height = obj.totalHeight + "px";
+ gameGroup.style.left = (obj.clientWidth - obj.totalWidth) / 2 + "px";
+ gameGroup.style.top = (obj.clientHeight - obj.totalHeight) / 2 + "px";
+ //floorMsgGroup为切换楼层中生效,显示时间可通过‘全塔属性’——‘切换楼层时间’或游戏内设置调整
+ //显示内容为游戏名/版本号/楼层名
+ // floorMsgGroup
+ var floorMsgGroup = core.dom.floorMsgGroup;
+ var globalAttribute =
+ core.status.globalAttribute || core.initStatus.globalAttribute;
+ floorMsgGroup.style = globalAttribute.floorChangingStyle;
+ floorMsgGroup.style.height = floorMsgGroup.style.width =
+ (GAMEVIEW_HEIGHT / 3) * core.domStyle.scale + "px";
+ floorMsgGroup.style.fontSize = 16 * core.domStyle.scale + "px";
- if (core.domStyle.isVertical) {
- floorMsgGroup.style.left = "0px";
- floorMsgGroup.style.top =
- ((GAMEVIEW_HEIGHT_VERTICAL / 3 - GAMEVIEW_WIDTH_VERTICAL / 3) *
- core.domStyle.scale) /
- 2 +
- "px";
- } else {
- floorMsgGroup.style.left =
- ((GAMEVIEW_WIDTH / 3 - GAMEVIEW_HEIGHT / 3) * core.domStyle.scale) /
- 2 +
- "px";
- floorMsgGroup.style.top = "0px";
- }
- core.dom.musicBtn.style.right =
- (obj.clientWidth - obj.totalWidth) / 2 + "px";
- core.dom.musicBtn.style.bottom =
- (obj.clientHeight - obj.totalHeight) / 2 - 27 + "px";
- let startBackground = core.domStyle.isVertical ?
- main.styles.startVerticalBackground || main.styles.startBackground :
- main.styles.startBackground;
- if (main.dom.startBackground.getAttribute("__src__") != startBackground) {
- main.dom.startBackground.setAttribute("__src__", startBackground);
- main.dom.startBackground.src = startBackground;
- }
- const span = document
- .getElementById("startButtons")
- .getElementsByTagName("span");
- let font = (GAMEVIEW_WIDTH / 100) * core.domStyle.scale;
- if (core.domStyle.isVertical)
- font = ((GAMEVIEW_WIDTH_VERTICAL * 2) / 100) * core.domStyle.scale;
+ if (core.domStyle.isVertical) {
+ floorMsgGroup.style.left = "0px";
+ floorMsgGroup.style.top =
+ ((GAMEVIEW_HEIGHT_VERTICAL / 3 - GAMEVIEW_WIDTH_VERTICAL / 3) *
+ core.domStyle.scale) /
+ 2 +
+ "px";
+ } else {
+ floorMsgGroup.style.left =
+ ((GAMEVIEW_WIDTH / 3 - GAMEVIEW_HEIGHT / 3) * core.domStyle.scale) /
+ 2 +
+ "px";
+ floorMsgGroup.style.top = "0px";
+ }
+ core.dom.musicBtn.style.right =
+ (obj.clientWidth - obj.totalWidth) / 2 + "px";
+ core.dom.musicBtn.style.bottom =
+ (obj.clientHeight - obj.totalHeight) / 2 - 27 + "px";
+ let startBackground = core.domStyle.isVertical
+ ? main.styles.startVerticalBackground || main.styles.startBackground
+ : main.styles.startBackground;
+ if (main.dom.startBackground.getAttribute("__src__") != startBackground) {
+ main.dom.startBackground.setAttribute("__src__", startBackground);
+ main.dom.startBackground.src = startBackground;
+ }
+ const span = document
+ .getElementById("startButtons")
+ .getElementsByTagName("span");
+ let font = (GAMEVIEW_WIDTH / 100) * core.domStyle.scale;
+ if (core.domStyle.isVertical)
+ font = ((GAMEVIEW_WIDTH_VERTICAL * 2) / 100) * core.domStyle.scale;
- core.dom.playGame.style.fontSize = font + "px";
- core.dom.loadGame.style.fontSize = font + "px";
- core.dom.CGMode.style.fontSize = font + "px";
- core.dom.musicMode.style.fontSize = font + "px";
- core.dom.replayGame.style.fontSize = font + "px";
- core.dom.startButtonGroup.style.padding = font * 0.3 + "px 25px";
- };
- const _resize_canvas = function (obj) {
- //自适应画布
- main.dom.outerBackground.style.width = obj.totalWidth + "px";
- main.dom.outerBackground.style.height = obj.totalHeight + "px";
- main.dom.outerUI.style.width = obj.totalWidth + "px";
- main.dom.outerUI.style.height = obj.totalHeight + "px";
- if (main.dom.CGUI) {
- main.dom.CGUI.style.width = obj.totalWidth + 3 + "px";
- main.dom.CGUI.style.height = obj.totalHeight + 3 + "px";
- }
- if (main.dom.music) {
- main.dom.music.style.width = obj.totalWidth + 3 + "px";
- main.dom.music.style.height = obj.totalHeight + 3 + "px";
- }
- if (main.dom.cgText) {
- main.dom.cgText.style.width = obj.totalWidth + 3 + "px";
- main.dom.cgText.style.height = obj.totalHeight + 3 + "px";
- }
- if (main.dom.logcanvas) {
- main.dom.logcanvas.style.width = obj.totalWidth + 3 + "px";
- main.dom.logcanvas.style.height = obj.totalHeight + 3 + "px";
- }
- if (main.dom.over) {
- main.dom.over.style.width = obj.totalWidth + 3 + "px";
- main.dom.over.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";
- if (core.domStyle.isVertical)
- main.dom.video.style.width = obj.totalHeight + 3 + "px";
- if (core.domStyle.isVertical)
- main.dom.video.style.height = obj.totalWidth + 3 + "px";
- main.dom.video.style.top = "50%";
- main.dom.video.style.left = "50%";
+ core.dom.playGame.style.fontSize = font + "px";
+ core.dom.loadGame.style.fontSize = font + "px";
+ core.dom.CGMode.style.fontSize = font + "px";
+ core.dom.musicMode.style.fontSize = font + "px";
+ core.dom.replayGame.style.fontSize = font + "px";
+ core.dom.startButtonGroup.style.padding = font * 0.3 + "px 25px";
+ };
+ const _resize_canvas = function (obj) {
+ //自适应画布
+ main.dom.outerBackground.style.width = obj.totalWidth + "px";
+ main.dom.outerBackground.style.height = obj.totalHeight + "px";
+ main.dom.outerUI.style.width = obj.totalWidth + "px";
+ main.dom.outerUI.style.height = obj.totalHeight + "px";
+ if (main.dom.CGUI) {
+ main.dom.CGUI.style.width = obj.totalWidth + 3 + "px";
+ main.dom.CGUI.style.height = obj.totalHeight + 3 + "px";
+ }
+ if (main.dom.music) {
+ main.dom.music.style.width = obj.totalWidth + 3 + "px";
+ main.dom.music.style.height = obj.totalHeight + 3 + "px";
+ }
+ if (main.dom.cgText) {
+ main.dom.cgText.style.width = obj.totalWidth + 3 + "px";
+ main.dom.cgText.style.height = obj.totalHeight + 3 + "px";
+ }
+ if (main.dom.logcanvas) {
+ main.dom.logcanvas.style.width = obj.totalWidth + 3 + "px";
+ main.dom.logcanvas.style.height = obj.totalHeight + 3 + "px";
+ }
+ if (main.dom.over) {
+ main.dom.over.style.width = obj.totalWidth + 3 + "px";
+ main.dom.over.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";
+ if (core.domStyle.isVertical)
+ main.dom.video.style.width = obj.totalHeight + 3 + "px";
+ if (core.domStyle.isVertical)
+ main.dom.video.style.height = obj.totalWidth + 3 + "px";
+ main.dom.video.style.top = "50%";
+ main.dom.video.style.left = "50%";
- main.dom.video.style.transform = "translate(-50%,-50%)";
+ main.dom.video.style.transform = "translate(-50%,-50%)";
- if (core.domStyle.isVertical)
- main.dom.video.style.transform = "translate(-50%,-50%) rotate(90deg)";
- }
- if (main.dom.video1) {
- main.dom.video1.style.width = obj.totalWidth + 3 + "px";
- main.dom.video1.style.height = obj.totalHeight + 3 + "px";
- }
+ if (core.domStyle.isVertical)
+ main.dom.video.style.transform = "translate(-50%,-50%) rotate(90deg)";
+ }
+ if (main.dom.video1) {
+ main.dom.video1.style.width = obj.totalWidth + 3 + "px";
+ main.dom.video1.style.height = obj.totalHeight + 3 + "px";
+ }
- const innerSize = obj.canvasWidth * core.domStyle.scale + "px";
- for (let i = 0; i < core.dom.gameCanvas.length; ++i)
- core.dom.gameCanvas[i].style.width = core.dom.gameCanvas[
- i
- ].style.height = innerSize;
- core.dom.gif.style.width = core.dom.gif.style.height = innerSize;
- core.dom.gif2.style.width = core.dom.gif2.style.height = innerSize;
+ const innerSize = obj.canvasWidth * core.domStyle.scale + "px";
+ for (let i = 0; i < core.dom.gameCanvas.length; ++i)
+ core.dom.gameCanvas[i].style.width = core.dom.gameCanvas[
+ i
+ ].style.height = innerSize;
+ core.dom.gif.style.width = core.dom.gif.style.height = innerSize;
+ core.dom.gif2.style.width = core.dom.gif2.style.height = innerSize;
- core.dom.gameDraw.style.width = core.dom.gameDraw.style.height =
- innerSize;
- core.dom.gameDraw.style.top =
- obj.gameDrawBox.top * core.domStyle.scale + "px";
- core.dom.gameDraw.style.left =
- obj.gameDrawBox.left * core.domStyle.scale + "px";
- // resize bigmap
- core.bigmap.canvas.forEach(function (cn) {
- const ratio = core.canvas[cn].canvas.hasAttribute("isHD") ?
- core.domStyle.ratio :
- 1;
- core.canvas[cn].canvas.style.width =
- (innerSize / ratio) * core.domStyle.scale + "px";
- core.canvas[cn].canvas.style.height =
- (innerSize / ratio) * core.domStyle.scale + "px";
- });
- // resize dynamic canvas
- for (const name in core.dymCanvas) {
- const ctx = core.dymCanvas[name],
- canvas = ctx.canvas;
- const ratio = canvas.hasAttribute("isHD") ? core.domStyle.ratio : 1;
- canvas.style.width = (innerSize / ratio) * core.domStyle.scale + "px";
- canvas.style.height = (innerSize / ratio) * core.domStyle.scale + "px";
- canvas.style.left =
- parseFloat(canvas.getAttribute("_left")) * core.domStyle.scale + "px";
- canvas.style.top =
- parseFloat(canvas.getAttribute("_top")) * core.domStyle.scale + "px";
- }
- // resize next
- main.dom.next.style.width = main.dom.next.style.height =
- 5 * core.domStyle.scale + "px";
- main.dom.next.style.borderBottomWidth =
- main.dom.next.style.borderRightWidth = 4 * core.domStyle.scale + "px";
- };
- const bgctx = main.dom.outerBackground.getContext("2d");
- const uictx = main.dom.outerUI.getContext("2d");
- let now = 0;
- core.registerAnimationFrame("lightFloor", true, function (timestamp) {
- if (timestamp - now > 1000 / 60) {
- now = timestamp;
- globalAlphafloor += globalAlphafloorStatus;
- if (globalAlphafloor === 100) globalAlphafloorStatus = -2;
- if (globalAlphafloor === 0) globalAlphafloorStatus = 2;
+ core.dom.gameDraw.style.width = core.dom.gameDraw.style.height =
+ innerSize;
+ core.dom.gameDraw.style.top =
+ obj.gameDrawBox.top * core.domStyle.scale + "px";
+ core.dom.gameDraw.style.left =
+ obj.gameDrawBox.left * core.domStyle.scale + "px";
+ // resize bigmap
+ core.bigmap.canvas.forEach(function (cn) {
+ const ratio = core.canvas[cn].canvas.hasAttribute("isHD")
+ ? core.domStyle.ratio
+ : 1;
+ core.canvas[cn].canvas.style.width =
+ (innerSize / ratio) * core.domStyle.scale + "px";
+ core.canvas[cn].canvas.style.height =
+ (innerSize / ratio) * core.domStyle.scale + "px";
+ });
+ // resize dynamic canvas
+ for (const name in core.dymCanvas) {
+ const ctx = core.dymCanvas[name],
+ canvas = ctx.canvas;
+ const ratio = canvas.hasAttribute("isHD") ? core.domStyle.ratio : 1;
+ canvas.style.width = (innerSize / ratio) * core.domStyle.scale + "px";
+ canvas.style.height = (innerSize / ratio) * core.domStyle.scale + "px";
+ canvas.style.left =
+ parseFloat(canvas.getAttribute("_left")) * core.domStyle.scale + "px";
+ canvas.style.top =
+ parseFloat(canvas.getAttribute("_top")) * core.domStyle.scale + "px";
+ }
+ // resize next
+ main.dom.next.style.width = main.dom.next.style.height =
+ 5 * core.domStyle.scale + "px";
+ main.dom.next.style.borderBottomWidth =
+ main.dom.next.style.borderRightWidth = 4 * core.domStyle.scale + "px";
+ };
+ const bgctx = main.dom.outerBackground.getContext("2d");
+ const uictx = main.dom.outerUI.getContext("2d");
+ let now = 0;
+ core.registerAnimationFrame("lightFloor", true, function (timestamp) {
+ if (timestamp - now > 1000 / 60) {
+ now = timestamp;
+ globalAlphafloor += globalAlphafloorStatus;
+ if (globalAlphafloor === 100) globalAlphafloorStatus = -2;
+ if (globalAlphafloor === 0) globalAlphafloorStatus = 2;
- if (core.domStyle.isVertical) {
- core.clearMap(
- uictx,
- MAP_BLOCK_LEFT_VERTICAL,
- MAP_BLOCK_TOP_VERTICAL,
- 340,
- 360
- );
- if (core.status.event.id === "viewMaps") {
- core.ui.statusBar._update_map(core.status.event.data.floorId);
- } else {
- core.ui.statusBar._update_map();
- }
+ if (core.domStyle.isVertical) {
+ core.clearMap(
+ uictx,
+ MAP_BLOCK_LEFT_VERTICAL,
+ MAP_BLOCK_TOP_VERTICAL,
+ 340,
+ 360
+ );
+ if (core.status.event.id === "viewMaps") {
+ core.ui.statusBar._update_map(core.status.event.data.floorId);
+ } else {
+ core.ui.statusBar._update_map();
+ }
- uictx.globalAlpha = globalAlphafloor / 100;
- core.drawImage(
- uictx,
- "green.webp",
- MAP_BLOCK_LEFT_VERTICAL + 135,
- MAP_BLOCK_TOP_VERTICAL + 170
- );
- uictx.globalAlpha = 1;
- } else {
- core.clearMap(uictx, MAP_BLOCK_LEFT, MAP_BLOCK_TOP, 340, 360);
- if (core.status.event.id === "viewMaps") {
- core.ui.statusBar._update_map(core.status.event.data.floorId);
- } else {
- core.ui.statusBar._update_map();
- }
- uictx.globalAlpha = globalAlphafloor / 100;
- core.drawImage(
- uictx,
- "green.webp",
- MAP_BLOCK_LEFT + 150,
- MAP_BLOCK_TOP + 180
- );
- uictx.globalAlpha = 1;
- }
- }
- });
+ uictx.globalAlpha = globalAlphafloor / 100;
+ core.drawImage(
+ uictx,
+ "green.webp",
+ MAP_BLOCK_LEFT_VERTICAL + 135,
+ MAP_BLOCK_TOP_VERTICAL + 170
+ );
+ uictx.globalAlpha = 1;
+ } else {
+ core.clearMap(uictx, MAP_BLOCK_LEFT, MAP_BLOCK_TOP, 340, 360);
+ if (core.status.event.id === "viewMaps") {
+ core.ui.statusBar._update_map(core.status.event.data.floorId);
+ } else {
+ core.ui.statusBar._update_map();
+ }
+ uictx.globalAlpha = globalAlphafloor / 100;
+ core.drawImage(
+ uictx,
+ "green.webp",
+ MAP_BLOCK_LEFT + 150,
+ MAP_BLOCK_TOP + 180
+ );
+ uictx.globalAlpha = 1;
+ }
+ }
+ });
- core.control.resize = function () {
- //自适应,可实现横竖屏切换
- if (main.mode == "editor") return;
+ core.control.resize = function () {
+ //自适应,可实现横竖屏切换
+ if (main.mode == "editor") return;
- const clientWidth = main.dom.body.clientWidth,
- clientHeight = main.dom.body.clientHeight;
- const canvasWidth = core.__PIXELS__;
+ const clientWidth = main.dom.body.clientWidth,
+ clientHeight = main.dom.body.clientHeight;
+ const canvasWidth = core.__PIXELS__;
- const isVertical = clientHeight > clientWidth;
- core.domStyle.isVertical = isVertical;
+ const isVertical = clientHeight > clientWidth;
+ core.domStyle.isVertical = isVertical;
- const totalWidth = isVertical ?
- GAMEVIEW_WIDTH_VERTICAL / 3 :
- GAMEVIEW_WIDTH / 3,
- totalHeight = isVertical ?
- GAMEVIEW_HEIGHT_VERTICAL / 3 :
- GAMEVIEW_HEIGHT / 3;
+ const totalWidth = isVertical
+ ? GAMEVIEW_WIDTH_VERTICAL / 3
+ : GAMEVIEW_WIDTH / 3,
+ totalHeight = isVertical
+ ? GAMEVIEW_HEIGHT_VERTICAL / 3
+ : GAMEVIEW_HEIGHT / 3;
- const maxRatio = Math.min(
- clientWidth / totalWidth,
- clientHeight / totalHeight
- );
+ const maxRatio = Math.min(
+ clientWidth / totalWidth,
+ clientHeight / totalHeight
+ );
- core.domStyle.availableScale = [];
- [1, 1.25, 1.5, 1.75, 2].forEach(function (v) {
- if (maxRatio >= v) {
- core.domStyle.availableScale.push(v);
- }
- });
+ core.domStyle.availableScale = [];
+ [1, 1.25, 1.5, 1.75, 2].forEach(function (v) {
+ if (maxRatio >= v) {
+ core.domStyle.availableScale.push(v);
+ }
+ });
- if (core.domStyle.availableScale.indexOf(core.domStyle.scale) < 0) {
- core.domStyle.scale = Math.min(1, maxRatio);
- } else if (
- core.getLocalStorage("scale") == null &&
- core.domStyle.availableScale.length >= 2
- ) {
- core.domStyle.scale =
- core.domStyle.availableScale[core.domStyle.availableScale.length - 2];
- core.setLocalStorage("scale", core.domStyle.scale);
- }
+ if (core.domStyle.availableScale.indexOf(core.domStyle.scale) < 0) {
+ core.domStyle.scale = Math.min(1, maxRatio);
+ } else if (
+ core.getLocalStorage("scale") == null &&
+ core.domStyle.availableScale.length >= 2
+ ) {
+ core.domStyle.scale =
+ core.domStyle.availableScale[core.domStyle.availableScale.length - 2];
+ core.setLocalStorage("scale", core.domStyle.scale);
+ }
- const totalWidthScaled = totalWidth * core.domStyle.scale,
- totalHeightScaled = totalHeight * core.domStyle.scale;
+ const totalWidthScaled = totalWidth * core.domStyle.scale,
+ totalHeightScaled = totalHeight * core.domStyle.scale;
- const gameDrawBox = isVertical ? {
- left: BORDER_WIDTH / 3,
- top: BAR_HEIGHT_VERTICAL / 3 + BORDER_HEIGHT / 3,
- } : { left: BAR_WIDTH / 3 + BORDER_WIDTH / 3, top: BORDER_HEIGHT / 3 };
+ const gameDrawBox = isVertical
+ ? {
+ left: BORDER_WIDTH / 3,
+ top: BAR_HEIGHT_VERTICAL / 3 + BORDER_HEIGHT / 3,
+ }
+ : { left: BAR_WIDTH / 3 + BORDER_WIDTH / 3, top: BORDER_HEIGHT / 3 };
- const obj = {
- clientWidth: clientWidth,
- clientHeight: clientHeight,
- canvasWidth: canvasWidth,
- totalWidth: totalWidthScaled,
- totalHeight: totalHeightScaled,
- gameDrawBox: gameDrawBox,
- globalAttribute: core.status.globalAttribute || core.initStatus.globalAttribute,
- };
+ const obj = {
+ clientWidth: clientWidth,
+ clientHeight: clientHeight,
+ canvasWidth: canvasWidth,
+ totalWidth: totalWidthScaled,
+ totalHeight: totalHeightScaled,
+ gameDrawBox: gameDrawBox,
+ globalAttribute:
+ core.status.globalAttribute || core.initStatus.globalAttribute,
+ };
- _resize_gameGroup(obj);
- _resize_canvas(obj);
+ _resize_gameGroup(obj);
+ _resize_canvas(obj);
- if (core.status.automaticRoute == null) core.status.automaticRoute = {};
- core.updateStatusBar();
- if (main.dom.CGUI && main.dom.CGUI.style.display === "block")
- core.ui.CG.update();
- if (main.dom.music && main.dom.music.style.display === "block")
- core.ui.music.update();
- if (main.dom.cgText && main.dom.cgText.style.display === "block")
- core.ui.cgText.update();
- if (main.dom.logcanvas && main.dom.logcanvas.style.display === "block")
- core.ui.cgText.update();
- };
+ if (core.status.automaticRoute == null) core.status.automaticRoute = {};
+ core.updateStatusBar();
+ if (main.dom.CGUI && main.dom.CGUI.style.display === "block")
+ core.ui.CG.update();
+ if (main.dom.music && main.dom.music.style.display === "block")
+ core.ui.music.update();
+ if (main.dom.cgText && main.dom.cgText.style.display === "block")
+ core.ui.cgText.update();
+ if (main.dom.logcanvas && main.dom.logcanvas.style.display === "block")
+ core.ui.cgText.update();
+ };
- class StatusBar {
- constructor() {
- //道具栏列表
- this.itemMx = [
- //空位用‘none’填充,当前ui至多4列6行
- ["book", "wand", "none", "fly"],
- ["cross", "superPotion", "pickaxe"],
- ["bomb", "centerFly", "upFly"],
- ["none", "none", "none"],
- ["downFly", "knife", "snow"],
- ["bigKey", "earthquake", "coin"],
- ];
- }
- //初始化内容(工具栏/录像操作执行函数)
- init() {
- this.toolbarAction = [
- [
- main.core.openKeyBoard,
- main.core.openQuickShop,
- core.openToolbox,
- core.doSL,
- ],
- [main.core.openSettings, main.core.save, main.core.load, core.doSL],
- ];
- this.replayAction = [
- [core.triggerReplay, core.stopReplay, core.rewindReplay],
- [core.speedDownReplay, core.speedUpReplay, core.saveReplay],
- ];
- }
- //更新
- update() {
- this._update_background(); //更新背景
- this._update_props(); //更新属性
- //this._update_items(); //更新道具
- //this._update_equips(); //更新装备
- //this._update_keys(); //更新钥匙
- //this._update_infoWindow(); //更新道具说明
- this._update_toolBox(); //更新工具栏
- this._redrawMap();
- }
- _redrawMap() {
- if (core.domStyle.isVertical) {
- core.clearMap(
- uictx,
- MAP_BLOCK_LEFT_VERTICAL,
- MAP_BLOCK_TOP_VERTICAL,
- 340,
- 360
- );
- this._update_map();
- uictx.globalAlpha = globalAlphafloor / 100;
- core.drawImage(
- uictx,
- "green.webp",
- MAP_BLOCK_LEFT_VERTICAL + 125,
- MAP_BLOCK_TOP_VERTICAL + 170
- );
- uictx.globalAlpha = 1;
- } else {
- core.clearMap(uictx, MAP_BLOCK_LEFT, MAP_BLOCK_TOP, 340, 360);
- this._update_map();
- uictx.globalAlpha = globalAlphafloor / 100;
- core.drawImage(
- uictx,
- "green.webp",
- MAP_BLOCK_LEFT + 150,
- MAP_BLOCK_TOP + 170
- );
- uictx.globalAlpha = 1;
- }
- }
- //更新背景
- _update_background() {
- if (core.domStyle.isVertical) {
- bgctx.canvas.width = GAMEVIEW_WIDTH_VERTICAL;
- bgctx.canvas.height = GAMEVIEW_HEIGHT_VERTICAL;
- uictx.canvas.width = GAMEVIEW_WIDTH_VERTICAL;
- uictx.canvas.height = GAMEVIEW_HEIGHT_VERTICAL;
+ class StatusBar {
+ constructor() {
+ //道具栏列表
+ this.itemMx = [
+ //空位用‘none’填充,当前ui至多4列6行
+ ["book", "wand", "none", "fly"],
+ ["cross", "superPotion", "pickaxe"],
+ ["bomb", "centerFly", "upFly"],
+ ["none", "none", "none"],
+ ["downFly", "knife", "snow"],
+ ["bigKey", "earthquake", "coin"],
+ ];
+ }
+ //初始化内容(工具栏/录像操作执行函数)
+ init() {
+ this.toolbarAction = [
+ [
+ main.core.openKeyBoard,
+ main.core.openQuickShop,
+ core.openToolbox,
+ core.doSL,
+ ],
+ [main.core.openSettings, main.core.save, main.core.load, core.doSL],
+ ];
+ this.replayAction = [
+ [core.triggerReplay, core.stopReplay, core.rewindReplay],
+ [core.speedDownReplay, core.speedUpReplay, core.saveReplay],
+ ];
+ }
+ //更新
+ update() {
+ this._update_background(); //更新背景
+ this._update_props(); //更新属性
+ //this._update_items(); //更新道具
+ //this._update_equips(); //更新装备
+ //this._update_keys(); //更新钥匙
+ //this._update_infoWindow(); //更新道具说明
+ this._update_toolBox(); //更新工具栏
+ this._redrawMap();
+ }
+ _redrawMap() {
+ if (core.domStyle.isVertical) {
+ core.clearMap(
+ uictx,
+ MAP_BLOCK_LEFT_VERTICAL,
+ MAP_BLOCK_TOP_VERTICAL,
+ 340,
+ 360
+ );
+ this._update_map();
+ uictx.globalAlpha = globalAlphafloor / 100;
+ core.drawImage(
+ uictx,
+ "green.webp",
+ MAP_BLOCK_LEFT_VERTICAL + 125,
+ MAP_BLOCK_TOP_VERTICAL + 170
+ );
+ uictx.globalAlpha = 1;
+ } else {
+ core.clearMap(uictx, MAP_BLOCK_LEFT, MAP_BLOCK_TOP, 340, 360);
+ this._update_map();
+ uictx.globalAlpha = globalAlphafloor / 100;
+ core.drawImage(
+ uictx,
+ "green.webp",
+ MAP_BLOCK_LEFT + 150,
+ MAP_BLOCK_TOP + 170
+ );
+ uictx.globalAlpha = 1;
+ }
+ }
+ //更新背景
+ _update_background() {
+ if (core.domStyle.isVertical) {
+ bgctx.canvas.width = GAMEVIEW_WIDTH_VERTICAL;
+ bgctx.canvas.height = GAMEVIEW_HEIGHT_VERTICAL;
+ uictx.canvas.width = GAMEVIEW_WIDTH_VERTICAL;
+ uictx.canvas.height = GAMEVIEW_HEIGHT_VERTICAL;
- const bg = core.material.images.images["status.webp"]; //竖屏背景(上)
- bgctx.drawImage(
- bg,
- 0,
- 0,
- GAMEVIEW_WIDTH_VERTICAL,
- BAR_HEIGHT_VERTICAL
- );
- const bg2 = core.material.images.images["status.webp"]; //竖屏背景(下)
- bgctx.drawImage(
- bg2,
- 0,
- BAR_HEIGHT_VERTICAL + GAMEVIEW_WIDTH_VERTICAL,
- GAMEVIEW_WIDTH_VERTICAL,
- BAR_HEIGHT_VERTICAL
- );
- bgctx.globalAlpha = globalAlpha;
- bgctx.globalAlpha = 1;
- core.setTextAlign("outerUI", "center");
- } else {
- bgctx.canvas.width = GAMEVIEW_WIDTH;
- bgctx.canvas.height = GAMEVIEW_HEIGHT;
- uictx.canvas.width = GAMEVIEW_WIDTH;
- uictx.canvas.height = GAMEVIEW_HEIGHT;
+ const bg = core.material.images.images["status.webp"]; //竖屏背景(上)
+ bgctx.drawImage(
+ bg,
+ 0,
+ 0,
+ GAMEVIEW_WIDTH_VERTICAL,
+ BAR_HEIGHT_VERTICAL
+ );
+ const bg2 = core.material.images.images["status.webp"]; //竖屏背景(下)
+ bgctx.drawImage(
+ bg2,
+ 0,
+ BAR_HEIGHT_VERTICAL + GAMEVIEW_WIDTH_VERTICAL,
+ GAMEVIEW_WIDTH_VERTICAL,
+ BAR_HEIGHT_VERTICAL
+ );
+ bgctx.globalAlpha = globalAlpha;
+ bgctx.globalAlpha = 1;
+ core.setTextAlign("outerUI", "center");
+ } else {
+ bgctx.canvas.width = GAMEVIEW_WIDTH;
+ bgctx.canvas.height = GAMEVIEW_HEIGHT;
+ uictx.canvas.width = GAMEVIEW_WIDTH;
+ uictx.canvas.height = GAMEVIEW_HEIGHT;
- const bg = core.material.images.images["status.webp"]; //横屏背景(左)
- bgctx.drawImage(bg, 0, 0, BAR_WIDTH, GAMEVIEW_HEIGHT);
- const bg2 = core.material.images.images["status.webp"]; //横屏背景(右)
- bgctx.drawImage(
- bg2,
- BAR_WIDTH + GAMEVIEW_HEIGHT,
- 0,
- BAR_WIDTH,
- GAMEVIEW_HEIGHT
- );
- bgctx.globalAlpha = globalAlpha;
+ const bg = core.material.images.images["status.webp"]; //横屏背景(左)
+ bgctx.drawImage(bg, 0, 0, BAR_WIDTH, GAMEVIEW_HEIGHT);
+ const bg2 = core.material.images.images["status.webp"]; //横屏背景(右)
+ bgctx.drawImage(
+ bg2,
+ BAR_WIDTH + GAMEVIEW_HEIGHT,
+ 0,
+ BAR_WIDTH,
+ GAMEVIEW_HEIGHT
+ );
+ bgctx.globalAlpha = globalAlpha;
- bgctx.globalAlpha = 1;
- core.setTextAlign("outerUI", "center");
- }
- }
- // 更新属性
- _update_props(updatedFloorTitle) {
- 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 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
- );
+ bgctx.globalAlpha = 1;
+ core.setTextAlign("outerUI", "center");
+ }
+ }
+ // 更新属性
+ _update_props(updatedFloorTitle) {
+ 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 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.fillBoldText1(
- "outerUI",
- core.getRealStatus(item),
- baseX,
- curh,
- TEXT_COLOR,
- "#000000",
- 6
- );
- curh += 24 * 3;
- if (curh > 130 * 3 && core.domStyle.isVertical) {
- curh = 24 * 3;
- baseX += 105 * 3;
- }
- });
- core.setTextAlign("outerUI", "center");
- };
- if (core.domStyle.isVertical) {
- core.clearMap("outerUI", 10 * 3, 0, 210 * 3, 120 * 3);
- core.setFont("outerUI", "bold 42px Verdana");
- if (updatedFloorTitle) {
- core.fillBoldText1(
- "outerUI",
- updatedFloorTitle,
- 60 * 3,
- 22 * 3,
- TEXT_COLOR,
- "#000000",
- 6
- );
- }
- //drawStatusList(96 * 3, 46 * 3);
- //core.drawImage("outerUI", "lane1.png", 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");
- if (updatedFloorTitle) {
- core.fillBoldText1(
- "outerUI",
- updatedFloorTitle,
- 62 * 3,
- 41 * 3,
- TEXT_COLOR,
- "#000000",
- 6
- );
- }
- //drawStatusList(110 * 3, 93 * 3);
- //core.drawImage("outerUI", "lane1.png", 0, 30)
- core.drawImage(
- "outerUI",
- "cao.webp",
- 0,
- 0,
- 400,
- 350,
- 0,
- 30,
- 360,
- 315
- );
- }
- }
- _update_items() {
- //更新道具栏
- const drawItemMx = (drawFn) => {
- for (let i = 0; i < this.itemMx.length; i++) {
- for (let j = 0; j < this.itemMx[i].length; j++) {
- var item = this.itemMx[i][j];
- drawFn(i, j, item);
- }
- }
- };
- const drawItem = (item, posx, posy) => {
- const icon = core.material.icons.items[item],
- image = core.material.images.items;
- core.drawImage(
- "outerUI",
- image,
- 0,
- 32 * icon,
- 32,
- 32,
- posx,
- posy,
- 30 * 3,
- 30 * 3
- );
- const cnt = core.itemCount(item);
- if (
- (core.items.items[item].cls === "tools" && cnt > 1) ||
- FORCE_COUNTABLE_ITEMS.includes(item)
- ) {
- core.fillText(
- "outerUI",
- cnt,
- posx + 25 * 3,
- posy + 28 * 3,
- "#FFFFFF",
- "bold 36px Verdana"
- );
- }
- };
- if (core.domStyle.isVertical) {
- core.clearMap(
- "outerUI",
- ITEM_BOX_LEFT_VERTICAL,
- ITEM_BOX_TOP_VERTICAL,
- 185 * 3,
- 125 * 3
- );
+ // 四舍五入
+ core.status.hero[item] = Math.round(core.status.hero[item]);
+ // 大数据格式化
+ core.fillBoldText1(
+ "outerUI",
+ core.getRealStatus(item),
+ baseX,
+ curh,
+ TEXT_COLOR,
+ "#000000",
+ 6
+ );
+ curh += 24 * 3;
+ if (curh > 130 * 3 && core.domStyle.isVertical) {
+ curh = 24 * 3;
+ baseX += 105 * 3;
+ }
+ });
+ core.setTextAlign("outerUI", "center");
+ };
+ if (core.domStyle.isVertical) {
+ core.clearMap("outerUI", 10 * 3, 0, 210 * 3, 120 * 3);
+ core.setFont("outerUI", "bold 42px Verdana");
+ if (updatedFloorTitle) {
+ core.fillBoldText1(
+ "outerUI",
+ updatedFloorTitle,
+ 60 * 3,
+ 22 * 3,
+ TEXT_COLOR,
+ "#000000",
+ 6
+ );
+ }
+ //drawStatusList(96 * 3, 46 * 3);
+ //core.drawImage("outerUI", "lane1.png", 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");
+ if (updatedFloorTitle) {
+ core.fillBoldText1(
+ "outerUI",
+ updatedFloorTitle,
+ 62 * 3,
+ 41 * 3,
+ TEXT_COLOR,
+ "#000000",
+ 6
+ );
+ }
+ //drawStatusList(110 * 3, 93 * 3);
+ //core.drawImage("outerUI", "lane1.png", 0, 30)
+ core.drawImage(
+ "outerUI",
+ "cao.webp",
+ 0,
+ 0,
+ 400,
+ 350,
+ 0,
+ 30,
+ 360,
+ 315
+ );
+ }
+ }
+ _update_items() {
+ //更新道具栏
+ const drawItemMx = (drawFn) => {
+ for (let i = 0; i < this.itemMx.length; i++) {
+ for (let j = 0; j < this.itemMx[i].length; j++) {
+ var item = this.itemMx[i][j];
+ drawFn(i, j, item);
+ }
+ }
+ };
+ const drawItem = (item, posx, posy) => {
+ const icon = core.material.icons.items[item],
+ image = core.material.images.items;
+ core.drawImage(
+ "outerUI",
+ image,
+ 0,
+ 32 * icon,
+ 32,
+ 32,
+ posx,
+ posy,
+ 30 * 3,
+ 30 * 3
+ );
+ const cnt = core.itemCount(item);
+ if (
+ (core.items.items[item].cls === "tools" && cnt > 1) ||
+ FORCE_COUNTABLE_ITEMS.includes(item)
+ ) {
+ core.fillText(
+ "outerUI",
+ cnt,
+ posx + 25 * 3,
+ posy + 28 * 3,
+ "#FFFFFF",
+ "bold 36px Verdana"
+ );
+ }
+ };
+ if (core.domStyle.isVertical) {
+ core.clearMap(
+ "outerUI",
+ ITEM_BOX_LEFT_VERTICAL,
+ ITEM_BOX_TOP_VERTICAL,
+ 185 * 3,
+ 125 * 3
+ );
- drawItemMx((i, j, item) => {
- if (core.hasItem(item)) {
- const posx = ITEM_BOX_LEFT_VERTICAL + i * 30 * 3,
- posy = ITEM_BOX_TOP_VERTICAL + j * 31 * 3;
- drawItem(item, posx, posy);
- }
- });
- } else {
- core.clearMap(
- "outerUI",
- ITEM_BOX_LEFT,
- ITEM_BOX_TOP,
- 125 * 3,
- 185 * 3
- );
+ drawItemMx((i, j, item) => {
+ if (core.hasItem(item)) {
+ const posx = ITEM_BOX_LEFT_VERTICAL + i * 30 * 3,
+ posy = ITEM_BOX_TOP_VERTICAL + j * 31 * 3;
+ drawItem(item, posx, posy);
+ }
+ });
+ } else {
+ core.clearMap(
+ "outerUI",
+ ITEM_BOX_LEFT,
+ ITEM_BOX_TOP,
+ 125 * 3,
+ 185 * 3
+ );
- drawItemMx((i, j, item) => {
- if (core.hasItem(item)) {
- const posx = ITEM_BOX_LEFT + j * 30 * 3,
- posy = ITEM_BOX_TOP + i * 31 * 3;
- drawItem(item, posx, posy);
- }
- });
- }
- }
+ drawItemMx((i, j, item) => {
+ if (core.hasItem(item)) {
+ const posx = ITEM_BOX_LEFT + j * 30 * 3,
+ posy = ITEM_BOX_TOP + i * 31 * 3;
+ drawItem(item, posx, posy);
+ }
+ });
+ }
+ }
- _update_map(floorId = core.status.floorId) {
- const x = core.domStyle.isVertical ?
- MAP_BLOCK_LEFT_VERTICAL :
- MAP_BLOCK_LEFT;
- const y = core.domStyle.isVertical ?
- MAP_BLOCK_TOP_VERTICAL :
- MAP_BLOCK_TOP;
+ _update_map(floorId = core.status.floorId) {
+ const x = core.domStyle.isVertical
+ ? MAP_BLOCK_LEFT_VERTICAL
+ : MAP_BLOCK_LEFT;
+ const y = core.domStyle.isVertical
+ ? MAP_BLOCK_TOP_VERTICAL
+ : MAP_BLOCK_TOP;
- if (!floorId) return;
- const info = core.plugin.getMapDrawInfo(floorId, Infinity, true);
- core.setTextAlign("outerUI", "center");
+ if (!floorId) return;
+ const info = core.plugin.getMapDrawInfo(floorId, Infinity, true);
+ core.setTextAlign("outerUI", "center");
- core.plugin.drawSmallMap(uictx, info, floorId, x, y, 300, 300);
- }
+ core.plugin.drawSmallMap(uictx, info, floorId, x, y, 300, 300);
+ }
- _update_equips() {
- return;
- core.setFont("outerUI", "bold 48px Verdana");
- const drawEquip = (baseX, baseY, id, color, back) => {
- if (!id)
- core.fillText(
- "outerUI",
- back,
- baseX + 20 * 3,
- baseY + 22 * 3,
- color
- );
- else {
- var icon = core.material.icons.items[id];
- core.drawImage(
- "outerUI",
- core.material.images.items,
- 0,
- 32 * icon,
- 32,
- 32,
- baseX + 5 * 3,
- baseY,
- 32 * 3,
- 32 * 3
- );
- }
- };
- if (core.domStyle.isVertical) {
- core.clearMap(
- "outerUI",
- EQUIP_BLOCK_LEFT_VERTICAL,
- EQUIP_BLOCK_TOP_VERTICAL,
- 90 * 3,
- 130 * 3
- );
- drawEquip(
- EQUIP_BLOCK_LEFT_VERTICAL,
- EQUIP_BLOCK_TOP_VERTICAL,
- core.getEquip(0),
- "#D1CEFF",
- "无"
- );
- drawEquip(
- EQUIP_BLOCK_LEFT_VERTICAL + 45 * 3,
- EQUIP_BLOCK_TOP_VERTICAL,
- core.getEquip(1),
- "#D1CEFF",
- "无"
- );
- drawEquip(
- EQUIP_BLOCK_LEFT_VERTICAL,
- EQUIP_BLOCK_TOP_VERTICAL + 45 * 3,
- core.getEquip(2),
- "#D1CEFF",
- "无"
- );
- drawEquip(
- EQUIP_BLOCK_LEFT_VERTICAL + 45 * 3,
- EQUIP_BLOCK_TOP_VERTICAL + 45 * 3,
- core.getEquip(3),
- "#D1CEFF",
- "无"
- );
- drawEquip(
- EQUIP_BLOCK_LEFT_VERTICAL,
- EQUIP_BLOCK_TOP_VERTICAL + 90 * 3,
- core.getEquip(4),
- "#D1CEFF",
- "无"
- );
- drawEquip(
- EQUIP_BLOCK_LEFT_VERTICAL + 45 * 3,
- EQUIP_BLOCK_TOP_VERTICAL + 90 * 3,
- core.getEquip(5),
- "#D1CEFF",
- "无"
- );
- } else {
- core.clearMap(
- "outerUI",
- EQUIP_BLOCK_LEFT,
- EQUIP_BLOCK_TOP,
- 130 * 3,
- 95 * 3
- );
- drawEquip(
- EQUIP_BLOCK_LEFT,
- EQUIP_BLOCK_TOP,
- core.getEquip(0),
- "#D1CEFF",
- "无"
- );
- drawEquip(
- EQUIP_BLOCK_LEFT + 42 * 3,
- EQUIP_BLOCK_TOP,
- core.getEquip(1),
- "#D1CEFF",
- "无"
- );
- drawEquip(
- EQUIP_BLOCK_LEFT + 85 * 3,
- EQUIP_BLOCK_TOP,
- core.getEquip(2),
- "#D1CEFF",
- "无"
- );
- drawEquip(
- EQUIP_BLOCK_LEFT,
- EQUIP_BLOCK_TOP + 45 * 3,
- core.getEquip(3),
- "#D1CEFF",
- "无"
- );
- drawEquip(
- EQUIP_BLOCK_LEFT + 42 * 3,
- EQUIP_BLOCK_TOP + 45 * 3,
- core.getEquip(4),
- "#D1CEFF",
- "无"
- );
- drawEquip(
- EQUIP_BLOCK_LEFT + 85 * 3,
- EQUIP_BLOCK_TOP + 45 * 3,
- core.getEquip(5),
- "#D1CEFF",
- "无"
- );
- }
- }
- _update_keys() {
- const drawKeyList = (baseX, baseY) => {
- const todraw = [],
- keyList = ["yellowKey", "blueKey", "redKey", "greenKey"];
- let total = 0;
- keyList.forEach(function (key, i) {
- todraw[i] = core.itemCount(key);
- total += todraw[i];
- });
+ _update_equips() {
+ return;
+ core.setFont("outerUI", "bold 48px Verdana");
+ const drawEquip = (baseX, baseY, id, color, back) => {
+ if (!id)
+ core.fillText(
+ "outerUI",
+ back,
+ baseX + 20 * 3,
+ baseY + 22 * 3,
+ color
+ );
+ else {
+ var icon = core.material.icons.items[id];
+ core.drawImage(
+ "outerUI",
+ core.material.images.items,
+ 0,
+ 32 * icon,
+ 32,
+ 32,
+ baseX + 5 * 3,
+ baseY,
+ 32 * 3,
+ 32 * 3
+ );
+ }
+ };
+ if (core.domStyle.isVertical) {
+ core.clearMap(
+ "outerUI",
+ EQUIP_BLOCK_LEFT_VERTICAL,
+ EQUIP_BLOCK_TOP_VERTICAL,
+ 90 * 3,
+ 130 * 3
+ );
+ drawEquip(
+ EQUIP_BLOCK_LEFT_VERTICAL,
+ EQUIP_BLOCK_TOP_VERTICAL,
+ core.getEquip(0),
+ "#D1CEFF",
+ "无"
+ );
+ drawEquip(
+ EQUIP_BLOCK_LEFT_VERTICAL + 45 * 3,
+ EQUIP_BLOCK_TOP_VERTICAL,
+ core.getEquip(1),
+ "#D1CEFF",
+ "无"
+ );
+ drawEquip(
+ EQUIP_BLOCK_LEFT_VERTICAL,
+ EQUIP_BLOCK_TOP_VERTICAL + 45 * 3,
+ core.getEquip(2),
+ "#D1CEFF",
+ "无"
+ );
+ drawEquip(
+ EQUIP_BLOCK_LEFT_VERTICAL + 45 * 3,
+ EQUIP_BLOCK_TOP_VERTICAL + 45 * 3,
+ core.getEquip(3),
+ "#D1CEFF",
+ "无"
+ );
+ drawEquip(
+ EQUIP_BLOCK_LEFT_VERTICAL,
+ EQUIP_BLOCK_TOP_VERTICAL + 90 * 3,
+ core.getEquip(4),
+ "#D1CEFF",
+ "无"
+ );
+ drawEquip(
+ EQUIP_BLOCK_LEFT_VERTICAL + 45 * 3,
+ EQUIP_BLOCK_TOP_VERTICAL + 90 * 3,
+ core.getEquip(5),
+ "#D1CEFF",
+ "无"
+ );
+ } else {
+ core.clearMap(
+ "outerUI",
+ EQUIP_BLOCK_LEFT,
+ EQUIP_BLOCK_TOP,
+ 130 * 3,
+ 95 * 3
+ );
+ drawEquip(
+ EQUIP_BLOCK_LEFT,
+ EQUIP_BLOCK_TOP,
+ core.getEquip(0),
+ "#D1CEFF",
+ "无"
+ );
+ drawEquip(
+ EQUIP_BLOCK_LEFT + 42 * 3,
+ EQUIP_BLOCK_TOP,
+ core.getEquip(1),
+ "#D1CEFF",
+ "无"
+ );
+ drawEquip(
+ EQUIP_BLOCK_LEFT + 85 * 3,
+ EQUIP_BLOCK_TOP,
+ core.getEquip(2),
+ "#D1CEFF",
+ "无"
+ );
+ drawEquip(
+ EQUIP_BLOCK_LEFT,
+ EQUIP_BLOCK_TOP + 45 * 3,
+ core.getEquip(3),
+ "#D1CEFF",
+ "无"
+ );
+ drawEquip(
+ EQUIP_BLOCK_LEFT + 42 * 3,
+ EQUIP_BLOCK_TOP + 45 * 3,
+ core.getEquip(4),
+ "#D1CEFF",
+ "无"
+ );
+ drawEquip(
+ EQUIP_BLOCK_LEFT + 85 * 3,
+ EQUIP_BLOCK_TOP + 45 * 3,
+ core.getEquip(5),
+ "#D1CEFF",
+ "无"
+ );
+ }
+ }
+ _update_keys() {
+ const drawKeyList = (baseX, baseY) => {
+ const todraw = [],
+ keyList = ["yellowKey", "blueKey", "redKey", "greenKey"];
+ let total = 0;
+ keyList.forEach(function (key, i) {
+ todraw[i] = core.itemCount(key);
+ total += todraw[i];
+ });
- let dn = 3;
- for (let i = 0; i <= dn; i++) {
- let delta = i * 32 * 3;
+ let dn = 3;
+ for (let i = 0; i <= dn; i++) {
+ let delta = i * 32 * 3;
- if (core.domStyle.isVertical) {
- this.drawKey(keyList[i], baseX, baseY + delta);
- } else {
- this.drawKey(keyList[i], baseX + delta, baseY);
- }
+ if (core.domStyle.isVertical) {
+ this.drawKey(keyList[i], baseX, baseY + delta);
+ } else {
+ this.drawKey(keyList[i], baseX + delta, baseY);
+ }
- core.setFont("outerUI", "bold 48px Verdana");
- core.setTextAlign("outerUI", "left");
- if (core.domStyle.isVertical) {
- core.fillText(
- "outerUI",
- todraw[i],
- baseX + 20 * 3,
- baseY + 14 * 3 + delta,
- TEXT_COLOR
- );
- } else {
- core.fillText(
- "outerUI",
- todraw[i],
- baseX + delta,
- baseY + 32 * 3,
- TEXT_COLOR
- );
- }
- }
- };
- if (core.domStyle.isVertical) {
- core.clearMap(
- "outerUI",
- KEY_BLOCK_LEFT_VERTICAL,
- KEY_BLOCK_TOP_VERTICAL,
- 45 * 3,
- 130 * 3
- );
- drawKeyList(
- KEY_BLOCK_LEFT_VERTICAL + 3 * 3,
- KEY_BLOCK_TOP_VERTICAL + 5 * 3
- );
- } else {
- core.clearMap(
- "outerUI",
- KEY_BLOCK_LEFT,
- KEY_BLOCK_TOP,
- 130 * 3,
- 45 * 3
- );
- drawKeyList(KEY_BLOCK_LEFT + 10 * 3, KEY_BLOCK_TOP);
- }
- }
- drawKey(key, x, y) {
- let sx = 0,
- sy = 0;
+ core.setFont("outerUI", "bold 48px Verdana");
+ core.setTextAlign("outerUI", "left");
+ if (core.domStyle.isVertical) {
+ core.fillText(
+ "outerUI",
+ todraw[i],
+ baseX + 20 * 3,
+ baseY + 14 * 3 + delta,
+ TEXT_COLOR
+ );
+ } else {
+ core.fillText(
+ "outerUI",
+ todraw[i],
+ baseX + delta,
+ baseY + 32 * 3,
+ TEXT_COLOR
+ );
+ }
+ }
+ };
+ if (core.domStyle.isVertical) {
+ core.clearMap(
+ "outerUI",
+ KEY_BLOCK_LEFT_VERTICAL,
+ KEY_BLOCK_TOP_VERTICAL,
+ 45 * 3,
+ 130 * 3
+ );
+ drawKeyList(
+ KEY_BLOCK_LEFT_VERTICAL + 3 * 3,
+ KEY_BLOCK_TOP_VERTICAL + 5 * 3
+ );
+ } else {
+ core.clearMap(
+ "outerUI",
+ KEY_BLOCK_LEFT,
+ KEY_BLOCK_TOP,
+ 130 * 3,
+ 45 * 3
+ );
+ drawKeyList(KEY_BLOCK_LEFT + 10 * 3, KEY_BLOCK_TOP);
+ }
+ }
+ drawKey(key, x, y) {
+ let sx = 0,
+ sy = 0;
- if (key == "yellowKey") sx += 13;
- else if (key == "blueKey") sx += 26;
- else if (key == "greenKey") sx += 39;
+ if (key == "yellowKey") sx += 13;
+ else if (key == "blueKey") sx += 26;
+ else if (key == "greenKey") sx += 39;
- core.drawImage(
- "outerUI",
- "maba.webp",
- sx,
- sy,
- 13,
- 26,
- x,
- y,
- 13 * 3,
- 26 * 3
- );
- }
- _update_infoWindow() {
- const itemId = this.selectedItem;
- let text = "";
- if (this.selectedItem) {
- text = core.replaceText(core.material.items[itemId]?.text);
- if (text[0] == "," || text[0] == ",") text = text.substring(1);
- }
- if (core.domStyle.isVertical) {
- core.clearMap(
- "outerUI",
- INFO_BLOCK_LEFT_VERTICAL,
- INFO_BLOCK_TOP_VERTICAL,
- 300 * 3,
- 120 * 3
- );
+ core.drawImage(
+ "outerUI",
+ "maba.webp",
+ sx,
+ sy,
+ 13,
+ 26,
+ x,
+ y,
+ 13 * 3,
+ 26 * 3
+ );
+ }
+ _update_infoWindow() {
+ const itemId = this.selectedItem;
+ let text = "";
+ if (this.selectedItem) {
+ text = core.replaceText(core.material.items[itemId]?.text);
+ if (text[0] == "," || text[0] == ",") text = text.substring(1);
+ }
+ if (core.domStyle.isVertical) {
+ core.clearMap(
+ "outerUI",
+ INFO_BLOCK_LEFT_VERTICAL,
+ INFO_BLOCK_TOP_VERTICAL,
+ 300 * 3,
+ 120 * 3
+ );
- if (this.selectedItem) {
- const icon = core.material.icons.items[itemId];
- core.setTextAlign("outerUI", "left");
- core.fillText(
- "outerUI",
- core.material.items[itemId].name,
- INFO_BLOCK_LEFT_VERTICAL + 50 * 3,
- INFO_BLOCK_TOP_VERTICAL + 27 * 3,
- "#D1CEFF"
- );
- core.drawImage(
- "outerUI",
- core.material.images.items,
- 0,
- 32 * icon,
- 32,
- 32,
- INFO_BLOCK_LEFT_VERTICAL + 10 * 3,
- INFO_BLOCK_TOP_VERTICAL + 8 * 3,
- 32 * 3,
- 32 * 3
- );
- core.ui.drawTextContent("outerUI", text, {
- left: INFO_BLOCK_LEFT_VERTICAL + 10 * 3,
- top: INFO_BLOCK_TOP_VERTICAL + 40 * 3,
- maxWidth: 275 * 3,
- color: "#D1CEFF",
- fontSize: 36,
- });
- }
- } else {
- core.clearMap(
- "outerUI",
- INFO_BLOCK_LEFT,
- INFO_BLOCK_TOP,
- 115 * 3,
- 230 * 3
- );
+ if (this.selectedItem) {
+ const icon = core.material.icons.items[itemId];
+ core.setTextAlign("outerUI", "left");
+ core.fillText(
+ "outerUI",
+ core.material.items[itemId].name,
+ INFO_BLOCK_LEFT_VERTICAL + 50 * 3,
+ INFO_BLOCK_TOP_VERTICAL + 27 * 3,
+ "#D1CEFF"
+ );
+ core.drawImage(
+ "outerUI",
+ core.material.images.items,
+ 0,
+ 32 * icon,
+ 32,
+ 32,
+ INFO_BLOCK_LEFT_VERTICAL + 10 * 3,
+ INFO_BLOCK_TOP_VERTICAL + 8 * 3,
+ 32 * 3,
+ 32 * 3
+ );
+ core.ui.drawTextContent("outerUI", text, {
+ left: INFO_BLOCK_LEFT_VERTICAL + 10 * 3,
+ top: INFO_BLOCK_TOP_VERTICAL + 40 * 3,
+ maxWidth: 275 * 3,
+ color: "#D1CEFF",
+ fontSize: 36,
+ });
+ }
+ } else {
+ core.clearMap(
+ "outerUI",
+ INFO_BLOCK_LEFT,
+ INFO_BLOCK_TOP,
+ 115 * 3,
+ 230 * 3
+ );
- if (this.selectedItem) {
- const icon = core.material.icons.items[itemId];
- core.setTextAlign("outerUI", "center");
- core.fillText(
- "outerUI",
- core.material.items[itemId].name,
- INFO_BLOCK_LEFT + 60 * 3,
- INFO_BLOCK_TOP + 25 * 3,
- "#D1CEFF"
- );
- core.drawImage(
- "outerUI",
- core.material.images.items,
- 0,
- 32 * icon,
- 32,
- 32,
- INFO_BLOCK_LEFT + 45 * 3,
- INFO_BLOCK_TOP + 30 * 3,
- 32 * 3,
- 32 * 3
- );
- core.ui.drawTextContent("outerUI", text, {
- left: INFO_BLOCK_LEFT + 10 * 3,
- top: INFO_BLOCK_TOP + 60 * 3,
- maxWidth: 105 * 3,
- color: "#D1CEFF",
- fontSize: 36,
- });
- }
- }
- }
- showItemInfo(itemId) {
- //展示道具说明
- this.selectedItem = itemId;
- this._update_infoWindow();
- }
- clearItemInfo() {
- //清除道具说明
- this.selectedItem = null;
- this._update_infoWindow();
- }
- _update_toolBox() {
- const tools = core.isReplaying() ? [
- [core.status.replay.pausing ? "play" : "pause", "stop", "rewind"],
- ["speedDown", "speedUp", "save"],
- ] : [
- ["keyboard", "shop", "pack", "T332"],
- ["settings", "save", "load", "T331"],
- ];
- if (core.domStyle.isVertical) {
- core.clearMap(
- "outerUI",
- TOOL_BOX_LEFT_VERTICAL,
- TOOL_BOX_TOP_VERTICAL,
- 115,
- 130
- );
+ if (this.selectedItem) {
+ const icon = core.material.icons.items[itemId];
+ core.setTextAlign("outerUI", "center");
+ core.fillText(
+ "outerUI",
+ core.material.items[itemId].name,
+ INFO_BLOCK_LEFT + 60 * 3,
+ INFO_BLOCK_TOP + 25 * 3,
+ "#D1CEFF"
+ );
+ core.drawImage(
+ "outerUI",
+ core.material.images.items,
+ 0,
+ 32 * icon,
+ 32,
+ 32,
+ INFO_BLOCK_LEFT + 45 * 3,
+ INFO_BLOCK_TOP + 30 * 3,
+ 32 * 3,
+ 32 * 3
+ );
+ core.ui.drawTextContent("outerUI", text, {
+ left: INFO_BLOCK_LEFT + 10 * 3,
+ top: INFO_BLOCK_TOP + 60 * 3,
+ maxWidth: 105 * 3,
+ color: "#D1CEFF",
+ fontSize: 36,
+ });
+ }
+ }
+ }
+ showItemInfo(itemId) {
+ //展示道具说明
+ this.selectedItem = itemId;
+ this._update_infoWindow();
+ }
+ clearItemInfo() {
+ //清除道具说明
+ this.selectedItem = null;
+ this._update_infoWindow();
+ }
+ _update_toolBox() {
+ const tools = core.isReplaying()
+ ? [
+ [core.status.replay.pausing ? "play" : "pause", "stop", "rewind"],
+ ["speedDown", "speedUp", "save"],
+ ]
+ : [
+ ["keyboard", "shop", "pack", "T332"],
+ ["settings", "save", "load", "T331"],
+ ];
+ if (core.domStyle.isVertical) {
+ core.clearMap(
+ "outerUI",
+ TOOL_BOX_LEFT_VERTICAL,
+ TOOL_BOX_TOP_VERTICAL,
+ 115,
+ 130
+ );
- for (let i = 0; i < tools.length; i++) {
- for (let j = 0; j < tools[i].length; j++) {
- core.drawIcon(
- "outerUI",
- tools[i][j],
- TOOL_BOX_LEFT_VERTICAL + i * 31 * 3,
- TOOL_BOX_TOP_VERTICAL + j * 31 * 3,
- 30 * 3,
- 30 * 3
- );
- }
- }
- } else {
- core.clearMap(
- "outerUI",
- TOOL_BOX_LEFT,
- TOOL_BOX_TOP,
- 130 * 3,
- 80 * 3
- );
+ for (let i = 0; i < tools.length; i++) {
+ for (let j = 0; j < tools[i].length; j++) {
+ core.drawIcon(
+ "outerUI",
+ tools[i][j],
+ TOOL_BOX_LEFT_VERTICAL + i * 31 * 3,
+ TOOL_BOX_TOP_VERTICAL + j * 31 * 3,
+ 30 * 3,
+ 30 * 3
+ );
+ }
+ }
+ } else {
+ core.clearMap(
+ "outerUI",
+ TOOL_BOX_LEFT,
+ TOOL_BOX_TOP,
+ 130 * 3,
+ 80 * 3
+ );
- for (let i = 0; i < tools.length; i++) {
- for (let j = 0; j < tools[i].length; j++) {
- core.drawIcon(
- "outerUI",
- tools[i][j],
- TOOL_BOX_LEFT + j * 31 * 3,
- TOOL_BOX_TOP + i * 31 * 3,
- 30 * 3,
- 30 * 3
- );
- }
- }
- }
- }
- onclick(x, y) {
- const makeBox = ([x, y], [w, h]) => {
- return [
- [x, y],
- [x + w, y + h],
- ];
- };
- const gridify = ([x, y], [gw, gh]) => {
- return [Math.floor(x / gw), Math.floor(y / gh)];
- };
- const useItem = (itemId) => {
- if (!core.hasItem(itemId)) return;
+ for (let i = 0; i < tools.length; i++) {
+ for (let j = 0; j < tools[i].length; j++) {
+ core.drawIcon(
+ "outerUI",
+ tools[i][j],
+ TOOL_BOX_LEFT + j * 31 * 3,
+ TOOL_BOX_TOP + i * 31 * 3,
+ 30 * 3,
+ 30 * 3
+ );
+ }
+ }
+ }
+ }
+ onclick(x, y) {
+ const makeBox = ([x, y], [w, h]) => {
+ return [
+ [x, y],
+ [x + w, y + h],
+ ];
+ };
+ const gridify = ([x, y], [gw, gh]) => {
+ return [Math.floor(x / gw), Math.floor(y / gh)];
+ };
+ const useItem = (itemId) => {
+ if (!core.hasItem(itemId)) return;
- if (itemId != this.selectedItem) {
- this.showItemInfo(itemId);
- } else {
- switch (itemId) {
- case "centerFly":
- core.ui._drawCenterFly();
- break;
- case "book":
- core.openBook(true);
- break;
- case "wand":
- core.insertAction({
- type: "useItem",
- id: itemId,
- });
- break;
- case "fly":
- core.useItem(itemId);
- break;
- default:
- core.useItem(itemId);
- }
- }
- };
- const inRect = ([x, y], [
- [sx, sy],
- [dx, dy]
- ]) => {
- return sx <= x && x <= dx && sy <= y && y <= dy;
- };
- const relativeTo = ([x, y], [ax, ay]) => {
- return [x - ax, y - ay];
- };
- const pos = [x, y];
- if (core.domStyle.isVertical) {
- const itemBox = makeBox(
- [ITEM_BOX_LEFT_VERTICAL, ITEM_BOX_TOP_VERTICAL],
- [30 * 6 * 3, 31 * 4 * 3]
- );
- if (inRect(pos, itemBox)) {
- const [gx, gy] = gridify(relativeTo(pos, itemBox[0]), [
- 30 * 3,
- 31 * 3,
- ]);
- const itemId = this.itemMx[gx][gy];
- if (
- (core.status.event.id == "viewMaps" ||
- core.status.event.id == "fly") &&
- itemId === "book"
- )
- core.openBook(true);
- if (
- core.isReplaying() ||
- core.status.lockControl ||
- core.isMoving()
- )
- return;
- useItem(itemId);
- return;
- }
- const toolBox = makeBox(
- [TOOL_BOX_LEFT_VERTICAL, TOOL_BOX_TOP_VERTICAL],
- [31 * 2 * 3, 31 * 4 * 3]
- );
- if (inRect(pos, toolBox)) {
- const [col, row] = gridify(relativeTo(pos, toolBox[0]), [
- 31 * 3,
- 31 * 3,
- ]);
- if (core.status.lockControl || core.isMoving()) return;
- if (core.isReplaying()) {
- this.replayAction[col][row].call(core);
- } else if (core.isPlaying()) {
- if (col === 0 && row === 3) {
- core.doSL("autoSave", "load");
- } else if (col === 1 && row === 3) {
- core.doSL("autoSave", "reload");
- } else {
- this.toolbarAction[col][row].call(core, true);
- }
- }
- return;
- }
- const mapBox = makeBox(
- [MAP_BLOCK_LEFT_VERTICAL, MAP_BLOCK_TOP_VERTICAL],
- [350, 350]
- );
- if (inRect(pos, mapBox)) {
- if (
- core.isReplaying() ||
- core.status.lockControl ||
- core.isMoving()
- )
- return;
- core.useItem("fly");
- return;
- }
- /*const equipBox = makeBox([EQUIP_BLOCK_LEFT_VERTICAL, EQUIP_BLOCK_TOP_VERTICAL], [90 * 3, 130 * 3])
+ if (itemId != this.selectedItem) {
+ this.showItemInfo(itemId);
+ } else {
+ switch (itemId) {
+ case "centerFly":
+ core.ui._drawCenterFly();
+ break;
+ case "book":
+ core.openBook(true);
+ break;
+ case "wand":
+ core.insertAction({
+ type: "useItem",
+ id: itemId,
+ });
+ break;
+ case "fly":
+ core.useItem(itemId);
+ break;
+ default:
+ core.useItem(itemId);
+ }
+ }
+ };
+ const inRect = ([x, y], [[sx, sy], [dx, dy]]) => {
+ return sx <= x && x <= dx && sy <= y && y <= dy;
+ };
+ const relativeTo = ([x, y], [ax, ay]) => {
+ return [x - ax, y - ay];
+ };
+ const pos = [x, y];
+ if (core.domStyle.isVertical) {
+ const itemBox = makeBox(
+ [ITEM_BOX_LEFT_VERTICAL, ITEM_BOX_TOP_VERTICAL],
+ [30 * 6 * 3, 31 * 4 * 3]
+ );
+ if (inRect(pos, itemBox)) {
+ const [gx, gy] = gridify(relativeTo(pos, itemBox[0]), [
+ 30 * 3,
+ 31 * 3,
+ ]);
+ const itemId = this.itemMx[gx][gy];
+ if (
+ (core.status.event.id == "viewMaps" ||
+ core.status.event.id == "fly") &&
+ itemId === "book"
+ )
+ core.openBook(true);
+ if (
+ core.isReplaying() ||
+ core.status.lockControl ||
+ core.isMoving()
+ )
+ return;
+ useItem(itemId);
+ return;
+ }
+ const toolBox = makeBox(
+ [TOOL_BOX_LEFT_VERTICAL, TOOL_BOX_TOP_VERTICAL],
+ [31 * 2 * 3, 31 * 4 * 3]
+ );
+ if (inRect(pos, toolBox)) {
+ const [col, row] = gridify(relativeTo(pos, toolBox[0]), [
+ 31 * 3,
+ 31 * 3,
+ ]);
+ if (core.status.lockControl || core.isMoving()) return;
+ if (core.isReplaying()) {
+ this.replayAction[col][row].call(core);
+ } else if (core.isPlaying()) {
+ if (col === 0 && row === 3) {
+ core.doSL("autoSave", "load");
+ } else if (col === 1 && row === 3) {
+ core.doSL("autoSave", "reload");
+ } else {
+ this.toolbarAction[col][row].call(core, true);
+ }
+ }
+ return;
+ }
+ const mapBox = makeBox(
+ [MAP_BLOCK_LEFT_VERTICAL, MAP_BLOCK_TOP_VERTICAL],
+ [350, 350]
+ );
+ if (inRect(pos, mapBox)) {
+ if (
+ core.isReplaying() ||
+ core.status.lockControl ||
+ core.isMoving()
+ )
+ return;
+ core.useItem("fly");
+ return;
+ }
+ /*const equipBox = makeBox([EQUIP_BLOCK_LEFT_VERTICAL, EQUIP_BLOCK_TOP_VERTICAL], [90 * 3, 130 * 3])
if (inRect(pos, equipBox)) {
if (core.isReplaying() || core.status.lockControl || core.isMoving()) return;
core.openEquipbox(true)
return;
}*/
- } else {
- const mapBox = makeBox([MAP_BLOCK_LEFT, MAP_BLOCK_TOP], [350, 350]);
- if (inRect(pos, mapBox)) {
- if (
- core.isReplaying() ||
- core.status.lockControl ||
- core.isMoving()
- )
- return;
- core.useItem("fly");
- return;
- }
- /*
+ } else {
+ const mapBox = makeBox([MAP_BLOCK_LEFT, MAP_BLOCK_TOP], [350, 350]);
+ if (inRect(pos, mapBox)) {
+ if (
+ core.isReplaying() ||
+ core.status.lockControl ||
+ core.isMoving()
+ )
+ return;
+ core.useItem("fly");
+ return;
+ }
+ /*
const equipBox = makeBox([EQUIP_BLOCK_LEFT, EQUIP_BLOCK_TOP], [130, 95])
if (inRect(pos, equipBox)) {
if (core.isReplaying() || core.status.lockControl || core.isMoving()) return;
core.openEquipbox(true)
return;
}*/
- const itemBox = makeBox(
- [ITEM_BOX_LEFT, ITEM_BOX_TOP],
- [31 * 4 * 3, 30 * 6 * 3]
- );
- if (inRect(pos, itemBox)) {
- const [gx, gy] = gridify(relativeTo(pos, itemBox[0]), [
- 31 * 3,
- 30 * 3,
- ]);
- const itemId = this.itemMx[gy][gx];
- if (
- (core.status.event.id == "viewMaps" ||
- core.status.event.id == "fly") &&
- itemId === "book"
- )
- core.openBook(true);
- if (
- core.isReplaying() ||
- core.status.lockControl ||
- core.isMoving()
- )
- return;
- useItem(itemId);
- return;
- }
- const toolBox = makeBox(
- [TOOL_BOX_LEFT, TOOL_BOX_TOP],
- [31 * 4 * 3, 31 * 2 * 3]
- );
- if (inRect(pos, toolBox)) {
- const [row, col] = gridify(relativeTo(pos, toolBox[0]), [
- 31 * 3,
- 31 * 3,
- ]);
- if (core.status.lockControl || core.isMoving()) return;
- if (core.isReplaying()) {
- this.replayAction[col][row].call(core);
- } else if (core.isPlaying()) {
- if (col === 0 && row === 3) {
- core.doSL("autoSave", "load");
- } else if (col === 1 && row === 3) {
- core.doSL("autoSave", "reload");
- } else {
- this.toolbarAction[col][row].call(core, true);
- }
- }
- return;
- }
- }
- }
- }
+ const itemBox = makeBox(
+ [ITEM_BOX_LEFT, ITEM_BOX_TOP],
+ [31 * 4 * 3, 30 * 6 * 3]
+ );
+ if (inRect(pos, itemBox)) {
+ const [gx, gy] = gridify(relativeTo(pos, itemBox[0]), [
+ 31 * 3,
+ 30 * 3,
+ ]);
+ const itemId = this.itemMx[gy][gx];
+ if (
+ (core.status.event.id == "viewMaps" ||
+ core.status.event.id == "fly") &&
+ itemId === "book"
+ )
+ core.openBook(true);
+ if (
+ core.isReplaying() ||
+ core.status.lockControl ||
+ core.isMoving()
+ )
+ return;
+ useItem(itemId);
+ return;
+ }
+ const toolBox = makeBox(
+ [TOOL_BOX_LEFT, TOOL_BOX_TOP],
+ [31 * 4 * 3, 31 * 2 * 3]
+ );
+ if (inRect(pos, toolBox)) {
+ const [row, col] = gridify(relativeTo(pos, toolBox[0]), [
+ 31 * 3,
+ 31 * 3,
+ ]);
+ if (core.status.lockControl || core.isMoving()) return;
+ if (core.isReplaying()) {
+ this.replayAction[col][row].call(core);
+ } else if (core.isPlaying()) {
+ if (col === 0 && row === 3) {
+ core.doSL("autoSave", "load");
+ } else if (col === 1 && row === 3) {
+ core.doSL("autoSave", "reload");
+ } else {
+ this.toolbarAction[col][row].call(core, true);
+ }
+ }
+ return;
+ }
+ }
+ }
+ }
- core.ui.statusBar = new StatusBar();
+ core.ui.statusBar = new StatusBar();
- core.control.clearStatusBar = function () {
- core.clearMap("outerUI");
- };
- // init() called in `afterLoadResources`.
-},
+ core.control.clearStatusBar = function () {
+ core.clearMap("outerUI");
+ };
+ // init() called in `afterLoadResources`.
+ },
"override": function () {
- core.statusBar.icons = {
- floor: 0,
- name: null,
- lv: 1,
- hpmax: 2,
- hp: 3,
- atk: 4,
- def: 5,
- mdef: 6,
- money: 7,
- exp: 8,
- up: 9,
- book: 10,
- fly: 11,
- toolbox: 12,
- keyboard: 13,
- shop: 14,
- save: 15,
- load: 16,
- settings: 17,
- play: 18,
- pause: 19,
- stop: 20,
- speedDown: 21,
- speedUp: 22,
- rewind: 23,
- equipbox: 24,
- mana: 25,
- skill: 26,
- exit: 27,
- btn1: 28,
- btn2: 29,
- btn3: 30,
- btn4: 31,
- btn5: 32,
- btn6: 33,
- btn7: 34,
- alt: 35,
- keys: 36,
- help: 37,
- battle: 38,
- };
- core.actions._getClickLoc = function (x, y) {
- var size = 32 * core.domStyle.scale;
- var left = main.dom.gameDraw.offsetLeft + main.dom.gameGroup.offsetLeft;
- var top = main.dom.gameDraw.offsetTop + main.dom.gameGroup.offsetTop;
- var loc = {
- x: Math.max(x - left, 0),
- y: Math.max(y - top, 0),
- size: size,
- };
- return loc;
- };
- core.ui._drawWindowSelector = function (background, x, y, w, h) {
- w = Math.round(w) + 48;
- h = Math.round(h);
- var ctx = core.ui.createCanvas("_selector", x - 24, y, w, h, 165);
- ctx.canvas.id = "";
- this._drawSelector(ctx, background, w, h);
- };
+ core.statusBar.icons = {
+ floor: 0,
+ name: null,
+ lv: 1,
+ hpmax: 2,
+ hp: 3,
+ atk: 4,
+ def: 5,
+ mdef: 6,
+ money: 7,
+ exp: 8,
+ up: 9,
+ book: 10,
+ fly: 11,
+ toolbox: 12,
+ keyboard: 13,
+ shop: 14,
+ save: 15,
+ load: 16,
+ settings: 17,
+ play: 18,
+ pause: 19,
+ stop: 20,
+ speedDown: 21,
+ speedUp: 22,
+ rewind: 23,
+ equipbox: 24,
+ mana: 25,
+ skill: 26,
+ exit: 27,
+ btn1: 28,
+ btn2: 29,
+ btn3: 30,
+ btn4: 31,
+ btn5: 32,
+ btn6: 33,
+ btn7: 34,
+ alt: 35,
+ keys: 36,
+ help: 37,
+ battle: 38,
+ };
+ core.actions._getClickLoc = function (x, y) {
+ var size = 32 * core.domStyle.scale;
+ var left = main.dom.gameDraw.offsetLeft + main.dom.gameGroup.offsetLeft;
+ var top = main.dom.gameDraw.offsetTop + main.dom.gameGroup.offsetTop;
+ var loc = {
+ x: Math.max(x - left, 0),
+ y: Math.max(y - top, 0),
+ size: size,
+ };
+ return loc;
+ };
+ core.ui._drawWindowSelector = function (background, x, y, w, h) {
+ w = Math.round(w) + 48;
+ h = Math.round(h);
+ var ctx = core.ui.createCanvas("_selector", x - 24, y, w, h, 165);
+ ctx.canvas.id = "";
+ this._drawSelector(ctx, background, w, h);
+ };
- core.ui._drawSelector = function (ctx, background, w, h, left, top) {
- left = left || 0;
- top = top || 0;
- ctx = this.getContextByName(ctx);
- if (!ctx) return;
- if (typeof background == "string")
- background = core.material.images.images[background];
- if (!(background instanceof Image)) return;
- // badge
- ctx.drawImage(background, 132, 68, 24, 24, left + 4, top + 4, 24, 24);
- ctx.drawImage(
- background,
- 132,
- 68,
- 24,
- 24,
- w - left - 28,
- top + 4,
- 24,
- 24
- );
- };
+ core.ui._drawSelector = function (ctx, background, w, h, left, top) {
+ left = left || 0;
+ top = top || 0;
+ ctx = this.getContextByName(ctx);
+ if (!ctx) return;
+ if (typeof background == "string")
+ background = core.material.images.images[background];
+ if (!(background instanceof Image)) return;
+ // badge
+ ctx.drawImage(background, 132, 68, 24, 24, left + 4, top + 4, 24, 24);
+ ctx.drawImage(
+ background,
+ 132,
+ 68,
+ 24,
+ 24,
+ w - left - 28,
+ top + 4,
+ 24,
+ 24
+ );
+ };
- enemys.prototype._nextCriticals_useBinarySearch = function (
- enemy,
- info,
- number,
- x,
- y,
- floorId
- ) {
- var mon_hp = info.mon_hp,
- hero_atk = core.status.hero.atk,
- mon_def = info.mon_def,
- pre = info.damage;
- var list = [];
- var start_atk = hero_atk;
- if (info.__over__) {
- start_atk += info.__overAtk__;
- list.push([info.__overAtk__, -info.damage]);
- }
- var calNext = function (currAtk, maxAtk) {
- var start = Math.floor(currAtk),
- end = Math.floor(maxAtk);
- if (start > end) return null;
+ enemys.prototype._nextCriticals_useBinarySearch = function (
+ enemy,
+ info,
+ number,
+ x,
+ y,
+ floorId
+ ) {
+ var mon_hp = info.mon_hp,
+ hero_atk = core.status.hero.atk,
+ mon_def = info.mon_def,
+ pre = info.damage;
+ var list = [];
+ var start_atk = hero_atk;
+ if (info.__over__) {
+ start_atk += info.__overAtk__;
+ list.push([info.__overAtk__, -info.damage]);
+ }
+ var calNext = function (currAtk, maxAtk) {
+ var start = Math.floor(currAtk),
+ end = Math.floor(maxAtk);
+ if (start > end) return null;
- while (start < end) {
- var mid = Math.floor((start + end) / 2);
- if (mid - start > end - mid) mid--;
- var nextInfo = core.enemys.getDamageInfo(
- enemy, { atk: mid },
- x,
- y,
- floorId
- );
- if (nextInfo == null || typeof nextInfo == "number") return null;
- if (pre > nextInfo.damage) end = mid;
- else start = mid + 1;
- }
- var nextInfo = core.enemys.getDamageInfo(
- enemy, { atk: start },
- x,
- y,
- floorId
- );
- return nextInfo == null ||
- typeof nextInfo == "number" ||
- nextInfo.damage >= pre ?
- null : [start, nextInfo.damage];
- };
- var currAtk = start_atk;
- while (true) {
- var next = calNext(currAtk + 1, Number.MAX_SAFE_INTEGER, pre);
- if (next == null) break;
- currAtk = next[0];
- pre = next[1];
- list.push([currAtk - hero_atk, info.damage - pre]);
- if (pre <= 0 && !core.flags.enableNegativeDamage) break;
- if (list.length >= number) break;
- }
- if (list.length == 0) list.push([0, 0]);
- return list;
- };
- core.ui.clearMap = function (name, x, y, width, height) {
- if (name == "all") {
- for (var m in core.canvas) {
- core.canvas[m].clearRect(
- -32,
- -32,
- core.canvas[m].canvas.width + 32,
- core.canvas[m].canvas.height + 32
- );
- }
- core.clearMap("outerUI");
- core.dom.gif.innerHTML = "";
- core.removeGlobalAnimate();
- core.deleteCanvas(function (one) {
- return one.startsWith("_bigImage_");
- });
- core.setWeather(null);
- } else {
- var ctx = this.getContextByName(name);
- if (ctx)
- ctx.clearRect(
- x || 0,
- y || 0,
- width || ctx.canvas.width,
- height || ctx.canvas.height
- );
- }
- };
- events.prototype.openBook = function (fromUserAction) {
- if (core.isReplaying()) return;
- // 如果能恢复事件(从callBook事件触发)
- if (
- core.status.event.id == "book" &&
- core.events.recoverEvents(core.status.event.interval)
- )
- return;
- // 当前是book,且从“浏览地图”打开
- if (core.status.event.id == "book" && core.status.event.ui) {
- core.status.boxAnimateObjs = [];
- core.ui._drawViewMaps(core.status.event.ui);
- return;
- }
- // 从“浏览地图”页面打开
- if (core.status.event.id == "viewMaps" || core.status.event.id == "fly") {
- fromUserAction = false;
- core.status.event.ui = core.status.event.data;
- }
- if (!this._checkStatus("book", fromUserAction, true)) return;
- core.playSound("打开界面");
- core.useItem("book", true);
- };
- ////// 怪物手册界面时,放开某个键的操作 //////
- core.actions._keyUpBook = function (keycode) {
- if (keycode == 27 || keycode == 88) {
- core.playSound("取消");
- if (core.events.recoverEvents(core.status.event.interval)) {
- return;
- } else if (core.status.event.ui != null) {
- core.status.boxAnimateObjs = [];
- if (typeof core.status.event.ui === "number") {
- core.status.event.id = "fly";
- core.ui.drawFly(core.status.event.ui);
- } else {
- core.ui._drawViewMaps(core.status.event.ui);
- }
- } else core.ui.closePanel();
- return;
- }
- if (keycode == 13 || keycode == 32 || keycode == 67) {
- var data = core.status.event.data;
- if (data != null) {
- core.ui._drawBookDetail(data);
- }
- return;
- }
- };
- ////// 怪物手册界面的点击操作 //////
- actions.prototype._clickBook = function (x, y) {
- var pageinfo = core.ui._drawBook_pageinfo();
- // 上一页
- if (
- (x == this._HX_ - 2 || x == this._HX_ - 3) &&
- y === core._HEIGHT_ - 1
- ) {
- core.playSound("光标移动");
- core.ui.drawBook(core.status.event.data - pageinfo.per_page);
- return;
- }
- // 下一页
- if (
- (x == this._HX_ + 2 || x == this._HX_ + 3) &&
- y === core._HEIGHT_ - 1
- ) {
- core.playSound("光标移动");
- core.ui.drawBook(core.status.event.data + pageinfo.per_page);
- return;
- }
- // 返回
- if (x >= this.LAST - 2 && y === core._HEIGHT_ - 1) {
- core.playSound("取消");
- if (core.events.recoverEvents(core.status.event.interval)) {
- return;
- } else if (core.status.event.ui != null) {
- core.status.boxAnimateObjs = [];
- if (typeof core.status.event.ui === "number") {
- core.status.event.id = "fly";
- core.ui.drawFly(core.status.event.ui);
- } else {
- core.ui._drawViewMaps(core.status.event.ui);
- }
- } else core.ui.closePanel();
- return;
- }
- // 怪物信息
- var data = core.status.event.data;
- if (data != null && y < core._HEIGHT_ - 1) {
- var per_page = pageinfo.per_page,
- page = parseInt(data / per_page);
- var u = (core._HEIGHT_ - 1) / per_page;
- for (var i = 0; i < per_page; ++i) {
- if (y >= u * i && y < u * (i + 1)) {
- var index = per_page * page + i;
- core.ui.drawBook(index);
- core.ui._drawBookDetail(index);
- break;
- }
- }
- return;
- }
- return;
- };
+ while (start < end) {
+ var mid = Math.floor((start + end) / 2);
+ if (mid - start > end - mid) mid--;
+ var nextInfo = core.enemys.getDamageInfo(
+ enemy,
+ { atk: mid },
+ x,
+ y,
+ floorId
+ );
+ if (nextInfo == null || typeof nextInfo == "number") return null;
+ if (pre > nextInfo.damage) end = mid;
+ else start = mid + 1;
+ }
+ var nextInfo = core.enemys.getDamageInfo(
+ enemy,
+ { atk: start },
+ x,
+ y,
+ floorId
+ );
+ return nextInfo == null ||
+ typeof nextInfo == "number" ||
+ nextInfo.damage >= pre
+ ? null
+ : [start, nextInfo.damage];
+ };
+ var currAtk = start_atk;
+ while (true) {
+ var next = calNext(currAtk + 1, Number.MAX_SAFE_INTEGER, pre);
+ if (next == null) break;
+ currAtk = next[0];
+ pre = next[1];
+ list.push([currAtk - hero_atk, info.damage - pre]);
+ if (pre <= 0 && !core.flags.enableNegativeDamage) break;
+ if (list.length >= number) break;
+ }
+ if (list.length == 0) list.push([0, 0]);
+ return list;
+ };
+ core.ui.clearMap = function (name, x, y, width, height) {
+ if (name == "all") {
+ for (var m in core.canvas) {
+ core.canvas[m].clearRect(
+ -32,
+ -32,
+ core.canvas[m].canvas.width + 32,
+ core.canvas[m].canvas.height + 32
+ );
+ }
+ core.clearMap("outerUI");
+ core.dom.gif.innerHTML = "";
+ core.removeGlobalAnimate();
+ core.deleteCanvas(function (one) {
+ return one.startsWith("_bigImage_");
+ });
+ core.setWeather(null);
+ } else {
+ var ctx = this.getContextByName(name);
+ if (ctx)
+ ctx.clearRect(
+ x || 0,
+ y || 0,
+ width || ctx.canvas.width,
+ height || ctx.canvas.height
+ );
+ }
+ };
+ events.prototype.openBook = function (fromUserAction) {
+ if (core.isReplaying()) return;
+ // 如果能恢复事件(从callBook事件触发)
+ if (
+ core.status.event.id == "book" &&
+ core.events.recoverEvents(core.status.event.interval)
+ )
+ return;
+ // 当前是book,且从“浏览地图”打开
+ if (core.status.event.id == "book" && core.status.event.ui) {
+ core.status.boxAnimateObjs = [];
+ core.ui._drawViewMaps(core.status.event.ui);
+ return;
+ }
+ // 从“浏览地图”页面打开
+ if (core.status.event.id == "viewMaps" || core.status.event.id == "fly") {
+ fromUserAction = false;
+ core.status.event.ui = core.status.event.data;
+ }
+ if (!this._checkStatus("book", fromUserAction, true)) return;
+ core.playSound("打开界面");
+ core.useItem("book", true);
+ };
+ ////// 怪物手册界面时,放开某个键的操作 //////
+ core.actions._keyUpBook = function (keycode) {
+ if (keycode == 27 || keycode == 88) {
+ core.playSound("取消");
+ if (core.events.recoverEvents(core.status.event.interval)) {
+ return;
+ } else if (core.status.event.ui != null) {
+ core.status.boxAnimateObjs = [];
+ if (typeof core.status.event.ui === "number") {
+ core.status.event.id = "fly";
+ core.ui.drawFly(core.status.event.ui);
+ } else {
+ core.ui._drawViewMaps(core.status.event.ui);
+ }
+ } else core.ui.closePanel();
+ return;
+ }
+ if (keycode == 13 || keycode == 32 || keycode == 67) {
+ var data = core.status.event.data;
+ if (data != null) {
+ core.ui._drawBookDetail(data);
+ }
+ return;
+ }
+ };
+ ////// 怪物手册界面的点击操作 //////
+ actions.prototype._clickBook = function (x, y) {
+ var pageinfo = core.ui._drawBook_pageinfo();
+ // 上一页
+ if (
+ (x == this._HX_ - 2 || x == this._HX_ - 3) &&
+ y === core._HEIGHT_ - 1
+ ) {
+ core.playSound("光标移动");
+ core.ui.drawBook(core.status.event.data - pageinfo.per_page);
+ return;
+ }
+ // 下一页
+ if (
+ (x == this._HX_ + 2 || x == this._HX_ + 3) &&
+ y === core._HEIGHT_ - 1
+ ) {
+ core.playSound("光标移动");
+ core.ui.drawBook(core.status.event.data + pageinfo.per_page);
+ return;
+ }
+ // 返回
+ if (x >= this.LAST - 2 && y === core._HEIGHT_ - 1) {
+ core.playSound("取消");
+ if (core.events.recoverEvents(core.status.event.interval)) {
+ return;
+ } else if (core.status.event.ui != null) {
+ core.status.boxAnimateObjs = [];
+ if (typeof core.status.event.ui === "number") {
+ core.status.event.id = "fly";
+ core.ui.drawFly(core.status.event.ui);
+ } else {
+ core.ui._drawViewMaps(core.status.event.ui);
+ }
+ } else core.ui.closePanel();
+ return;
+ }
+ // 怪物信息
+ var data = core.status.event.data;
+ if (data != null && y < core._HEIGHT_ - 1) {
+ var per_page = pageinfo.per_page,
+ page = parseInt(data / per_page);
+ var u = (core._HEIGHT_ - 1) / per_page;
+ for (var i = 0; i < per_page; ++i) {
+ if (y >= u * i && y < u * (i + 1)) {
+ var index = per_page * page + i;
+ core.ui.drawBook(index);
+ core.ui._drawBookDetail(index);
+ break;
+ }
+ }
+ return;
+ }
+ return;
+ };
- ////// 执行当前自定义事件列表中的下一个事件 //////
- events.prototype.doAction = function () {
- // 清空boxAnimate和UI层
- clearInterval(core.status.event.interval);
- clearTimeout(core.status.event.interval);
- clearInterval(core.status.event.animateUI);
- core.status.event.interval = null;
- delete core.status.event.aniamteUI;
- if (core.status.gameOver || core.status.replay.failed) return;
- // 判定是否执行完毕
- if (this._doAction_finishEvents()) return;
- core.clearUI();
- var floorId = core.status.event.data.floorId || core.status.floorId;
- // 当前点坐标和前缀
- var x = core.status.event.data.x,
- y = core.status.event.data.y;
- var prefix = [
- floorId || ":f",
- x != null ? x : "x",
- y != null ? y : "y",
- ].join("@");
- var current = core.status.event.data.list[0];
- if (this._popEvents(current, prefix)) return;
- // 当前要执行的事件
- var data = current.todo.shift();
- core.status.event.data.current = data;
- if (typeof data == "string") data = { type: "text", text: data };
- // 该事件块已经被禁用
- if (data._disabled) return core.doAction();
- if (data.type !== "cgtext") {
- core.unregisterAnimationFrame("skip");
- core.setFlag("skip", false);
- }
- data.floorId = data.floorId || floorId;
- core.status.event.data.type = data.type;
- this.doEvent(data, x, y, prefix);
- return;
- };
+ ////// 执行当前自定义事件列表中的下一个事件 //////
+ events.prototype.doAction = function () {
+ // 清空boxAnimate和UI层
+ clearInterval(core.status.event.interval);
+ clearTimeout(core.status.event.interval);
+ clearInterval(core.status.event.animateUI);
+ core.status.event.interval = null;
+ delete core.status.event.aniamteUI;
+ if (core.status.gameOver || core.status.replay.failed) return;
+ // 判定是否执行完毕
+ if (this._doAction_finishEvents()) return;
+ core.clearUI();
+ var floorId = core.status.event.data.floorId || core.status.floorId;
+ // 当前点坐标和前缀
+ var x = core.status.event.data.x,
+ y = core.status.event.data.y;
+ var prefix = [
+ floorId || ":f",
+ x != null ? x : "x",
+ y != null ? y : "y",
+ ].join("@");
+ var current = core.status.event.data.list[0];
+ if (this._popEvents(current, prefix)) return;
+ // 当前要执行的事件
+ var data = current.todo.shift();
+ core.status.event.data.current = data;
+ if (typeof data == "string") data = { type: "text", text: data };
+ // 该事件块已经被禁用
+ if (data._disabled) return core.doAction();
+ if (data.type !== "cgtext") {
+ core.unregisterAnimationFrame("skip");
+ core.setFlag("skip", false);
+ }
+ data.floorId = data.floorId || floorId;
+ core.status.event.data.type = data.type;
+ this.doEvent(data, x, y, prefix);
+ return;
+ };
- ////// 在某个canvas上绘制粗体 //////
- core.fillBoldText1 = function (
- name,
- text,
- x,
- y,
- style,
- strokeStyle,
- lineWidth,
- font,
- maxWidth
- ) {
- var ctx = this.getContextByName(name);
- if (!ctx) return;
- if (font) ctx.font = font;
- if (!style) style = ctx.fillStyle;
- style = core.arrayToRGBA(style);
- if (!strokeStyle) strokeStyle = "#000000";
- strokeStyle = core.arrayToRGBA(strokeStyle);
- if (maxWidth != null) {
- this.setFontForMaxWidth(ctx, text, maxWidth);
- }
- ctx.strokeStyle = strokeStyle;
+ ////// 在某个canvas上绘制粗体 //////
+ core.fillBoldText1 = function (
+ name,
+ text,
+ x,
+ y,
+ style,
+ strokeStyle,
+ lineWidth,
+ font,
+ maxWidth
+ ) {
+ var ctx = this.getContextByName(name);
+ if (!ctx) return;
+ if (font) ctx.font = font;
+ if (!style) style = ctx.fillStyle;
+ style = core.arrayToRGBA(style);
+ if (!strokeStyle) strokeStyle = "#000000";
+ strokeStyle = core.arrayToRGBA(strokeStyle);
+ if (maxWidth != null) {
+ this.setFontForMaxWidth(ctx, text, maxWidth);
+ }
+ ctx.strokeStyle = strokeStyle;
- if (!lineWidth) lineWidth = 2;
- ctx.lineWidth = lineWidth;
- ctx.strokeText(text, x, y);
- ctx.fillStyle = style;
- ctx.fillText(text, x, y);
- };
- ////// 绘制 WindowSkin
- ui.prototype.drawWindowSkin = function (
- background,
- ctx,
- x,
- y,
- w,
- h,
- direction,
- px,
- py,
- size = 1
- ) {
- background = background || core.status.textAttribute.background;
+ if (!lineWidth) lineWidth = 2;
+ ctx.lineWidth = lineWidth;
+ ctx.strokeText(text, x, y);
+ ctx.fillStyle = style;
+ ctx.fillText(text, x, y);
+ };
+ ////// 绘制 WindowSkin
+ ui.prototype.drawWindowSkin = function (
+ background,
+ ctx,
+ x,
+ y,
+ w,
+ h,
+ direction,
+ px,
+ py,
+ size = 1
+ ) {
+ background = background || core.status.textAttribute.background;
- // 仿RM窗口皮肤 ↓
- // 绘制背景
- core.drawImage(
- ctx,
- background,
- 0,
- 0,
- 128,
- 128,
- x + 2 * size,
- y + 2 * size,
- w - 4 * size,
- h - 4 * size
- );
- // 绘制边框
- // 上方
- core.drawImage(
- ctx,
- background,
- 128,
- 0,
- 16,
- 16,
- x,
- y,
- 16 * size,
- 16 * size
- );
- for (var dx = 0; dx < w - 64 * size; dx += 32 * size) {
- core.drawImage(
- ctx,
- background,
- 144,
- 0,
- 32,
- 16,
- x + dx + 16 * size,
- y,
- 32 * size,
- 16 * size
- );
- core.drawImage(
- ctx,
- background,
- 144,
- 48,
- 32,
- 16,
- x + dx + 16 * size,
- y + h - 16 * size,
- 32 * size,
- 16 * size
- );
- }
- core.drawImage(
- ctx,
- background,
- 144,
- 0,
- (w - dx - 32 * size) / size,
- 16,
- x + dx + 16 * size,
- y,
- w - dx - 32 * size,
- 16 * size
- );
- core.drawImage(
- ctx,
- background,
- 144,
- 48,
- (w - dx - 32 * size) / size,
- 16,
- x + dx + 16 * size,
- y + h - 16 * size,
- w - dx - 32 * size,
- 16 * size
- );
- core.drawImage(
- ctx,
- background,
- 176,
- 0,
- 16,
- 16,
- x + w - 16 * size,
- y,
- 16 * size,
- 16 * size
- );
- // 左右
- for (var dy = 0; dy < h - 64 * size; dy += 32 * size) {
- core.drawImage(
- ctx,
- background,
- 128,
- 16,
- 16,
- 32,
- x,
- y + dy + 16 * size,
- 16 * size,
- 32 * size
- );
- core.drawImage(
- ctx,
- background,
- 176,
- 16,
- 16,
- 32,
- x + w - 16 * size,
- y + dy + 16 * size,
- 16 * size,
- 32 * size
- );
- }
- core.drawImage(
- ctx,
- background,
- 128,
- 16,
- 16,
- (h - dy - 32 * size) / size,
- x,
- y + dy + 16 * size,
- 16 * size,
- h - dy - 32 * size
- );
- core.drawImage(
- ctx,
- background,
- 176,
- 16,
- 16,
- (h - dy - 32 * size) / size,
- x + w - 16 * size,
- y + dy + 16 * size,
- 16 * size,
- h - dy - 32 * size
- );
- //下方
- core.drawImage(
- ctx,
- background,
- 128,
- 48,
- 16,
- 16,
- x,
- y + h - 16 * size,
- 16 * size,
- 16 * size
- );
- core.drawImage(
- ctx,
- background,
- 176,
- 48,
- 16,
- 16,
- x + w - 16 * size,
- y + h - 16 * size,
- 16 * size,
- 16 * size
- );
+ // 仿RM窗口皮肤 ↓
+ // 绘制背景
+ core.drawImage(
+ ctx,
+ background,
+ 0,
+ 0,
+ 128,
+ 128,
+ x + 2 * size,
+ y + 2 * size,
+ w - 4 * size,
+ h - 4 * size
+ );
+ // 绘制边框
+ // 上方
+ core.drawImage(
+ ctx,
+ background,
+ 128,
+ 0,
+ 16,
+ 16,
+ x,
+ y,
+ 16 * size,
+ 16 * size
+ );
+ for (var dx = 0; dx < w - 64 * size; dx += 32 * size) {
+ core.drawImage(
+ ctx,
+ background,
+ 144,
+ 0,
+ 32,
+ 16,
+ x + dx + 16 * size,
+ y,
+ 32 * size,
+ 16 * size
+ );
+ core.drawImage(
+ ctx,
+ background,
+ 144,
+ 48,
+ 32,
+ 16,
+ x + dx + 16 * size,
+ y + h - 16 * size,
+ 32 * size,
+ 16 * size
+ );
+ }
+ core.drawImage(
+ ctx,
+ background,
+ 144,
+ 0,
+ (w - dx - 32 * size) / size,
+ 16,
+ x + dx + 16 * size,
+ y,
+ w - dx - 32 * size,
+ 16 * size
+ );
+ core.drawImage(
+ ctx,
+ background,
+ 144,
+ 48,
+ (w - dx - 32 * size) / size,
+ 16,
+ x + dx + 16 * size,
+ y + h - 16 * size,
+ w - dx - 32 * size,
+ 16 * size
+ );
+ core.drawImage(
+ ctx,
+ background,
+ 176,
+ 0,
+ 16,
+ 16,
+ x + w - 16 * size,
+ y,
+ 16 * size,
+ 16 * size
+ );
+ // 左右
+ for (var dy = 0; dy < h - 64 * size; dy += 32 * size) {
+ core.drawImage(
+ ctx,
+ background,
+ 128,
+ 16,
+ 16,
+ 32,
+ x,
+ y + dy + 16 * size,
+ 16 * size,
+ 32 * size
+ );
+ core.drawImage(
+ ctx,
+ background,
+ 176,
+ 16,
+ 16,
+ 32,
+ x + w - 16 * size,
+ y + dy + 16 * size,
+ 16 * size,
+ 32 * size
+ );
+ }
+ core.drawImage(
+ ctx,
+ background,
+ 128,
+ 16,
+ 16,
+ (h - dy - 32 * size) / size,
+ x,
+ y + dy + 16 * size,
+ 16 * size,
+ h - dy - 32 * size
+ );
+ core.drawImage(
+ ctx,
+ background,
+ 176,
+ 16,
+ 16,
+ (h - dy - 32 * size) / size,
+ x + w - 16 * size,
+ y + dy + 16 * size,
+ 16 * size,
+ h - dy - 32 * size
+ );
+ //下方
+ core.drawImage(
+ ctx,
+ background,
+ 128,
+ 48,
+ 16,
+ 16,
+ x,
+ y + h - 16 * size,
+ 16 * size,
+ 16 * size
+ );
+ core.drawImage(
+ ctx,
+ background,
+ 176,
+ 48,
+ 16,
+ 16,
+ x + w - 16 * size,
+ y + h - 16 * size,
+ 16 * size,
+ 16 * size
+ );
- // arrow
- if (px != null && py != null) {
- if (direction == "up") {
- core.drawImage(
- ctx,
- background,
- 128,
- 96,
- 32,
- 32,
- px,
- y + h - 3 * size,
- 32 * size,
- 32 * size
- );
- } else if (direction == "down") {
- core.drawImage(
- ctx,
- background,
- 160,
- 96,
- 32,
- 32,
- px,
- y - 29 * size,
- 32 * size,
- 32 * size
- );
- }
- }
- // 仿RM窗口皮肤 ↑
- };
- events.prototype.battle = function (id, x, y, force, callback) {
- core.saveAndStopAutomaticRoute();
- id = id || core.getBlockId(x, y);
- const cls = core.getClsFromId(id)
- if (!id || !cls || !(cls === 'enemys' || cls === 'enemy48')) return core.clearContinueAutomaticRoute(callback);
- // 非强制战斗
- if (!core.enemys.canBattle(id, x, y) && !force && !core.status.event.id) {
- core.stopSound();
- core.playSound("操作失败");
- core.drawTip("你打不过此怪物!", id);
- return core.clearContinueAutomaticRoute(callback);
- }
- // 自动存档
- if (!core.status.event.id) core.autosave(true);
- // 战前事件
- if (!this.beforeBattle(id, x, y))
- return core.clearContinueAutomaticRoute(callback);
- // 战后事件
- this.afterBattle(id, x, y);
- if (callback) callback();
- };
-
-},
+ // arrow
+ if (px != null && py != null) {
+ if (direction == "up") {
+ core.drawImage(
+ ctx,
+ background,
+ 128,
+ 96,
+ 32,
+ 32,
+ px,
+ y + h - 3 * size,
+ 32 * size,
+ 32 * size
+ );
+ } else if (direction == "down") {
+ core.drawImage(
+ ctx,
+ background,
+ 160,
+ 96,
+ 32,
+ 32,
+ px,
+ y - 29 * size,
+ 32 * size,
+ 32 * size
+ );
+ }
+ }
+ // 仿RM窗口皮肤 ↑
+ };
+ events.prototype.battle = function (id, x, y, force, callback) {
+ core.saveAndStopAutomaticRoute();
+ id = id || core.getBlockId(x, y);
+ const cls = core.getClsFromId(id);
+ if (!id || !cls || !(cls === "enemys" || cls === "enemy48"))
+ return core.clearContinueAutomaticRoute(callback);
+ // 非强制战斗
+ if (!core.enemys.canBattle(id, x, y) && !force && !core.status.event.id) {
+ core.stopSound();
+ core.playSound("操作失败");
+ core.drawTip("你打不过此怪物!", id);
+ return core.clearContinueAutomaticRoute(callback);
+ }
+ // 自动存档
+ if (!core.status.event.id) core.autosave(true);
+ // 战前事件
+ if (!this.beforeBattle(id, x, y))
+ return core.clearContinueAutomaticRoute(callback);
+ // 战后事件
+ this.afterBattle(id, x, y);
+ if (callback) callback();
+ };
+ },
"额外信息": function () {
/* 宝石血瓶左下角显示数值
* 注意!!!不要在道具属性中直接操作flags,使用core.status.hero.flags或core.setFlag系列函数代替!
@@ -8724,8 +8732,8 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
};
},
"音频系统": function () {
- // 在此增加新插件
- /*首先,在造塔群下载所需的库文件,然后放置在塔目录下的 libs/thirdparty 或其他目录下,之后在 index.html 的最后加上下面这几行:
+ // 在此增加新插件
+ /*首先,在造塔群下载所需的库文件,然后放置在塔目录下的 libs/thirdparty 或其他目录下,之后在 index.html 的最后加上下面这几行:
@@ -8733,2327 +8741,2081 @@ 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();
- };
-},
- "怪物碎裂特效": function () {
- // 在此增加新插件
- // -------------------- 安装说明 -------------------- //
- // 先安装两个在插件简介中说明的前置插件
- // 然后再将本插件复制到插件编写中即可
- // 插件自带一个打怪后显示碎裂特效的功能
- // -------------------- 使用说明 -------------------- //
- /*
-
- 本插件的核心是一个名为 applyFragWith 的函数,打怪后的碎裂特效也是由它执行的。
- 我们来说明一下这个函数的使用方式。
- 1. 引入
- 你可以使用 const { applyFragWith } = core.plugin.frag; 在任何地方来引入这个函数。
-
- 2. 函数的参数
- 该函数有三个参数,分别是canvas, length, time。
- 其中,第一个参数意思是,在执行碎裂时,其内容由该画布决定,这个特效并不会修改传入的画布,因此原画布的内容会依然存在
- 第二个参数指的是每个碎片的边长,虽然原则上每个碎片都是正方形,但边缘一周的碎片可能不是正方形,但中间的碎片一定是
- 第三个参数指的是这个特效要执行多长时间
- 第四个参数是一个对象,包含四种配置量,均为可选,分别是maxMoveLength,moveFlush,maxRotate,fragTiming
- 当这些不存在时会默认取同名的常量作为默认值。这些值有什么用可以看下面的常量注释。
-
- 3. 函数的返回值
- 这个函数会返回一个特效控制器对象,这个控制器共有三个属性。
- animation: 指的是当前特效的高级动画对象
- onEnd: 一个Promise,当这个特效执行完毕后会被 fulfilled
- canvas: 特效所显示的画布。这个画布不会自动部署到样板中,需要你手动使用appendChild来部署,具体可参考打怪后碎裂的样例
-
- 4. 修改一些常量
- 在下面有四个有注释的常量MAX_MOVE_LENGTH ~ FRAG_TIMING,你可以根据你自己的需要来更改。
-
- */
-
- if (main.replayChecking) return (core.plugin.frag = {});
-
- const { Animation, linear, sleep } = core.plugin.animate;
- const { has } = core.plugin.utils;
-
- /** 最大移动距离,最终位置距离中心的距离变成原来的几倍 */
- const MAX_MOVE_LENGTH = 1.15;
- /** 移动距离波动,在最大移动距离的基础上加上多少倍距离的波动距离 */
- const MOVE_FLUSH = 0.7;
- /** 最大旋转角,单位是弧度,每个碎片都会有自己的旋转程度,是随机的 */
- const MAX_ROTATE = 0.5;
- /** 碎裂动画的速率曲线函数 */
- const FRAG_TIMING = linear();
-
+ // 将__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 {HTMLCanvasElement} canvas 要执行特效的画布
- * @param {number} length 切分成的碎片的边长,碎片为正方形
- * @param {number} time 特效持续时长
- * @returns 返回一个碎裂特效控制器,是一个对象,详见开头的使用注释
+ * 检查一种音频类型是否能被播放
+ * @param type 音频类型 AudioType
*/
- function applyFragWith(canvas, length = 4, time = 2000, config = {}) {
- // 先切分图片
- const imgs = splitCanvas(canvas, length);
- const cx = canvas.width / 2;
- const cy = canvas.height / 2;
-
- let maxX = 0;
- let maxY = 0;
- const toMove = imgs.map((v) => {
- const centerX = v.x + v.canvas.width / 2;
- const centerY = v.y + v.canvas.height / 2;
- const onX = centerX === cx;
- const onY = centerY === cy;
- const mml = config.maxMoveLength ?? MAX_MOVE_LENGTH;
- const mf = config.moveFlush ?? MOVE_FLUSH;
- const rate = mml - 1 + Math.random() ** 3 * mf;
- let endX = onY ? 0 : (centerX - cx) * rate;
- let endY = onX ? 0 : (centerY - cy) * rate;
- const mx = Math.abs(endX + centerX) + Math.abs(v.canvas.width);
- const my = Math.abs(endY + centerY) + Math.abs(v.canvas.height);
- if (mx > maxX) maxX = mx;
- if (my > maxY) maxY = my;
- const r = config.maxRotate ?? MAX_ROTATE;
- const endRad = Math.random() * r * 2 - r;
-
- return {
- deltaX: endX,
- deltaY: endY,
- endRad,
- x: centerX,
- y: centerY,
- canvas: v.canvas,
- };
- });
-
- // 再执行动画
- const frag = document.createElement("canvas");
- const ctx = frag.getContext("2d");
- const ani = new Animation();
- ani.register("rate", 0);
- const ft = config.fragTiming ?? FRAG_TIMING;
- ani.absolute().time(time).mode(ft).apply("rate", 1);
- frag.width = maxX * 2;
- frag.height = maxY * 2;
- ctx.save();
- const dw = maxX - canvas.width / 2;
- const dh = maxY - canvas.height / 2;
-
- const fragFn = () => {
- const rate = ani.value.rate;
- const opacity = 1 - rate;
- ctx.globalAlpha = opacity;
- ctx.clearRect(0, 0, frag.width, frag.height);
- toMove.forEach((v) => {
- ctx.save();
- const nx = v.deltaX * rate;
- const ny = v.deltaY * rate;
- const rotate = v.endRad * rate;
-
- ctx.translate(nx + v.x + dw, ny + v.y + dh);
- ctx.rotate(rotate);
- ctx.drawImage(
- v.canvas,
- nx - v.canvas.width / 2,
- ny - v.canvas.height / 2
- );
- ctx.restore();
- });
- };
- const onEnd = () => {};
- ani.ticker.add(fragFn);
-
- return makeFragManager(frag, ani, time, onEnd);
- }
-
- function makeFragManager(canvas, ani, time, onEnd) {
- const promise = sleep(time + 50);
-
- return {
- animation: ani,
-
- onEnd: promise.then(() => {
- ani.ticker.destroy();
- onEnd();
- }),
- canvas,
- };
- }
-
- function withImage(image, sx, sy, sw, sh) {
- const canvas = document.createElement("canvas");
- const ctx = canvas.getContext("2d");
- canvas.width = sw;
- canvas.height = sh;
- ctx.drawImage(image, sx, sy, sw, sh, 0, 0, sw, sh);
- return { canvas, x: sx, y: sy };
- }
-
- /**
- * 切分画布
- * @param canvas 要被切分的画布
- * @param l 切分小块的边长
- */
- function splitCanvas(canvas, l) {
- if (canvas.width / l < 2 || canvas.height / l < 2) {
- console.warn("切分画布要求切分边长大于等于画布长宽的一半!");
- return [];
+ 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 w = canvas.width;
- const h = canvas.height;
- const numX = Math.floor(w / l);
- const numY = Math.floor(h / l);
- const rw = (w - numX * l) / 2;
- const rh = (h - numY * l) / 2;
+ }
- const res = [];
+ const typeMap = new Map([
+ ["ogg", AudioType.Ogg],
+ ["mp3", AudioType.Mp3],
+ ["wav", AudioType.Wav],
+ ["flac", AudioType.Flac],
+ ["opus", AudioType.Opus],
+ ["aac", AudioType.Aac],
+ ]);
- if (rw > 0) {
- if (rh > 0) {
- res.push(
- withImage(canvas, 0, 0, rw, rh),
- withImage(canvas, 0, canvas.height - rh, rw, rh),
- withImage(canvas, canvas.width - rw, 0, rw, rh),
- withImage(canvas, canvas.width - rw, canvas.height - rh, rw, rh)
- );
- }
- for (const x of [0, canvas.width - rw]) {
- for (let ny = 0; ny < numY; ny++) {
- res.push(withImage(canvas, x, rh + l * ny, rw, l));
+ /**
+ * 根据文件名拓展猜测其类型
+ * @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);
}
}
}
- if (rh > 0) {
- for (const y of [0, canvas.height - rh]) {
- for (let nx = 0; nx < numX; nx++) {
- res.push(withImage(canvas, rw + l * nx, y, l, rh));
+ }
+
+ 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;
}
}
}
- for (let nx = 0; nx < numX; nx++) {
- for (let ny = 0; ny < numY; ny++) {
- res.push(withImage(canvas, rw + l * nx, rh + l * ny, l, l));
+
+ 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;
+ }
}
}
-
- return res;
}
- const origin = core.events.afterBattle;
- core.events.afterBattle = function (enemyId, x, y) {
- // 打怪特效
- if (has(x) && has(y)) {
- const frame = core.status.globalAnimateStatus % 2;
- // 生成怪物图像
- const canvas = document.createElement("canvas");
- canvas.width = 32;
- canvas.height = 32;
- core.drawIcon(canvas, enemyId, 0, 0, 32, 32, frame);
- // 执行动画
- const manager = applyFragWith(canvas);
- const frag = manager.canvas;
- // 设置特效画布的css属性
- frag.style.imageRendering = "pixelated";
- frag.style.width = `${frag.width * core.domStyle.scale}px`;
- frag.style.height = `${frag.height * core.domStyle.scale}px`;
- const left =
- (x * 32 + 16 - frag.width / 2 - core.bigmap.offsetX) *
- core.domStyle.scale;
- const top =
- (y * 32 + 16 - frag.height / 2 - core.bigmap.offsetY) *
- core.domStyle.scale;
- frag.style.left = `${left}px`;
- frag.style.top = `${top}px`;
- frag.style.zIndex = "45";
- frag.style.position = "absolute";
- // 将特效画布部署到样板上
- core.dom.gameDraw.appendChild(frag);
- // 当特效执行完毕后移除这个特效画布
- manager.onEnd.then(() => {
- frag.remove();
- });
+ class VorbisDecoder {
+ /**
+ * 创建音频解码器
+ */
+ async create() {
+ this.decoder = new OggVorbisDecoderWebWorker();
+ await this.decoder.ready;
}
- return origin.apply(this, arguments);
+ /**
+ * 摧毁这个解码器
+ */
+ 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",
};
- if ("frag" in core.plugin) {
- throw new ReferenceError(`core.plugin上已存在名为frag的属性!`);
+ function isOggPage(data) {
+ return !isNil(data.isFirstPage);
}
- core.plugin.frag = {
- applyFragWith,
+ 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 () {
@@ -13096,8 +12858,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
core.drawImage(ctx, img, 0, 0, 60, 60, fx, fy, w, h);
const layer = info.upOrDown[id];
const min = Math.min(w, h);
- if (core.getFlag("任务地点") && core.getFlag("任务地点") === id)
- ctx.drawImage(tesk, fx + min / 4, fy + min / 4, min / 2, min / 2);
+
if (layer?.includes("upFloor"))
core.drawIcon(
ctx,
@@ -13116,7 +12877,21 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
min / 2,
min / 2
);
-
+ if (core.getFlag("任务地点") && core.getFlag("任务地点") === id)
+ ctx.drawImage(tesk, fx + min / 4, fy + min / 4, min / 2, min / 2);
+ if (id === core.status.floorId)
+ core.drawImage(
+ ctx,
+ "hero.webp",
+ 0,
+ 0,
+ 32,
+ 19,
+ fx + min / 4,
+ fy + (min * 5) / 16,
+ 32,
+ 19
+ );
// 显示漏怪数量
if (core.getFlag("showEnemy")) {
ctx.textAlign = "center";
@@ -13139,1124 +12914,1145 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
);
ctx.shadowBlur = 0;
}
+ if (!core.hasVisitedFloor(id)) {
+ core.fillRect(ctx, fx, fy, w, h, "rgba(0,0,0,0.7)");
+ core.fillText(
+ ctx,
+ "?",
+ fx + min / 2,
+ fy + (min * 3) / 4,
+ "#FFFFFF",
+ "bold 42px Verdana"
+ );
+ }
}
};
},
"楼传": 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.drawImage(
- "ui",
- "lock.webp",
- 0,
- 0,
- size,
- size,
+ 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,
- 58,
- size - 8,
- size - 8
- );
+ size - 50,
+ size - 50, "rgba(0,0,0,0.5)")*/
+ core.getContextByName("ui").globalAlpha = 0.7;
- 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.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,
+ 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,
- "#FFFFFF",
- "#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
- );
- }
+ 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))
- };
+ //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) {
- //竖向文字绘制
+ 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("");
+ 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 arrWidth = arrText.map(function (letter) {
+ return context.measureText(letter).width;
+ });
- let align = context.textAlign;
+ 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;
- }
+ 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;
- }
+ 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.textAlign = "center";
- context.textBaseline = "middle";
- context.lineWidth = 6;
+ context.textBaseline = "middle";
+ context.lineWidth = 6;
- // 开始逐字绘制
+ // 开始逐字绘制
- arrText.forEach(function (letter, index) {
- // 确定下一个字符的纵坐标位置
+ arrText.forEach(function (letter, index) {
+ // 确定下一个字符的纵坐标位置
- context.strokeText(letter, sx, sy);
- context.fillText(letter, sx, sy);
- // 旋转坐标系还原成初始态
+ context.strokeText(letter, sx, sy);
+ context.fillText(letter, sx, sy);
+ // 旋转坐标系还原成初始态
- context.setTransform(1, 0, 0, 1, 0, 0);
+ context.setTransform(1, 0, 0, 1, 0, 0);
- // 确定下一个字符的纵坐标位置
+ // 确定下一个字符的纵坐标位置
- var letterWidth = 54;
+ var letterWidth = 54;
- sy = sy + letterWidth;
- });
+ sy = sy + letterWidth;
+ });
- // 水平垂直对齐方式还原
+ // 水平垂直对齐方式还原
- context.textAlign = align;
+ context.textAlign = align;
- context.textBaseline = baseline;
+ context.textBaseline = baseline;
- //绘制到目标位置
- ctx.drawImage(
- canvas,
- x,
- y - (fontsize / 3) * length,
- canvas.width / 3,
- canvas.height / 3
- );
- }
+ //绘制到目标位置
+ 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;
- }
+ ////// 点击楼层传送器时的打开操作 //////
+ 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 (!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 (
+ (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);
- ////// 查看地图界面时,放开某个键的操作 //////
+ 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];
+ 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 == 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;
+ 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;
+ 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;
- };
+ 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
+ actions.prototype._sys_onmousewheel = function (direct) {
+ // 向下滚动是 -1 ,向上是 1
- if (this._checkReplaying()) {
- // 滚轮控制速度
- if (direct == 1) core.speedUpReplay();
- if (direct == -1) core.speedDownReplay();
- return;
- }
+ 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 == "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 == "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 == "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;
- }
+ // 浏览地图
+ 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
- );
-},
+ // 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画布设置
@@ -15425,12 +15221,15 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
const pageupboxVertical = makeBox([18, 300], [100, 200]);
const pagedownbox = makeBox([1500, 1130], [200, 100]);
const pagedownboxVertical = makeBox([18, 1500], [100, 200]);
+ const soundbox = makeBox([550, 150], [100, 900]);
+ const soundboxVertical = makeBox([198, 550], [900, 100]);
if (this.log) {
if (
(core.domStyle.isVertical && inRect(pos, backboxVertical)) ||
(!core.domStyle.isVertical && inRect(pos, backbox))
) {
core.clearMap(logctx);
+ core.stopSound()
main.dom.logcanvas.style.display = "none";
this.log = false;
} else if (
@@ -15447,6 +15246,17 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
core.clearMap(logctx);
if (this.page < this.overpage) this.page++;
this.logdraw(this.page);
+ } else if ((core.domStyle.isVertical && inRect(pos, soundboxVertical)) ||
+ (!core.domStyle.isVertical && inRect(pos, soundbox))) {
+ if (core.domStyle.isVertical) {
+ const sound = this.textList[(this.page - 1) * 6 + Math.min(Math.floor((px - 198) / 150), 5)][2]
+ core.stopSound()
+ core.playSound(sound)
+ } else {
+ const sound = this.textList[(this.page - 1) * 6 + Math.min(Math.floor((py - 150) / 150), 5)][2]
+ core.stopSound()
+ core.playSound(sound)
+ }
}
} else {
if (
@@ -15758,6 +15568,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
const name = this.textList[i][0] ?
"【" + this.textList[i][0] + "】" :
"";
+ const sound = this.textList[i][2]
if (name) {
core.fillBoldText1(
logctx,
@@ -15770,6 +15581,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
core.ui._buildFont(42, true)
);
}
+ if (sound) core.drawImage(logctx, "sound.webp", 550, posy + 30)
if (text.length < 30) {
core.fillBoldText1(
logctx,
@@ -18096,7 +17908,6 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
music.loop = "loop";
core.material.bgms[name] = music;*/
};
-
},
"横屏切换": function () {
// 在此增加新插件
@@ -18210,7 +18021,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
core.setFlag("animate_" + name);
};
let thistime = 0;
- this.playanimate = function (name, x, y, hero, scalex, scaley) {
+ this.playanimate = function (name, x, y, hero, scalex, scaley, callback) {
const data = {
name: name,
x: x,
@@ -18219,6 +18030,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
scalex: scalex,
scaley: scaley,
farme: 0,
+ callback,
};
core.plugin.playing.add(data);
@@ -18357,21 +18169,26 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
}
});
one.farme++;
- if (one.farme > data.allFarme) core.plugin.playing.delete(one);
+ 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 () {
// 在此增加新插件
@@ -18708,876 +18525,1044 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
};
},
"回合战斗动画": function () {
- // 在此增加新插件
- const animateAttack = document.createElement("canvas"); //画布设置
- animateAttack.style.zIndex = 80;
- animateAttack.id = "animateAttack";
- animateAttack.classList.add("gameCanvas", "anti-aliasing");
- animateAttack.style.display = "block";
- animateAttack.width = 416;
- animateAttack.height = 416;
- animateAttack.style.width = core.__PIXELS__ * core.domStyle.scale + "px";
- animateAttack.style.height = core.__PIXELS__ * core.domStyle.scale + "px";
- main.dom.animateAttack = animateAttack;
- const ctx = animateAttack.getContext("2d");
+ // 在此增加新插件
+ const animateAttack = document.createElement("canvas"); //画布设置
+ animateAttack.style.zIndex = 80;
+ animateAttack.id = "animateAttack";
+ animateAttack.classList.add("gameCanvas", "anti-aliasing");
+ animateAttack.style.display = "block";
+ animateAttack.width = 416;
+ animateAttack.height = 416;
+ animateAttack.style.width = core.__PIXELS__ * core.domStyle.scale + "px";
+ animateAttack.style.height = core.__PIXELS__ * core.domStyle.scale + "px";
+ main.dom.animateAttack = animateAttack;
+ const ctx = animateAttack.getContext("2d");
- main.dom.gameDraw.appendChild(animateAttack);
+ main.dom.gameDraw.appendChild(animateAttack);
- this.drawAttackAnimate = function (
- heroInfo,
- oneTurn,
- enemyInfo,
- equipInfo,
- farme
- ) {
- core.clearMap(ctx);
- let animate = Math.floor(farme / 30);
- core.fillRect(ctx, 64, 64, 288, 288, "rgba(0,0,0,0.5)");
- core.strokeRect(ctx, 64, 64, 288, 288, "rgba(255,255,255,0.5)", 4);
- core.setTextAlign(ctx, "center");
- core.fillBoldText(
- ctx,
- hero.name,
- 127,
- 123,
- "#FFFFFF",
- "#000000",
- 'bold 14px pala'
- );
- core.setTextAlign(ctx, "left");
- core.drawIcon(ctx, 'hp', 70, 190, 16, 16)
- core.drawIcon(ctx, 'atk', 70, 210, 16, 16)
- core.drawIcon(ctx, 'def', 70, 230, 16, 16)
- core.drawIcon(ctx, 'I374', 70, 250, 16, 16)
- core.drawIcon(ctx, 'I375', 70, 270, 16, 16)
- core.drawIcon(ctx, 'mdef', 70, 290, 16, 16)
- core.drawIcon(ctx, 'amulet', 70, 310, 16, 16)
- core.drawIcon(ctx, 'jumpShoes', 70, 330, 16, 16)
- core.fillBoldText(
- ctx,
- '生命 ' + core.formatBigNumber(heroInfo.hp, true) + " / " + core.formatBigNumber(heroInfo.hpmax, true),
- 90,
- 205,
- "#FFFFFF",
- "#000000",
- 'bold 14px pala'
- );
- core.fillBoldText(
- ctx,
- '攻击 ' + core.formatBigNumber(heroInfo.atk),
- 90,
- 225,
- "#FFFFFF",
- "#000000",
- 'bold 14px pala'
- );
- core.fillBoldText(
- ctx,
- '防御 ' + core.formatBigNumber(heroInfo.def),
- 90,
- 245,
- "#FFFFFF",
- "#000000",
- 'bold 14px pala'
- );
- core.fillBoldText(
- ctx,
- "法强 " + core.formatBigNumber(heroInfo.spell),
- 90,
- 265,
- "#FFFFFF",
- "#000000",
- 'bold 14px pala'
- );
- core.fillBoldText(
- ctx,
- "法攻 " + core.formatBigNumber(heroInfo.matk / 100 * heroInfo.spell) + "(" + heroInfo.matk + "%)",
- 90,
- 285,
- "#FFFFFF",
- "#000000",
- 'bold 14px pala'
- );
- core.fillBoldText(
- ctx,
- '护盾 ' + core.formatBigNumber(heroInfo.mdef / 100 * heroInfo.spell) + "(" + heroInfo.mdef + "%)",
- 90,
- 305,
- "#FFFFFF",
- "#000000",
- 'bold 14px pala'
- );
- core.fillBoldText(
- ctx,
- '法抗 ' + heroInfo.spelldef + "%",
- 90,
- 325,
- "#FFFFFF",
- "#000000",
- 'bold 14px pala'
- );
- core.fillBoldText(
- ctx,
- '速度 ' + core.formatBigNumber(heroInfo.speed),
- 90,
- 345,
- "#FFFFFF",
- "#000000",
- 'bold 14px pala'
- );
+ this.drawAttackAnimate = function (
+ heroInfo,
+ oneTurn,
+ enemyInfo,
+ equipInfo,
+ farme,
+ damageInfo
+ ) {
+ let attack = false;
+ if (heroInfo.isAttack) attack = true;
+ if (enemyInfo.isAttack) attack = true;
+ equipInfo.forEach(function (v) {
+ if (v.isAttack) attack = true;
+ });
+ core.clearMap(ctx);
+ let animate = Math.floor(farme / 30);
+ core.fillRect(ctx, 64, 64, 288, 288, "rgba(0,0,0,0.5)");
+ core.strokeRect(ctx, 64, 64, 288, 288, "rgba(255,255,255,0.5)", 4);
+ core.setTextAlign(ctx, "center");
+ core.fillBoldText(
+ ctx,
+ hero.name,
+ 127,
+ 128,
+ "#FFFFFF",
+ "#000000",
+ "bold 14px pala"
+ );
+ core.setTextAlign(ctx, "left");
+ core.drawIcon(ctx, "hp", 70, 190, 16, 16);
+ core.drawIcon(ctx, "atk", 70, 210, 16, 16);
+ core.drawIcon(ctx, "def", 70, 230, 16, 16);
+ core.drawIcon(ctx, "I374", 70, 250, 16, 16);
+ core.drawIcon(ctx, "I375", 70, 270, 16, 16);
+ core.drawIcon(ctx, "mdef", 70, 290, 16, 16);
+ core.drawIcon(ctx, "amulet", 70, 310, 16, 16);
+ core.drawIcon(ctx, "jumpShoes", 70, 330, 16, 16);
+ core.fillBoldText(
+ ctx,
+ "生命 " +
+ core.formatBigNumber(heroInfo.hp, true) +
+ " / " +
+ core.formatBigNumber(heroInfo.hpmax, true),
+ 90,
+ 205,
+ "#FFFFFF",
+ "#000000",
+ "bold 14px pala"
+ );
+ core.fillBoldText(
+ ctx,
+ "攻击 " + core.formatBigNumber(heroInfo.atk),
+ 90,
+ 225,
+ "#FFFFFF",
+ "#000000",
+ "bold 14px pala"
+ );
+ core.fillBoldText(
+ ctx,
+ "防御 " + core.formatBigNumber(heroInfo.def),
+ 90,
+ 245,
+ "#FFFFFF",
+ "#000000",
+ "bold 14px pala"
+ );
+ core.fillBoldText(
+ ctx,
+ "法强 " + core.formatBigNumber(heroInfo.spell),
+ 90,
+ 265,
+ "#FFFFFF",
+ "#000000",
+ "bold 14px pala"
+ );
+ core.fillBoldText(
+ ctx,
+ "法攻 " +
+ core.formatBigNumber((heroInfo.matk / 100) * heroInfo.spell) +
+ "(" +
+ heroInfo.matk +
+ "%)",
+ 90,
+ 285,
+ "#FFFFFF",
+ "#000000",
+ "bold 14px pala"
+ );
+ core.fillBoldText(
+ ctx,
+ "护盾 " +
+ core.formatBigNumber((heroInfo.mhp / 100) * heroInfo.spell) +
+ "(" +
+ heroInfo.mhp +
+ "%)",
+ 90,
+ 305,
+ "#FFFFFF",
+ "#000000",
+ "bold 14px pala"
+ );
+ core.fillBoldText(
+ ctx,
+ "法抗 " + heroInfo.mdef + "%",
+ 90,
+ 325,
+ "#FFFFFF",
+ "#000000",
+ "bold 14px pala"
+ );
+ core.fillBoldText(
+ ctx,
+ "速度 " + core.formatBigNumber(heroInfo.speed),
+ 90,
+ 345,
+ "#FFFFFF",
+ "#000000",
+ "bold 14px pala"
+ );
- core.strokeRect(ctx, 112, 139, 32, 48, "rgba(255,255,255,1)", 1);
- core.drawImage(
- ctx,
- "hero.webp",
- 32 * (animate % 4),
- 0,
- 32,
- 48,
- 112,
- 139,
- 32,
- 48
- );
+ core.strokeRect(ctx, 112, 139, 32, 48, "rgba(255,255,255,1)", 1);
+ core.drawImage(
+ ctx,
+ "hero.webp",
+ 32 * (animate % 4),
+ 0,
+ 32,
+ 48,
+ 112,
+ 139,
+ 32,
+ 48
+ );
+ core.setTextAlign(ctx, "center");
+ core.fillBoldText(
+ ctx,
+ enemyInfo.name,
+ 289,
+ 128,
+ "#FFFFFF",
+ "#000000",
+ "bold 14px pala"
+ );
- core.setTextAlign(ctx, "center");
- core.fillBoldText(
- ctx,
- enemyInfo.name,
- 289,
- 123,
- "#FFFFFF",
- "#000000",
- 'bold 14px pala'
- );
- core.setTextAlign(ctx, "right");
- if (enemyInfo.cls === "enemys") {
- core.strokeRect(ctx, 272, 155, 32, 32, "rgba(255,255,255,1)", 1);
+ core.setTextAlign(ctx, "right");
+ if (enemyInfo.cls === "enemys") {
+ core.strokeRect(ctx, 272, 155, 32, 32, "rgba(255,255,255,1)", 1);
- core.drawImage(
- ctx,
- core.getBlockInfo(enemyInfo.id).image,
- 32 * (animate % 2),
- core.getBlockInfo(enemyInfo.id).posY * 32,
- 32,
- 32,
- 272,
- 155,
- 32,
- 32
- );
- } else {
- core.strokeRect(ctx, 272, 139, 32, 48, "rgba(255,255,255,1)", 1);
+ core.drawImage(
+ ctx,
+ core.getBlockInfo(enemyInfo.id).image,
+ 32 * (animate % 2),
+ core.getBlockInfo(enemyInfo.id).posY * 32,
+ 32,
+ 32,
+ 272,
+ 155,
+ 32,
+ 32
+ );
+ } else {
+ core.strokeRect(ctx, 272, 139, 32, 48, "rgba(255,255,255,1)", 1);
- core.drawImage(
- ctx,
- core.getBlockInfo(enemyInfo.id).image,
- 32 * (animate % 4),
- core.getBlockInfo(enemyInfo.id).posY * 48,
- 32,
- 48,
- 272,
- 139,
- 32,
- 48
- );
- }
- core.drawIcon(ctx, 'hp', 330, 190, 16, 16)
- core.drawIcon(ctx, 'atk', 330, 210, 16, 16)
- core.drawIcon(ctx, 'def', 330, 230, 16, 16)
- core.drawIcon(ctx, 'amulet', 330, 250, 16, 16)
- core.drawIcon(ctx, 'jumpShoes', 330, 270, 16, 16)
- core.fillBoldText(
- ctx,
- core.formatBigNumber(enemyInfo.hp, true) + ' 生命',
- 330,
- 205,
- "#FFFFFF",
- "#000000",
- 'bold 14px pala'
- );
- core.fillBoldText(
- ctx,
- core.formatBigNumber(enemyInfo.atk) + ' 攻击',
- 330,
- 225,
- "#FFFFFF",
- "#000000",
- 'bold 14px pala'
- );
- core.fillBoldText(
- ctx,
- core.formatBigNumber(enemyInfo.def) + ' 防御',
- 330,
- 245,
- "#FFFFFF",
- "#000000",
- 'bold 14px pala'
- );
+ core.drawImage(
+ ctx,
+ core.getBlockInfo(enemyInfo.id).image,
+ 32 * (animate % 4),
+ core.getBlockInfo(enemyInfo.id).posY * 48,
+ 32,
+ 48,
+ 272,
+ 139,
+ 32,
+ 48
+ );
+ }
+ core.drawIcon(ctx, "hp", 330, 190, 16, 16);
+ core.drawIcon(ctx, "atk", 330, 210, 16, 16);
+ core.drawIcon(ctx, "def", 330, 230, 16, 16);
+ core.drawIcon(ctx, "amulet", 330, 250, 16, 16);
+ core.drawIcon(ctx, "jumpShoes", 330, 270, 16, 16);
+ core.fillBoldText(
+ ctx,
+ core.formatBigNumber(enemyInfo.hp, true) + " 生命",
+ 330,
+ 205,
+ "#FFFFFF",
+ "#000000",
+ "bold 14px pala"
+ );
+ core.fillBoldText(
+ ctx,
+ core.formatBigNumber(enemyInfo.atk) + " 攻击",
+ 330,
+ 225,
+ "#FFFFFF",
+ "#000000",
+ "bold 14px pala"
+ );
+ core.fillBoldText(
+ ctx,
+ core.formatBigNumber(enemyInfo.def) + " 防御",
+ 330,
+ 245,
+ "#FFFFFF",
+ "#000000",
+ "bold 14px pala"
+ );
- core.fillBoldText(
- ctx,
- (enemyInfo.mdef ?? 0) * 100 + "% 法抗",
- 330,
- 265,
- "#FFFFFF",
- "#000000",
- 'bold 14px pala'
- );
- core.fillBoldText(
- ctx,
- core.formatBigNumber(enemyInfo.speed) + " 速度",
- 330,
- 285,
- "#FFFFFF",
- "#000000",
- 'bold 14px pala'
- );
- core.fillBoldText(ctx,
- "V",
- 219,
- 163,
- "#FFFFFF",
- "#000000",
- 'bold 48px pala')
- core.fillBoldText(ctx,
- "s",
- 231,
- 163,
- "#FFFFFF",
- "#000000",
- 'bold 36px pala')
- };
+ core.fillBoldText(
+ ctx,
+ (enemyInfo.mdef ?? 0) * 100 + "% 法抗",
+ 330,
+ 265,
+ "#FFFFFF",
+ "#000000",
+ "bold 14px pala"
+ );
+ core.fillBoldText(
+ ctx,
+ core.formatBigNumber(enemyInfo.speed) + " 速度",
+ 330,
+ 285,
+ "#FFFFFF",
+ "#000000",
+ "bold 14px pala"
+ );
+ core.fillBoldText(
+ ctx,
+ "V",
+ 219,
+ 163,
+ "#FFFFFF",
+ "#000000",
+ "bold 48px pala"
+ );
+ core.fillBoldText(
+ ctx,
+ "s",
+ 231,
+ 163,
+ "#FFFFFF",
+ "#000000",
+ "bold 36px pala"
+ );
- this.attackAnimate = function (
- enemyId,
- enemyInfo,
- damageInfo,
- equipInfo = []
- ) {
- //参数分别为怪物真实属性,战斗信息,特殊装备(如火焰风衣)属性特殊装备属性为以元组{equipId,oneDamage,speed,now:0}构成的数组(列出每个需要计算的特殊装备,没有则为空数组或不填)
- core.lockControl();
- core.clearMap(ctx);
- core.status.event.id = "attackAnimate";
- let hero_hp = core.getRealStatusOrDefault(hero, "hp"),
- hero_atk = core.getRealStatusOrDefault(hero, "atk"),
- hero_def = core.getRealStatusOrDefault(hero, "def"),
- hero_spell = core.getRealStatusOrDefault(hero, "spell"),
- hero_matk = core.getRealStatusOrDefault(hero, "mdef"),
- hero_mdef = core.getRealStatusOrDefault(hero, "mdef"),
- hero_speed = core.getRealStatusOrDefault(hero, "speed"),
- hero_hpmax = core.getRealStatusOrDefault(hero, "hpmax"),
- hero_spelldef = core.getRealStatusOrDefault(hero, "spelldef");
- const heroInfo = {
- hp: hero_hp,
- hpmax: hero_hpmax,
- atk: hero_atk,
- def: hero_def,
- spell: hero_spell,
- spelldef: hero_spelldef,
- matk: hero_matk,
- mdef: hero_mdef,
- speed: hero_speed,
- now: 0,
- };
- enemyInfo.id = enemyId;
- enemyInfo.cls = core.getClsFromId(enemyId);
- enemyInfo.name = core.material.enemys[enemyId].name;
+ if (!attack) enemyInfo.now += (enemyInfo.speed / oneTurn) * 215;
+ let enemynow = Math.min(100 + enemyInfo.now, 315);
+ ctx.fillStyle = "#FFFFFF";
+ ctx.beginPath();
+ ctx.moveTo(enemynow, 100);
+ ctx.lineTo(enemynow + 3, 90);
+ ctx.lineTo(enemynow - 3, 90);
+ ctx.closePath();
+ ctx.fill();
- let oneTurn = heroInfo.speed + enemyInfo.speed;
- if (equipInfo.length > 0) {
- for (let i; i < equipInfo.length - 1; i++) {
- oneTurn += equipInfo[i].speed;
- }
- }
- oneTurn *= 100;
- let time = 0,
- farme = 0;
- core.registerAnimationFrame("attackAnimate", true, (temptime) => {
- if (temptime - time > 1000 / 60) {
- time = temptime;
- this.drawAttackAnimate(
- heroInfo,
- oneTurn,
- enemyInfo,
- equipInfo,
- farme
- );
- farme++;
- }
- });
- };
-},
+ if (enemyInfo.cls === "enemys") {
+ core.drawImage(
+ ctx,
+ core.getBlockInfo(enemyInfo.id).image,
+ 32,
+ core.getBlockInfo(enemyInfo.id).posY * 32,
+ 32,
+ 32,
+ enemynow - 16,
+ 64,
+ 32,
+ 32
+ );
+ } else {
+ core.drawImage(
+ ctx,
+ core.getBlockInfo(enemyInfo.id).image,
+ 32,
+ core.getBlockInfo(enemyInfo.id).posY * 48,
+ 32,
+ 19,
+ enemynow - 16,
+ 70,
+ 32,
+ 19
+ );
+ }
+ core.drawLine(ctx, 100, 105, 315, 105, "#FFFFFF", 5);
+ equipInfo.forEach(function (v) {
+ if (!attack) v.now += (v.speed / oneTurn) * 215;
+ let vnow = Math.min(100 + v.now, 315);
+ ctx.beginPath();
+ ctx.moveTo(vnow, 100);
+ ctx.lineTo(vnow + 3, 90);
+ ctx.lineTo(vnow - 3, 90);
+ ctx.closePath();
+
+ ctx.fill();
+
+ core.drawIcon(ctx, v.id, vnow - 16, 64, 32, 32);
+ });
+ if (!attack) heroInfo.now += (heroInfo.speed / oneTurn) * 215;
+ let heronow = Math.min(100 + heroInfo.now, 315);
+ ctx.beginPath();
+ ctx.moveTo(heronow, 100);
+ ctx.lineTo(heronow + 3, 90);
+ ctx.lineTo(heronow - 3, 90);
+ ctx.closePath();
+
+ ctx.fill();
+ core.drawImage(ctx, "hero.webp", 0, 0, 32, 19, heronow - 16, 70, 32, 19);
+
+ if (heroInfo.now >= 215 && !heroInfo.isAttack) {
+ heroInfo.isAttack = true;
+ animateOnAttack("sword", true, () => {
+ heroInfo.now -= 215;
+ heroInfo.isAttack = false;
+ });
+ }
+ if (enemyInfo.now >= 215 && !enemyInfo.isAttack) {
+ enemyInfo.isAttack = true;
+ animateOnAttack("sword", false, () => {
+ enemyInfo.now -= 215;
+ enemyInfo.isAttack = false;
+ });
+ }
+ equipInfo.forEach((v) => {
+ if (v.now >= 215 && !v.isAttack) {
+ v.isAttack = true;
+
+ animateOnAttack("sword", true, () => {
+ v.now -= 215;
+ v.isAttack = false;
+ });
+ }
+ });
+ };
+
+ function animateOnAttack(name, onenemy, callback) {
+ if (onenemy) {
+ core.playanimate(name, 290, 160, null, 1, 1, callback);
+ } else {
+ core.playanimate(name, 130, 160, null, 1, 1, callback);
+ }
+ }
+
+ this.attackAnimate = function (
+ enemyId,
+ enemyInfo,
+ damageInfo,
+ equipInfo = []
+ ) {
+ //参数分别为怪物真实属性,战斗信息,特殊装备(如火焰风衣)属性特殊装备属性为以元组{equipId,oneDamage,speed,now:0}构成的数组(列出每个需要计算的特殊装备,没有则为空数组或不填)
+ core.lockControl();
+ core.clearMap(ctx);
+ core.status.event.id = "attackAnimate";
+ let hero_hp = core.getRealStatusOrDefault(hero, "hp"),
+ hero_atk = core.getRealStatusOrDefault(hero, "atk"),
+ hero_def = core.getRealStatusOrDefault(hero, "def"),
+ hero_spell = core.getRealStatusOrDefault(hero, "spell"),
+ hero_matk = core.getRealStatusOrDefault(hero, "matk"),
+ hero_mdef = core.getRealStatusOrDefault(hero, "mdef"),
+ hero_speed = core.getRealStatusOrDefault(hero, "speed"),
+ hero_hpmax = core.getRealStatusOrDefault(hero, "hpmax"),
+ hero_mhp = core.getRealStatusOrDefault(hero, "mhp");
+ const heroInfo = {
+ hp: hero_hp,
+ hpmax: hero_hpmax,
+ atk: hero_atk,
+ def: hero_def,
+ spell: hero_spell,
+ mhp: hero_mhp,
+ matk: hero_matk,
+ mdef: hero_mdef,
+ speed: hero_speed,
+ now: 0,
+ isAttack: false,
+ };
+ enemyInfo.id = enemyId;
+ enemyInfo.cls = core.getClsFromId(enemyId);
+ enemyInfo.name = core.material.enemys[enemyId].name;
+ enemyInfo.now = 0;
+ enemyInfo.isAttack = false;
+ let oneTurn = heroInfo.speed + enemyInfo.speed;
+ if (equipInfo.length > 0) {
+ for (let i; i < equipInfo.length - 1; i++) {
+ equipInfo[i].now = 0;
+ equipInfo[i].isAttack = false;
+ oneTurn += equipInfo[i].speed;
+ }
+ }
+ oneTurn *= 25;
+ let time = 0,
+ farme = 0;
+
+ core.registerAnimationFrame("attackAnimate", true, (temptime) => {
+ if (temptime - time > 1000 / 60) {
+ time = temptime;
+ this.drawAttackAnimate(
+ heroInfo,
+ oneTurn,
+ enemyInfo,
+ equipInfo,
+ farme,
+ damageInfo
+ );
+ farme++;
+ }
+ });
+ };
+ },
"剧情内容": function () {
- // 在此增加新插件
- // 每项为一个数组,第一项是名字,第二项是对话内容
- // 回放只会在同一个this下回放,进入剧情前请以事件块声明进入哪个剧情数组
- // 可以自由添加,但不能与已有插件及函数名相同,可以使用中文。
- this.chapter0 = [
- ["", "这些天,街道不曾下雨。"],
- ["", "所以,那浸湿地面的,定是那些女孩们流落的鲜血无疑。"],
- ["", "我蹲在充斥着铁锈味般恶臭的小巷中,悠闲地如是想着。"],
- ["", "扑哧。"],
- ["", "耳旁再次响起象征着某个女孩子死去的声音。"],
- ["", "再一次——"],
- ["", "再一次。"],
- ["", "女子们被肢解成单纯的肉块。"],
- ["", "我任由流下的血浸满全身,屏住自己的呼吸。"],
- ["", "祈求自己能拥有从猎人手中逃脱的幸运。"],
- ["", "扑哧。"],
- ["", "直到刚才,我们还坐在去往娼馆的马车的路上。"],
- ["", "而在这之中的某些人,已经不在这个世上了。"],
- ["", "不,应该把“某些”换成“几乎所有”才更为恰当吧。"],
- ["", "恐怕,不久之后我也会变成小巷中血腥的装饰品。"],
- ["", "我是为了得到这种死法,才辛苦苟活至今的吗?"],
- ["", "来个人告诉我啊——"],
- ["", "谁都好。"],
- ["", "来人啊!!"],
- ["少女", "「呃······!?」"],
- ["", "漆黑的物体充斥了我的整个视野"],
- ["", "我很快意识到,那是只很大的脚。"],
- ["", "必须要出声求救。"],
- ["", "可是,耳中却只能听到自己的牙关不停交战的声音。"],
- ["", "我是如此的无助。"],
- ["", "逃跑也好,道歉也罢。"],
- ["", "就连抬头看一眼将要杀掉我的人的面孔都做不到。"],
- ["少女", "「······被杀」"],
- ["", "会被杀。"],
- ["", "会被杀!!"],
- ["", "来自内心深处的冰冷预感,渐渐地在体内蔓延开来。"],
- ["少女", "「不,不要······」"],
- ["", "浮游都市,《诺瓦斯·艾蒂尔》。"],
- ["", "《特别受灾地区》——"],
- ["", "通称,《牢狱》"],
- ["", "是被险峻的峭壁环绕,与世隔绝的,都市的最底部。"],
- ["年轻人", "「放开我!」"],
- ["年轻人", "「我只是在帮那个女人而已!」"],
- ["年轻人", "「你们没听到吗!?」"],
- ["年轻人", "「她是被受骗才会被卖到娼馆来的」"],
- ["年轻人", "「用肮脏的手段把钱借给她父母的,就是你们这些家伙吧!?」"],
- ["年轻人", "「给我说些什么啊」"],
- ["凯伊姆", "「这些话等到了娼馆再说吧」"],
- ["凯伊姆", "「我来抓你,只是受雇于人而已」"],
- ["", "我走进娼馆《莉莉乌姆》的接待室。"],
- ["", "正在桌旁整理账簿的奥兹停下手头的工作,抬起头向我看来。"],
- ["奥兹", "「这不是凯伊姆先生吗,辛苦了」"],
- ["奥兹", "「委托已经完成了吗?」"],
- ["凯伊姆", "「啊啊,是这家伙没错吧」"],
- ["", "奥兹用只要接触到就能杀人般的眼神在男人脸上搜过。"],
- ["奥兹", "「没错,就是这个人」"],
- ["凯伊姆", "「是么」"],
- ["年轻人", "「你,你们要对我做什么」"],
- ["奥兹", "「······」"],
- ["", "奥兹用一个眼神,就让男人闭上了嘴。"],
- ["", "然后,向我这边转过身来。"],
- ["奥兹", "「抱歉啊,总是麻烦你去做这些无聊的事」"],
- ["奥兹", "「都怪我们这边的年轻人太没用」"],
- ["凯伊姆", "「客套话就免了」"],
- ["奥兹", "「这还真是失礼了」"],
- ["奥兹", "「喂,来个人」"],
- ["光头男人", "「是」"],
- ["奥兹", "「凯伊姆先生做完工作回来了」"],
- ["光头男人", "「是,是,那个······」"],
- ["奥兹", "「我是要你拿些酒来,这个蠢材!」"],
- ["", "喀!"],
- ["", "奥兹扔出的烟灰缸砸中了手下的额头。"],
- ["", "鲜血四溅。"],
- ["凯伊姆", "「不用这么麻烦」"],
- ["凯伊姆", "「我接下来要去《菲诺列塔》」"],
- ["奥兹", "「喔唷」"],
- ["奥兹", "「既然如此,我就不留您在这里喝难饮的劣质酒了」"],
- ["", "奥兹斜眼看着正捂住额头呻吟的手下,轻描淡写地说道。"],
- ["凯伊姆", "「用这些钱去买药」"],
- ["", "我将几枚铜钱仍在那个手下的身前。"],
- ["奥兹", "「凯伊姆先生,不用对他们这么好」"],
- ["凯伊姆", "「无妨」"],
- ["凯伊姆", "「话说回来,那个要落跑的女人呢?」"],
- ["奥兹", "「我把她交给那些年轻人了,现在应该正在体会人生的严苛吧」"],
- ["奥兹", "「正好,趁此机会凯伊姆先生也来享受一番如何?」"],
- ["年轻人", "「你,你们这些家伙,要对她做什么!?」"],
- ["", "咣!"],
- ["", "奥兹给了他一拳。"],
- ["", "一击即倒。"],
- ["", "喀,咚,咯!"],
- ["", "奥兹毫不留情地向男人的脸上踩去。"],
- ["年轻人", "「咕······呃咳······」"],
- ["", "折断的牙齿伴着血泡被吐出。"],
- ["", "这份白色在鲜红色的液体中格外显眼。"],
- ["年轻人", "「你们以为做出这种事······卫兵会坐视不理吗······」"],
- ["奥兹", "「啊啊,不会坐视不理的」"],
- ["奥兹", "「应该会拿出你的钱包,和我们商量如何瓜分吧」"],
- ["年轻人", "「那,那种事······」"],
- ["", "这在牢狱是理所当然的事。"],
- ["奥兹", "「怎么,头一回来牢狱么?」"],
- ["", "男人点了点头。"],
- ["奥兹", "「为了被骗的女人而来到牢狱,真是个规矩人啊」"],
- ["奥兹", "「······前提是,被骗的人不是你」"],
- ["年轻人", "「你说······我被骗了?」"],
- ["年轻人", "「那,那是怎么回事!?」"],
- ["奥兹", "「不用急,今天晚上会好好告诉你的」"],
- ["", "奥兹抓起男人的脸。"],
- ["", "为引诱客人的怜悯之心而装纯,是娼妇的惯用手段。"],
- ["", "双亲被骗而借钱,结果作为抵押而将自己卖到这里,这是典型的说法。"],
- [
- "",
- "如果只是头脑发热而成为常客也就罢了,这次的男人热血过头,居然想出了要带女人私奔的计划。",
- ],
- [
- "",
- "虽然女人半开玩笑地予以拒绝,但不知天高地厚的这家伙还是拉着她逃跑了。",
- ],
- ["", "不过,想要逃脱追击本来就是不可能的任务。"],
- ["", "但即便如此,这种事情还是会一再的出现。"],
- ["", "说谎的女人和被骗的男人。"],
- ["", "在娼馆街,这是令人看到生厌的日常的风景。"],
- ["凯伊姆", "「我要走了」"],
- ["奥兹", "「好的,下次再麻烦您」"],
- ["奥兹", "「之后吉克先生会将谢礼交给您的」"],
- ["凯伊姆", "「啊啊」"],
- ["", "我背向奥兹走出娼馆。"],
- ["凯伊姆", "「······?」"],
- ["", "从远方传来微弱的歌声。"],
- ["", "是关卡广场的方向。"],
- ["", "对了。"],
- ["", "今天有觐见圣女的仪式。"],
- ["", "当代的圣女伊莲——"],
- ["", "俗称《盲眼之圣女》,据说即使在历代的圣女中,人气也是数一数二的。"],
- ["", "广场上的人估计相当多吧。"],
- ["", "虽然我也想去看看她长什么样,不过要在人潮中挤来挤去就免了。"],
- ["", "还是老老实实去菲诺列塔喝烧酒吧。"],
- ["", "正当我这样想着的时候,一个身影自小巷的那头走来。"],
- ["凯伊姆", "「艾莉斯」"],
- ];
- this.chapter01 = [
- ["艾莉斯", "「啊,凯伊姆」"],
- ["艾莉斯", "「正好,我还想要去找你呢」"],
- ["艾莉斯", "「没想到凯伊姆会主动出现······这是命运吗?」"],
- ["凯伊姆", "「显然不是吧」"],
- ["艾莉斯", "「啊,是么」"],
- ["", "艾莉斯挑了挑整齐的双眉,微微地哼了一声。"],
- [
- "",
- "虽然是个相当引人注目的美人,但她这个将亲切儿子丢入无底深渊的性格,为自己扣了不少的分",
- ],
- ["", "给人印象最深的,就是那潭水般的双瞳。"],
- ["", "在漆黑的瞳孔中,完全看不出感情的波动。"],
- ["艾莉斯", "「喜欢我的眼睛吗?」"],
- ["艾莉斯", "「如果想要的话就给你吧?」"],
- ["凯伊姆", "「用不着」"],
- ["艾莉斯", "「阿拉,可惜」"],
- ["凯伊姆", "「那么,找我有什么事」"],
- ["艾莉斯", "「梅尔特的钱好像被偷了」"],
- ["凯伊姆", "「钱被偷了?都几岁了还这么没用」"],
- ["艾莉斯", "「不要对我说啊」"],
- ["凯伊姆", "「那家伙,该不会说要让我去抓那个小偷吧?」"],
- ["艾莉斯", "「就是这样」"],
- ["凯伊姆", "「笨蛋吗」"],
- ["凯伊姆", "「如果是小钱的话,就当做是买个教训吧」"],
- ["艾莉斯", "「说起来,被盗的是这个月的上纳金」"],
- ["凯伊姆", "「你说什么?」"],
- ["艾莉斯", "「用这些钱买教训,也太过奢侈了呢」"],
- ["凯伊姆", "「知道了,我去找」"],
- ["凯伊姆", "「小偷的特征呢」"],
- ["艾莉斯", "「男孩子」"],
- ["艾莉斯", "「······而且,背后有翅膀」"],
- ["艾莉斯", "「虽然姑且是藏在身后,但是仔细观察的话是很明显的」"],
- ["凯伊姆", "「羽化病吗」"],
- [
- "艾莉斯",
- "「那些人可是毫不留情的,所以即使是为了那个孩子,也要赶快抓到他」",
- ],
- ["凯伊姆", "「注意到他逃窜的方向了吗?」"],
- ["艾莉斯", "「广场那边」"],
- ["艾莉斯", "「虽然刚才《不蚀金锁》的人去追了,不过多半是······」"],
- ["凯伊姆", "「偏偏还是广场吗」"],
- ["艾莉斯", "「今天是觐见圣女大人的日子」"],
- ["凯伊姆", "「我知道」"],
- ["凯伊姆", "「尽量找找看就好」"],
- ];
- this.chapter02 = [
- ["不蚀金锁成员", "「凯伊姆先生,凯伊姆先生」"],
- ["不蚀金锁成员", "「您已经和艾莉斯大夫见过面了吗?」"],
- ["凯伊姆", "「啊啊,所以才会追过来的」"],
- ["凯伊姆", "「看到小偷了吗?」"],
- [
- "不蚀金锁成员",
- "「没有,他向广场那边逃了过去,今天这么拥挤,我们也只能放弃了」",
- ],
- [
- "不蚀金锁成员",
- "「不过,我也只是刚好在店里所以才追了过去,并不是受人所托」",
- ],
- ["不蚀金锁成员", "「我已经准备撤退了」"],
- ["不蚀金锁成员", "「凯伊姆先生还要继续追吗?」"],
- ["凯伊姆", "「啊啊」"],
- ["", "做完情报交换之后,我跟男人道别。"],
- ["凯伊姆", "「和我想的一样啊······」"],
- ["", "在牢狱中最大的广场上,聚集着看不到尽头的人群。"],
- ["", "就算是来参见圣女祈祷,这人数也太多了点吧。"],
- ["", "自然,我也找不到逃跑的孩子。"],
- ["", "是混杂到人群中了吧。"],
- ["", "如果已经从广场上脱身了的话,就更难发现了。"],
- ["", "只好赌他还在这里了。"],
- ["", "我先移动到了一个视野良好的地方。"],
- ["", "从这里,一眼就可以看到人群的变化。"],
- ["", "广场还是沸腾起来。"],
- ["", "抬头望去,原来是在天台之上出现了一个人影"],
- ["", "但是,与周围的期待不同,现身的是一名中年的神官。"],
- ["", "骂声四溢。"],
- ["", "神官则是笑着摆正衣领"],
- ["神官", "「从现在开始,举行谒见的仪式」"],
- [
- "神官",
- "「在参见那位大人之前,我希望牢狱的诸位再次思考这个《诺瓦斯·艾蒂尔》存在的意义······」",
- ],
- [
- "神官",
- "「初代圣女伊莲大人,便是也难怪这崇高的祈祷之力,令《诺瓦斯·艾蒂尔》浮在空中,拯救了我们的祖先」",
- ],
- [
- "神官",
- "「这之后的几百年来,传承了初代大人力量的历代圣女伊莲大人,让这里留在了空中」",
- ],
- [
- "神官",
- "「这座都市是被圣女大人守护的人类最后的圣域,而我们则是被选召的虔诚的信徒」",
- ],
- ["神官", "「怀着对圣女的感激祈祷吧,感谢圣女伊莲吧!并献上祈祷!」"],
- ["圣女", "「不忘感谢与祈祷,神才会拯救我们」"],
- ["圣女", "「与我一起,向神虔诚地祈祷吧」"],
- ["", "广场上欢声雷动。"],
- ["", "圣女没有回应喧嚣的人声,而是静静地合上双眼面向广场。"],
- ["", "虽然感觉有些冷淡,但总比像个傻瓜似的笑着向这群人挥手要强。"],
- ["", "她掌握着这条街道,还有在这条街上生活的人的命运。"],
- ["", "比起揽得人气,她更想要为了街道的继续存在而献出全力。"],
- ["", "也是为了不让《大崩落》的惨剧再度发生。"],
- ["", "十几年前的那场悲剧。"],
- [
- "",
- "虽然在我脑海中的记忆已经相当模糊,但哪怕只是稍有触及,不快的感觉都会在胸口蔓延开。",
- ],
- ["凯伊姆", "「······」"],
- ["", "这时我才想起,现在不是我在这里看圣女的时候。"],
- ["女声", "「——っ!?」"],
- ["围观的女人", "「羽,羽化病人!?」"],
- ["围观的中年人", "「喂,谁去叫下羽狩」"],
- ["惊慌的观众", "「你这家伙不要靠近我,要是传染了可怎么办」"],
- ["粗鲁的观众", "「你这小鬼赶快滚开」"],
- ["凯伊姆", "「接下来」"],
- ["圣女", "「发生什么事了?看上去似乎很嘈杂」"],
- ["随从", "「似乎是某个人逃跑了······具体的我也不是很清楚」"],
- ["神官", "「圣女大人,继续待在天台上可能会出事,请您先回到室内吧」"],
- ["圣女", "「不用在意我,比起那个,我更关心究竟发生了什么事」"],
- ["神官", "「对不起,我真的不知道」"],
- ["圣女", "「······是吗」"],
- ["男", "「恕我僭越,请准许我说明情况」"],
- ["男", "「在来觐见的人群中出现了《羽化病》的患者」"],
- ["男", "「围观的人群因而产生了骚动」"],
- [
- "男",
- "「现在,《防疫局》已经派遣了部队。我想不久之后,他们就会安静下来了」",
- ],
- ["圣女", "「羽化病······」"],
- ["男", "「怎么了?」"],
- ["圣女", "「没什么」"],
- ["圣女", "「辛苦了,你的名字是?」"],
- ["男", "「属下是在防疫局任职的,鲁基乌斯· 迪斯·米利尤」"],
- ["神官", "「噢噢,阁下就是鲁基乌斯卿吗,我听说过你的传闻」"],
- ["神官", "「阁下是在工作上相当出色的人呢」"],
- ["鲁基乌斯", "「不敢当」"],
- [
- "鲁基乌斯",
- "「话说回来,这次是属下警备工作的失职。让圣女大人见到这不成体统的一面,请您见谅」",
- ],
- [
- "圣女",
- "「即使是目不见物的我,也能感受到聚集于此的民众数量之多。警备工作难以展开也在情理之中」",
- ],
- ["鲁基乌斯", "「属下不胜惶恐」"],
- ["鲁基乌斯", "「接下来属下还要回到工作岗位上,在这里就先告退了」"],
- ["圣女", "「鲁基乌斯先生」"],
- ["鲁基乌斯", "「属下在」"],
- ["圣女", "「你是怎样看待羽狩的工作的呢?」"],
- ["神官", "「圣,圣女大人」"],
- [
- "鲁基乌斯",
- "「防疫局的工作是国王陛下赐予的重要职务。属下非常荣幸能够为这个都市的繁荣尽一份微薄之力」",
- ],
- ["神官", "「不,不亏是鲁基乌斯卿,相当优秀的想法」"],
- ["圣女", "「是吗。辛苦你了」"],
- ["随从", "「圣女大人······」"],
- ["鲁基乌斯", "「······」"],
- ["鲁基乌斯", "「那么,属下就回岗位去了」"],
- ];
- this.chapter03 = [
- ["", "从羽化病的少年纷乱的足音中,可以听得出相当的疲劳。"],
- ["", "显然,他并没有想到我会捷足先登吧。"],
- ["", "少年惶恐地回头看了一眼后,微微露出安心的表情,双手拄在膝盖上。。"],
- ["凯伊姆", "「辛苦你了」"],
- ["羽化病患少年", "「稀!?」"],
- ["凯伊姆", "「逃到贫民区是个不错的想法」"],
- ["羽化病患少年", "「你,你是,羽狩吗?」"],
- ["凯伊姆", "「不是」"],
- ["羽化病患少年", "「什,什么啊······混蛋,不要吓我啊」"],
- ["凯伊姆", "「我对令你受惊这件事致以歉意」"],
- ["凯伊姆", "「作为回报,麻烦你把从店里偷的钱交出来吧」"],
- ["羽化病患少年", "「钱?你在说什么」"],
- ["凯伊姆", "「你要找的腰上的东西,掉在你身后了」"],
- ["羽化病患少年", "「哎?」"],
- ["羽化病患少年", "「呃呀」"],
- ["羽化病患少年", "「你······你这混蛋」"],
- ["凯伊姆", "「······」"],
- ["凯伊姆", "「把偷的钱交出来」"],
- ["羽化病患少年", "「我不知道你在······咕」"],
- ["羽化病患少年", "「你,你说是我偷的······有什么证据吗」"],
- ["凯伊姆", "「你还挺倔的啊」"],
- ["凯伊姆", "「不过,给我听好了」"],
- ["凯伊姆", "「你偷的那些钱,是要上缴给《不蚀金锁》的上纳金」"],
- ["凯伊姆", "「而且,钱的主人是从前和吉克颇有渊源的女人」"],
- ["羽化病患少年", "「吉克?」"],
- ["凯伊姆", "「他是《不蚀金锁》的主人,这么说你就明白了吧」"],
- ["羽化病患少年", "「哎?哎?怎么会······」"],
- ["凯伊姆", "「再问你一遍,钱在哪里?」"],
- ["羽化病患少年", "「是,是,是,在我的怀里」"],
- ["凯伊姆", "「你没有擅自拿掉一部分吧」"],
- ["羽化病患少年", "「是,是的」"],
- ["羽化病患少年", "「那,那个,您是《不蚀金锁》的人吗?」"],
- ["凯伊姆", "「算是吧」"],
- ["羽化病患少年", "「我什么都可以做,请您一定要帮帮我」"],
- ["凯伊姆", "「抱歉,我并没有兴趣去帮助他人」"],
- ["羽化病患少年", "「我什么······什么,都会做的······」"],
- ["羽化病患少年", "「我一直都是生活在下层的」"],
- [
- "羽化病患少年",
- "「可是,不知何时染上了羽化病······背后长出了翅膀······」",
- ],
- ["羽化病患少年", "「被寄宿工作的店赶了出来,只得流落到牢狱这里」"],
- ["羽化病患少年", "「因为独自实在是饿的不行了,所以才会偷这些钱的」"],
- [
- "羽化病患少年",
- "「我明明没有做任何坏事······为什么······会遇到这种事······」",
- ],
- ["凯伊姆", "「谁知道」"],
- ["羽化病患少年", "「呜······呜呜······接下来,要对我做什么?」"],
- ["凯伊姆", "「我要把你带到组织那里」"],
- ["羽化病患少年", "「怎,怎么这样」"],
- ["凯伊姆", "「不过,那样做的前提是你不是羽化病人」"],
- ["凯伊姆", "「组织也没有笨到把羽化病人招待到家里的程度」"],
- ["羽化病患少年", "「那么,是要放我逃走吗?」"],
- ["凯伊姆", "「我要让你学到教训」"],
- ["凯伊姆", "「如果换做是组织的制裁,至少要有断条胳膊的觉悟」"],
- ["凯伊姆", "「你的运气不错」"],
- ["羽化病患少年", "「唔······啊,是的······」"],
- ["凯伊姆", "「滚」"],
- ["羽化病患少年", "「非常感谢」"],
- ["羽化病患少年", "「唔啊!?」"],
- ["男", "「到这里就结束了,羽化病人」"],
- ["男", "「确认他的翅膀」"],
- ["", "趁还没有被卷入麻烦的事情之前,赶快离开这里吧"],
- ["羽狩的队长", "「那边的那个人」"],
- ["凯伊姆", "「······有什么事?」"],
- ["羽狩的队长", "「可以稍微让我问几句话吗」"],
- ["凯伊姆", "「······」"],
- ["凯伊姆", "「啊啊,无妨」"],
- ["羽狩的队长", "「感谢您的合作」"],
- ["", "队长殷勤地致以谢礼。"],
- ["", "而在他的眼前,少年的衣服已经被他的补下们扯破。"],
- ["", "在瘦骨嶙峋的裸露后背上,长有纯白的羽翼。"],
- ["红发的羽狩", "「副队长,确认翅膀的持有了」"],
- ["羽狩的副队长", "「保护他」"],
- ["羽化病患少年", "「不要······请原谅,我······」"],
- [
- "羽狩的副队长",
- "「我们只是要带你去治愈院治疗羽化病,不是什么应该感到害怕的事情」",
- ],
- ["羽化病患少年", "「可是,可是」"],
- ["羽狩的副队长", "「没关系的」"],
- ["羽化病患少年", "「······哥,哥哥」"],
- ["羽狩的副队长", "「你是羽化病人的亲属吗?」"],
- ["凯伊姆", "「只是路人而已」"],
- ["凯伊姆", "「顺带一提,我也没有打算找你们的麻烦」"],
- [
- "羽狩的副队长",
- "「前几天,有个和你说了同样的话的人,在我们背向他的瞬间对我们发动了袭击」",
- ],
- ["羽狩的副队长", "「我的一个部下就此永久失去了半截胳膊」"],
- ["凯伊姆", "「我表示同情」"],
- ["凯伊姆", "「我马上就会消失的,这样就没问题了吧?」"],
- ["羽狩的副队长", "「嘛,不要这么慌张」"],
- ["", "副队长看着羽化的少年。"],
- ["羽狩的副队长", "「你与这个人是什么关系?没有被他殴打吗?」"],
- ["羽化病患少年", "「没,没有」"],
- [
- "羽狩的副队长",
- "「如何对我们保持合作,你就可以在治愈院得到优先的治疗」",
- ],
- ["羽化病患少年", "「······」"],
- ["羽化病患少年", "「那个人,是《不蚀金锁》的组织成员······」"],
- ["羽化病患少年", "「突然说让我拿出钱来,我刚一拒绝他就打我」"],
- ["羽狩的副队长", "「原来如此······」"],
- [
- "羽狩的副队长",
- "「那位少年说你是《不蚀金锁》的一员,不知此事是否属实?」",
- ],
- ["凯伊姆", "「当然不是」"],
- ["凯伊姆", "「我只是从那里接受工作而已,并不是他们的成员」"],
- ["羽狩的副队长", "「你的意思是说,少年在说谎吗?」"],
- ["凯伊姆", "「啊啊」"],
- [
- "凯伊姆",
- "「如果你们和组织有关系的话,只要问问我是不是那里的成员就能明白事实了吧」",
- ],
- ["羽狩的副队长", "「就算我去询问,也无法从他们那里得到事实」"],
- [
- "羽狩的副队长",
- "「《不蚀金锁》的那些人一向都不对我们合作,我对此深感困扰」",
- ],
- ["凯伊姆", "「真是辛苦啊」"],
- ["羽狩的副队长", "「说的是啊」"],
- ["羽狩的副队长", "「其实,砍下我部下胳膊的似乎也是组织的成员呢」"],
- [
- "羽狩的副队长",
- "「无需如此警戒,我只是想在看守所向你咨询一些事情而已」",
- ],
- [
- "羽狩的副队长",
- "「如果能够知晓牢狱与组织的事情,我们也可以尽可能地对更多的羽化病人进行保护」",
- ],
- ["羽狩的副队长", "「那和整条街道的和平也是紧密相关的吧?」"],
- ["凯伊姆", "「我知道,你们有逮捕干扰狩猎羽化病人的权力」"],
- [
- "凯伊姆",
- "「但是,我没有对你们做出任何干扰,为什么要对我如此纠缠不休呢」",
- ],
- ["羽狩的副队长", "「那些话,我们会在看守所对你详细说明的」"],
- ["凯伊姆", "「······」"],
- ["", "在这里起争执的话,就会被羽狩加害。"],
- ["", "就算能从这里脱身,今后只要碰面就会产生纠纷也是摆明的事情。"],
- ["", "就算逃跑,也没有好的结果。"],
- ["", "正当我想要打圆场的时候,刚才的气氛一瞬间产生了转变。"],
- ["", "发生了什么事······"],
- ["???", "「我认为,那位先生是正确的」"],
- ["", "羽狩们一起回头。"],
- ["", "而在他们视线的焦点处,"],
- ["", "伫立着一位女性。"],
- ["", "在端正的容颜下,代表着强烈意志的双眉十分显眼。"],
- ["", "身体的柔软与紧紧包裹在其身上的羽狩制服,两者显得十分的不搭配。"],
- ["", "我还是第一次看到女性的羽狩。"],
- ["羽狩的副队长", "「队长,这是获得《不蚀金锁》情报的好机会」"],
- [
- "羽狩的队长",
- "「兰格副队长,就算是为了获得情报,也不能做出恫吓的发言啊」",
- ],
- ["兰格副队长", "「我并没有打算去恫吓他······」"],
- ["羽狩的队长", "「告诉我那个被砍掉胳膊的队员的名字」"],
- ["羽狩的队长", "「我会去探望他的」"],
- ["兰格副队长", "「那个是······」"],
- ["羽狩的队长", "「我知道,你一直在为有所收获而努力工作」"],
- ["羽狩的队长", "「但是,正因为我们的工作是为民众提供帮助」"],
- ["羽狩的队长", "「所以就更不能损害人与人之间的信赖」"],
- ["兰格副队长", "「我会铭记在心」"],
- ["羽狩的队长", "「这位先生,我的部下失礼了」"],
- ["凯伊姆", "「只要不对我再来一次就好」"],
- ["羽狩的队长", "「请稍等」"],
- ["凯伊姆", "「有什么事?」"],
- ["羽狩的队长", "「我想确认一件事」"],
- ["羽狩的队长", "「你真的不是《不蚀金锁》的成员吗?」"],
- ["凯伊姆", "「真的」"],
- ["凯伊姆", "「如果我说是的话,你有什么打算?」"],
- ["羽狩的队长", "「我听过传闻,说他们是用依靠暴力而得的钱在生活」"],
- ["凯伊姆", "「······这样啊」"],
- ["凯伊姆", "「如果能有收获就好了啊」"],
- ];
- this.chapter04 = [
- ["梅尔特", "「欢迎光临」"],
- ["梅尔特", "「辛苦了」"],
- ["梅尔特", "「抱歉,又拜托给你了个这么麻烦的工作」"],
- ["凯伊姆", "「没什么,比想象中完成的更容易」"],
- ["梅尔特", "「那就好」"],
- ["梅尔特", "「这是我的一点谢意」"],
- ["凯伊姆", "「味道有些变化啊」"],
- ["梅尔特", "「啊,被发现了?」"],
- ["梅尔特", "「最近,没能到手什么好的原料呢」"],
- ["凯伊姆", "「去拜托吉克如何?」"],
- [
- "梅尔特",
- "「话是这么说,但是总不能用店里采购的这种小事去麻烦他吧······」",
- ],
- ["凯伊姆", "「那希望你也不要来麻烦我」"],
- ["梅尔特", "「那 是 两 码 事」"],
- ["梅尔特", "「再说,凯伊姆是靠着工作来生活的吧」"],
- [
- "梅尔特",
- "「而且,自己的钱被偷了这么害羞的事,向凯伊姆意外的其他人都说不出口」",
- ],
- ["凯伊姆", "「反正,也已经传到吉克的耳朵里了」"],
- ["梅尔特", "「这是面子问题啊,面子问题」"],
- ["凯伊姆", "「嘛,算了」"],
- ["凯伊姆", "「这样就好了吧?」"],
- ["梅尔特", "「这是钱包呢」"],
- ["梅尔特", "「嗯,东西没少」"],
- ["梅尔特", "「太好啦—这个月的上纳金,我可全部都放在里面了呢」"],
- ["梅尔特", "「如果没有找到的话,说不定就又会被送到娼馆里了呢」"],
- ["凯伊姆", "「在那边不是来钱更快吗?」"],
- ["梅尔特", "「阿拉,你是在说我还能有魅力吗?」"],
- ["凯伊姆", "「这是客套话而已」"],
- ["梅尔特", "「欺负人」"],
- ["梅尔特", "「总而言之,今天帮大忙了」"],
- ["梅尔特", "「谢礼嘛······」"],
- ["凯伊姆", "「就记在账单上吧」"],
- ["梅尔特", "「了解—盛谢惠顾了哦?」"],
- ["", "喀啷喀啷"],
- ["", "门铃响起"],
- ["", "喧哗瞬间安静下来。"],
- ["", "进来的人是吉克。"],
- ["", "是掌控着牢狱的组织之一,《不蚀金锁》的头目。"],
- ["", "不仅组织的成员,就连店内一般的客人也对他以注目礼表示敬意。"],
- ["吉克", "「各位继续吧」"],
- ["", "仿佛停滞的时钟重新转动了一般,店内恢复了热闹的气氛。"],
- ["吉克", "「抱歉,今天拜托你去做了无聊的工作」。"],
- ["凯伊姆", "「不用介意」"],
- ["", "吉克轻轻点了点头,在我右边坐了下来"],
- ["凯伊姆", "「逃跑的男人怎么样了?」"],
- ["吉克", "「嗯?已经不在这个世上了」。"],
- ["吉克", "「有什么想要知道的事吗?」"],
- ["凯伊姆", "「不,没什么」"],
- ["吉克", "「那个无聊的家伙,完全没有趣味呢」"],
- ["吉克", "「真希望他也替我负责清扫的部下也考虑考虑」"],
- ["凯伊姆", "「真是灾难啊」"],
- ["吉克", "「比起那个,我听说了哦。你去追羽化病人了啊」"],
- ["凯伊姆", "「消息真灵通」"],
- ["吉克", "「梅尔特也注意点」"],
- ["吉克", "「你丢钱已经不是一回两回了」"],
- ["梅尔特", "「好的—我会注意的。」"],
- ["梅尔特", "「吉克还是平常的点单吧」"],
- ["梅尔特", "「凯伊姆要再来一杯吗?」"],
- ["", "我们用眼神点头示意后,梅尔特开始准备起酒来。"],
- ["", "悠然地吐出眼圈后,吉克取出一个纸包放在柜台上。"],
- ["吉克", "「这是抓捕逃跑男人的报酬」"],
- ["凯伊姆", "「下次有什么事再告诉我」"],
- ["梅尔特", "「来,久等了」"],
- ["凯伊姆", "「话说回来梅尔特,为什么会被那种孩子偷到钱?」"],
- ["吉克", "「让我猜猜看」"],
- ["吉克", "「是那个吧,看某个特立独行的男人入迷了,所以就有了空隙?」"],
- ["梅尔特", "「可惜—」"],
- ["梅尔特", "「事实恰恰相反,是那家伙一直在纠缠我」"],
- ["凯伊姆", "「完全把你当成新进的女佣了么」"],
- ["梅尔特", "「我从前可是很有名的,不会被当成这种下人吧」"],
- ["梅尔特", "「······而且,我没法对对我这么钟情的人发火啊」"],
- ["凯伊姆&吉克", "「你傻啊」"],
- ["梅尔特", "「异口同声呢,不亏是兄弟」"],
- ["凯伊姆", "「别用这种称呼,怪恶心的」"],
- ["吉克", "「说得没错」"],
- ["吉克", "「······说起来······」"],
- ["梅尔特", "「怎么了?」"],
- ["吉克", "「有件事我一直很在意,我和凯伊姆,哪个是哥哥啊?」"],
- ["凯伊姆", "「你也说这么无聊的话题」"],
- ["吉克", "「不,这是很重要的事情」"],
- ["吉克", "「梅尔特,事实是怎么样的?」"],
- ["梅尔特", "「啊~是怎么样的呢~」"],
- ["梅尔特", "「我忘记了」"],
- ["吉克", "「骗人」"],
- ];
-}
+ // 在此增加新插件
+ // 每项为一个数组,第一项是名字,第二项是对话内容
+ // 回放只会在同一个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 = [
+ ["不蚀金锁成员", "「凯伊姆先生,凯伊姆先生」"],
+ ["不蚀金锁成员", "「您已经和艾莉斯大夫见过面了吗?」"],
+ ["凯伊姆", "「啊啊,所以才会追过来的」"], //男主31
+ ["凯伊姆", "「看到小偷了吗?」"], //男主32
+ [
+ "不蚀金锁成员",
+ "「没有,他向广场那边逃了过去,今天这么拥挤,我们也只能放弃了」",
+ ],
+ [
+ "不蚀金锁成员",
+ "「不过,我也只是刚好在店里所以才追了过去,并不是受人所托」",
+ ],
+ ["不蚀金锁成员", "「我已经准备撤退了」"],
+ ["不蚀金锁成员", "「凯伊姆先生还要继续追吗?」"],
+ ["凯伊姆", "「啊啊」"], //男主33
+ ["", "做完情报交换之后,我跟男人道别。"],
+ ["凯伊姆", "「和我想的一样啊······」"], //男主34
+ ["", "在牢狱中最大的广场上,聚集着看不到尽头的人群。"],
+ ["", "就算是来参见圣女祈祷,这人数也太多了点吧。"],
+ ["", "自然,我也找不到逃跑的孩子。"],
+ ["", "是混杂到人群中了吧。"],
+ ["", "如果已经从广场上脱身了的话,就更难发现了。"],
+ ["", "只好赌他还在这里了。"],
+ ["", "我先移动到了一个视野良好的地方。"],
+ ["", "从这里,一眼就可以看到人群的变化。"],
+ ["", "广场还是沸腾起来。"],
+ ["", "抬头望去,原来是在天台之上出现了一个人影"],
+ ["", "但是,与周围的期待不同,现身的是一名中年的神官。"],
+ ["", "骂声四溢。"],
+ ["", "神官则是笑着摆正衣领"],
+ ["神官", "「从现在开始,举行谒见的仪式」"],
+ [
+ "神官",
+ "「在参见那位大人之前,我希望牢狱的诸位再次思考这个《诺瓦斯·艾蒂尔》存在的意义······」",
+ ],
+ [
+ "神官",
+ "「初代圣女伊莲大人,便是也难怪这崇高的祈祷之力,令《诺瓦斯·艾蒂尔》浮在空中,拯救了我们的祖先」",
+ ],
+ [
+ "神官",
+ "「这之后的几百年来,传承了初代大人力量的历代圣女伊莲大人,让这里留在了空中」",
+ ],
+ [
+ "神官",
+ "「这座都市是被圣女大人守护的人类最后的圣域,而我们则是被选召的虔诚的信徒」",
+ ],
+ ["神官", "「怀着对圣女的感激祈祷吧,感谢圣女伊莲吧!并献上祈祷!」"],
+ ["圣女", "「不忘感谢与祈祷,神才会拯救我们」"],
+ ["圣女", "「与我一起,向神虔诚地祈祷吧」"],
+ ["", "广场上欢声雷动。"],
+ ["", "圣女没有回应喧嚣的人声,而是静静地合上双眼面向广场。"],
+ ["", "虽然感觉有些冷淡,但总比像个傻瓜似的笑着向这群人挥手要强。"],
+ ["", "她掌握着这条街道,还有在这条街上生活的人的命运。"],
+ ["", "比起揽得人气,她更想要为了街道的继续存在而献出全力。"],
+ ["", "也是为了不让《大崩落》的惨剧再度发生。"],
+ ["", "十几年前的那场悲剧。"],
+ [
+ "",
+ "虽然在我脑海中的记忆已经相当模糊,但哪怕只是稍有触及,不快的感觉都会在胸口蔓延开。",
+ ],
+ ["凯伊姆", "「······」"], //男主35
+ ["", "这时我才想起,现在不是我在这里看圣女的时候。"],
+ ["女声", "「——っ!?」"],
+ ["围观的女人", "「羽,羽化病人!?」"],
+ ["围观的中年人", "「喂,谁去叫下羽狩」"],
+ ["惊慌的观众", "「你这家伙不要靠近我,要是传染了可怎么办」"],
+ ["粗鲁的观众", "「你这小鬼赶快滚开」"],
+ ["凯伊姆", "「接下来」"],
+ ["圣女", "「发生什么事了?看上去似乎很嘈杂」"],
+ ["随从", "「似乎是某个人逃跑了······具体的我也不是很清楚」"],
+ ["神官", "「圣女大人,继续待在天台上可能会出事,请您先回到室内吧」"],
+ ["圣女", "「不用在意我,比起那个,我更关心究竟发生了什么事」"],
+ ["神官", "「对不起,我真的不知道」"],
+ ["圣女", "「······是吗」"],
+ ["男", "「恕我僭越,请准许我说明情况」"],
+ ["男", "「在来觐见的人群中出现了《羽化病》的患者」"],
+ ["男", "「围观的人群因而产生了骚动」"],
+ [
+ "男",
+ "「现在,《防疫局》已经派遣了部队。我想不久之后,他们就会安静下来了」",
+ ],
+ ["圣女", "「羽化病······」"],
+ ["男", "「怎么了?」"],
+ ["圣女", "「没什么」"],
+ ["圣女", "「辛苦了,你的名字是?」"],
+ ["男", "「属下是在防疫局任职的,鲁基乌斯· 迪斯·米利尤」"],
+ ["神官", "「噢噢,阁下就是鲁基乌斯卿吗,我听说过你的传闻」"],
+ ["神官", "「阁下是在工作上相当出色的人呢」"],
+ ["鲁基乌斯", "「不敢当」"],
+ [
+ "鲁基乌斯",
+ "「话说回来,这次是属下警备工作的失职。让圣女大人见到这不成体统的一面,请您见谅」",
+ ],
+ [
+ "圣女",
+ "「即使是目不见物的我,也能感受到聚集于此的民众数量之多。警备工作难以展开也在情理之中」",
+ ],
+ ["鲁基乌斯", "「属下不胜惶恐」"],
+ ["鲁基乌斯", "「接下来属下还要回到工作岗位上,在这里就先告退了」"],
+ ["圣女", "「鲁基乌斯先生」"],
+ ["鲁基乌斯", "「属下在」"],
+ ["圣女", "「你是怎样看待羽狩的工作的呢?」"],
+ ["神官", "「圣,圣女大人」"],
+ [
+ "鲁基乌斯",
+ "「防疫局的工作是国王陛下赐予的重要职务。属下非常荣幸能够为这个都市的繁荣尽一份微薄之力」",
+ ],
+ ["神官", "「不,不亏是鲁基乌斯卿,相当优秀的想法」"],
+ ["圣女", "「是吗。辛苦你了」"],
+ ["随从", "「圣女大人······」"],
+ ["鲁基乌斯", "「······」"],
+ ["鲁基乌斯", "「那么,属下就回岗位去了」"],
+ ];
+ this.chapter03 = [
+ ["", "从羽化病的少年纷乱的足音中,可以听得出相当的疲劳。"],
+ ["", "显然,他并没有想到我会捷足先登吧。"],
+ ["", "少年惶恐地回头看了一眼后,微微露出安心的表情,双手拄在膝盖上。。"],
+ ["凯伊姆", "「辛苦你了」"], //男主37
+ ["羽化病患少年", "「稀!?」"],
+ ["凯伊姆", "「逃到贫民区是个不错的想法」"], //男主38
+ ["羽化病患少年", "「你,你是,羽狩吗?」"],
+ ["凯伊姆", "「不是」"], //男主39
+ ["羽化病患少年", "「什,什么啊······混蛋,不要吓我啊」"],
+ ["凯伊姆", "「我对令你受惊这件事致以歉意」"], //男主40
+ ["凯伊姆", "「作为回报,麻烦你把从店里偷的钱交出来吧」"], //男主41
+ ["羽化病患少年", "「钱?你在说什么」"],
+ ["凯伊姆", "「你要找的腰上的东西,掉在你身后了」"], //男主42
+ ["羽化病患少年", "「哎?」"],
+ ["羽化病患少年", "「呃呀」"],
+ ["羽化病患少年", "「你······你这混蛋」"],
+ ["凯伊姆", "「······」"], //男主43
+ ["凯伊姆", "「把偷的钱交出来」"], //男主44
+ ["羽化病患少年", "「我不知道你在······咕」"],
+ ["羽化病患少年", "「你,你说是我偷的······有什么证据吗」"],
+ ["凯伊姆", "「你还挺倔的啊」"], //男主45
+ ["凯伊姆", "「不过,给我听好了」"], //男主46
+ ["凯伊姆", "「你偷的那些钱,是要上缴给《不蚀金锁》的上纳金」"], //男主47
+ ["凯伊姆", "「而且,钱的主人是从前和吉克颇有渊源的女人」"], //男主48
+ ["羽化病患少年", "「吉克?」"],
+ ["凯伊姆", "「他是《不蚀金锁》的主人,这么说你就明白了吧」"], //男主49
+ ["羽化病患少年", "「哎?哎?怎么会······」"],
+ ["凯伊姆", "「再问你一遍,钱在哪里?」"], //男主50
+ ["羽化病患少年", "「是,是,是,在我的怀里」"],
+ ["凯伊姆", "「你没有擅自拿掉一部分吧」"], //男主51
+ ["羽化病患少年", "「是,是的」"],
+ ["羽化病患少年", "「那,那个,您是《不蚀金锁》的人吗?」"],
+ ["凯伊姆", "「算是吧」"], //男主52
+ ["羽化病患少年", "「我什么都可以做,请您一定要帮帮我」"],
+ ["凯伊姆", "「抱歉,我并没有兴趣去帮助他人」"], //男主53+54
+ ["羽化病患少年", "「我什么······什么,都会做的······」"],
+ ["羽化病患少年", "「我一直都是生活在下层的」"],
+ [
+ "羽化病患少年",
+ "「可是,不知何时染上了羽化病······背后长出了翅膀······」",
+ ],
+ ["羽化病患少年", "「被寄宿工作的店赶了出来,只得流落到牢狱这里」"],
+ ["羽化病患少年", "「因为独自实在是饿的不行了,所以才会偷这些钱的」"],
+ [
+ "羽化病患少年",
+ "「我明明没有做任何坏事······为什么······会遇到这种事······」",
+ ],
+ ["凯伊姆", "「谁知道」"], //男主55
+ ["羽化病患少年", "「呜······呜呜······接下来,要对我做什么?」"],
+ ["凯伊姆", "「我要把你带到组织那里」"], //男主56
+ ["羽化病患少年", "「怎,怎么这样」"],
+ ["凯伊姆", "「不过,那样做的前提是你不是羽化病人」"],
+ ["凯伊姆", "「组织也没有笨到把羽化病人招待到家里的程度」"],
+ ["羽化病患少年", "「那么,是要放我逃走吗?」"],
+ ["凯伊姆", "「我要让你学到教训」"],
+ ["凯伊姆", "「如果换做是组织的制裁,至少要有断条胳膊的觉悟」"],
+ ["凯伊姆", "「你的运气不错」"],
+ ["羽化病患少年", "「唔······啊,是的······」"],
+ ["凯伊姆", "「滚」"],
+ ["羽化病患少年", "「非常感谢」"],
+ ["羽化病患少年", "「唔啊!?」"],
+ ["男", "「到这里就结束了,羽化病人」"],
+ ["男", "「确认他的翅膀」"],
+ ["", "趁还没有被卷入麻烦的事情之前,赶快离开这里吧"],
+ ["羽狩的队长", "「那边的那个人」"],
+ ["凯伊姆", "「······有什么事?」"],
+ ["羽狩的队长", "「可以稍微让我问几句话吗」"],
+ ["凯伊姆", "「······」"],
+ ["凯伊姆", "「啊啊,无妨」"],
+ ["羽狩的队长", "「感谢您的合作」"],
+ ["", "队长殷勤地致以谢礼。"],
+ ["", "而在他的眼前,少年的衣服已经被他的补下们扯破。"],
+ ["", "在瘦骨嶙峋的裸露后背上,长有纯白的羽翼。"],
+ ["红发的羽狩", "「副队长,确认翅膀的持有了」"],
+ ["羽狩的副队长", "「保护他」"],
+ ["羽化病患少年", "「不要······请原谅,我······」"],
+ [
+ "羽狩的副队长",
+ "「我们只是要带你去治愈院治疗羽化病,不是什么应该感到害怕的事情」",
+ ],
+ ["羽化病患少年", "「可是,可是」"],
+ ["羽狩的副队长", "「没关系的」"],
+ ["羽化病患少年", "「······哥,哥哥」"],
+ ["羽狩的副队长", "「你是羽化病人的亲属吗?」"],
+ ["凯伊姆", "「只是路人而已」"],
+ ["凯伊姆", "「顺带一提,我也没有打算找你们的麻烦」"],
+ [
+ "羽狩的副队长",
+ "「前几天,有个和你说了同样的话的人,在我们背向他的瞬间对我们发动了袭击」",
+ ],
+ ["羽狩的副队长", "「我的一个部下就此永久失去了半截胳膊」"],
+ ["凯伊姆", "「我表示同情」"],
+ ["凯伊姆", "「我马上就会消失的,这样就没问题了吧?」"],
+ ["羽狩的副队长", "「嘛,不要这么慌张」"],
+ ["", "副队长看着羽化的少年。"],
+ ["羽狩的副队长", "「你与这个人是什么关系?没有被他殴打吗?」"],
+ ["羽化病患少年", "「没,没有」"],
+ [
+ "羽狩的副队长",
+ "「如何对我们保持合作,你就可以在治愈院得到优先的治疗」",
+ ],
+ ["羽化病患少年", "「······」"],
+ ["羽化病患少年", "「那个人,是《不蚀金锁》的组织成员······」"],
+ ["羽化病患少年", "「突然说让我拿出钱来,我刚一拒绝他就打我」"],
+ ["羽狩的副队长", "「原来如此······」"],
+ [
+ "羽狩的副队长",
+ "「那位少年说你是《不蚀金锁》的一员,不知此事是否属实?」",
+ ],
+ ["凯伊姆", "「当然不是」"],
+ ["凯伊姆", "「我只是从那里接受工作而已,并不是他们的成员」"],
+ ["羽狩的副队长", "「你的意思是说,少年在说谎吗?」"],
+ ["凯伊姆", "「啊啊」"],
+ [
+ "凯伊姆",
+ "「如果你们和组织有关系的话,只要问问我是不是那里的成员就能明白事实了吧」",
+ ],
+ ["羽狩的副队长", "「就算我去询问,也无法从他们那里得到事实」"],
+ [
+ "羽狩的副队长",
+ "「《不蚀金锁》的那些人一向都不对我们合作,我对此深感困扰」",
+ ],
+ ["凯伊姆", "「真是辛苦啊」"],
+ ["羽狩的副队长", "「说的是啊」"],
+ ["羽狩的副队长", "「其实,砍下我部下胳膊的似乎也是组织的成员呢」"],
+ [
+ "羽狩的副队长",
+ "「无需如此警戒,我只是想在看守所向你咨询一些事情而已」",
+ ],
+ [
+ "羽狩的副队长",
+ "「如果能够知晓牢狱与组织的事情,我们也可以尽可能地对更多的羽化病人进行保护」",
+ ],
+ ["羽狩的副队长", "「那和整条街道的和平也是紧密相关的吧?」"],
+ ["凯伊姆", "「我知道,你们有逮捕干扰狩猎羽化病人的权力」"],
+ [
+ "凯伊姆",
+ "「但是,我没有对你们做出任何干扰,为什么要对我如此纠缠不休呢」",
+ ],
+ ["羽狩的副队长", "「那些话,我们会在看守所对你详细说明的」"],
+ ["凯伊姆", "「······」"],
+ ["", "在这里起争执的话,就会被羽狩加害。"],
+ ["", "就算能从这里脱身,今后只要碰面就会产生纠纷也是摆明的事情。"],
+ ["", "就算逃跑,也没有好的结果。"],
+ ["", "正当我想要打圆场的时候,刚才的气氛一瞬间产生了转变。"],
+ ["", "发生了什么事······"],
+ ["???", "「我认为,那位先生是正确的」"],
+ ["", "羽狩们一起回头。"],
+ ["", "而在他们视线的焦点处,"],
+ ["", "伫立着一位女性。"],
+ ["", "在端正的容颜下,代表着强烈意志的双眉十分显眼。"],
+ ["", "身体的柔软与紧紧包裹在其身上的羽狩制服,两者显得十分的不搭配。"],
+ ["", "我还是第一次看到女性的羽狩。"],
+ ["羽狩的副队长", "「队长,这是获得《不蚀金锁》情报的好机会」"],
+ [
+ "羽狩的队长",
+ "「兰格副队长,就算是为了获得情报,也不能做出恫吓的发言啊」",
+ ],
+ ["兰格副队长", "「我并没有打算去恫吓他······」"],
+ ["羽狩的队长", "「告诉我那个被砍掉胳膊的队员的名字」"],
+ ["羽狩的队长", "「我会去探望他的」"],
+ ["兰格副队长", "「那个是······」"],
+ ["羽狩的队长", "「我知道,你一直在为有所收获而努力工作」"],
+ ["羽狩的队长", "「但是,正因为我们的工作是为民众提供帮助」"],
+ ["羽狩的队长", "「所以就更不能损害人与人之间的信赖」"],
+ ["兰格副队长", "「我会铭记在心」"],
+ ["羽狩的队长", "「这位先生,我的部下失礼了」"],
+ ["凯伊姆", "「只要不对我再来一次就好」"],
+ ["羽狩的队长", "「请稍等」"],
+ ["凯伊姆", "「有什么事?」"],
+ ["羽狩的队长", "「我想确认一件事」"],
+ ["羽狩的队长", "「你真的不是《不蚀金锁》的成员吗?」"],
+ ["凯伊姆", "「真的」"],
+ ["凯伊姆", "「如果我说是的话,你有什么打算?」"],
+ ["羽狩的队长", "「我听过传闻,说他们是用依靠暴力而得的钱在生活」"],
+ ["凯伊姆", "「······这样啊」"],
+ ["凯伊姆", "「如果能有收获就好了啊」"],
+ ];
+ this.chapter04 = [
+ ["梅尔特", "「欢迎光临」"],
+ ["梅尔特", "「辛苦了」"],
+ ["梅尔特", "「抱歉,又拜托给你了个这么麻烦的工作」"],
+ ["凯伊姆", "「没什么,比想象中完成的更容易」"],
+ ["梅尔特", "「那就好」"],
+ ["梅尔特", "「这是我的一点谢意」"],
+ ["凯伊姆", "「味道有些变化啊」"],
+ ["梅尔特", "「啊,被发现了?」"],
+ ["梅尔特", "「最近,没能到手什么好的原料呢」"],
+ ["凯伊姆", "「去拜托吉克如何?」"],
+ [
+ "梅尔特",
+ "「话是这么说,但是总不能用店里采购的这种小事去麻烦他吧······」",
+ ],
+ ["凯伊姆", "「那希望你也不要来麻烦我」"],
+ ["梅尔特", "「那 是 两 码 事」"],
+ ["梅尔特", "「再说,凯伊姆是靠着工作来生活的吧」"],
+ [
+ "梅尔特",
+ "「而且,自己的钱被偷了这么害羞的事,向凯伊姆意外的其他人都说不出口」",
+ ],
+ ["凯伊姆", "「反正,也已经传到吉克的耳朵里了」"],
+ ["梅尔特", "「这是面子问题啊,面子问题」"],
+ ["凯伊姆", "「嘛,算了」"],
+ ["凯伊姆", "「这样就好了吧?」"],
+ ["梅尔特", "「这是钱包呢」"],
+ ["梅尔特", "「嗯,东西没少」"],
+ ["梅尔特", "「太好啦—这个月的上纳金,我可全部都放在里面了呢」"],
+ ["梅尔特", "「如果没有找到的话,说不定就又会被送到娼馆里了呢」"],
+ ["凯伊姆", "「在那边不是来钱更快吗?」"],
+ ["梅尔特", "「阿拉,你是在说我还能有魅力吗?」"],
+ ["凯伊姆", "「这是客套话而已」"],
+ ["梅尔特", "「欺负人」"],
+ ["梅尔特", "「总而言之,今天帮大忙了」"],
+ ["梅尔特", "「谢礼嘛······」"],
+ ["凯伊姆", "「就记在账单上吧」"],
+ ["梅尔特", "「了解—盛谢惠顾了哦?」"],
+ ["", "喀啷喀啷"],
+ ["", "门铃响起"],
+ ["", "喧哗瞬间安静下来。"],
+ ["", "进来的人是吉克。"],
+ ["", "是掌控着牢狱的组织之一,《不蚀金锁》的头目。"],
+ ["", "不仅组织的成员,就连店内一般的客人也对他以注目礼表示敬意。"],
+ ["吉克", "「各位继续吧」"],
+ ["", "仿佛停滞的时钟重新转动了一般,店内恢复了热闹的气氛。"],
+ ["吉克", "「抱歉,今天拜托你去做了无聊的工作」。"],
+ ["凯伊姆", "「不用介意」"],
+ ["", "吉克轻轻点了点头,在我右边坐了下来"],
+ ["凯伊姆", "「逃跑的男人怎么样了?」"],
+ ["吉克", "「嗯?已经不在这个世上了」。"],
+ ["吉克", "「有什么想要知道的事吗?」"],
+ ["凯伊姆", "「不,没什么」"],
+ ["吉克", "「那个无聊的家伙,完全没有趣味呢」"],
+ ["吉克", "「真希望他也替我负责清扫的部下也考虑考虑」"],
+ ["凯伊姆", "「真是灾难啊」"],
+ ["吉克", "「比起那个,我听说了哦。你去追羽化病人了啊」"],
+ ["凯伊姆", "「消息真灵通」"],
+ ["吉克", "「梅尔特也注意点」"],
+ ["吉克", "「你丢钱已经不是一回两回了」"],
+ ["梅尔特", "「好的—我会注意的。」"],
+ ["梅尔特", "「吉克还是平常的点单吧」"],
+ ["梅尔特", "「凯伊姆要再来一杯吗?」"],
+ ["", "我们用眼神点头示意后,梅尔特开始准备起酒来。"],
+ ["", "悠然地吐出眼圈后,吉克取出一个纸包放在柜台上。"],
+ ["吉克", "「这是抓捕逃跑男人的报酬」"],
+ ["凯伊姆", "「下次有什么事再告诉我」"],
+ ["梅尔特", "「来,久等了」"],
+ ["凯伊姆", "「话说回来梅尔特,为什么会被那种孩子偷到钱?」"],
+ ["吉克", "「让我猜猜看」"],
+ ["吉克", "「是那个吧,看某个特立独行的男人入迷了,所以就有了空隙?」"],
+ ["梅尔特", "「可惜—」"],
+ ["梅尔特", "「事实恰恰相反,是那家伙一直在纠缠我」"],
+ ["凯伊姆", "「完全把你当成新进的女佣了么」"],
+ ["梅尔特", "「我从前可是很有名的,不会被当成这种下人吧」"],
+ ["梅尔特", "「······而且,我没法对对我这么钟情的人发火啊」"],
+ ["凯伊姆&吉克", "「你傻啊」"],
+ ["梅尔特", "「异口同声呢,不亏是兄弟」"],
+ ["凯伊姆", "「别用这种称呼,怪恶心的」"],
+ ["吉克", "「说得没错」"],
+ ["吉克", "「······说起来······」"],
+ ["梅尔特", "「怎么了?」"],
+ ["吉克", "「有件事我一直很在意,我和凯伊姆,哪个是哥哥啊?」"],
+ ["凯伊姆", "「你也说这么无聊的话题」"],
+ ["吉克", "「不,这是很重要的事情」"],
+ ["吉克", "「梅尔特,事实是怎么样的?」"],
+ ["梅尔特", "「啊~是怎么样的呢~」"],
+ ["梅尔特", "「我忘记了」"],
+ ["吉克", "「骗人」"],
+ ];
+ }
}
\ No newline at end of file
diff --git a/styles.css b/styles.css
index e7ba189..e300825 100644
--- a/styles.css
+++ b/styles.css
@@ -544,9 +544,9 @@ p#name {
}
/* 注释下面这三行以开启抗锯齿 */
-.anti-aliasing {
+/* .anti-aliasing {
image-rendering: pixelated;
-}
+} */
.warning {
transition: left cubic-bezier(0, 0.9, 1, 0.1) 2.5s;