diff --git a/_saves/Eustia_autoSave b/_saves/Eustia_autoSave index e5caddf..a0e7916 100644 --- a/_saves/Eustia_autoSave +++ b/_saves/Eustia_autoSave @@ -1 +1 @@ -N4IgZgNg9lBOCSATEAuEBnALrApjzADAIwgA0IAFjrFKqAJYC2AhgOY6qXVQB0A7jgBGABzIhmAOybNMHFGGYR0OchOaM5IAMLMmYiADdURchWEsAHsYI3TolERsFyLNZesvJzVM/GYA1h4giDhgQYwhYQ6+jFASOACePuQ4Fva+OACOAK705jgSmKgA2gC65PSyjOh0IADGcViSmDUooIIwgQ7kkEkOAL7kmDBKdIMgWbnCrcD949B1tYj0uHWY9HGc2aLkVigArOR9AJzjkGwzIJU4jAAi+LoQqNjZKiDZygBC+AIFADL0VgUIooF5vAD64OUOEQkNQABYAGwAdgAHAAmDH7Y7kSGwSSw8EIlEYrE48S4ZitYqgNyaAA62XhOAIgkZ+zq8PRYhY0xK2l0jAoUA0IFKg1p6gZTJZbOyHK5POYfJQxRAACt6NlWNlJGKJSA6ZxGczWezOdzPCq1QBpAAqADV9aRJaK0IzkejEeiPeiwCQrdSQPaHQAxbnil2GqXG7Ke72+/1K60gVhQCCIfyJZ2u6WmuUKy0gXlBwT0CgfbK0SO52Om5jmxWB/ma5hQTCSVg56NukAmlkN+UW5NB9BUCSsCQGYWims9vMDxtFkv8sf0Kczjhzo3uuNen17pPN1Ua+gwtvdnd9vcJw8B4vK0fYPCEe9YXD4AhFnWduoUTtiD+E5/p2RYWPQbbgZ2xBiFBUBQROX6wRB8EQROADMl4xigEjZBAEDHmqCT0DkJDbthuH4YRIDETkEYGjulEEQ+Ka0dkmHkW6THUWx8JYVxeHMSuJ5sfs/FyNxLFBmxiLiagknCURJFxnJOGCTxymoqpCmPvybHHNp6lSXpymOPq5QYP4eSoAoShvP+sDICgviQg5iBaOmcBwmguDILi4LXIwAAS66YN5ZT+RAODMAYOB/FAdTebM/kGPQ6DXIStTvi+MGgrArzjIIPx4BIACCmAdnU/i3DI3hqVRICQswOD0OFFn/s+TnouQ6BWfhySWfQ+EAHLYdeiL7CyYiQss6DMIIUWZW0GDPp+JCqsURDoui5RlOKZzptAAiwNSFlYDgKrdQ+AQDegwh4E5jg9dgQRsPQQShUEDQSOEb2LPIijKM9MhpesdSXMMHYQHaTByEQaIYsino8PsTgEIiRCoqi5B1NksCwDDbqIqiSLwjw5JmANggyJgUXGC4cTZs5KRpFTNNRTVLDsANwhQGlcSc2wcgZBY2DMIL3PM8WUCxbcKw4GsEB9FdgISHAOAAMqyJdwOwCCyJbcixw8PCcymMwjmcCOWWra+tS8iUzhO6Qzuuy7pDFAAtCY3ukL7/smM4Ad+z7ochyH5Su/t5A0NksicH88AOqwAAapXqqVtylZkrAAF6lQAog6ADipUSFnfzqgAsgAigAvA3YgGIorwzOMsUnRsP27scODoYg7KCKjHrMMcA/ZMcX4EOyqL7PC5oEGAjLHBjYTkDq9BOcEdRgOh6KCFj4LMJjYDgvCzXHEfiJgIlYDHKi6HIogiBEIizDogQYjrG68PoYixPIn2OhFe6JTZAA= \ No newline at end of file +N4IgZgNg9lBOCSATEAuEBnALrApjzADAIwgA0IAFjrFKqAJYC2AhgOY6qXVQB0A7jgBGABzIhmAOybNMHFGGYR0OchOaM5IAMLMmYiADdURchWEsAHqgCct66dEoiBF+RZrLqALQmQ75qgE5DIA1sauIIg4YOFBflExKHHownjISW5QEjgAnoHkOBaOcTgAjgCu9OY4EpioANoAuuT0sozodCAAxllYkpgdKKCCMGFO5JB5TgC+5JgwSnSzIGWVwoOg6HxwiCQzy9BdnYj0uF2Y9Fmc5aLkVigArORTzsuQbBsgrTiMACL4uggqGw5RUIHKygAQvgBDUADL0VgUOooEFggD66OUOEQmOMAHYAGwEawADgATOSACxxTGwSS49EE4lkyk04K4ZiDeqgDyaAA65SpOAIgkFDy6VPJYhY6wa2l0jAoUA0IEas156gFQpFYvKEqlMuYcpQ9RAACt6OVWOVJGqNSA+ZxBcLReLJdK3MbuSAANIAFQAavbSJrVWhBfjyYTyZHyWASF6TWaA4GAGLS9Whx1a53lKMxuMJo3JkCsKAQRAhXIhsPa116g2evze+WCegUCHlWhZut513Md2GpM+y3MKCYSSsWs58MgF0iwf6j0ln3oKgSVgSAzK1W92f1xdD5uytcUejb3ccfdOiP56Ox+/Fkfyy048cz2/z++Fp+JlullguD4MQYhAXghDNjaU5dBQU5iNBm6wVOzYWPQ45oVOoF3OhUCYZuBCobh+GsAAzJ+uYoBI5QQBAL6miAOT0BUJA3pR1G0fRZpMRUmYOreHF0QBPo8eU5FseGglcYxzFChRkk0UJp7yqJDzyXIUnCSpsmEupqCacpDGifielUYp0miaSpkGa2RmydY1nmVpdksQQ9rNBgIRVKgChKGCcGwOktLogFiBaBWcB4mguDIOQmLfIwAASF6YFFTRxeiEA4MwBg4HCUBdFFwDLJiBj0Og3yMp04EgXsaLLIIMJ4BIACCmCTl0IS/DIARmZxICYswOD0GlHmYic6DMIIWVVUMGDYBBoGmvURCkQ8zRNOqbwVtAAiwNyHlYDgJq+H0FxYPQXSfPMk4QP6TByOSDxEEQUpRjwhJ2C91hPN05SwLA93hkQDxUtYPCkXYUNQ4SDj5CAggyJgWXw4wWQ1hkKxFPDiPtVl3UsOw8PCFA5VZATbByCUFjYMwFNE5jaO5b8pw4OcEBTHEiISHAOAAMqyCaySTrAKKElSDykTwVLTMsoWcKu1ULbVnSyg0QQa6Qmva1ruv1D4pAG0bJgG0ExuGyblsWxbzQa1t5A0OUsicL6UAZloVKsAAvGIBiKKCGzLLl+2XBIebWDgpGIOKggPAQkbMNY0flNYhHx/qpKg+6BBgIK1iEkQMTkDa9DpCA5LMIghKEog1iFYgYBgFS6JUqSifooIVKEmA6JgIgU0EDgNJV3gYgXMD+KkficfWKRBBSi40xAA== diff --git a/_server/MotaAction.g4 b/_server/MotaAction.g4 index 296d8a1..10b3ad5 100644 --- a/_server/MotaAction.g4 +++ b/_server/MotaAction.g4 @@ -958,6 +958,8 @@ action | removeMouse_s | drawWarning_s | addPop_s + | setq_s + | setcgs_s | animationDrawable_s | over_s | overlist_s @@ -2241,12 +2243,12 @@ setanimate_s tooltip : setanimate:设置帧动画/特效(此项仅储存,不播放) helpUrl : /_docs/#/instruction default : ["sword","","",192,192,60] -colour : this.soundColor +colour : this.imageColor IntString_0 = IntString_0 ? (', "px": '+IntString_0+'') : ''; IntString_1 = IntString_1 ? (', "py": '+IntString_1+'') : ''; var imageList=animateDrawableimage_0?',"imageList": [\n'+animateDrawableimage_0.slice(0,-1)+'\n]':'' var soundList=animateDrawablesound_0?',"soundList": [\n'+animateDrawablesound_0.slice(0,-1)+'\n]':'' -var code = '{"type": "setanimate", "name": "'+EvalString_0+'",'+IntString_0+IntString_1+' "width": '+IntString_2+', "height": '+IntString_3+', "allFarme": '+IntString_4+imageList+soundList+'},\n'; +var code = '{"type": "setanimate", "name": "'+EvalString_0+'"'+IntString_0+IntString_1+' ,"width": '+IntString_2+', "height": '+IntString_3+', "allFarme": '+IntString_4+imageList+soundList+'},\n'; return code; */; @@ -2320,9 +2322,9 @@ deleteanimate_s /* deleteanimate_s tooltip : deleteanimate:删除储存的帧动画 helpUrl : /_docs/#/instruction -default : [""] +default : ["zone"] -colour : this.soundColor +colour : this.imageColor var code = '{"type": "deleteanimate", "name": "'+EvalString_0+'"},\n'; return code; @@ -2336,7 +2338,7 @@ tooltip : playanimate:播放帧动画,选择跟随勇士后x、y将失效改 helpUrl : /_docs/#/instruction default : ["zone","","",false,"",""] -colour : this.soundColor +colour : this.imageColor IntString_0 = IntString_0 ? (', "x": '+IntString_0+'') : ''; IntString_1 = IntString_1 ? (', "y": '+IntString_1+'') : ''; if(EvalString_1&&!/^(0|([1-9][0-9]*))(\.[\d]+)?$/.test(EvalString_1))throw new Error("此项仅能填写小数、整数或不填"); @@ -2354,7 +2356,7 @@ clearanimate_s tooltip : clearanimate:清空正在播放的帧动画 helpUrl : /_docs/#/instruction -colour : this.soundColor +colour : this.imageColor var code = '{"type": "clearanimate"},\n'; return code; @@ -2402,7 +2404,7 @@ stopAnimate_s tooltip : stopAnimate:停止所有动画 helpUrl : /_docs/#/instruction default : [false] -colour : this.soundColor +colour : this.imageColor Bool_0 = Bool_0?', "doCallback": true':''; var code = '{"type": "stopAnimate"'+Bool_0+'},\n'; return code; @@ -2596,6 +2598,35 @@ var code = '{"type": "rotateImage", "code": '+NInt_0+loc+', "angle": '+NInt_1+Mo return code; */; +setq_s + : '设置任务目标楼层'IdString?'不填为清空当前任务指引' Newline + +/* setq_s +tooltip : setq:设置任务目标楼层(显示在小地图) +helpUrl : /_docs/#/instruction +default : [""] +allFloorIds : ['IdString_0'] +colour : this.soundColor +IdString_0 = IdString_0 ? (', "id": "'+IdString_0+'"') : ''; +var code = '{"type": "setq"'+IdString_0+'},\n'; +return code; +*/; + + +setcgs_s + : 'cg回廊获取cg 文件名'EvalString?'不填为清空cg获取记录' Newline + +/* setcgs_s +tooltip : setcgs:cg回廊中的cg获取 +helpUrl : /_docs/#/instruction +default : [""] +allImages : ['EvalString_0'] +colour : this.imageColor +EvalString_0 = EvalString_0 ? (', "img": "'+EvalString_0+'"') : ''; +var code = '{"type": "setcgs"'+EvalString_0+'},\n'; +return code; +*/; + scaleImage_s : '图片放缩' '图片编号' NInt '中心点像素' 'x' PosString? 'y' PosString? '移动方式' MoveMode_List BGNL? '放缩比例' Number '动画时间' Int '不等待执行完毕' Bool Newline @@ -2615,6 +2646,7 @@ var code = '{"type": "scaleImage", "code": '+NInt_0+loc+', "scale": '+Number_0+M return code; */; + animationDrawable_s : '帧动画' '总显示帧数' IntString '底色' ColorString? Colour '底色不透明度' IntString? BGNL?Newline '图片序列(同一帧后面覆盖先前的,默认起始帧为0,结束帧为最后一帧)'BGNL?Newline @@ -4596,8 +4628,8 @@ EnemyPoint_List /*EnemyPoint_List ['hp','atk','def','money','exp','point','name']*/; Equip_List - : '生命'|'生命上限'|'攻击'|'防御'|'护盾'|'魔力'|'魔力上限' - /*Equip_List ['hp','hpmax','atk','def','mdef','mana','manamax']*/; + : '生命'|'生命上限'|'攻击'|'防御'|'法强'|'魔力'|'魔力上限'|'速度' + /*Equip_List ['hp','hpmax','atk','def','mdef','mana','manamax','speed']*/; Key_List : '黄钥匙'|'蓝钥匙'|'红钥匙'|'绿钥匙'|'铁门钥匙' diff --git a/_server/MotaActionParser.js b/_server/MotaActionParser.js index 68e1d9c..06c2081 100644 --- a/_server/MotaActionParser.js +++ b/_server/MotaActionParser.js @@ -614,6 +614,12 @@ MotaActionParser = function () { this.next, ]); break; + case "setq": + this.next = MotaActionBlocks["setq_s"].xmlText([data.id, this.next]); + break; + case "setcgs": + this.next = MotaActionBlocks["setcgs_s"].xmlText([data.img, this.next]); + break; case "comment": // 注释 this.next = MotaActionBlocks["comment_s"].xmlText([ this.EvalString_Multi(data.text), @@ -645,6 +651,7 @@ MotaActionParser = function () { this.next, ]); break; + case "addPop": this.next = MotaActionBlocks["addPop_s"].xmlText([ data.value, @@ -770,18 +777,18 @@ MotaActionParser = function () { break; case "deleteanimate": this.next = MotaActionBlocks["deleteanimate_s"].xmlText([ - this.name, + data.name, this.next, ]); break; case "playanimate": this.next = MotaActionBlocks["playanimate_s"].xmlText([ - this.name, - this.x, - this.y, - this.hero, - this.scalex, - this.scaley, + data.name, + data.x, + data.y, + data.hero, + data.scalex, + data.scaley, this.next, ]); break; @@ -840,6 +847,7 @@ MotaActionParser = function () { this.next, ]); break; + case "tip": this.next = MotaActionBlocks["tip_s"].xmlText([ data.text, diff --git a/_server/config.json b/_server/config.json index 2f57734..79984e9 100644 --- a/_server/config.json +++ b/_server/config.json @@ -1 +1 @@ -{"viewportLoc":[0,0],"editorLastFloorId":"shinvhome","lastUsed":[{"idnum":210,"id":"skeletonWarrior","images":"enemys","y":9,"recent":1735825145197,"frequent":4},{"idnum":21,"id":"yellowKey","images":"items","y":0,"recent":1735824906066,"frequent":14},{"idnum":81,"id":"yellowDoor","images":"animates","y":4,"recent":1735824901122,"frequent":26},{"idnum":214,"id":"zombieKnight","images":"enemys","y":13,"recent":1735824888165,"frequent":2},{"idnum":82,"id":"blueDoor","images":"animates","y":5,"recent":1735824878838,"frequent":4},{"idnum":32,"id":"bluePotion","images":"items","y":21,"recent":1735824871469,"frequent":2},{"idnum":28,"id":"blueGem","images":"items","y":17,"recent":1735824867878,"frequent":6},{"idnum":27,"id":"redGem","images":"items","y":16,"recent":1735824864181,"frequent":5},{"idnum":22,"id":"blueKey","images":"items","y":1,"recent":1735824852246,"frequent":4},{"idnum":140,"id":"autotile4","images":"autotile","y":0,"recent":1735824840165,"frequent":138},{"idnum":209,"id":"skeleton","images":"enemys","y":8,"recent":1735824813505,"frequent":2},{"idnum":94,"id":"rightPortal","images":"animates","y":25,"recent":1735824733893,"frequent":6},{"idnum":92,"id":"leftPortal","images":"animates","y":24,"recent":1735824084823,"frequent":2},{"idnum":91,"id":"upPortal","images":"animates","y":26,"recent":1735821889246,"frequent":2},{"idnum":85,"id":"specialDoor","images":"animates","y":8,"recent":1735820976103,"frequent":3},{"idnum":93,"id":"downPortal","images":"animates","y":23,"recent":1735820969951,"frequent":2},{"idnum":89,"id":"portal","images":"animates","y":17,"recent":1735820958612,"frequent":1},{"idnum":26,"id":"bigKey","images":"items","y":6,"recent":1735820920269,"frequent":1},{"idnum":34,"id":"yellowPotion","images":"items","y":23,"recent":1735820909149,"frequent":1},{"idnum":33,"id":"greenPotion","images":"items","y":22,"recent":1735820906301,"frequent":1},{"idnum":83,"id":"redDoor","images":"animates","y":6,"recent":1735820844323,"frequent":2},{"idnum":247,"id":"magicMaster","images":"enemys","y":46,"recent":1735820830425,"frequent":1},{"idnum":20160,"id":"X20160","images":"5.png","x":0,"y":20,"isTile":true,"recent":1735398503013,"frequent":2},{"idnum":20168,"id":"X20168","images":"5.png","x":0,"y":21,"isTile":true,"recent":1735398496973,"frequent":3},{"idnum":20176,"id":"X20176","images":"5.png","x":0,"y":22,"isTile":true,"recent":1735398485125,"frequent":1},{"idnum":71742,"id":"X71742","images":"11.png","x":6,"y":217,"isTile":true,"recent":1735398452693,"frequent":1},{"idnum":71750,"id":"X71750","images":"11.png","x":6,"y":218,"isTile":true,"recent":1735398448325,"frequent":1},{"idnum":71751,"id":"X71751","images":"11.png","x":7,"y":218,"isTile":true,"recent":1735398443645,"frequent":1},{"idnum":71783,"id":"X71783","images":"11.png","x":7,"y":222,"isTile":true,"recent":1735398426909,"frequent":7},{"idnum":71799,"id":"X71799","images":"11.png","x":7,"y":224,"isTile":true,"recent":1735398421365,"frequent":5},{"idnum":71826,"id":"X71826","images":"11.png","x":2,"y":228,"isTile":true,"recent":1735398415661,"frequent":2},{"idnum":71818,"id":"X71818","images":"11.png","x":2,"y":227,"isTile":true,"recent":1735398413269,"frequent":3},{"idnum":224,"id":"swordsman","images":"enemys","y":23,"recent":1735398341974,"frequent":6},{"idnum":71842,"id":"X71842","images":"11.png","x":2,"y":230,"isTile":true,"recent":1735398315069,"frequent":1},{"idnum":71834,"id":"X71834","images":"11.png","x":2,"y":229,"isTile":true,"recent":1735398312437,"frequent":1},{"idnum":110114,"id":"X110114","images":"C4.png","x":2,"y":14,"isTile":true,"recent":1735398246502,"frequent":6},{"idnum":110122,"id":"X110122","images":"C4.png","x":2,"y":15,"isTile":true,"recent":1735398239998,"frequent":1},{"idnum":110028,"id":"X110028","images":"C4.png","x":4,"y":3,"isTile":true,"recent":1735398198709,"frequent":2},{"idnum":110020,"id":"X110020","images":"C4.png","x":4,"y":2,"isTile":true,"recent":1735398191398,"frequent":2},{"idnum":71791,"id":"X71791","images":"11.png","x":7,"y":223,"isTile":true,"recent":1735398163774,"frequent":3},{"idnum":71785,"id":"X71785","images":"11.png","x":1,"y":223,"isTile":true,"recent":1735398120734,"frequent":2},{"idnum":71784,"id":"X71784","images":"11.png","x":0,"y":223,"isTile":true,"recent":1735398118318,"frequent":3},{"idnum":71793,"id":"X71793","images":"11.png","x":1,"y":224,"isTile":true,"recent":1735398115446,"frequent":2},{"idnum":71792,"id":"X71792","images":"11.png","x":0,"y":224,"isTile":true,"recent":1735398113142,"frequent":2},{"idnum":71787,"id":"X71787","images":"11.png","x":3,"y":223,"isTile":true,"recent":1735398102326,"frequent":1},{"idnum":71786,"id":"X71786","images":"11.png","x":2,"y":223,"isTile":true,"recent":1735398099430,"frequent":1},{"idnum":71795,"id":"X71795","images":"11.png","x":3,"y":224,"isTile":true,"recent":1735398097359,"frequent":1},{"idnum":71794,"id":"X71794","images":"11.png","x":2,"y":224,"isTile":true,"recent":1735398094982,"frequent":1},{"idnum":130006,"id":"X130006","images":"C2.png","x":6,"y":0,"isTile":true,"recent":1735398082894,"frequent":3},{"idnum":130011,"id":"X130011","images":"C2.png","x":3,"y":1,"isTile":true,"recent":1735398078792,"frequent":2},{"idnum":71817,"id":"X71817","images":"11.png","x":1,"y":227,"isTile":true,"recent":1735398027294,"frequent":3},{"idnum":71837,"id":"X71837","images":"11.png","x":5,"y":229,"isTile":true,"recent":1735398013126,"frequent":1},{"idnum":71829,"id":"X71829","images":"11.png","x":5,"y":228,"isTile":true,"recent":1735398008166,"frequent":1},{"idnum":71821,"id":"X71821","images":"11.png","x":5,"y":227,"isTile":true,"recent":1735398005430,"frequent":1},{"idnum":71836,"id":"X71836","images":"11.png","x":4,"y":229,"isTile":true,"recent":1735397997622,"frequent":1},{"idnum":71828,"id":"X71828","images":"11.png","x":4,"y":228,"isTile":true,"recent":1735397993455,"frequent":1},{"idnum":71820,"id":"X71820","images":"11.png","x":4,"y":227,"isTile":true,"recent":1735397989903,"frequent":1},{"idnum":30217,"id":"X30217","images":"4.png","x":1,"y":27,"isTile":true,"recent":1735397944838,"frequent":3},{"idnum":110012,"id":"X110012","images":"C4.png","x":4,"y":1,"isTile":true,"recent":1735397929366,"frequent":2},{"idnum":100485,"id":"X100485","images":"Outside_B.png","x":5,"y":20,"isTile":true,"recent":1735397919927,"frequent":2},{"idnum":100436,"id":"X100436","images":"Outside_B.png","x":4,"y":18,"isTile":true,"recent":1735397880486,"frequent":1},{"idnum":100437,"id":"X100437","images":"Outside_B.png","x":5,"y":18,"isTile":true,"recent":1735397877086,"frequent":1},{"idnum":100461,"id":"X100461","images":"Outside_B.png","x":5,"y":19,"isTile":true,"recent":1735397868606,"frequent":1},{"idnum":100460,"id":"X100460","images":"Outside_B.png","x":4,"y":19,"isTile":true,"recent":1735397843448,"frequent":2},{"idnum":100484,"id":"X100484","images":"Outside_B.png","x":4,"y":20,"isTile":true,"recent":1735397840545,"frequent":2},{"idnum":40136,"id":"X40136","images":"3.png","x":0,"y":17,"isTile":true,"recent":1735397799150,"frequent":1},{"idnum":40144,"id":"X40144","images":"3.png","x":0,"y":18,"isTile":true,"recent":1735397796038,"frequent":2},{"idnum":30227,"id":"X30227","images":"4.png","x":3,"y":28,"isTile":true,"recent":1735397775591,"frequent":2},{"idnum":30214,"id":"X30214","images":"4.png","x":6,"y":26,"isTile":true,"recent":1735397768303,"frequent":1},{"idnum":30218,"id":"X30218","images":"4.png","x":2,"y":27,"isTile":true,"recent":1735397761062,"frequent":1},{"idnum":120041,"id":"X120041","images":"C3.png","x":1,"y":5,"isTile":true,"recent":1735397710494,"frequent":1},{"idnum":120042,"id":"X120042","images":"C3.png","x":2,"y":5,"isTile":true,"recent":1735397702167,"frequent":2},{"idnum":120006,"id":"X120006","images":"C3.png","x":6,"y":0,"isTile":true,"recent":1735397659951,"frequent":5},{"idnum":120014,"id":"X120014","images":"C3.png","x":6,"y":1,"isTile":true,"recent":1735397644591,"frequent":4},{"idnum":120090,"id":"X120090","images":"C3.png","x":2,"y":11,"isTile":true,"recent":1735397629759,"frequent":3},{"idnum":120150,"id":"X120150","images":"C3.png","x":6,"y":18,"isTile":true,"recent":1735397613207,"frequent":3},{"idnum":120166,"id":"X120166","images":"C3.png","x":6,"y":20,"isTile":true,"recent":1735397574639,"frequent":1},{"idnum":140170,"id":"X140170","images":"C1.png","x":2,"y":21,"isTile":true,"recent":1735397516295,"frequent":1},{"idnum":110119,"id":"X110119","images":"C4.png","x":7,"y":14,"isTile":true,"recent":1735397434752,"frequent":3},{"idnum":80083,"id":"X80083","images":"6.png","x":3,"y":10,"isTile":true,"recent":1735397403120,"frequent":6},{"idnum":80082,"id":"X80082","images":"6.png","x":2,"y":10,"isTile":true,"recent":1735397393215,"frequent":2},{"idnum":71824,"id":"X71824","images":"11.png","x":0,"y":228,"isTile":true,"recent":1735397302354,"frequent":1},{"idnum":71816,"id":"X71816","images":"11.png","x":0,"y":227,"isTile":true,"recent":1735397300089,"frequent":1},{"idnum":71825,"id":"X71825","images":"11.png","x":1,"y":228,"isTile":true,"recent":1735397296728,"frequent":1},{"idnum":71841,"id":"X71841","images":"11.png","x":1,"y":230,"isTile":true,"recent":1735397274905,"frequent":1},{"idnum":71840,"id":"X71840","images":"11.png","x":0,"y":230,"isTile":true,"recent":1735397272160,"frequent":1},{"idnum":71833,"id":"X71833","images":"11.png","x":1,"y":229,"isTile":true,"recent":1735397269433,"frequent":1},{"idnum":71832,"id":"X71832","images":"11.png","x":0,"y":229,"isTile":true,"recent":1735397266704,"frequent":1},{"idnum":71815,"id":"X71815","images":"11.png","x":7,"y":226,"isTile":true,"recent":1735397232288,"frequent":1},{"idnum":71807,"id":"X71807","images":"11.png","x":7,"y":225,"isTile":true,"recent":1735397229624,"frequent":1},{"idnum":71827,"id":"X71827","images":"11.png","x":3,"y":228,"isTile":true,"recent":1735397220728,"frequent":1},{"idnum":71819,"id":"X71819","images":"11.png","x":3,"y":227,"isTile":true,"recent":1735397218496,"frequent":1},{"idnum":120173,"id":"X120173","images":"C3.png","x":5,"y":21,"isTile":true,"recent":1735397183385,"frequent":3},{"idnum":120174,"id":"X120174","images":"C3.png","x":6,"y":21,"isTile":true,"recent":1735397125953,"frequent":6},{"idnum":120134,"id":"X120134","images":"C3.png","x":6,"y":16,"isTile":true,"recent":1735396971049,"frequent":1},{"idnum":130173,"id":"X130173","images":"C2.png","x":5,"y":21,"isTile":true,"recent":1735396958897,"frequent":1},{"idnum":120109,"id":"X120109","images":"C3.png","x":5,"y":13,"isTile":true,"recent":1735396928298,"frequent":2},{"idnum":120117,"id":"X120117","images":"C3.png","x":5,"y":14,"isTile":true,"recent":1735396877690,"frequent":1},{"idnum":120125,"id":"X120125","images":"C3.png","x":5,"y":15,"isTile":true,"recent":1735396864194,"frequent":6},{"idnum":70169,"id":"X70169","images":"11.png","x":1,"y":21,"isTile":true,"recent":1735396825666,"frequent":3},{"idnum":70161,"id":"X70161","images":"11.png","x":1,"y":20,"isTile":true,"recent":1735396814418,"frequent":3},{"idnum":70145,"id":"X70145","images":"11.png","x":1,"y":18,"isTile":true,"recent":1735396802466,"frequent":14},{"idnum":70146,"id":"X70146","images":"11.png","x":2,"y":18,"isTile":true,"recent":1735396788810,"frequent":1},{"idnum":70144,"id":"X70144","images":"11.png","x":0,"y":18,"isTile":true,"recent":1735396782475,"frequent":4},{"idnum":100386,"id":"X100386","images":"Outside_B.png","x":2,"y":16,"isTile":true,"recent":1735396757386,"frequent":1},{"idnum":100362,"id":"X100362","images":"Outside_B.png","x":2,"y":15,"isTile":true,"recent":1735396754546,"frequent":1},{"idnum":100385,"id":"X100385","images":"Outside_B.png","x":1,"y":16,"isTile":true,"recent":1735396751066,"frequent":1},{"idnum":100384,"id":"X100384","images":"Outside_B.png","x":0,"y":16,"isTile":true,"recent":1735396747826,"frequent":1},{"idnum":100361,"id":"X100361","images":"Outside_B.png","x":1,"y":15,"isTile":true,"recent":1735396745106,"frequent":2},{"idnum":100360,"id":"X100360","images":"Outside_B.png","x":0,"y":15,"isTile":true,"recent":1735396742682,"frequent":3},{"idnum":90196,"id":"X90196","images":"12.png","x":4,"y":24,"isTile":true,"recent":1735396698234,"frequent":1},{"idnum":90195,"id":"X90195","images":"12.png","x":3,"y":24,"isTile":true,"recent":1735396695530,"frequent":1},{"idnum":90194,"id":"X90194","images":"12.png","x":2,"y":24,"isTile":true,"recent":1735396691098,"frequent":1},{"idnum":90187,"id":"X90187","images":"12.png","x":3,"y":23,"isTile":true,"recent":1735396687866,"frequent":3},{"idnum":90186,"id":"X90186","images":"12.png","x":2,"y":23,"isTile":true,"recent":1735396672410,"frequent":1},{"idnum":31,"id":"redPotion","images":"items","y":20,"recent":1735396611866,"frequent":7},{"idnum":221,"id":"yellowGateKeeper","images":"enemys","y":20,"recent":1735396537794,"frequent":4},{"idnum":222,"id":"blueGateKeeper","images":"enemys","y":21,"recent":1735396534626,"frequent":3},{"idnum":226,"id":"yellowKnight","images":"enemys","y":25,"recent":1735396460524,"frequent":1},{"idnum":225,"id":"soldier","images":"enemys","y":24,"recent":1735396456036,"frequent":1},{"idnum":326,"id":"tulipFairy","images":"enemys","y":72,"recent":1735396229196,"frequent":1},{"idnum":141,"id":"autotile8","images":"autotile","y":0,"recent":1735391328901,"frequent":2},{"idnum":30,"id":"yellowGem","images":"items","y":19,"recent":1735391294213,"frequent":1},{"idnum":44,"id":"shield5","images":"items","y":59,"recent":1735391193096,"frequent":1},{"idnum":138,"id":"blueTrader","images":"npcs","y":13,"recent":1735391190680,"frequent":1},{"idnum":43,"id":"sword5","images":"items","y":54,"recent":1735391188576,"frequent":1}]} \ No newline at end of file +{ "viewportLoc": [0, 0], "editorLastFloorId": "jiedao" } diff --git a/_server/editor_blocklyconfig.js b/_server/editor_blocklyconfig.js index be72015..6c99618 100644 --- a/_server/editor_blocklyconfig.js +++ b/_server/editor_blocklyconfig.js @@ -1,705 +1,908 @@ -editor_blocklyconfig=(function(){ -// start mark sfergsvae +editor_blocklyconfig = function () { + // start mark sfergsvae + (function () { + var getCategory = function (name, custom) { + for (var node of document.getElementById("toolbox").children) { + if (node.getAttribute("name") == name) return node; + } + var node = document.createElement("category"); + node.setAttribute("name", name); + if (custom) node.setAttribute("custom", custom); + document.getElementById("toolbox").appendChild(node); + return node; + }; - -(function(){ - var getCategory = function(name,custom){ - for(var node of document.getElementById('toolbox').children) { - if(node.getAttribute('name')==name) return node; - } - var node = document.createElement('category'); - node.setAttribute('name',name); - if(custom)node.setAttribute('custom',custom); - document.getElementById('toolbox').appendChild(node); - return node; - } - - var toolboxObj = { - '入口方块':[ - '', - MotaActionFunctions.actionParser.parse([ - "欢迎使用事件编辑器", - "本事件触发一次后会消失", - {"type": "hide", "time": 500}, - ],'event'), - MotaActionFunctions.actionParser.parse({ - "condition": "flag:__door__===2", - "currentFloor": true, - "priority": 0, - "delayExecute": false, - "multiExecute": false, - "data": [ - {"type": "openDoor", "loc": [10,5]} - ], - },'autoEvent'), - MotaActionBlocks['changeFloor_m'].xmlText(), - MotaActionFunctions.actionParser.parse([{ - "id": "shop1", - "text": "\t[贪婪之神,moneyShop]勇敢的武士啊, 给我${20+2*flag:shop1}金币就可以:", - "textInList": "1F金币商店", - "choices": [ - {"text": "生命+800", "need": "status:money>=20+2*flag:shop1", "action": [ - {"type": "comment", "text": "新版商店中需要手动扣减金币和增加访问次数"}, - {"type": "setValue", "name": "status:money", "operator": "-=", "value": "20+2*flag:shop1"}, - {"type": "setValue", "name": "flag:shop1", "operator": "+=", "value": "1"}, - {"type": "setValue", "name": "status:hp", "operator": "+=", "value": "800"} - ]} - ] - },{ - "id": "itemShop", - "item": true, - "textInList": "道具商店", - "choices": [ - {"id": "yellowKey", "number": 10, "money": 10} - ] - },{ - "id": "keyShop1", - "textInList": "回收钥匙商店", - "commonEvent": "回收钥匙商店", - "args": "" - }],'shop'), - MotaActionBlocks['common_m'].xmlText(), - MotaActionBlocks['beforeBattle_m'].xmlText(), - MotaActionBlocks['afterBattle_m'].xmlText(), - MotaActionBlocks['afterGetItem_m'].xmlText(), - MotaActionBlocks['afterOpenDoor_m'].xmlText(), - MotaActionBlocks['firstArrive_m'].xmlText(), - MotaActionBlocks['eachArrive_m'].xmlText(), - MotaActionBlocks['level_m'].xmlText(), - MotaActionFunctions.actionParser.parse([ - ['MTx', ''] - ], 'floorPartition'), - MotaActionBlocks['commonEvent_m'].xmlText(), - MotaActionBlocks['item_m'].xmlText(), - MotaActionFunctions.actionParser.parse([ - {"title":"简单", "name": "Easy", "hard": 1, "action": [ - {"type": "comment", "text": "在这里写该难度需执行的事件"} - ]} - ], 'levelChoose'), - MotaActionFunctions.actionParser.parse({ - "type": 0, "value": {"atk": 10}, "percentage": {"speed": 10}, - }, 'equip'), - MotaActionFunctions.actionParser.parse([{ - "name": "bg.jpg", "x": 0, "y": 0, "canvas": "bg" - }], 'floorImage'), - MotaActionFunctions.actionParser.parse({ - "time": 160, "openSound": "door.mp3", "closeSound": "door.mp3", "keys": {"yellowKey": 1, "orangeKey": 1} - }, 'doorInfo'), - MotaActionBlocks['faceIds_m'].xmlText(), - MotaActionBlocks['mainStyle_m'].xmlText(), - MotaActionFunctions.actionParser.parse({ - "背景音乐": "bgm.mp3", "确定": "confirm.mp3", "攻击": "attack.mp3", "背景图": "bg.jpg", "领域": "zone", "文件名": "file.jpg" - }, 'nameMap'), - MotaActionFunctions.actionParser.parse([ - {"name": "hero.png", "width": 32, "height": 32, "prefix": "hero_"}, - ], 'splitImages'), - ], - '显示文字':[ - MotaActionBlocks['text_0_s'].xmlText(), - MotaActionBlocks['text_1_s'].xmlText(), - MotaActionFunctions.actionParser.parseList("\t[小妖精,fairy]\f[fairy.png,0,0]欢迎使用事件编辑器(双击方块可直接预览)"), - MotaActionBlocks['moveTextBox_s'].xmlText(), - MotaActionBlocks['clearTextBox_s'].xmlText(), - MotaActionBlocks['comment_s'].xmlText(), - MotaActionBlocks['autoText_s'].xmlText(), - MotaActionBlocks['scrollText_s'].xmlText(), - MotaActionBlocks['setText_s'].xmlText(), - MotaActionBlocks['tip_s'].xmlText(), - MotaActionBlocks['confirm_s'].xmlText(), - MotaActionBlocks['choices_s'].xmlText([ - '选择剑或者盾','流浪者','man',0,'',MotaActionBlocks['choicesContext'].xmlText([ - '剑','','',null,'','',MotaActionFunctions.actionParser.parseList([{"type": "openDoor", "loc": [3,3]}]), - ]) - ]), - MotaActionBlocks['win_s'].xmlText(), - MotaActionBlocks['lose_s'].xmlText(), - MotaActionBlocks['restart_s'].xmlText(), - ], - '数据相关':[ - MotaActionBlocks['setValue_s'].xmlText([ - MotaActionBlocks['idIdList_e'].xmlText(['status','生命']), '=', '', false - ]), - MotaActionBlocks['setEnemy_s'].xmlText(), - MotaActionBlocks['setEnemyOnPoint_s'].xmlText(), - MotaActionBlocks['resetEnemyOnPoint_s'].xmlText(), - MotaActionBlocks['moveEnemyOnPoint_s'].xmlText(), - MotaActionBlocks['moveEnemyOnPoint_1_s'].xmlText(), - MotaActionBlocks['setEquip_s'].xmlText(), - MotaActionBlocks['setFloor_s'].xmlText(), - MotaActionBlocks['setGlobalAttribute_s'].xmlText(), - MotaActionBlocks['setGlobalValue_s'].xmlText(), - MotaActionBlocks['setGlobalFlag_s'].xmlText(), - MotaActionBlocks['setNameMap_s'].xmlText(), - MotaActionBlocks['input_s'].xmlText(), - MotaActionBlocks['input2_s'].xmlText(), - MotaActionBlocks['update_s'].xmlText(), - MotaActionBlocks['moveAction_s'].xmlText(), - MotaActionBlocks['changeFloor_s'].xmlText(), - MotaActionBlocks['changePos_s'].xmlText(), - MotaActionBlocks['battle_s'].xmlText(), - MotaActionBlocks['useItem_s'].xmlText(), - MotaActionBlocks['loadEquip_s'].xmlText(), - MotaActionBlocks['unloadEquip_s'].xmlText(), - MotaActionBlocks['openShop_s'].xmlText(), - MotaActionBlocks['disableShop_s'].xmlText(), - MotaActionBlocks['setHeroIcon_s'].xmlText(), - MotaActionBlocks['follow_s'].xmlText(), - MotaActionBlocks['unfollow_s'].xmlText(), - ], - '地图处理':[ - MotaActionBlocks['battle_1_s'].xmlText(), - MotaActionBlocks['openDoor_s'].xmlText(), - MotaActionBlocks['closeDoor_s'].xmlText(), - MotaActionBlocks['show_s'].xmlText(), - MotaActionBlocks['hide_s'].xmlText(), - MotaActionBlocks['setBlock_s'].xmlText(), - MotaActionBlocks['setBlockOpacity_s'].xmlText(), - MotaActionBlocks['setBlockFilter_s'].xmlText(), - MotaActionBlocks['turnBlock_s'].xmlText(), - MotaActionBlocks['moveHero_s'].xmlText(), - MotaActionBlocks['move_s'].xmlText(), - MotaActionBlocks['jumpHero_s'].xmlText(), - MotaActionBlocks['jumpHero_1_s'].xmlText(), - MotaActionBlocks['jump_s'].xmlText(), - MotaActionBlocks['jump_1_s'].xmlText(), - MotaActionBlocks['showBgFgMap_s'].xmlText(), - MotaActionBlocks['hideBgFgMap_s'].xmlText(), - MotaActionBlocks['setBgFgBlock_s'].xmlText(), - MotaActionBlocks['showFloorImg_s'].xmlText(), - MotaActionBlocks['hideFloorImg_s'].xmlText(), - ], - '事件控制':[ - MotaActionBlocks['if_1_s'].xmlText(), - MotaActionBlocks['if_s'].xmlText(), - MotaActionFunctions.actionParser.parseList({"type": "switch", "condition": "判别值", "caseList": [ - {"action": [{"type": "comment", "text": "当判别值是值的场合执行此事件"}]}, - {"case": "default", "action": [{"type": "comment", "text": "当没有符合的值的场合执行default事件"}]}, - ]}), - MotaActionFunctions.actionParser.parseList({"type": "for", "name": "temp:A", "from": "0", "to": "12", "step": "1", "data": []}), - MotaActionFunctions.actionParser.parseList({"type": "forEach", "name": "temp:A", "list": ["status:atk","status:def"], "data": []}), - MotaActionBlocks['while_s'].xmlText(), - MotaActionBlocks['dowhile_s'].xmlText(), - MotaActionBlocks['break_s'].xmlText(), - MotaActionBlocks['continue_s'].xmlText(), - MotaActionBlocks['exit_s'].xmlText(), - MotaActionBlocks['trigger_s'].xmlText(), - MotaActionBlocks['insert_1_s'].xmlText(), - MotaActionBlocks['insert_2_s'].xmlText(), - ], - '特效表现':[ - MotaActionBlocks['sleep_s'].xmlText(), - MotaActionFunctions.actionParser.parseList({"type": "wait", "timeout": 0, "data": [ - {"case": "keyboard", "keycode": "13,32", "action": [{"type": "comment", "text": "当按下回车(keycode=13)或空格(keycode=32)时执行此事件\n超时剩余时间会写入flag:timeout"}]}, - {"case": "mouse", "px": [0,32], "py": [0,32], "action": [{"type": "comment", "text": "当点击地图左上角时执行此事件\n超时剩余时间会写入flag:timeout"}]}, - {"case": "condition", "condition": "flag:type==0\n&&flag:keycode==13", "action": [{"type": "comment", "text": "当满足自定义条件时会执行此事件\n超时剩余时间会写入flag:timeout"}]}, - {"case": "timeout", "action": [{"type": "comment", "text": "当超时未操作时执行此事件"}]}, - ]}), - MotaActionBlocks['waitAsync_s'].xmlText(), - MotaActionBlocks['stopAsync_s'].xmlText(), - MotaActionBlocks['vibrate_s'].xmlText(), - MotaActionBlocks['animate_s'].xmlText(), - MotaActionBlocks['animate_1_s'].xmlText(), - MotaActionBlocks['stopAnimate_s'].xmlText(), - MotaActionBlocks['setViewport_s'].xmlText(), - MotaActionBlocks['setViewport_1_s'].xmlText(), - MotaActionBlocks['lockViewport_s'].xmlText(), - MotaActionBlocks['showStatusBar_s'].xmlText(), - MotaActionBlocks['hideStatusBar_s'].xmlText(), - MotaActionBlocks['setHeroOpacity_s'].xmlText(), - MotaActionBlocks['setCurtain_0_s'].xmlText(), - MotaActionBlocks['setCurtain_1_s'].xmlText(), - MotaActionBlocks['screenFlash_s'].xmlText(), - MotaActionBlocks['setWeather_s'].xmlText(), - MotaActionBlocks['callBook_s'].xmlText(), - MotaActionBlocks['callSave_s'].xmlText(), - MotaActionBlocks['autoSave_s'].xmlText(), - MotaActionBlocks['forbidSave_s'].xmlText(), - MotaActionBlocks['callLoad_s'].xmlText(), - ], - '音像处理':[ - MotaActionBlocks['showImage_s'].xmlText(), - MotaActionBlocks['showImage_1_s'].xmlText(), - MotaActionBlocks['hideImage_s'].xmlText(), - MotaActionBlocks['showTextImage_s'].xmlText(), - MotaActionBlocks['moveImage_s'].xmlText(), - MotaActionBlocks['rotateImage_s'].xmlText(), - MotaActionBlocks['scaleImage_s'].xmlText(), - MotaActionBlocks['showGif_s'].xmlText(), - MotaActionBlocks['playBgm_s'].xmlText(), - MotaActionBlocks['pauseBgm_s'].xmlText(), - MotaActionBlocks['resumeBgm_s'].xmlText(), - MotaActionBlocks['loadBgm_s'].xmlText(), - MotaActionBlocks['freeBgm_s'].xmlText(), - MotaActionBlocks['playSound_s'].xmlText(), - MotaActionBlocks['playSound_1_s'].xmlText(), - MotaActionBlocks['stopSound_s'].xmlText(), - MotaActionBlocks['setVolume_s'].xmlText(), - MotaActionBlocks['setBgmSpeed_s'].xmlText(), - ], - 'UI绘制':[ - MotaActionBlocks['previewUI_s'].xmlText(), - MotaActionBlocks['clearMap_s'].xmlText(), - MotaActionBlocks['setAttribute_s'].xmlText(), - MotaActionBlocks['setFilter_s'].xmlText(), - MotaActionBlocks['fillText_s'].xmlText(), - MotaActionBlocks['fillBoldText_s'].xmlText(), - MotaActionBlocks['drawTextContent_s'].xmlText(), - MotaActionBlocks['fillRect_s'].xmlText(), - MotaActionBlocks['strokeRect_s'].xmlText(), - MotaActionBlocks['drawLine_s'].xmlText(), - MotaActionBlocks['drawArrow_s'].xmlText(), - MotaActionBlocks['fillPolygon_s'].xmlText(), - MotaActionBlocks['strokePolygon_s'].xmlText(), - MotaActionBlocks['fillEllipse_s'].xmlText(), - MotaActionBlocks['strokeEllipse_s'].xmlText(), - MotaActionBlocks['fillArc_s'].xmlText(), - MotaActionBlocks['strokeArc_s'].xmlText(), - MotaActionBlocks['drawImage_s'].xmlText(), - MotaActionBlocks['drawImage_1_s'].xmlText(), - MotaActionBlocks['drawIcon_s'].xmlText(), - MotaActionBlocks['drawBackground_s'].xmlText(), - MotaActionBlocks['drawSelector_s'].xmlText(), - MotaActionBlocks['drawSelector_1_s'].xmlText(), - ], - '原生脚本':[ - MotaActionBlocks['function_s'].xmlText(), - MotaActionBlocks['unknown_s'].xmlText(), - ], - '值块':[ - MotaActionBlocks['setValue_s'].xmlText([ - MotaActionBlocks['idIdList_e'].xmlText(['status','生命']), '=', '', false - ]), - MotaActionBlocks['expression_arithmetic_0'].xmlText(), - MotaActionBlocks['idFlag_e'].xmlText(), - MotaActionBlocks['idTemp_e'].xmlText(), - MotaActionBlocks['negate_e'].xmlText(), - MotaActionBlocks['unaryOperation_e'].xmlText(), - MotaActionBlocks['bool_e'].xmlText(), - MotaActionBlocks['idString_e'].xmlText(), - MotaActionBlocks['idIdList_e'].xmlText(), - MotaActionBlocks['idFixedList_e'].xmlText(), - MotaActionBlocks['enemyattr_e'].xmlText(), - MotaActionBlocks['blockId_e'].xmlText(), - MotaActionBlocks['blockNumber_e'].xmlText(), - MotaActionBlocks['blockCls_e'].xmlText(), - MotaActionBlocks['hasEquip_e'].xmlText(), - MotaActionBlocks['equip_e'].xmlText(), - MotaActionBlocks['nextXY_e'].xmlText(), - MotaActionBlocks['isReplaying_e'].xmlText(), - MotaActionBlocks['hasVisitedFloor_e'].xmlText(), - MotaActionBlocks['isShopVisited_e'].xmlText(), - MotaActionBlocks['canBattle_e'].xmlText(), - MotaActionBlocks['damage_e'].xmlText(), - MotaActionBlocks['damage_1_e'].xmlText(), - MotaActionBlocks['rand_e'].xmlText(), - MotaActionBlocks['evalString_e'].xmlText(), - ], - '常见事件模板':[ - '', - MotaActionFunctions.actionParser.parseList({"type": "if", "condition": "!core.musicStatus.bgmStatus", - "true": [ - "\t[系统提示]你当前音乐处于关闭状态,本塔开音乐游戏效果更佳" - ], - "false": [] - }), - '', - MotaActionFunctions.actionParser.parse([ - { - "type": "if", - "condition": "switch:A", - "true": [ - "\t[行商,trader]\b[this]这是购买我的道具后我给玩家的提示。", - { - "type": "comment", - "text": "下一条指令可视情况使用或不使用" - }, - { - "type": "hide", - "remove": true, - "time": 250 - } + var toolboxObj = { + 入口方块: [ + '', + MotaActionFunctions.actionParser.parse( + [ + "欢迎使用事件编辑器", + "本事件触发一次后会消失", + { type: "hide", time: 500 }, ], - "false": [ + "event" + ), + MotaActionFunctions.actionParser.parse( + { + condition: "flag:__door__===2", + currentFloor: true, + priority: 0, + delayExecute: false, + multiExecute: false, + data: [{ type: "openDoor", loc: [10, 5] }], + }, + "autoEvent" + ), + MotaActionBlocks["changeFloor_m"].xmlText(), + MotaActionFunctions.actionParser.parse( + [ { - "type": "confirm", - "text": "我有3把黄钥匙,\n你出50金币就卖给你。", - "yes": [ + id: "shop1", + text: "\t[贪婪之神,moneyShop]勇敢的武士啊, 给我${20+2*flag:shop1}金币就可以:", + textInList: "1F金币商店", + choices: [ { - "type": "if", - "condition": "status:money>=50", - "true": [ + text: "生命+800", + need: "status:money>=20+2*flag:shop1", + action: [ { - "type": "setValue", - "name": "status:money", - "operator": "-=", - "value": "50" + type: "comment", + text: "新版商店中需要手动扣减金币和增加访问次数", }, { - "type": "setValue", - "name": "item:yellowKey", - "operator": "+=", - "value": "3" + type: "setValue", + name: "status:money", + operator: "-=", + value: "20+2*flag:shop1", }, { - "type": "playSound", - "name": "确定", - "stop": true + type: "setValue", + name: "flag:shop1", + operator: "+=", + value: "1", }, { - "type": "setValue", - "name": "switch:A", - "value": "true" - } + type: "setValue", + name: "status:hp", + operator: "+=", + value: "800", + }, ], - "false": [ - { - "type": "playSound", - "name": "操作失败" - }, - "\t[行商,trader]\b[this]你的金币不足!" - ] - } + }, ], - "no": [] - } - ] - } - ], 'event'), - '', - MotaActionFunctions.actionParser.parse([ - { - "type": "comment", - "text": "全地图选中一个点,需要用鼠标或触屏操作" - }, - { - "type": "setValue", - "name": "temp:X", - "value": "status:x" - }, - { - "type": "setValue", - "name": "temp:Y", - "value": "status:y" - }, - { - "type": "tip", - "text": "再次点击闪烁位置确认" - }, - { - "type": "while", - "condition": "true", - "data": [ - { - "type": "drawSelector", - "image": "winskin.png", - "code": 1, - "x": "32*temp:X", - "y": "32*temp:Y", - "width": 32, - "height": 32 }, { - "type": "wait" + id: "itemShop", + item: true, + textInList: "道具商店", + choices: [{ id: "yellowKey", number: 10, money: 10 }], }, { - "type": "if", - "condition": "(flag:type === 1)", - "true": [ + id: "keyShop1", + textInList: "回收钥匙商店", + commonEvent: "回收钥匙商店", + args: "", + }, + ], + "shop" + ), + MotaActionBlocks["common_m"].xmlText(), + MotaActionBlocks["beforeBattle_m"].xmlText(), + MotaActionBlocks["afterBattle_m"].xmlText(), + MotaActionBlocks["afterGetItem_m"].xmlText(), + MotaActionBlocks["afterOpenDoor_m"].xmlText(), + MotaActionBlocks["firstArrive_m"].xmlText(), + MotaActionBlocks["eachArrive_m"].xmlText(), + MotaActionBlocks["level_m"].xmlText(), + MotaActionFunctions.actionParser.parse([["MTx", ""]], "floorPartition"), + MotaActionBlocks["commonEvent_m"].xmlText(), + MotaActionBlocks["item_m"].xmlText(), + MotaActionFunctions.actionParser.parse( + [ + { + title: "简单", + name: "Easy", + hard: 1, + action: [{ type: "comment", text: "在这里写该难度需执行的事件" }], + }, + ], + "levelChoose" + ), + MotaActionFunctions.actionParser.parse( + { + type: 0, + value: { atk: 10 }, + percentage: { speed: 10 }, + }, + "equip" + ), + MotaActionFunctions.actionParser.parse( + [ + { + name: "bg.jpg", + x: 0, + y: 0, + canvas: "bg", + }, + ], + "floorImage" + ), + MotaActionFunctions.actionParser.parse( + { + time: 160, + openSound: "door.mp3", + closeSound: "door.mp3", + keys: { yellowKey: 1, orangeKey: 1 }, + }, + "doorInfo" + ), + MotaActionBlocks["faceIds_m"].xmlText(), + MotaActionBlocks["mainStyle_m"].xmlText(), + MotaActionFunctions.actionParser.parse( + { + 背景音乐: "bgm.mp3", + 确定: "confirm.mp3", + 攻击: "attack.mp3", + 背景图: "bg.jpg", + 领域: "zone", + 文件名: "file.jpg", + }, + "nameMap" + ), + MotaActionFunctions.actionParser.parse( + [{ name: "hero.png", width: 32, height: 32, prefix: "hero_" }], + "splitImages" + ), + ], + 显示文字: [ + MotaActionBlocks["text_0_s"].xmlText(), + MotaActionBlocks["text_1_s"].xmlText(), + MotaActionFunctions.actionParser.parseList( + "\t[小妖精,fairy]\f[fairy.png,0,0]欢迎使用事件编辑器(双击方块可直接预览)" + ), + MotaActionBlocks["moveTextBox_s"].xmlText(), + MotaActionBlocks["clearTextBox_s"].xmlText(), + MotaActionBlocks["comment_s"].xmlText(), + MotaActionBlocks["autoText_s"].xmlText(), + MotaActionBlocks["scrollText_s"].xmlText(), + MotaActionBlocks["setText_s"].xmlText(), + MotaActionBlocks["tip_s"].xmlText(), + MotaActionBlocks["confirm_s"].xmlText(), + MotaActionBlocks["choices_s"].xmlText([ + "选择剑或者盾", + "流浪者", + "man", + 0, + "", + MotaActionBlocks["choicesContext"].xmlText([ + "剑", + "", + "", + null, + "", + "", + MotaActionFunctions.actionParser.parseList([ + { type: "openDoor", loc: [3, 3] }, + ]), + ]), + ]), + MotaActionBlocks["win_s"].xmlText(), + MotaActionBlocks["lose_s"].xmlText(), + MotaActionBlocks["restart_s"].xmlText(), + ], + 数据相关: [ + MotaActionBlocks["setValue_s"].xmlText([ + MotaActionBlocks["idIdList_e"].xmlText(["status", "生命"]), + "=", + "", + false, + ]), + MotaActionBlocks["setEnemy_s"].xmlText(), + MotaActionBlocks["setEnemyOnPoint_s"].xmlText(), + MotaActionBlocks["resetEnemyOnPoint_s"].xmlText(), + MotaActionBlocks["moveEnemyOnPoint_s"].xmlText(), + MotaActionBlocks["moveEnemyOnPoint_1_s"].xmlText(), + MotaActionBlocks["setEquip_s"].xmlText(), + MotaActionBlocks["setFloor_s"].xmlText(), + MotaActionBlocks["setGlobalAttribute_s"].xmlText(), + MotaActionBlocks["setGlobalValue_s"].xmlText(), + MotaActionBlocks["setGlobalFlag_s"].xmlText(), + MotaActionBlocks["setNameMap_s"].xmlText(), + MotaActionBlocks["input_s"].xmlText(), + MotaActionBlocks["input2_s"].xmlText(), + MotaActionBlocks["update_s"].xmlText(), + MotaActionBlocks["moveAction_s"].xmlText(), + MotaActionBlocks["changeFloor_s"].xmlText(), + MotaActionBlocks["changePos_s"].xmlText(), + MotaActionBlocks["battle_s"].xmlText(), + MotaActionBlocks["useItem_s"].xmlText(), + MotaActionBlocks["loadEquip_s"].xmlText(), + MotaActionBlocks["unloadEquip_s"].xmlText(), + MotaActionBlocks["openShop_s"].xmlText(), + MotaActionBlocks["disableShop_s"].xmlText(), + MotaActionBlocks["setHeroIcon_s"].xmlText(), + MotaActionBlocks["follow_s"].xmlText(), + MotaActionBlocks["unfollow_s"].xmlText(), + ], + 地图处理: [ + MotaActionBlocks["battle_1_s"].xmlText(), + MotaActionBlocks["openDoor_s"].xmlText(), + MotaActionBlocks["closeDoor_s"].xmlText(), + MotaActionBlocks["show_s"].xmlText(), + MotaActionBlocks["hide_s"].xmlText(), + MotaActionBlocks["setBlock_s"].xmlText(), + MotaActionBlocks["setBlockOpacity_s"].xmlText(), + MotaActionBlocks["setBlockFilter_s"].xmlText(), + MotaActionBlocks["turnBlock_s"].xmlText(), + MotaActionBlocks["moveHero_s"].xmlText(), + MotaActionBlocks["move_s"].xmlText(), + MotaActionBlocks["jumpHero_s"].xmlText(), + MotaActionBlocks["jumpHero_1_s"].xmlText(), + MotaActionBlocks["jump_s"].xmlText(), + MotaActionBlocks["jump_1_s"].xmlText(), + MotaActionBlocks["showBgFgMap_s"].xmlText(), + MotaActionBlocks["hideBgFgMap_s"].xmlText(), + MotaActionBlocks["setBgFgBlock_s"].xmlText(), + MotaActionBlocks["showFloorImg_s"].xmlText(), + MotaActionBlocks["hideFloorImg_s"].xmlText(), + ], + 事件控制: [ + MotaActionBlocks["if_1_s"].xmlText(), + MotaActionBlocks["if_s"].xmlText(), + MotaActionFunctions.actionParser.parseList({ + type: "switch", + condition: "判别值", + caseList: [ + { + action: [ + { type: "comment", text: "当判别值是值的场合执行此事件" }, + ], + }, + { + case: "default", + action: [ { - "type": "if", - "condition": "((temp:X===flag:x)&&(temp:Y===flag:y))", - "true": [ + type: "comment", + text: "当没有符合的值的场合执行default事件", + }, + ], + }, + ], + }), + MotaActionFunctions.actionParser.parseList({ + type: "for", + name: "temp:A", + from: "0", + to: "12", + step: "1", + data: [], + }), + MotaActionFunctions.actionParser.parseList({ + type: "forEach", + name: "temp:A", + list: ["status:atk", "status:def"], + data: [], + }), + MotaActionBlocks["while_s"].xmlText(), + MotaActionBlocks["dowhile_s"].xmlText(), + MotaActionBlocks["break_s"].xmlText(), + MotaActionBlocks["continue_s"].xmlText(), + MotaActionBlocks["exit_s"].xmlText(), + MotaActionBlocks["trigger_s"].xmlText(), + MotaActionBlocks["insert_1_s"].xmlText(), + MotaActionBlocks["insert_2_s"].xmlText(), + ], + 特效表现: [ + MotaActionBlocks["sleep_s"].xmlText(), + MotaActionFunctions.actionParser.parseList({ + type: "wait", + timeout: 0, + data: [ + { + case: "keyboard", + keycode: "13,32", + action: [ + { + type: "comment", + text: "当按下回车(keycode=13)或空格(keycode=32)时执行此事件\n超时剩余时间会写入flag:timeout", + }, + ], + }, + { + case: "mouse", + px: [0, 32], + py: [0, 32], + action: [ + { + type: "comment", + text: "当点击地图左上角时执行此事件\n超时剩余时间会写入flag:timeout", + }, + ], + }, + { + case: "condition", + condition: "flag:type==0\n&&flag:keycode==13", + action: [ + { + type: "comment", + text: "当满足自定义条件时会执行此事件\n超时剩余时间会写入flag:timeout", + }, + ], + }, + { + case: "timeout", + action: [{ type: "comment", text: "当超时未操作时执行此事件" }], + }, + ], + }), + MotaActionBlocks["waitAsync_s"].xmlText(), + MotaActionBlocks["stopAsync_s"].xmlText(), + MotaActionBlocks["vibrate_s"].xmlText(), + MotaActionBlocks["animate_s"].xmlText(), + MotaActionBlocks["animate_1_s"].xmlText(), + MotaActionBlocks["stopAnimate_s"].xmlText(), + MotaActionBlocks["setViewport_s"].xmlText(), + MotaActionBlocks["setViewport_1_s"].xmlText(), + MotaActionBlocks["lockViewport_s"].xmlText(), + MotaActionBlocks["showStatusBar_s"].xmlText(), + MotaActionBlocks["hideStatusBar_s"].xmlText(), + MotaActionBlocks["setHeroOpacity_s"].xmlText(), + MotaActionBlocks["setCurtain_0_s"].xmlText(), + MotaActionBlocks["setCurtain_1_s"].xmlText(), + MotaActionBlocks["screenFlash_s"].xmlText(), + MotaActionBlocks["setWeather_s"].xmlText(), + MotaActionBlocks["callBook_s"].xmlText(), + MotaActionBlocks["callSave_s"].xmlText(), + MotaActionBlocks["autoSave_s"].xmlText(), + MotaActionBlocks["forbidSave_s"].xmlText(), + MotaActionBlocks["callLoad_s"].xmlText(), + ], + 音像处理: [ + MotaActionBlocks["showImage_s"].xmlText(), + MotaActionBlocks["showImage_1_s"].xmlText(), + MotaActionBlocks["hideImage_s"].xmlText(), + MotaActionBlocks["showTextImage_s"].xmlText(), + MotaActionBlocks["moveImage_s"].xmlText(), + MotaActionBlocks["rotateImage_s"].xmlText(), + MotaActionBlocks["scaleImage_s"].xmlText(), + MotaActionBlocks["showGif_s"].xmlText(), + MotaActionBlocks["playBgm_s"].xmlText(), + MotaActionBlocks["pauseBgm_s"].xmlText(), + MotaActionBlocks["resumeBgm_s"].xmlText(), + MotaActionBlocks["loadBgm_s"].xmlText(), + MotaActionBlocks["freeBgm_s"].xmlText(), + MotaActionBlocks["playSound_s"].xmlText(), + MotaActionBlocks["playSound_1_s"].xmlText(), + MotaActionBlocks["stopSound_s"].xmlText(), + MotaActionBlocks["setVolume_s"].xmlText(), + MotaActionBlocks["setBgmSpeed_s"].xmlText(), + ], + UI绘制: [ + MotaActionBlocks["previewUI_s"].xmlText(), + MotaActionBlocks["clearMap_s"].xmlText(), + MotaActionBlocks["setAttribute_s"].xmlText(), + MotaActionBlocks["setFilter_s"].xmlText(), + MotaActionBlocks["fillText_s"].xmlText(), + MotaActionBlocks["fillBoldText_s"].xmlText(), + MotaActionBlocks["drawTextContent_s"].xmlText(), + MotaActionBlocks["fillRect_s"].xmlText(), + MotaActionBlocks["strokeRect_s"].xmlText(), + MotaActionBlocks["drawLine_s"].xmlText(), + MotaActionBlocks["drawArrow_s"].xmlText(), + MotaActionBlocks["fillPolygon_s"].xmlText(), + MotaActionBlocks["strokePolygon_s"].xmlText(), + MotaActionBlocks["fillEllipse_s"].xmlText(), + MotaActionBlocks["strokeEllipse_s"].xmlText(), + MotaActionBlocks["fillArc_s"].xmlText(), + MotaActionBlocks["strokeArc_s"].xmlText(), + MotaActionBlocks["drawImage_s"].xmlText(), + MotaActionBlocks["drawImage_1_s"].xmlText(), + MotaActionBlocks["drawIcon_s"].xmlText(), + MotaActionBlocks["drawBackground_s"].xmlText(), + MotaActionBlocks["drawSelector_s"].xmlText(), + MotaActionBlocks["drawSelector_1_s"].xmlText(), + ], + 原生脚本: [ + MotaActionBlocks["function_s"].xmlText(), + MotaActionBlocks["unknown_s"].xmlText(), + ], + 值块: [ + MotaActionBlocks["setValue_s"].xmlText([ + MotaActionBlocks["idIdList_e"].xmlText(["status", "生命"]), + "=", + "", + false, + ]), + MotaActionBlocks["expression_arithmetic_0"].xmlText(), + MotaActionBlocks["idFlag_e"].xmlText(), + MotaActionBlocks["idTemp_e"].xmlText(), + MotaActionBlocks["negate_e"].xmlText(), + MotaActionBlocks["unaryOperation_e"].xmlText(), + MotaActionBlocks["bool_e"].xmlText(), + MotaActionBlocks["idString_e"].xmlText(), + MotaActionBlocks["idIdList_e"].xmlText(), + MotaActionBlocks["idFixedList_e"].xmlText(), + MotaActionBlocks["enemyattr_e"].xmlText(), + MotaActionBlocks["blockId_e"].xmlText(), + MotaActionBlocks["blockNumber_e"].xmlText(), + MotaActionBlocks["blockCls_e"].xmlText(), + MotaActionBlocks["hasEquip_e"].xmlText(), + MotaActionBlocks["equip_e"].xmlText(), + MotaActionBlocks["nextXY_e"].xmlText(), + MotaActionBlocks["isReplaying_e"].xmlText(), + MotaActionBlocks["hasVisitedFloor_e"].xmlText(), + MotaActionBlocks["isShopVisited_e"].xmlText(), + MotaActionBlocks["canBattle_e"].xmlText(), + MotaActionBlocks["damage_e"].xmlText(), + MotaActionBlocks["damage_1_e"].xmlText(), + MotaActionBlocks["rand_e"].xmlText(), + MotaActionBlocks["evalString_e"].xmlText(), + ], + 常见事件模板: [ + '', + MotaActionFunctions.actionParser.parseList({ + type: "if", + condition: "!core.musicStatus.bgmStatus", + true: ["\t[系统提示]你当前音乐处于关闭状态,本塔开音乐游戏效果更佳"], + false: [], + }), + '', + MotaActionFunctions.actionParser.parse( + [ + { + type: "if", + condition: "switch:A", + true: [ + "\t[行商,trader]\b[this]这是购买我的道具后我给玩家的提示。", + { + type: "comment", + text: "下一条指令可视情况使用或不使用", + }, + { + type: "hide", + remove: true, + time: 250, + }, + ], + false: [ + { + type: "confirm", + text: "我有3把黄钥匙,\n你出50金币就卖给你。", + yes: [ { - "type": "break", - "n": 1 - } - ] + type: "if", + condition: "status:money>=50", + true: [ + { + type: "setValue", + name: "status:money", + operator: "-=", + value: "50", + }, + { + type: "setValue", + name: "item:yellowKey", + operator: "+=", + value: "3", + }, + { + type: "playSound", + name: "确定", + stop: true, + }, + { + type: "setValue", + name: "switch:A", + value: "true", + }, + ], + false: [ + { + type: "playSound", + name: "操作失败", + }, + "\t[行商,trader]\b[this]你的金币不足!", + ], + }, + ], + no: [], }, - { - "type": "setValue", - "name": "temp:X", - "value": "flag:x" - }, - { - "type": "setValue", - "name": "temp:Y", - "value": "flag:y" - } - ] - } - ] - }, - { - "type": "drawSelector", - "code": 1 - }, - { - "type": "comment", - "text": "流程进行到这里可以对[X,Y]点进行处理,比如" - }, - { - "type": "closeDoor", - "id": "yellowDoor", - "loc": [ - "temp:X", - "temp:Y" - ] - } - ],'event'), - '', - MotaActionFunctions.actionParser.parse([ - { - "type": "comment", - "text": "多阶段boss,请直接作为战后事件使用" - }, - { - "type": "setValue", - "name": "switch:A", - "operator": "+=", - "value": "1" - }, - { - "type": "switch", - "condition": "switch:A", - "caseList": [ + ], + }, + ], + "event" + ), + '', + MotaActionFunctions.actionParser.parse( + [ { - "case": "1", - "action": [ - { - "type": "setBlock", - "number": "redSlime" - }, - "\t[2阶段boss,redSlime]\b[this]你以为你已经打败我了吗?没听说过史莱姆有九条命吗?" - ] + type: "comment", + text: "全地图选中一个点,需要用鼠标或触屏操作", }, { - "case": "2", - "action": [ - { - "type": "setBlock", - "number": "blackSlime" - }, - "\t[3阶段boss,blackSlime]\b[this]不能消灭我的,只会让我更强大!" - ] + type: "setValue", + name: "temp:X", + value: "status:x", }, { - "case": "3", - "action": [ - { - "type": "setBlock", - "number": "slimelord" - }, - "\t[4阶段boss,slimelord]\b[this]我还能打!" - ] + type: "setValue", + name: "temp:Y", + value: "status:y", }, { - "case": "4", - "action": [ - "\t[4阶段boss,slimelord]我一定会回来的!" - ] - } - ] - } - ],'afterBattle'), - ], - '最近使用事件':[ - '', - ] - } - var toolboxgap = '' - //xml_text = MotaActionFunctions.actionParser.parse(obj,type||'event') - //MotaActionBlocks['idString_e'].xmlText() + type: "tip", + text: "再次点击闪烁位置确认", + }, + { + type: "while", + condition: "true", + data: [ + { + type: "drawSelector", + image: "winskin.png", + code: 1, + x: "32*temp:X", + y: "32*temp:Y", + width: 32, + height: 32, + }, + { + type: "wait", + }, + { + type: "if", + condition: "(flag:type === 1)", + true: [ + { + type: "if", + condition: "((temp:X===flag:x)&&(temp:Y===flag:y))", + true: [ + { + type: "break", + n: 1, + }, + ], + }, + { + type: "setValue", + name: "temp:X", + value: "flag:x", + }, + { + type: "setValue", + name: "temp:Y", + value: "flag:y", + }, + ], + }, + ], + }, + { + type: "drawSelector", + code: 1, + }, + { + type: "comment", + text: "流程进行到这里可以对[X,Y]点进行处理,比如", + }, + { + type: "closeDoor", + id: "yellowDoor", + loc: ["temp:X", "temp:Y"], + }, + ], + "event" + ), + '', + MotaActionFunctions.actionParser.parse( + [ + { + type: "comment", + text: "多阶段boss,请直接作为战后事件使用", + }, + { + type: "setValue", + name: "switch:A", + operator: "+=", + value: "1", + }, + { + type: "switch", + condition: "switch:A", + caseList: [ + { + case: "1", + action: [ + { + type: "setBlock", + number: "redSlime", + }, + "\t[2阶段boss,redSlime]\b[this]你以为你已经打败我了吗?没听说过史莱姆有九条命吗?", + ], + }, + { + case: "2", + action: [ + { + type: "setBlock", + number: "blackSlime", + }, + "\t[3阶段boss,blackSlime]\b[this]不能消灭我的,只会让我更强大!", + ], + }, + { + case: "3", + action: [ + { + type: "setBlock", + number: "slimelord", + }, + "\t[4阶段boss,slimelord]\b[this]我还能打!", + ], + }, + { + case: "4", + action: ["\t[4阶段boss,slimelord]我一定会回来的!"], + }, + ], + }, + ], + "afterBattle" + ), + ], + 最近使用事件: [ + '', + ], + }; + var toolboxgap = ''; + //xml_text = MotaActionFunctions.actionParser.parse(obj,type||'event') + //MotaActionBlocks['idString_e'].xmlText() - for (var name in toolboxObj){ - var custom = null; - if(name=='最近使用事件')custom='searchBlockCategory'; - if(name=='入口方块')custom='entranceCategory'; - getCategory(name,custom).innerHTML = toolboxObj[name].join(toolboxgap); - } - -var blocklyArea = document.getElementById('blocklyArea'); -var blocklyDiv = document.getElementById('blocklyDiv'); -var workspace = Blockly.inject(blocklyDiv,{ - media: '_server/blockly/media/', - toolbox: document.getElementById('toolbox'), - zoom:{ - controls: true, - wheel: false,//滚轮改为上下(shift:左右)翻滚 - startScale: 1.0, - maxScale: 3, - minScale: 0.3, - scaleSpeed: 1.08 - }, - trashcan: false, -}); - -editor_blockly.isCommonEntry = function () { - var commonEntries = ['beforeBattle', 'afterBattle', 'afterOpenDoor', 'firstArrive', 'eachArrive', 'commonEvent', 'item']; - return commonEntries.indexOf(editor_blockly.entryType) >= 0; -} - -editor_blockly.entranceCategoryCallback = function(workspace) { - var list=toolboxObj['入口方块'] - var xmlList = []; - var eventType = (editor_blockly.isCommonEntry() ? 'common' : editor_blockly.entryType)+'_m'; - for(var ii=0,blockText;blockText=list[ii];ii++){ - if(new RegExp('').exec(blockText)){ - var block = Blockly.Xml.textToDom(''+blockText+'').firstChild; - block.setAttribute("gap", 5); - xmlList.push(block); + for (var name in toolboxObj) { + var custom = null; + if (name == "最近使用事件") custom = "searchBlockCategory"; + if (name == "入口方块") custom = "entranceCategory"; + getCategory(name, custom).innerHTML = toolboxObj[name].join(toolboxgap); } - } - return xmlList; -} -workspace.registerToolboxCategoryCallback( - 'entranceCategory', editor_blockly.entranceCategoryCallback); + var blocklyArea = document.getElementById("blocklyArea"); + var blocklyDiv = document.getElementById("blocklyDiv"); + var workspace = Blockly.inject(blocklyDiv, { + media: "_server/blockly/media/", + toolbox: document.getElementById("toolbox"), + zoom: { + controls: true, + wheel: false, //滚轮改为上下(shift:左右)翻滚 + startScale: 1.0, + maxScale: 3, + minScale: 0.3, + scaleSpeed: 1.08, + }, + trashcan: false, + }); -editor_blockly.searchBlockCategoryCallback = function(workspace) { - var xmlList = []; - var labels = editor_blockly.searchBlock(); - for (var i = 0; i < labels.length; i++) { - var blockText = '' + - MotaActionBlocks[labels[i]].xmlText() + - ''; - var block = Blockly.Xml.textToDom(blockText).firstChild; - block.setAttribute("gap", 5); - xmlList.push(block); - } - return xmlList; -}; + editor_blockly.isCommonEntry = function () { + var commonEntries = [ + "beforeBattle", + "afterBattle", + "afterOpenDoor", + "firstArrive", + "eachArrive", + "commonEvent", + "item", + ]; + return commonEntries.indexOf(editor_blockly.entryType) >= 0; + }; -workspace.registerToolboxCategoryCallback( - 'searchBlockCategory', editor_blockly.searchBlockCategoryCallback); - -var onresize = function(e) { - blocklyDiv.style.width = blocklyArea.offsetWidth + 'px'; - blocklyDiv.style.height = blocklyArea.offsetHeight + 'px'; - Blockly.svgResize(workspace); -}; -if(typeof editor !== "undefined" && !editor.isMobile)window.addEventListener('resize', onresize, false); -onresize(); -//Blockly.svgResize(workspace); - -//Blockly.bindEventWithChecks_(workspace.svgGroup_,"wheel",workspace,function(e){}); -document.getElementById('blocklyDiv').onmousewheel = function(e){ - //console.log(e); - e.preventDefault(); - var hvScroll = e.shiftKey?'hScroll':'vScroll'; - var mousewheelOffsetValue=20/380*workspace.scrollbar[hvScroll].handleLength_*3; - workspace.scrollbar[hvScroll].handlePosition_+=( ((e.deltaY||0)+(e.detail||0)) >0?mousewheelOffsetValue:-mousewheelOffsetValue); - workspace.scrollbar[hvScroll].onScroll_(); - // workspace.setScale(workspace.scale); -} - -var doubleClickCheck=[[0,'abc']]; -function omitedcheckUpdateFunction(event) { - if(event.type==='create'){ - editor_blockly.addIntoLastUsedType(event.blockId); - } - if(event.type==='ui' && event.element == 'click'){ - var newClick = [new Date().getTime(),event.blockId]; - var lastClick = doubleClickCheck.shift(); - doubleClickCheck.push(newClick); - if(newClick[0]-lastClick[0]<500){ - if(newClick[1]===lastClick[1]){ - editor_blockly.doubleClickBlock(newClick[1]); - } - } - } - // Only handle these events - if (["create", "move", "change", "delete"].indexOf(event.type) < 0) return; - if(editor_blockly.workspace.topBlocks_.length>=2){ - editor_blockly.setValue('入口方块只能有一个'); - return; - } - var eventType = editor_blockly.entryType; - if(editor_blockly.workspace.topBlocks_.length==1){ - var blockType = editor_blockly.workspace.topBlocks_[0].type; - if(blockType!==eventType+'_m' && !(editor_blockly.isCommonEntry() && blockType == 'common_m')){ - editor_blockly.setValue('入口方块类型错误'); - return; - } - } - try { - var code = Blockly.JavaScript.workspaceToCode(workspace).replace(/\\(i|c|d|e|g|z)/g, '\\\\$1'); - editor_blockly.setValue(code); - } catch (error) { - editor_blockly.setValue(String(error)); - if (error instanceof OmitedError){ - var blockName = error.blockName; - var varName = error.varName; - var block = error.block; - } - // console.log(error); - } - } - - workspace.addChangeListener(omitedcheckUpdateFunction); - - workspace.addChangeListener(Blockly.Events.disableOrphans); - - editor_blockly.workspace = workspace; - - MotaActionFunctions.workspace = function(){ - return editor_blockly.workspace; - } - - // 因为在editor_blockly.parse里已经HTML转义过一次了,所以这里要覆盖掉以避免在注释中出现<等 - MotaActionFunctions.xmlText = function (ruleName,inputs,isShadow,comment,collapsed,disabled) { - var rule = MotaActionBlocks[ruleName]; - var blocktext = isShadow?'shadow':'block'; - var xmlText = []; - xmlText.push('<'+blocktext+' type="'+ruleName+'"'+(collapsed ? ' collapsed="true"' : '')+(disabled ? ' disabled="true"' : '')+'>'); - if(!inputs)inputs=[]; - for (var ii=0,inputType;inputType=rule.argsType[ii];ii++) { - var input = inputs[ii]; - var _input = ''; - var noinput = (input===null || input===undefined); - if(noinput && inputType==='field' && MotaActionBlocks[rule.argsGrammarName[ii]].type!=='field_dropdown') continue; - if(noinput && inputType==='field') { - noinput = false; - input = rule.fieldDefault(rule.args[ii]) - } - if(noinput) input = ''; - if(inputType==='field' && MotaActionBlocks[rule.argsGrammarName[ii]].type==='field_checkbox')input=input?'TRUE':'FALSE'; - if(inputType!=='field') { - var subList = false; - var subrulename = rule.argsGrammarName[ii]; - var subrule = MotaActionBlocks[subrulename]; - if (subrule instanceof Array) { - subrulename=subrule[subrule.length-1]; - subrule = MotaActionBlocks[subrulename]; - subList = true; - } - _input = subrule.xmlText([],true); - if(noinput && !subList && !isShadow) { - //无输入的默认行为是: 如果语句块的备选方块只有一个,直接代入方块 - input = subrule.xmlText(); + editor_blockly.entranceCategoryCallback = function (workspace) { + var list = toolboxObj["入口方块"]; + var xmlList = []; + var eventType = + (editor_blockly.isCommonEntry() ? "common" : editor_blockly.entryType) + + "_m"; + for (var ii = 0, blockText; (blockText = list[ii]); ii++) { + if (new RegExp('').exec(blockText)) { + var block = Blockly.Xml.textToDom( + "" + blockText + "" + ).firstChild; + block.setAttribute("gap", 5); + xmlList.push(block); } } - xmlText.push('<'+inputType+' name="'+rule.args[ii]+'">'); - xmlText.push(_input+input); - xmlText.push(''); - } - if(comment){ - xmlText.push(''); - xmlText.push(comment); - xmlText.push(''); - } - var next = inputs[rule.args.length]; - if (next) {//next - xmlText.push(''); - xmlText.push(next); - xmlText.push(''); - } - xmlText.push(''); - return xmlText.join(''); - } -})(); + return xmlList; + }; + workspace.registerToolboxCategoryCallback( + "entranceCategory", + editor_blockly.entranceCategoryCallback + ); + editor_blockly.searchBlockCategoryCallback = function (workspace) { + var xmlList = []; + var labels = editor_blockly.searchBlock(); + for (var i = 0; i < labels.length; i++) { + var blockText = + "" + MotaActionBlocks[labels[i]].xmlText() + ""; + var block = Blockly.Xml.textToDom(blockText).firstChild; + block.setAttribute("gap", 5); + xmlList.push(block); + } + return xmlList; + }; -// end mark sfergsvae -}).toString().split('// start mark sfergsvae')[1].split('// end mark sfergsvae')[0] + workspace.registerToolboxCategoryCallback( + "searchBlockCategory", + editor_blockly.searchBlockCategoryCallback + ); + + var onresize = function (e) { + blocklyDiv.style.width = blocklyArea.offsetWidth + "px"; + blocklyDiv.style.height = blocklyArea.offsetHeight + "px"; + Blockly.svgResize(workspace); + }; + if (typeof editor !== "undefined" && !editor.isMobile) + window.addEventListener("resize", onresize, false); + onresize(); + //Blockly.svgResize(workspace); + + //Blockly.bindEventWithChecks_(workspace.svgGroup_,"wheel",workspace,function(e){}); + document.getElementById("blocklyDiv").onmousewheel = function (e) { + //console.log(e); + e.preventDefault(); + var hvScroll = e.shiftKey ? "hScroll" : "vScroll"; + var mousewheelOffsetValue = + (20 / 380) * workspace.scrollbar[hvScroll].handleLength_ * 3; + workspace.scrollbar[hvScroll].handlePosition_ += + (e.deltaY || 0) + (e.detail || 0) > 0 + ? mousewheelOffsetValue + : -mousewheelOffsetValue; + workspace.scrollbar[hvScroll].onScroll_(); + // workspace.setScale(workspace.scale); + }; + + var doubleClickCheck = [[0, "abc"]]; + function omitedcheckUpdateFunction(event) { + if (event.type === "create") { + editor_blockly.addIntoLastUsedType(event.blockId); + } + if (event.type === "ui" && event.element == "click") { + var newClick = [new Date().getTime(), event.blockId]; + var lastClick = doubleClickCheck.shift(); + doubleClickCheck.push(newClick); + if (newClick[0] - lastClick[0] < 500) { + if (newClick[1] === lastClick[1]) { + editor_blockly.doubleClickBlock(newClick[1]); + } + } + } + // Only handle these events + if (["create", "move", "change", "delete"].indexOf(event.type) < 0) + return; + if (editor_blockly.workspace.topBlocks_.length >= 2) { + editor_blockly.setValue("入口方块只能有一个"); + return; + } + var eventType = editor_blockly.entryType; + if (editor_blockly.workspace.topBlocks_.length == 1) { + var blockType = editor_blockly.workspace.topBlocks_[0].type; + if ( + blockType !== eventType + "_m" && + !(editor_blockly.isCommonEntry() && blockType == "common_m") + ) { + editor_blockly.setValue("入口方块类型错误"); + return; + } + } + try { + var code = Blockly.JavaScript.workspaceToCode(workspace).replace( + /\\(i|c|d|e|g|z)/g, + "\\\\$1" + ); + editor_blockly.setValue(code); + } catch (error) { + editor_blockly.setValue(String(error)); + if (error instanceof OmitedError) { + var blockName = error.blockName; + var varName = error.varName; + var block = error.block; + } + // console.log(error); + } + } + + workspace.addChangeListener(omitedcheckUpdateFunction); + + workspace.addChangeListener(Blockly.Events.disableOrphans); + + editor_blockly.workspace = workspace; + + MotaActionFunctions.workspace = function () { + return editor_blockly.workspace; + }; + + // 因为在editor_blockly.parse里已经HTML转义过一次了,所以这里要覆盖掉以避免在注释中出现<等 + MotaActionFunctions.xmlText = function ( + ruleName, + inputs, + isShadow, + comment, + collapsed, + disabled + ) { + var rule = MotaActionBlocks[ruleName]; + var blocktext = isShadow ? "shadow" : "block"; + var xmlText = []; + xmlText.push( + "<" + + blocktext + + ' type="' + + ruleName + + '"' + + (collapsed ? ' collapsed="true"' : "") + + (disabled ? ' disabled="true"' : "") + + ">" + ); + if (!inputs) inputs = []; + for (var ii = 0, inputType; (inputType = rule.argsType[ii]); ii++) { + var input = inputs[ii]; + var _input = ""; + var noinput = input === null || input === undefined; + if ( + noinput && + inputType === "field" && + MotaActionBlocks[rule.argsGrammarName[ii]].type !== "field_dropdown" + ) + continue; + if (noinput && inputType === "field") { + noinput = false; + input = rule.fieldDefault(rule.args[ii]); + } + if (noinput) input = ""; + if ( + inputType === "field" && + MotaActionBlocks[rule.argsGrammarName[ii]].type === "field_checkbox" + ) + input = input ? "TRUE" : "FALSE"; + if (inputType !== "field") { + var subList = false; + var subrulename = rule.argsGrammarName[ii]; + var subrule = MotaActionBlocks[subrulename]; + if (subrule instanceof Array) { + subrulename = subrule[subrule.length - 1]; + subrule = MotaActionBlocks[subrulename]; + subList = true; + } + _input = subrule.xmlText([], true); + if (noinput && !subList && !isShadow) { + //无输入的默认行为是: 如果语句块的备选方块只有一个,直接代入方块 + input = subrule.xmlText(); + } + } + xmlText.push("<" + inputType + ' name="' + rule.args[ii] + '">'); + xmlText.push(_input + input); + xmlText.push(""); + } + if (comment) { + xmlText.push(""); + xmlText.push(comment); + xmlText.push(""); + } + var next = inputs[rule.args.length]; + if (next) { + //next + xmlText.push(""); + xmlText.push(next); + xmlText.push(""); + } + xmlText.push(""); + return xmlText.join(""); + }; + })(); + + // end mark sfergsvae +} + .toString() + .split("// start mark sfergsvae")[1] + .split("// end mark sfergsvae")[0]; diff --git a/_server/table/comment.js b/_server/table/comment.js index b417a50..f8660c0 100644 --- a/_server/table/comment.js +++ b/_server/table/comment.js @@ -187,24 +187,18 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "def": { "_leaf": true, "_type": "textarea", - "_data": "物理防御力" + "_data": "防御力" }, "mdef": { "_leaf": true, "_type": "textarea", - "_data": "魔法防御力" + "_data": "法抗(写为小数)" }, "speed": { "_leaf": true, "_type": "textarea", "_data": "速度" }, - "magic": { - "_leaf": true, - "_type": "checkbox", - "_docs": "是否为魔法攻击", - "_data": "勾选以魔法攻击计算,不勾选以物理攻击计算" - }, "money": { "_leaf": true, "_type": "textarea", diff --git a/_server/table/data.comment.js b/_server/table/data.comment.js index de82674..3a76bd7 100644 --- a/_server/table/data.comment.js +++ b/_server/table/data.comment.js @@ -89,7 +89,7 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_range": "editor.mode.checkUnique(thiseval)", "_directory": "./project/bgms/", "_transform": (function (one) { - if (one.endsWith('.mp3') || one.endsWith('.ogg') || one.endsWith('.wav') || one.endsWith('.m4a') || one.endsWith('.flac')) + if (one.endsWith('.mp3') || one.endsWith('.ogg') || one.endsWith('.wav') || one.endsWith('.m4a') || one.endsWith('.flac') || one.endsWith('.opus')) return one; return null; }).toString(), @@ -102,7 +102,7 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_range": "editor.mode.checkUnique(thiseval)", "_directory": "./project/sounds/", "_transform": (function (one) { - if (one.endsWith('.mp3') || one.endsWith('.ogg') || one.endsWith('.wav') || one.endsWith('.m4a') || one.endsWith('.flac')) + if (one.endsWith('.mp3') || one.endsWith('.ogg') || one.endsWith('.wav') || one.endsWith('.m4a') || one.endsWith('.flac') || one.endsWith('.opus')) return one; return null; }).toString(), @@ -147,7 +147,7 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_type": "material", "_directory": "./project/bgms/", "_transform": (function (one) { - if (one.endsWith('.mp3') || one.endsWith('.ogg') || one.endsWith('.wav') || one.endsWith('.m4a') || one.endsWith('.flac')) + if (one.endsWith('.mp3') || one.endsWith('.ogg') || one.endsWith('.wav') || one.endsWith('.m4a') || one.endsWith('.flac') || one.endsWith('.opus')) return one; return null; }).toString(), @@ -262,44 +262,19 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "def": { "_leaf": true, "_type": "textarea", - "_data": "物理防御" + "_data": "防御" }, "mdef": { "_leaf": true, "_type": "textarea", - "_data": "魔法防御" + "_data": "法强" }, "speed": { "_leaf": true, "_type": "textarea", - "_data": "攻击速度" - }, - "str": { - "_leaf": true, - "_type": "textarea", - "_data": "力量" - }, - "agi": { - "_leaf": true, - "_type": "textarea", - "_data": "敏捷" - }, - "int": { - "_leaf": true, - "_type": "textarea", - "_data": "智力" - }, - "con": { - "_leaf": true, - "_type": "textarea", - "_data": "体质" - }, - "magic": { - "_leaf": true, - "_type": "checkbox", - "_docs": "攻击类型", - "_data": "攻击类型是否是魔法" + "_data": "速度" }, + "money": { "_leaf": true, "_type": "textarea", diff --git a/index.html b/index.html index dceab9b..c49e005 100644 --- a/index.html +++ b/index.html @@ -213,6 +213,9 @@
+ + + diff --git a/libs/thirdparty/codec-parser.min.js b/libs/thirdparty/codec-parser.min.js new file mode 100644 index 0000000..fb4ac2e --- /dev/null +++ b/libs/thirdparty/codec-parser.min.js @@ -0,0 +1 @@ +var CodecParser=function(e){"use strict";const t=Symbol,s=(()=>{const e="left",t="center",s="right";return["","front ","side ","rear "].map((i=>[[e,s],[e,s,t],[e,t,s],[t,e,s],[t]].flatMap((e=>e.map((e=>i+e)).join(", ")))))})(),i="LFE",r="monophonic (mono)",n="stereo",a="surround",o=(e,...t)=>`${[r,n,`linear ${a}`,"quadraphonic",`5.0 ${a}`,`5.1 ${a}`,`6.1 ${a}`,`7.1 ${a}`][e-1]} (${t.join(", ")})`,h=[r,o(2,s[0][0]),o(3,s[0][2]),o(4,s[1][0],s[3][0]),o(5,s[1][2],s[3][0]),o(6,s[1][2],s[3][0],i),o(7,s[1][2],s[2][0],s[3][4],i),o(8,s[1][2],s[2][0],s[3][0],i)],c=48e3,l=44100,u=32e3,d=24e3,p=22050,_=16e3,m=8e3,g="absoluteGranulePosition",f="bandwidth",b="bitDepth",C="bitrate",y=C+"Maximum",S=C+"Minimum",w=C+"Nominal",P="buffer",k=P+"Fullness",v="codec",F=v+"Frames",x="coupledStreamCount",H="crc",I=H+"16",M=H+"32",U="data",O="description",N="duration",$="emphasis",A="hasOpusPadding",R="header",B="isContinuedPacket",L="isCopyrighted",D="isFirstPage",T="isHome",E="isLastPage",G="isOriginal",z="isPrivate",q="isVbr",V="layer",j="length",W="mode",J=W+"Extension",K="mpeg",Q=K+"Version",X="numberAACFrames",Y="outputGain",Z="preSkip",ee="profile",te=t(),se="protection",ie="rawData",re="segments",ne="subarray",ae="version",oe="vorbis",he=oe+"Comments",ce=oe+"Setup",le="block",ue=le+"ingStrategy",de=t(),pe=le+"Size",_e=le+"size0",me=le+"size1",ge=t(),fe="channel",be=fe+"MappingFamily",Ce=fe+"MappingTable",ye=fe+"Mode",Se=t(),we=fe+"s",Pe="copyright",ke=Pe+"Id",ve=Pe+"IdStart",Fe="frame",xe=Fe+"Count",He=Fe+"Length",Ie="Number",Me=Fe+Ie,Ue=Fe+"Padding",Oe=Fe+"Size",Ne="Rate",$e="inputSample"+Ne,Ae="page",Re=Ae+"Checksum",Be=t(),Le=Ae+"SegmentTable",De=Ae+"Sequence"+Ie,Te="sample",Ee=Te+Ie,Ge=Te+Ne,ze=t(),qe=Te+"s",Ve="stream",je=Ve+"Count",We=Ve+"Info",Je=Ve+"Serial"+Ie,Ke=Ve+"StructureVersion",Qe="total",Xe=Qe+"BytesOut",Ye=Qe+"Duration",Ze=Qe+"Samples",et=t(),tt=t(),st=t(),it=t(),rt=t(),nt=t(),at=t(),ot=t(),ht=t(),ct=t(),lt=t(),ut=t(),dt=t(),pt=t(),_t=t(),mt=t(),gt=t(),ft=t(),bt=Uint8Array,Ct=DataView,yt="reserved",St="bad",wt="free",Pt="none",kt="16bit CRC",vt=(e,t,s)=>{for(let i=0;i0;e--)r=s(r);e[i]=r}return e},Ft=vt(new bt(256),(e=>e),(e=>128&e?7^e<<1:e<<1)),xt=[vt(new Uint16Array(256),(e=>e<<8),(e=>e<<1^(32768&e?32773:0)))],Ht=[vt(new Uint32Array(256),(e=>e),(e=>e>>>1^3988292384*(1&e)))];for(let e=0;e<15;e++){xt.push(new Uint16Array(256)),Ht.push(new Uint32Array(256));for(let t=0;t<=255;t++)xt[e+1][t]=xt[0][xt[e][t]>>>8]^xt[e][t]<<8,Ht[e+1][t]=Ht[e][t]>>>8^Ht[0][255&Ht[e][t]]}const It=e=>{const t=e[j],s=t-16;let i=0,r=0;for(;r<=s;)i=Ht[15][255&(e[r++]^i)]^Ht[14][255&(e[r++]^i>>>8)]^Ht[13][255&(e[r++]^i>>>16)]^Ht[12][e[r++]^i>>>24]^Ht[11][e[r++]]^Ht[10][e[r++]]^Ht[9][e[r++]]^Ht[8][e[r++]]^Ht[7][e[r++]]^Ht[6][e[r++]]^Ht[5][e[r++]]^Ht[4][e[r++]]^Ht[3][e[r++]]^Ht[2][e[r++]]^Ht[1][e[r++]]^Ht[0][e[r++]];for(;r!==t;)i=Ht[0][255&(i^e[r++])]^i>>>8;return~i},Mt=(...e)=>{const t=new bt(e.reduce(((e,t)=>e+t[j]),0));return e.reduce(((e,s)=>(t.set(s,e),e+s[j])),0),t},Ut=e=>String.fromCharCode(...e),Ot=[0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15],Nt=e=>Ot[15&e]<<4|Ot[e>>4];class $t{constructor(e){this._data=e,this._pos=8*e[j]}set position(e){this._pos=e}get position(){return this._pos}read(e){const t=Math.floor(this._pos/8),s=this._pos%8;this._pos-=e;return(Nt(this._data[t-1])<<8)+Nt(this._data[t])>>7-s&255}}class At{constructor(e,t){this._onCodecHeader=e,this._onCodecUpdate=t,this[_t]()}[mt](){this._isEnabled=!0}[_t](){this._headerCache=new Map,this._codecUpdateData=new WeakMap,this._codecHeaderSent=!1,this._codecShouldUpdate=!1,this._bitrate=null,this._isEnabled=!1}[pt](e,t){if(this._onCodecUpdate){this._bitrate!==e&&(this._bitrate=e,this._codecShouldUpdate=!0);const s=this._codecUpdateData.get(this._headerCache.get(this._currentHeader));this._codecShouldUpdate&&s&&this._onCodecUpdate({bitrate:e,...s},t),this._codecShouldUpdate=!1}}[ht](e){const t=this._headerCache.get(e);return t&&this._updateCurrentHeader(e),t}[ct](e,t,s){this._isEnabled&&(this._codecHeaderSent||(this._onCodecHeader({...t}),this._codecHeaderSent=!0),this._updateCurrentHeader(e),this._headerCache.set(e,t),this._codecUpdateData.set(t,s))}_updateCurrentHeader(e){this._onCodecUpdate&&e!==this._currentHeader&&(this._codecShouldUpdate=!0,this._currentHeader=e)}}const Rt=new WeakMap,Bt=new WeakMap;class Lt{constructor(e,t){this._codecParser=e,this._headerCache=t}*[at](){let e;for(;;){if(e=yield*this.Frame[lt](this._codecParser,this._headerCache,0),e)return e;this._codecParser[tt](1)}}*[ot](e){let t=yield*this[at]();const s=Bt.get(t)[j];if(e||this._codecParser._flushing||(yield*this.Header[ht](this._codecParser,this._headerCache,s)))return this._headerCache[mt](),this._codecParser[tt](s),this._codecParser[it](t),t;this._codecParser[rt](`Missing ${Fe} at ${s} bytes from current position.`,`Dropping current ${Fe} and trying again.`),this._headerCache[_t](),this._codecParser[tt](1)}}class Dt{constructor(e,t){Bt.set(this,{[R]:e}),this[U]=t}}class Tt extends Dt{static*[lt](e,t,s,i,r){const n=yield*e[ht](s,i,r);if(n){const e=Rt.get(n)[He],i=Rt.get(n)[qe];return new t(n,(yield*s[et](e,r))[ne](0,e),i)}return null}constructor(e,t,s){super(e,t),this[R]=e,this[qe]=s,this[N]=s/e[Ge]*1e3,this[Me]=null,this[Xe]=null,this[Ze]=null,this[Ye]=null,Bt.get(this)[j]=t[j]}}const Et="unsynchronizationFlag",Gt="extendedHeaderFlag",zt="experimentalFlag",qt="footerPresent";class Vt{static*getID3v2Header(e,t,s){const i={};let r=yield*e[et](3,s);if(73!==r[0]||68!==r[1]||51!==r[2])return null;if(r=yield*e[et](10,s),i[ae]=`id3v2.${r[3]}.${r[4]}`,15&r[5])return null;if(i[Et]=!!(128&r[5]),i[Gt]=!!(64&r[5]),i[zt]=!!(32&r[5]),i[qt]=!!(16&r[5]),128&r[6]||128&r[7]||128&r[8]||128&r[9])return null;const n=r[6]<<21|r[7]<<14|r[8]<<7|r[9];return i[j]=10+n,new Vt(i)}constructor(e){this[ae]=e[ae],this[Et]=e[Et],this[Gt]=e[Gt],this[zt]=e[zt],this[qt]=e[qt],this[j]=e[j]}}class jt{constructor(e){Rt.set(this,e),this[b]=e[b],this[C]=null,this[we]=e[we],this[ye]=e[ye],this[Ge]=e[Ge]}}const Wt={0:[wt,wt,wt,wt,wt],16:[32,32,32,32,8],240:[St,St,St,St,St]},Jt=(e,t,s)=>8*((e+s)%t+t)*(1<<(e+s)/t)-8*t*(t/8|0);for(let e=2;e<15;e++)Wt[e<<4]=[32*e,Jt(e,4,0),Jt(e,4,-1),Jt(e,8,4),Jt(e,8,0)];const Kt="bands ",Qt=" to 31",Xt={0:Kt+4+Qt,16:Kt+8+Qt,32:Kt+12+Qt,48:Kt+16+Qt},Yt="bitrateIndex",Zt="v2",es="v1",ts="Intensity stereo ",ss=", MS stereo ",is="on",rs="off",ns={0:ts+rs+ss+rs,16:ts+is+ss+rs,32:ts+rs+ss+is,48:ts+is+ss+is},as={0:{[O]:yt},2:{[O]:"Layer III",[Ue]:1,[J]:ns,[es]:{[Yt]:2,[qe]:1152},[Zt]:{[Yt]:4,[qe]:576}},4:{[O]:"Layer II",[Ue]:1,[J]:Xt,[qe]:1152,[es]:{[Yt]:1},[Zt]:{[Yt]:4}},6:{[O]:"Layer I",[Ue]:4,[J]:Xt,[qe]:384,[es]:{[Yt]:0},[Zt]:{[Yt]:3}}},os="MPEG Version ",hs="ISO/IEC ",cs={0:{[O]:`${os}2.5 (later extension of MPEG 2)`,[V]:Zt,[Ge]:{0:11025,4:12e3,8:m,12:yt}},8:{[O]:yt},16:{[O]:`${os}2 (${hs}13818-3)`,[V]:Zt,[Ge]:{0:p,4:d,8:_,12:yt}},24:{[O]:`${os}1 (${hs}11172-3)`,[V]:es,[Ge]:{0:l,4:c,8:u,12:yt}},length:j},ls={0:kt,1:Pt},us={0:Pt,1:"50/15 ms",2:yt,3:"CCIT J.17"},ds={0:{[we]:2,[O]:n},64:{[we]:2,[O]:"joint "+n},128:{[we]:2,[O]:"dual channel"},192:{[we]:1,[O]:r}};class ps extends jt{static*[ht](e,t,s){const i={},r=yield*Vt.getID3v2Header(e,t,s);r&&(yield*e[et](r[j],s),e[tt](r[j]));const n=yield*e[et](4,s),a=Ut(n[ne](0,4)),o=t[ht](a);if(o)return new ps(o);if(255!==n[0]||n[1]<224)return null;const h=cs[24&n[1]];if(h[O]===yt)return null;const c=6&n[1];if(as[c][O]===yt)return null;const l={...as[c],...as[c][h[V]]};if(i[Q]=h[O],i[V]=l[O],i[qe]=l[qe],i[se]=ls[1&n[1]],i[j]=4,i[C]=Wt[240&n[2]][l[Yt]],i[C]===St)return null;if(i[Ge]=h[Ge][12&n[2]],i[Ge]===yt)return null;if(i[Ue]=2&n[2]&&l[Ue],i[z]=!!(1&n[2]),i[He]=Math.floor(125*i[C]*i[qe]/i[Ge]+i[Ue]),!i[He])return null;const u=192&n[3];if(i[ye]=ds[u][O],i[we]=ds[u][we],i[J]=l[J][48&n[3]],i[L]=!!(8&n[3]),i[G]=!!(4&n[3]),i[$]=us[3&n[3]],i[$]===yt)return null;i[b]=16;{const{length:e,frameLength:s,samples:r,...n}=i;t[ct](a,i,n)}return new ps(i)}constructor(e){super(e),this[C]=e[C],this[$]=e[$],this[Ue]=e[Ue],this[L]=e[L],this[G]=e[G],this[z]=e[z],this[V]=e[V],this[J]=e[J],this[Q]=e[Q],this[se]=e[se]}}class _s extends Tt{static*[lt](e,t,s){return yield*super[lt](ps,_s,e,t,s)}constructor(e,t,s){super(e,t,s)}}class ms extends Lt{constructor(e,t,s){super(e,t),this.Frame=_s,this.Header=ps,s(this[v])}get[v](){return K}*[ut](){return yield*this[ot]()}}const gs={0:"MPEG-4",8:"MPEG-2"},fs={0:"valid",2:St,4:St,6:St},bs={0:kt,1:Pt},Cs={0:"AAC Main",64:"AAC LC (Low Complexity)",128:"AAC SSR (Scalable Sample Rate)",192:"AAC LTP (Long Term Prediction)"},ys={0:96e3,4:88200,8:64e3,12:c,16:l,20:u,24:d,28:p,32:_,36:12e3,40:11025,44:m,48:7350,52:yt,56:yt,60:"frequency is written explicitly"},Ss={0:{[we]:0,[O]:"Defined in AOT Specific Config"},64:{[we]:1,[O]:r},128:{[we]:2,[O]:o(2,s[0][0])},192:{[we]:3,[O]:o(3,s[1][3])},256:{[we]:4,[O]:o(4,s[1][3],s[3][4])},320:{[we]:5,[O]:o(5,s[1][3],s[3][0])},384:{[we]:6,[O]:o(6,s[1][3],s[3][0],i)},448:{[we]:8,[O]:o(8,s[1][3],s[2][0],s[3][0],i)}};class ws extends jt{static*[ht](e,t,s){const i={},r=yield*e[et](7,s),n=Ut([r[0],r[1],r[2],252&r[3]|3&r[6]]),a=t[ht](n);if(a)Object.assign(i,a);else{if(255!==r[0]||r[1]<240)return null;if(i[Q]=gs[8&r[1]],i[V]=fs[6&r[1]],i[V]===St)return null;const e=1&r[1];i[se]=bs[e],i[j]=e?7:9,i[te]=192&r[2],i[ze]=60&r[2];const s=2&r[2];if(i[ee]=Cs[i[te]],i[Ge]=ys[i[ze]],i[Ge]===yt)return null;i[z]=!!s,i[Se]=448&(r[2]<<8|r[3]),i[ye]=Ss[i[Se]][O],i[we]=Ss[i[Se]][we],i[G]=!!(32&r[3]),i[T]=!!(8&r[3]),i[ke]=!!(8&r[3]),i[ve]=!!(4&r[3]),i[b]=16,i[qe]=1024,i[X]=3&r[6];{const{length:e,channelModeBits:s,profileBits:r,sampleRateBits:a,frameLength:o,samples:h,numberAACFrames:c,...l}=i;t[ct](n,i,l)}}if(i[He]=8191&(r[3]<<11|r[4]<<3|r[5]>>5),!i[He])return null;const o=2047&(r[5]<<6|r[6]>>2);return i[k]=2047===o?"VBR":o,new ws(i)}constructor(e){super(e),this[ke]=e[ke],this[ve]=e[ve],this[k]=e[k],this[T]=e[T],this[G]=e[G],this[z]=e[z],this[V]=e[V],this[j]=e[j],this[Q]=e[Q],this[X]=e[X],this[ee]=e[ee],this[se]=e[se]}get audioSpecificConfig(){const e=Rt.get(this),t=e[te]+64<<5|e[ze]<<5|e[Se]>>3,s=new bt(2);return new Ct(s[P]).setUint16(0,t,!1),s}}class Ps extends Tt{static*[lt](e,t,s){return yield*super[lt](ws,Ps,e,t,s)}constructor(e,t,s){super(e,t,s)}}class ks extends Lt{constructor(e,t,s){super(e,t),this.Frame=Ps,this.Header=ws,s(this[v])}get[v](){return"aac"}*[ut](){return yield*this[ot]()}}class vs extends Tt{static _getFrameFooterCrc16(e){return(e[e[j]-2]<<8)+e[e[j]-1]}static[ft](e){const t=vs._getFrameFooterCrc16(e),s=(e=>{const t=e[j],s=t-16;let i=0,r=0;for(;r<=s;)i^=e[r++]<<8|e[r++],i=xt[15][i>>8]^xt[14][255&i]^xt[13][e[r++]]^xt[12][e[r++]]^xt[11][e[r++]]^xt[10][e[r++]]^xt[9][e[r++]]^xt[8][e[r++]]^xt[7][e[r++]]^xt[6][e[r++]]^xt[5][e[r++]]^xt[4][e[r++]]^xt[3][e[r++]]^xt[2][e[r++]]^xt[1][e[r++]]^xt[0][e[r++]];for(;r!==t;)i=(255&i)<<8^xt[0][i>>8^e[r++]];return i})(e[ne](0,-2));return t===s}constructor(e,t,s){t[We]=s,t[I]=vs._getFrameFooterCrc16(e),super(t,e,Rt.get(t)[qe])}}const Fs="get from STREAMINFO metadata block",xs={0:"Fixed",1:"Variable"},Hs={0:yt,16:192};for(let e=2;e<16;e++)Hs[e<<4]=e<6?576*2**(e-2):2**e;const Is={0:Fs,1:88200,2:176400,3:192e3,4:m,5:_,6:p,7:d,8:u,9:l,10:c,11:96e3,15:St},Ms={0:{[we]:1,[O]:r},16:{[we]:2,[O]:o(2,s[0][0])},32:{[we]:3,[O]:o(3,s[0][1])},48:{[we]:4,[O]:o(4,s[1][0],s[3][0])},64:{[we]:5,[O]:o(5,s[1][1],s[3][0])},80:{[we]:6,[O]:o(6,s[1][1],i,s[3][0])},96:{[we]:7,[O]:o(7,s[1][1],i,s[3][4],s[2][0])},112:{[we]:8,[O]:o(8,s[1][1],i,s[3][0],s[2][0])},128:{[we]:2,[O]:`${n} (left, diff)`},144:{[we]:2,[O]:`${n} (diff, right)`},160:{[we]:2,[O]:`${n} (avg, diff)`},176:yt,192:yt,208:yt,224:yt,240:yt},Us={0:Fs,2:8,4:12,6:yt,8:16,10:20,12:24,14:yt};class Os extends jt{static _decodeUTF8Int(e){if(e[0]>254)return null;if(e[0]<128)return{value:e[0],length:1};let t=1;for(let s=64;s&e[0];s>>=1)t++;let s=t-1,i=0,r=0;for(;s>0;r+=6,s--){if(128!=(192&e[s]))return null;i|=(63&e[s])<>t)<{let t=0;const s=e[j];for(let i=0;i!==s;i++)t=Ft[t^e[i]];return t})(i[ne](0,r[j]-1)))return null;if(!a){const{blockingStrategyBits:e,frameNumber:s,sampleNumber:i,samples:a,sampleRateBits:o,blockSizeBits:h,crc:c,length:l,...u}=r;t[ct](n,r,u)}return new Os(r)}constructor(e){super(e),this[I]=null,this[ue]=e[ue],this[pe]=e[pe],this[Me]=e[Me],this[Ee]=e[Ee],this[We]=null}}class Ns extends Lt{constructor(e,t,s){super(e,t),this.Frame=vs,this.Header=Os,s(this[v])}get[v](){return"flac"}*_getNextFrameSyncOffset(e){const t=yield*this._codecParser[et](2,0),s=t[j]-2;for(;e{const t=Os[gt](e,this._headerCache);if(t)return new vs(e,t,this._streamInfo);this._codecParser[rt]("Failed to parse Ogg FLAC frame","Skipping invalid FLAC frame")})).filter((e=>!!e))),e}}class $s{static*[ht](e,t,s){const i={};let r=yield*e[et](28,s);if(79!==r[0]||103!==r[1]||103!==r[2]||83!==r[3])return null;i[Ke]=r[4];if(248&r[5])return null;i[E]=!!(4&r[5]),i[D]=!!(2&r[5]),i[B]=!!(1&r[5]);const n=new Ct(bt.from(r[ne](0,28))[P]);i[g]=((e,t)=>{try{return e.getBigInt64(t,!0)}catch{const s=128&e.getUint8(t+7)?-1:1;let i=e.getUint32(t,!0),r=e.getUint32(t+4,!0);return-1===s&&(i=1+~i,r=1+~r),r>1048575&&console.warn("This platform does not support BigInt"),s*(i+r*2**32)}})(n,6),i[Je]=n.getInt32(14,!0),i[De]=n.getInt32(18,!0),i[Re]=n.getInt32(22,!0);const a=r[26];i[j]=a+27,r=yield*e[et](i[j],s),i[He]=0,i[Le]=[],i[Be]=bt.from(r[ne](27,i[j]));for(let e=0,t=0;e{const t=Ws[gt](this._identificationHeader,e,this._headerCache);if(t){null===this._preSkipRemaining&&(this._preSkipRemaining=t[Z]);let s=t[Oe]*t[xe]/1e3*t[Ge];return this._preSkipRemaining>0&&(this._preSkipRemaining-=s,s=this._preSkipRemaining<0?-this._preSkipRemaining:0),new Rs(e,t,s)}this._codecParser[nt]("Failed to parse Ogg Opus Header","Not a valid Ogg Opus file")}))),e}}class Ks extends Tt{constructor(e,t,s){super(t,e,s)}}const Qs={};for(let e=0;e<8;e++)Qs[e+6]=2**(6+e);class Xs extends jt{static[gt](e,t,s,i){if(e[j]<30)throw new Error("Out of data while inside an Ogg Page");const r=Ut(e[ne](0,30)),n=t[ht](r);if(n)return new Xs(n);const a={[j]:30};if("vorbis"!==r.substr(0,7))return null;a[U]=bt.from(e[ne](0,30));const o=new Ct(a[U][P]);if(a[ae]=o.getUint32(7,!0),0!==a[ae])return null;if(a[we]=e[11],a[ye]=h[a[we]-1]||"application defined",a[Ge]=o.getUint32(12,!0),a[y]=o.getInt32(16,!0),a[w]=o.getInt32(20,!0),a[S]=o.getInt32(24,!0),a[me]=Qs[(240&e[28])>>4],a[_e]=Qs[15&e[28]],a[_e]>a[me])return null;if(1!==e[29])return null;a[b]=32,a[ce]=i,a[he]=s;{const{length:e,data:s,version:i,vorbisSetup:n,vorbisComments:o,...h}=a;t[ct](r,a,h)}return new Xs(a)}constructor(e){super(e),this[y]=e[y],this[S]=e[S],this[w]=e[w],this[_e]=e[_e],this[me]=e[me],this[U]=e[U],this[he]=e[he],this[ce]=e[ce]}}class Ys extends Lt{constructor(e,t,s){super(e,t),this.Frame=Ks,s(this[v]),this._identificationHeader=null,this._setupComplete=!1,this._prevBlockSize=null}get[v](){return oe}[dt](e){e[F]=[];for(const t of Bt.get(e)[re])if(1===t[0])this._headerCache[mt](),this._identificationHeader=e[U],this._setupComplete=!1;else if(3===t[0])this._vorbisComments=t;else if(5===t[0])this._vorbisSetup=t,this._mode=this._parseSetupHeader(t),this._setupComplete=!0;else if(this._setupComplete){const s=Xs[gt](this._identificationHeader,this._headerCache,this._vorbisComments,this._vorbisSetup);s?e[F].push(new Ks(t,s,this._getSamples(t,s))):this._codecParser[logError]("Failed to parse Ogg Vorbis Header","Not a valid Ogg Vorbis file")}return e}_getSamples(e,t){const s=this._mode.blockFlags[e[0]>>1&this._mode.mask]?t[me]:t[_e],i=null===this._prevBlockSize?0:(this._prevBlockSize+s)/4;return this._prevBlockSize=s,i}_parseSetupHeader(e){const t=new $t(e),s={count:0,blockFlags:[]};for(;1&~t.read(1););let i;for(;s.count<64&&t.position>0;){Nt(t.read(8));let e=0;for(;0===t.read(8)&&e++<3;);if(4!==e){1+((126&Nt(i))>>1)!==s.count&&this._codecParser[rt]("vorbis derived mode count did not match actual mode count");break}i=t.read(7),s.blockFlags.unshift(1&i),t.position+=6,s.count++}return s.mask=(1<1&&e[De]>1&&this._codecParser[rt]("Unexpected gap in Ogg Page Sequence Number.",`Expected: ${this._pageSequenceNumber+1}, Got: ${e[De]}`),this._pageSequenceNumber=e[De]}_parsePage(e){null===this._isSupported&&(this._pageSequenceNumber=e[De],this._isSupported=this._checkCodecSupport(e)),this._checkPageSequenceNumber(e);const t=Bt.get(e),s=Rt.get(t[R]);let i=0;if(t[re]=s[Le].map((t=>e[U][ne](i,i+=t))),this._continuedPacket[j]&&(t[re][0]=Mt(this._continuedPacket,t[re][0]),this._continuedPacket=new bt),255===s[Be][s[Be][j]-1]&&(this._continuedPacket=Mt(this._continuedPacket,t[re].pop())),null!==this._previousAbsoluteGranulePosition&&(e[qe]=Number(e[g]-this._previousAbsoluteGranulePosition)),this._previousAbsoluteGranulePosition=e[g],this._isSupported){const t=this._parser[dt](e);return this._codecParser[it](t),t}return e}}class ei extends Lt{constructor(e,t,s){super(e,t),this._onCodec=s,this.Frame=As,this.Header=$s,this._streams=new Map,this._currentSerialNumber=null}get[v](){const e=this._streams.get(this._currentSerialNumber);return e?e.codec:""}*[ut](){const e=yield*this[ot](!0);this._currentSerialNumber=e[Je];let t=this._streams.get(this._currentSerialNumber);return t||(t=new Zs(this._codecParser,this._headerCache,this._onCodec),this._streams.set(this._currentSerialNumber,t)),e[E]&&this._streams.delete(this._currentSerialNumber),t._parsePage(e)}}const ti=()=>{};const si=g,ii=f,ri=b,ni=C,ai=y,oi=S,hi=w,ci=P,li=k,ui=v,di=F,pi=x,_i=H,mi=I,gi=M,fi=U,bi=O,Ci=N,yi=$,Si=A,wi=R,Pi=B,ki=L,vi=D,Fi=T,xi=E,Hi=G,Ii=z,Mi=q,Ui=V,Oi=j,Ni=W,$i=J,Ai=K,Ri=Q,Bi=X,Li=Y,Di=Z,Ti=ee,Ei=se,Gi=ie,zi=re,qi=ne,Vi=ae,ji=oe,Wi=he,Ji=ce,Ki=ue,Qi=pe,Xi=_e,Yi=me,Zi=be,er=Ce,tr=ye,sr=we,ir=ke,rr=ve,nr=Fe,ar=xe,or=He,hr=Me,cr=Ue,lr=Oe,ur=$e,dr=Re,pr=Le,_r=De,mr=Ee,gr=Ge,fr=qe,br=je,Cr=We,yr=Je,Sr=Ke,wr=Xe,Pr=Ye,kr=Ze;return e.CodecParser=class{constructor(e,{onCodec:t,onCodecHeader:s,onCodecUpdate:i,enableLogging:r=!1,enableFrameCRC32:n=!0}={}){this._inputMimeType=e,this._onCodec=t||ti,this._onCodecHeader=s||ti,this._onCodecUpdate=i,this._enableLogging=r,this._crc32=n?It:ti,this[_t]()}get[v](){return this._parser?this._parser[v]:""}[_t](){this._headerCache=new At(this._onCodecHeader,this._onCodecUpdate),this._generator=this._getGenerator(),this._generator.next()}*flush(){this._flushing=!0;for(let e=this._generator.next();e.value;e=this._generator.next())yield e.value;this._flushing=!1,this[_t]()}*parseChunk(e){for(let t=this._generator.next(e);t.value;t=this._generator.next())yield t.value}parseAll(e){return[...this.parseChunk(e),...this.flush()]}*_getGenerator(){if(this._inputMimeType.match(/aac/))this._parser=new ks(this,this._headerCache,this._onCodec);else if(this._inputMimeType.match(/mpeg/))this._parser=new ms(this,this._headerCache,this._onCodec);else if(this._inputMimeType.match(/flac/))this._parser=new Ns(this,this._headerCache,this._onCodec);else{if(!this._inputMimeType.match(/ogg/))throw new Error(`Unsupported Codec ${mimeType}`);this._parser=new ei(this,this._headerCache,this._onCodec)}for(this._frameNumber=0,this._currentReadPosition=0,this._totalBytesIn=0,this._totalBytesOut=0,this._totalSamples=0,this._sampleRate=void 0,this._rawData=new Uint8Array(0);;){const e=yield*this._parser[ut]();e&&(yield e)}}*[et](e=0,t=0){let s;for(;this._rawData[j]<=e+t;){if(s=yield,this._flushing)return this._rawData[ne](t);s&&(this._totalBytesIn+=s[j],this._rawData=Mt(this._rawData,s))}return this._rawData[ne](t)}[tt](e){this._currentReadPosition+=e,this._rawData=this._rawData[ne](e)}[st](e){this._sampleRate=e[R][Ge],e[R][C]=e[N]>0?8*Math.round(e[U][j]/e[N]):0,e[Me]=this._frameNumber++,e[Xe]=this._totalBytesOut,e[Ze]=this._totalSamples,e[Ye]=this._totalSamples/this._sampleRate*1e3,e[M]=this._crc32(e[U]),this._headerCache[pt](e[R][C],e[Ye]),this._totalBytesOut+=e[U][j],this._totalSamples+=e[qe]}[it](e){if(e[F]){if(e[E]){let t=e[qe];e[F].forEach((e=>{const s=e[qe];t0?t:0,e[N]=e[qe]/e[R][Ge]*1e3),t-=s,this[st](e)}))}else e[qe]=0,e[F].forEach((t=>{e[qe]+=t[qe],this[st](t)}));e[N]=e[qe]/this._sampleRate*1e3||0,e[Ze]=this._totalSamples,e[Ye]=this._totalSamples/this._sampleRate*1e3||0,e[Xe]=this._totalBytesOut}else this[st](e)}_log(e,t){if(this._enableLogging){const s=[`${v}: ${this[v]}`,`inputMimeType: ${this._inputMimeType}`,`readPosition: ${this._currentReadPosition}`,`totalBytesIn: ${this._totalBytesIn}`,`${Xe}: ${this._totalBytesOut}`],i=Math.max(...s.map((e=>e[j])));t.push(`--stats--${"-".repeat(i-9)}`,...s,"-".repeat(i)),e("codec-parser",t.reduce(((e,t)=>e+"\n "+t),""))}}[rt](...e){this._log(console.warn,e)}[nt](...e){this._log(console.error,e)}},e.absoluteGranulePosition=si,e.bandwidth=ii,e.bitDepth=ri,e.bitrate=ni,e.bitrateMaximum=ai,e.bitrateMinimum=oi,e.bitrateNominal=hi,e.blockSize=Qi,e.blockingStrategy=Ki,e.blocksize0=Xi,e.blocksize1=Yi,e.buffer=ci,e.bufferFullness=li,e.channelMappingFamily=Zi,e.channelMappingTable=er,e.channelMode=tr,e.channels=sr,e.codec=ui,e.codecFrames=di,e.copyrightId=ir,e.copyrightIdStart=rr,e.coupledStreamCount=pi,e.crc=_i,e.crc16=mi,e.crc32=gi,e.data=fi,e.description=bi,e.duration=Ci,e.emphasis=yi,e.frame=nr,e.frameCount=ar,e.frameLength=or,e.frameNumber=hr,e.framePadding=cr,e.frameSize=lr,e.hasOpusPadding=Si,e.header=wi,e.inputSampleRate=ur,e.isContinuedPacket=Pi,e.isCopyrighted=ki,e.isFirstPage=vi,e.isHome=Fi,e.isLastPage=xi,e.isOriginal=Hi,e.isPrivate=Ii,e.isVbr=Mi,e.layer=Ui,e.length=Oi,e.mode=Ni,e.modeExtension=$i,e.mpeg=Ai,e.mpegVersion=Ri,e.numberAACFrames=Bi,e.outputGain=Li,e.pageChecksum=dr,e.pageSegmentTable=pr,e.pageSequenceNumber=_r,e.preSkip=Di,e.profile=Ti,e.protection=Ei,e.rawData=Gi,e.sampleNumber=mr,e.sampleRate=gr,e.samples=fr,e.segments=zi,e.streamCount=br,e.streamInfo=Cr,e.streamSerialNumber=yr,e.streamStructureVersion=Sr,e.subarray=qi,e.totalBytesOut=wr,e.totalDuration=Pr,e.totalSamples=kr,e.version=Vi,e.vorbis=ji,e.vorbisComments=Wi,e.vorbisSetup=Ji,e}({}); diff --git a/libs/thirdparty/ogg-opus-decoder.min.js b/libs/thirdparty/ogg-opus-decoder.min.js new file mode 100644 index 0000000..9525201 Binary files /dev/null and b/libs/thirdparty/ogg-opus-decoder.min.js differ diff --git a/libs/thirdparty/ogg-vorbis-decoder.min.js b/libs/thirdparty/ogg-vorbis-decoder.min.js new file mode 100644 index 0000000..0f030ae --- /dev/null +++ b/libs/thirdparty/ogg-vorbis-decoder.min.js @@ -0,0 +1,195 @@ +/* Copyright 2021-2023 Ethan Halsall. This file is part of wasm-audio-decoders. https://github.com/eshaz/wasm-audio-decoders */ +var t,s;t=this,s=function(t,s){const i=(t,s=4294967295,i=79764919)=>{const e=new Int32Array(256);let r,n,h,o=s;for(r=0;r<256;r++){for(h=r<<24,n=8;n>0;--n)h=2147483648&h?h<<1^i:h<<1;e[r]=h}for(r=0;r>24^t[r])];return o},e=(t,s=i)=>{const e=t=>new Uint8Array(t.length/2).map(((s,i)=>parseInt(t.substring(2*i,2*(i+1)),16))),r=t=>e(t)[0],n=new Map;[,8364,,8218,402,8222,8230,8224,8225,710,8240,352,8249,338,,381,,,8216,8217,8220,8221,8226,8211,8212,732,8482,353,8250,339,,382,376].forEach(((t,s)=>n.set(t,s)));const h=new Uint8Array(t.length);let o,a,l,c=!1,u=0,U=42,d=t.length>13&&"dynEncode"===t.substring(0,9),f=0;d&&(f=11,a=r(t.substring(9,f)),a<=1&&(f+=2,U=r(t.substring(11,f))),1===a&&(f+=8,l=(t=>new DataView(e(t).buffer).getInt32(0,!0))(t.substring(13,f))));const p=256-U;for(let i=f;i255){const t=n.get(o);t&&(o=t+127)}c&&(c=!1,o-=64),h[u++]=o0?o+p:o-U}else c=!0;const M=h.subarray(0,u);if(d&&1===a){const t=s(M);if(t!==l){const s="Decode failed crc32 validation";throw console.error("`simple-yenc`\n",s+"\n","Expected: "+l+"; Got: "+t+"\n","Visit https://github.com/eshaz/simple-yenc for more information"),Error(s)}}return M};function r(){const t=Uint8Array,s=Float32Array;r.t||Object.defineProperties(r,{t:{value:new WeakMap},u:{value(t,s){r.t.set(t,Promise.resolve(s))}},U:{value(t,s){let i=r.t.get(t);return i||(s?i=WebAssembly.compile(e(s)):(s=t.M,i=r.Y(s).then((t=>WebAssembly.compile(t)))),r.t.set(t,i)),i}},T:{value(t,i){let e=new s(i),r=0,n=0;for(;r({O:t,channelData:s,samplesDecoded:i,sampleRate:e,bitDepth:r})},v:{value(t,s,i,e,n,h){let o,a,l=[];for(o=0;o{const e=String.raw`dynEncode0114db91da9bu‡*t“““t“““““t““““$#“U¤¤“U¤¤3yƒ†„‰zzss|yu„svu‡yÚ&ˆ“4<054<,5T44^T44<(6U~J(44< ~A544U~6J0444ˆ†545 444J0444‰J,4U“4ˆU“‡…Ò“7U45“4U4Z“4U4U^/6545T4T44BUˆ~64CU~O4U54U~5 U5T4B4Z!4U~5U5U5T4U~6U4ZTU5U5T44~4O4U2ZTU5T44Z!4B6T44Uˆ~64B6U~O44Uˆ~4O4U~54U~5 44~C4~54U~5 44~5454Uˆ4B6Ub!444~UO4U~5 “U5“4U4ZTUŠ#44U$4†64<4~B6^“4<444~Uˆ~B4U~54Uˆ544~544~Uˆ5 µ“Uä#UJUè#5TT4U0ZTTUX5U5T4T4Uà#~4OU4U $~Cˆ4~54U~5 T44$6U\!TTT4UaT4<6T4<64<Z!44~4N4<U~5 4U”Z!4U±_TUŠ#44U•Uˆ6UÔ~B$544$6U\!4Uˆ6U¤#~B44Uä#~B$~64<6_TU‰#444U”~B~6~54<Y!44<_!T4Y!4<64~444~AN44<U~6J4U5 44J4U”[!U#44UŠO4U~54U~5 U54 “7U6844J44J 4UJ4UJ04VK(44<J44<J$4U´~54U~5 4U¤~5!TTT4U$5"U“5TTTTTTT4U$"4VK,U54<(6U~64<$6_!4< 64~6A54A544U~6#J(U’54A4U‡[!44J(44#~A4Uˆ6U“‡UŠU…[!44†64~64_!4<64~54<6T4<4]TU5 T4Y!44~44~AN4U~54U~54U5 44J(44J UÄA!U5U”#UôJU"UÔJUœ#UÔ"JU˜#U´"JT4U´ZTU5T4UôZTU5T4UDZTU5T4U$[T44~UO4U~5 UÔUô4U~U´$.U5T4UP[T4U~4~UO4U~5 U˜#<Uœ#<4U~U2$.UÄUN 44 ~UO4U~5 44!~UO4U~5 4U~4~UO4U~5 44J44J(U5 44U¤~J@44Uä~J<44UD~J844U~J44U$54U$5U‘54U$54U1^4U1^†!4U•~54U~5U”54U~6U4U^/65T4T4U$54U~4BUˆ~4O4U54U~5 UU'464U'_/54UˆU”~5T4T4U~4BUˆ~UO4U54U~5 U54Uä~4U¤~4U~U'$!44~5U5T44\T44U<~$6U\!4U#aT4U~4Uˆ~4O4U~5 U5U5U5TTT4U$"4YTU5 4Uˆ4~C5U5 U5U5444$4~64~\TUŽ5 4U~4Uˆ~5T4Y!44O4U~54U~54U5 4CYTU‹5 4Uä~4U¤~4U~4$6TU54U\!44Bæ4Bä~[!4U~4UD~4U~4Uˆ~4$6TUŒ54U\!44B†4B„~[!44U<~4U4~$5 4U"U˜#$544"†Y!454U^!44<J44<(J454U~84­U”N!#%'+/37?GOWgw‡—·×÷Uä;U”9$%& !"#`;r.U(r,e).then((t=>WebAssembly.instantiate(t,{}))).then((({exports:e})=>{const r=new Map(Object.entries(e)),n=r.get("puff"),h=r.get("memory").buffer,o=new t(h),a=new DataView(h);let l=r.get("__heap_base");const c=s.length,u=l;l+=4,a.setInt32(u,c,!0);const U=l;l+=c,o.set(s,U);const d=l;l+=4,a.setInt32(d,o.byteLength-l,!0),n(l,d,U,u),i(o.slice(l,l+a.getInt32(d,!0)))}))}))}}}),Object.defineProperty(this,"M",{enumerable:!0,get:()=>this.B}),this.F=(t,s,i)=>{let e=[],r=0;for(;r{const e=this.B.V(s.BYTES_PER_ELEMENT*t);return i&&this.S.add(e),{H:e,$:t,C:new s(this.B.I,e,t)}},this.free=()=>{this.S.forEach((t=>{this.B.free(t)})),this.S.clear()},this.J=t=>{const s=[],i=new Uint8Array(this.B.I);for(let e=i[t];0!==e;e=i[++t])s.push(e);return String.fromCharCode.apply(null,s)},this.P=(t,s,i,e,r,n)=>{t.push({message:s,frameLength:i,frameNumber:e,inputBytes:r,outputSamples:n})},this.instantiate=(t,s)=>(s&&r.u(t,s),this.B=new t(r).instantiate(),this.S=new Set,this.B.ready.then((()=>this)))}class n extends((()=>globalThis.Worker||s)()){constructor(t,s,i,e){r.t||new r;let n=r.t.get(i);if(!n){let t,s="text/javascript",h=`'use strict';(${""+((t,s,i)=>{let e,r,n=new Promise((t=>{r=t}));self.onmessage=({data:{id:h,command:o,data:a}})=>{let l,c=n,u={id:h};"init"===o?(Object.defineProperties(t,{D:{value:s},N:{value:i},module:{value:a.module},Z:{value:!0}}),e=new t(a.options),r()):"free"===o?e.free():"ready"===o?c=c.then((()=>e.ready)):"reset"===o?c=c.then((()=>e.reset())):(Object.assign(u,e[o](Array.isArray(a)?a.map((t=>new Uint8Array(t))):new Uint8Array(a))),l=u.channelData?u.channelData.map((t=>t.buffer)):[]),c.then((()=>self.postMessage(u,l)))}})})(${i}, ${r}, ${e})`;try{t=void 0!==process.versions.node}catch{}n=t?`data:${s};base64,${Buffer.from(h).toString("base64")}`:URL.createObjectURL(new Blob([h],{type:s})),r.t.set(i,n)}super(n,{name:s}),this.K=Number.MIN_SAFE_INTEGER,this.R=new Map,this.onmessage=({data:t})=>{const{id:s,...i}=t;this.R.get(s)(i),this.R.delete(s)},new e(r).U().then((s=>{this.G("init",{module:s,options:t})}))}async G(t,s){return new Promise((i=>{this.postMessage({command:t,id:this.K,data:s}),this.R.set(this.K++,i)}))}get ready(){return this.G("ready")}async free(){await this.G("free").finally((()=>{this.terminate()}))}async reset(){await this.G("reset")}}const h=(t,s)=>{Object.defineProperty(t,"name",{value:s})},o=Symbol,a=(()=>{const t="left",s="center",i="right";return["","front ","side ","rear "].map((e=>[[t,i],[t,i,s],[t,s,i],[s,t,i],[s]].flatMap((t=>t.map((t=>e+t)).join(", ")))))})(),l="LFE",c="monophonic (mono)",u="stereo",U="surround",d=(t,...s)=>`${[c,u,"linear "+U,"quadraphonic","5.0 "+U,"5.1 "+U,"6.1 "+U,"7.1 "+U][t-1]} (${s.join(", ")})`,f=[c,d(2,a[0][0]),d(3,a[0][2]),d(4,a[1][0],a[3][0]),d(5,a[1][2],a[3][0]),d(6,a[1][2],a[3][0],l),d(7,a[1][2],a[2][0],a[3][4],l),d(8,a[1][2],a[2][0],a[3][0],l)],p=48e3,M=44100,y=32e3,m=24e3,w=22050,g=16e3,Y=8e3,T="absoluteGranulePosition",b="bandwidth",A="bitDepth",O="bitrate",v=O+"Maximum",B=O+"Minimum",F=O+"Nominal",_="buffer",V=_+"Fullness",k="codec",S=k+"Frames",q="coupledStreamCount",H="crc",$=H+"16",C=H+"32",I="data",j="description",J="duration",x="emphasis",P="hasOpusPadding",D="header",E="isContinuedPacket",N="isCopyrighted",Z="isFirstPage",z="isHome",K="isLastPage",Q="isOriginal",R="isPrivate",G="isVbr",X="layer",L="length",W="mode",tt=W+"Extension",st="mpeg",it=st+"Version",et="numberAACFrames",rt="outputGain",nt="preSkip",ht="profile",ot=o(),at="protection",lt="segments",ct="subarray",ut="version",Ut="vorbis",dt=Ut+"Comments",ft=Ut+"Setup",pt="block",Mt=pt+"ingStrategy",yt=o(),mt=pt+"Size",wt=pt+"size0",gt=pt+"size1",Yt=o(),Tt="channel",bt=Tt+"MappingFamily",At=Tt+"MappingTable",Ot=Tt+"Mode",vt=o(),Bt=Tt+"s",Ft="copyright",_t=Ft+"Id",Vt=Ft+"IdStart",kt="frame",St=kt+"Count",qt=kt+"Length",Ht="Number",$t=kt+Ht,Ct=kt+"Padding",It=kt+"Size",jt="Rate",Jt="inputSample"+jt,xt="page",Pt=xt+"Checksum",Dt=o(),Et=xt+"SegmentTable",Nt=xt+"Sequence"+Ht,Zt="sample",zt=Zt+Ht,Kt=Zt+jt,Qt=o(),Rt=Zt+"s",Gt="stream",Xt=Gt+"Count",Lt=Gt+"Info",Wt=Gt+"Serial"+Ht,ts=Gt+"StructureVersion",ss="total",is=ss+"BytesOut",es=ss+"Duration",rs=ss+"Samples",ns=o(),hs=o(),os=o(),as=o(),ls=o(),cs=o(),us=o(),Us=o(),ds=o(),fs=o(),ps=o(),Ms=o(),ys=o(),ms=o(),ws=o(),gs=o(),Ys=o(),Ts=o(),bs=Uint8Array,As=DataView,Os="reserved",vs="bad",Bs="free",Fs="none",_s="16bit CRC",Vs=(t,s,i)=>{for(let e=0;e0;t--)r=i(r);t[e]=r}return t},ks=Vs(new bs(256),(t=>t),(t=>128&t?7^t<<1:t<<1)),Ss=[Vs(new Uint16Array(256),(t=>t<<8),(t=>t<<1^(32768&t?32773:0)))],qs=[Vs(new Uint32Array(256),(t=>t),(t=>t>>>1^3988292384*(1&t)))];for(let Ye=0;Ye<15;Ye++){Ss.push(new Uint16Array(256)),qs.push(new Uint32Array(256));for(let t=0;t<=255;t++)Ss[Ye+1][t]=Ss[0][Ss[Ye][t]>>>8]^Ss[Ye][t]<<8,qs[Ye+1][t]=qs[Ye][t]>>>8^qs[0][255&qs[Ye][t]]}const Hs=t=>{const s=t[L],i=s-16;let e=0,r=0;for(;r<=i;)e=qs[15][255&(t[r++]^e)]^qs[14][255&(t[r++]^e>>>8)]^qs[13][255&(t[r++]^e>>>16)]^qs[12][t[r++]^e>>>24]^qs[11][t[r++]]^qs[10][t[r++]]^qs[9][t[r++]]^qs[8][t[r++]]^qs[7][t[r++]]^qs[6][t[r++]]^qs[5][t[r++]]^qs[4][t[r++]]^qs[3][t[r++]]^qs[2][t[r++]]^qs[1][t[r++]]^qs[0][t[r++]];for(;r!==s;)e=qs[0][255&(e^t[r++])]^e>>>8;return~e},$s=(...t)=>{const s=new bs(t.reduce(((t,s)=>t+s[L]),0));return t.reduce(((t,i)=>(s.set(i,t),t+i[L])),0),s},Cs=t=>String.fromCharCode(...t),Is=[0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15],js=t=>Is[15&t]<<4|Is[t>>4];class Js{constructor(t){this.X=t,this.L=8*t[L]}set position(t){this.L=t}get position(){return this.L}read(t){const s=Math.floor(this.L/8),i=this.L%8;return this.L-=t,(js(this.X[s-1])<<8)+js(this.X[s])>>7-i&255}}class xs{constructor(t,s){this.W=t,this.tt=s,this[ws]()}[gs](){this.st=!0}[ws](){this.it=new Map,this.et=new WeakMap,this.rt=!1,this.nt=!1,this.ht=null,this.st=!1}[ms](t,s){if(this.tt){this.ht!==t&&(this.ht=t,this.nt=!0);const i=this.et.get(this.it.get(this.ot));this.nt&&i&&this.tt({lt:t,...i},s),this.nt=!1}}[ds](t){const s=this.it.get(t);return s&&this.ct(t),s}[fs](t,s,i){this.st&&(this.rt||(this.W({...s}),this.rt=!0),this.ct(t),this.it.set(t,s),this.et.set(s,i))}ct(t){this.tt&&t!==this.ot&&(this.nt=!0,this.ot=t)}}const Ps=new WeakMap,Ds=new WeakMap;class Es{constructor(t,s){this.ut=t,this.it=s}*[us](){let t;for(;;){if(t=yield*this.Ut[ps](this.ut,this.it,0),t)return t;this.ut[hs](1)}}*[Us](t){let s=yield*this[us]();const i=Ds.get(s)[L];if(t||this.ut.dt||(yield*this.ft[ds](this.ut,this.it,i)))return this.it[gs](),this.ut[hs](i),this.ut[as](s),s;this.ut[ls](`Missing ${kt} at ${i} bytes from current position.`,`Dropping current ${kt} and trying again.`),this.it[ws](),this.ut[hs](1)}}class Ns{constructor(t,s){Ds.set(this,{[D]:t}),this[I]=s}}class Zs extends Ns{static*[ps](t,s,i,e,r){const n=yield*t[ds](i,e,r);if(n){const t=Ps.get(n)[qt],e=Ps.get(n)[Rt];return new s(n,(yield*i[ns](t,r))[ct](0,t),e)}return null}constructor(t,s,i){super(t,s),this[D]=t,this[Rt]=i,this[J]=i/t[Kt]*1e3,this[$t]=null,this[is]=null,this[rs]=null,this[es]=null,Ds.get(this)[L]=s[L]}}const zs="unsynchronizationFlag",Ks="extendedHeaderFlag",Qs="experimentalFlag",Rs="footerPresent";class Gs{static*Mt(t,s,i){const e={};let r=yield*t[ns](3,i);if(73!==r[0]||68!==r[1]||51!==r[2])return null;if(r=yield*t[ns](10,i),e[ut]=`id3v2.${r[3]}.${r[4]}`,15&r[5])return null;if(e[zs]=!!(128&r[5]),e[Ks]=!!(64&r[5]),e[Qs]=!!(32&r[5]),e[Rs]=!!(16&r[5]),128&r[6]||128&r[7]||128&r[8]||128&r[9])return null;const n=r[6]<<21|r[7]<<14|r[8]<<7|r[9];return e[L]=10+n,new Gs(e)}constructor(t){this[ut]=t[ut],this[zs]=t[zs],this[Ks]=t[Ks],this[Qs]=t[Qs],this[Rs]=t[Rs],this[L]=t[L]}}class Xs{constructor(t){Ps.set(this,t),this[A]=t[A],this[O]=null,this[Bt]=t[Bt],this[Ot]=t[Ot],this[Kt]=t[Kt]}}const Ls={0:[Bs,Bs,Bs,Bs,Bs],16:[32,32,32,32,8],240:[vs,vs,vs,vs,vs]},Ws=(t,s,i)=>8*((t+i)%s+s)*(1<<(t+i)/s)-8*s*(s/8|0);for(let Ye=2;Ye<15;Ye++)Ls[Ye<<4]=[32*Ye,Ws(Ye,4,0),Ws(Ye,4,-1),Ws(Ye,8,4),Ws(Ye,8,0)];const ti="bands ",si=" to 31",ii={0:ti+4+si,16:ti+8+si,32:ti+12+si,48:ti+16+si},ei="bitrateIndex",ri="v2",ni="v1",hi="Intensity stereo ",oi=", MS stereo ",ai="on",li="off",ci={0:hi+li+oi+li,16:hi+ai+oi+li,32:hi+li+oi+ai,48:hi+ai+oi+ai},ui={0:{[j]:Os},2:{[j]:"Layer III",[Ct]:1,[tt]:ci,[ni]:{[ei]:2,[Rt]:1152},[ri]:{[ei]:4,[Rt]:576}},4:{[j]:"Layer II",[Ct]:1,[tt]:ii,[Rt]:1152,[ni]:{[ei]:1},[ri]:{[ei]:4}},6:{[j]:"Layer I",[Ct]:4,[tt]:ii,[Rt]:384,[ni]:{[ei]:0},[ri]:{[ei]:3}}},Ui="MPEG Version ",di="ISO/IEC ",fi={0:{[j]:Ui+"2.5 (later extension of MPEG 2)",[X]:ri,[Kt]:{0:11025,4:12e3,8:Y,12:Os}},8:{[j]:Os},16:{[j]:`${Ui}2 (${di}13818-3)`,[X]:ri,[Kt]:{0:w,4:m,8:g,12:Os}},24:{[j]:`${Ui}1 (${di}11172-3)`,[X]:ni,[Kt]:{0:M,4:p,8:y,12:Os}},length:L},pi={0:_s,1:Fs},Mi={0:Fs,1:"50/15 ms",2:Os,3:"CCIT J.17"},yi={0:{[Bt]:2,[j]:u},64:{[Bt]:2,[j]:"joint "+u},128:{[Bt]:2,[j]:"dual channel"},192:{[Bt]:1,[j]:c}};class mi extends Xs{static*[ds](t,s,i){const e={},r=yield*Gs.Mt(t,s,i);r&&(yield*t[ns](r[L],i),t[hs](r[L]));const n=yield*t[ns](4,i),h=Cs(n[ct](0,4)),o=s[ds](h);if(o)return new mi(o);if(255!==n[0]||n[1]<224)return null;const a=fi[24&n[1]];if(a[j]===Os)return null;const l=6&n[1];if(ui[l][j]===Os)return null;const c={...ui[l],...ui[l][a[X]]};if(e[it]=a[j],e[X]=c[j],e[Rt]=c[Rt],e[at]=pi[1&n[1]],e[L]=4,e[O]=Ls[240&n[2]][c[ei]],e[O]===vs)return null;if(e[Kt]=a[Kt][12&n[2]],e[Kt]===Os)return null;if(e[Ct]=2&n[2]&&c[Ct],e[R]=!!(1&n[2]),e[qt]=Math.floor(125*e[O]*e[Rt]/e[Kt]+e[Ct]),!e[qt])return null;const u=192&n[3];if(e[Ot]=yi[u][j],e[Bt]=yi[u][Bt],e[tt]=c[tt][48&n[3]],e[N]=!!(8&n[3]),e[Q]=!!(4&n[3]),e[x]=Mi[3&n[3]],e[x]===Os)return null;e[A]=16;{const{length:t,frameLength:i,yt:r,...n}=e;s[fs](h,e,n)}return new mi(e)}constructor(t){super(t),this[O]=t[O],this[x]=t[x],this[Ct]=t[Ct],this[N]=t[N],this[Q]=t[Q],this[R]=t[R],this[X]=t[X],this[tt]=t[tt],this[it]=t[it],this[at]=t[at]}}class wi extends Zs{static*[ps](t,s,i){return yield*super[ps](mi,wi,t,s,i)}constructor(t,s,i){super(t,s,i)}}class gi extends Es{constructor(t,s,i){super(t,s),this.Ut=wi,this.ft=mi,i(this[k])}get[k](){return st}*[Ms](){return yield*this[Us]()}}const Yi={0:"MPEG-4",8:"MPEG-2"},Ti={0:"valid",2:vs,4:vs,6:vs},bi={0:_s,1:Fs},Ai={0:"AAC Main",64:"AAC LC (Low Complexity)",128:"AAC SSR (Scalable Sample Rate)",192:"AAC LTP (Long Term Prediction)"},Oi={0:96e3,4:88200,8:64e3,12:p,16:M,20:y,24:m,28:w,32:g,36:12e3,40:11025,44:Y,48:7350,52:Os,56:Os,60:"frequency is written explicitly"},vi={0:{[Bt]:0,[j]:"Defined in AOT Specific Config"},64:{[Bt]:1,[j]:c},128:{[Bt]:2,[j]:d(2,a[0][0])},192:{[Bt]:3,[j]:d(3,a[1][3])},256:{[Bt]:4,[j]:d(4,a[1][3],a[3][4])},320:{[Bt]:5,[j]:d(5,a[1][3],a[3][0])},384:{[Bt]:6,[j]:d(6,a[1][3],a[3][0],l)},448:{[Bt]:8,[j]:d(8,a[1][3],a[2][0],a[3][0],l)}};class Bi extends Xs{static*[ds](t,s,i){const e={},r=yield*t[ns](7,i),n=Cs([r[0],r[1],r[2],252&r[3]|3&r[6]]),h=s[ds](n);if(h)Object.assign(e,h);else{if(255!==r[0]||r[1]<240)return null;if(e[it]=Yi[8&r[1]],e[X]=Ti[6&r[1]],e[X]===vs)return null;const t=1&r[1];e[at]=bi[t],e[L]=t?7:9,e[ot]=192&r[2],e[Qt]=60&r[2];const i=2&r[2];if(e[ht]=Ai[e[ot]],e[Kt]=Oi[e[Qt]],e[Kt]===Os)return null;e[R]=!!i,e[vt]=448&(r[2]<<8|r[3]),e[Ot]=vi[e[vt]][j],e[Bt]=vi[e[vt]][Bt],e[Q]=!!(32&r[3]),e[z]=!!(8&r[3]),e[_t]=!!(8&r[3]),e[Vt]=!!(4&r[3]),e[A]=16,e[Rt]=1024,e[et]=3&r[6];{const{length:t,wt:i,gt:r,Yt:h,frameLength:o,yt:a,Tt:l,...c}=e;s[fs](n,e,c)}}if(e[qt]=8191&(r[3]<<11|r[4]<<3|r[5]>>5),!e[qt])return null;const o=2047&(r[5]<<6|r[6]>>2);return e[V]=2047===o?"VBR":o,new Bi(e)}constructor(t){super(t),this[_t]=t[_t],this[Vt]=t[Vt],this[V]=t[V],this[z]=t[z],this[Q]=t[Q],this[R]=t[R],this[X]=t[X],this[L]=t[L],this[it]=t[it],this[et]=t[et],this[ht]=t[ht],this[at]=t[at]}get bt(){const t=Ps.get(this),s=t[ot]+64<<5|t[Qt]<<5|t[vt]>>3,i=new bs(2);return new As(i[_]).setUint16(0,s,!1),i}}class Fi extends Zs{static*[ps](t,s,i){return yield*super[ps](Bi,Fi,t,s,i)}constructor(t,s,i){super(t,s,i)}}class _i extends Es{constructor(t,s,i){super(t,s),this.Ut=Fi,this.ft=Bi,i(this[k])}get[k](){return"aac"}*[Ms](){return yield*this[Us]()}}class Vi extends Zs{static At(t){return(t[t[L]-2]<<8)+t[t[L]-1]}static[Ts](t){const s=Vi.At(t),i=(t=>{const s=t[L],i=s-16;let e=0,r=0;for(;r<=i;)e^=t[r++]<<8|t[r++],e=Ss[15][e>>8]^Ss[14][255&e]^Ss[13][t[r++]]^Ss[12][t[r++]]^Ss[11][t[r++]]^Ss[10][t[r++]]^Ss[9][t[r++]]^Ss[8][t[r++]]^Ss[7][t[r++]]^Ss[6][t[r++]]^Ss[5][t[r++]]^Ss[4][t[r++]]^Ss[3][t[r++]]^Ss[2][t[r++]]^Ss[1][t[r++]]^Ss[0][t[r++]];for(;r!==s;)e=(255&e)<<8^Ss[0][e>>8^t[r++]];return e})(t[ct](0,-2));return s===i}constructor(t,s,i){s[Lt]=i,s[$]=Vi.At(t),super(s,t,Ps.get(s)[Rt])}}const ki="get from STREAMINFO metadata block",Si={0:"Fixed",1:"Variable"},qi={0:Os,16:192};for(let Ye=2;Ye<16;Ye++)qi[Ye<<4]=Ye<6?576*2**(Ye-2):2**Ye;const Hi={0:ki,1:88200,2:176400,3:192e3,4:Y,5:g,6:w,7:m,8:y,9:M,10:p,11:96e3,15:vs},$i={0:{[Bt]:1,[j]:c},16:{[Bt]:2,[j]:d(2,a[0][0])},32:{[Bt]:3,[j]:d(3,a[0][1])},48:{[Bt]:4,[j]:d(4,a[1][0],a[3][0])},64:{[Bt]:5,[j]:d(5,a[1][1],a[3][0])},80:{[Bt]:6,[j]:d(6,a[1][1],l,a[3][0])},96:{[Bt]:7,[j]:d(7,a[1][1],l,a[3][4],a[2][0])},112:{[Bt]:8,[j]:d(8,a[1][1],l,a[3][0],a[2][0])},128:{[Bt]:2,[j]:u+" (left, diff)"},144:{[Bt]:2,[j]:u+" (diff, right)"},160:{[Bt]:2,[j]:u+" (avg, diff)"},176:Os,192:Os,208:Os,224:Os,240:Os},Ci={0:ki,2:8,4:12,6:Os,8:16,10:20,12:24,14:Os};class Ii extends Xs{static Ot(t){if(t[0]>254)return null;if(t[0]<128)return{value:t[0],length:1};let s=1;for(let n=64;n&t[0];n>>=1)s++;let i=s-1,e=0,r=0;for(;i>0;r+=6,i--){if(128!=(192&t[i]))return null;e|=(63&t[i])<>s)<{let s=0;const i=t[L];for(let e=0;e!==i;e++)s=ks[s^t[e]];return s})(e[ct](0,r[L]-1)))return null;if(!h){const{vt:t,frameNumber:i,Bt:e,yt:h,Yt:o,Ft:a,_t:l,length:c,...u}=r;s[fs](n,r,u)}return new Ii(r)}constructor(t){super(t),this[$]=null,this[Mt]=t[Mt],this[mt]=t[mt],this[$t]=t[$t],this[zt]=t[zt],this[Lt]=null}}class ji extends Es{constructor(t,s,i){super(t,s),this.Ut=Vi,this.ft=Ii,i(this[k])}get[k](){return"flac"}*Vt(t){const s=yield*this.ut[ns](2,0),i=s[L]-2;for(;t{const s=Ii[Ys](t,this.it);if(s)return new Vi(t,s,this.kt);this.ut[ls]("Failed to parse Ogg FLAC frame","Skipping invalid FLAC frame")})).filter((t=>!!t))),t}}class Ji{static*[ds](t,s,i){const e={};let r=yield*t[ns](28,i);if(79!==r[0]||103!==r[1]||103!==r[2]||83!==r[3])return null;if(e[ts]=r[4],248&r[5])return null;e[K]=!!(4&r[5]),e[Z]=!!(2&r[5]),e[E]=!!(1&r[5]);const n=new As(bs.from(r[ct](0,28))[_]);e[T]=(t=>{try{return t.getBigInt64(6,!0)}catch{const s=128&t.getUint8(13)?-1:1;let i=t.getUint32(6,!0),e=t.getUint32(10,!0);return-1===s&&(i=1+~i,e=1+~e),e>1048575&&console.warn("This platform does not support BigInt"),s*(i+e*2**32)}})(n),e[Wt]=n.getInt32(14,!0),e[Nt]=n.getInt32(18,!0),e[Pt]=n.getInt32(22,!0);const h=r[26];e[L]=h+27,r=yield*t[ns](e[L],i),e[qt]=0,e[Et]=[],e[Dt]=bs.from(r[ct](27,e[L]));for(let o=0,a=0;o{const s=Li[Ys](this.Ht,t,this.it);if(s){null===this.$t&&(this.$t=s[nt]);let i=s[It]*s[St]/1e3*s[Kt];return this.$t>0&&(this.$t-=i,i=this.$t<0?-this.$t:0),new Pi(t,s,i)}this.ut[cs]("Failed to parse Ogg Opus Header","Not a valid Ogg Opus file")}))),t}}class te extends Zs{constructor(t,s,i){super(s,t,i)}}const se={};for(let Ye=0;Ye<8;Ye++)se[Ye+6]=2**(6+Ye);class ie extends Xs{static[Ys](t,s,i,e){if(t[L]<30)throw Error("Out of data while inside an Ogg Page");const r=Cs(t[ct](0,30)),n=s[ds](r);if(n)return new ie(n);const h={[L]:30};if("vorbis"!==r.substr(0,7))return null;h[I]=bs.from(t[ct](0,30));const o=new As(h[I][_]);if(h[ut]=o.getUint32(7,!0),0!==h[ut])return null;if(h[Bt]=t[11],h[Ot]=f[h[Bt]-1]||"application defined",h[Kt]=o.getUint32(12,!0),h[v]=o.getInt32(16,!0),h[F]=o.getInt32(20,!0),h[B]=o.getInt32(24,!0),h[gt]=se[(240&t[28])>>4],h[wt]=se[15&t[28]],h[wt]>h[gt])return null;if(1!==t[29])return null;h[A]=32,h[ft]=e,h[dt]=i;{const{length:t,data:i,version:e,Ct:n,It:o,...a}=h;s[fs](r,h,a)}return new ie(h)}constructor(t){super(t),this[v]=t[v],this[B]=t[B],this[F]=t[F],this[wt]=t[wt],this[gt]=t[gt],this[I]=t[I],this[dt]=t[dt],this[ft]=t[ft]}}class ee extends Es{constructor(t,s,i){super(t,s),this.Ut=te,i(this[k]),this.Ht=null,this.jt=!1,this.Jt=null}get[k](){return Ut}[ys](t){t[S]=[];for(const s of Ds.get(t)[lt])if(1===s[0])this.it[gs](),this.Ht=t[I],this.jt=!1;else if(3===s[0])this.xt=s;else if(5===s[0])this.Pt=s,this.Dt=this.Et(s),this.jt=!0;else if(this.jt){const i=ie[Ys](this.Ht,this.it,this.xt,this.Pt);i?t[S].push(new te(s,i,this.Nt(s,i))):this.ut[logError]("Failed to parse Ogg Vorbis Header","Not a valid Ogg Vorbis file")}return t}Nt(t,s){const i=this.Dt.Zt[t[0]>>1&this.Dt.mask]?s[gt]:s[wt],e=null===this.Jt?0:(this.Jt+i)/4;return this.Jt=i,e}Et(t){const s=new Js(t),i={count:0,Zt:[]};for(;1&~s.read(1););let e;for(;i.count<64&&s.position>0;){js(s.read(8));let t=0;for(;0===s.read(8)&&t++<3;);if(4!==t){1+((126&js(e))>>1)!==i.count&&this.ut[ls]("vorbis derived mode count did not match actual mode count");break}e=s.read(7),i.Zt.unshift(1&e),s.position+=6,i.count++}return i.mask=(1<1&&t[Nt]>1&&this.ut[ls]("Unexpected gap in Ogg Page Sequence Number.",`Expected: ${this.ss+1}, Got: ${t[Nt]}`),this.ss=t[Nt]}es(t){null===this.Rt&&(this.ss=t[Nt],this.Rt=this.Wt(t)),this.ts(t);const s=Ds.get(t),i=Ps.get(s[D]);let e=0;if(s[lt]=i[Et].map((s=>t[I][ct](e,e+=s))),this.Kt[L]&&(s[lt][0]=$s(this.Kt,s[lt][0]),this.Kt=new bs),255===i[Dt][i[Dt][L]-1]&&(this.Kt=$s(this.Kt,s[lt].pop())),null!==this.Gt&&(t[Rt]=Number(t[T]-this.Gt)),this.Gt=t[T],this.Rt){const s=this.Lt[ys](t);return this.ut[as](s),s}return t}}class ne extends Es{constructor(t,s,i){super(t,s),this.zt=i,this.Ut=xi,this.ft=Ji,this.rs=new Map,this.ns=null}get[k](){const t=this.rs.get(this.ns);return t?t.hs:""}*[Ms](){const t=yield*this[Us](!0);this.ns=t[Wt];let s=this.rs.get(this.ns);return s||(s=new re(this.ut,this.it,this.zt),this.rs.set(this.ns,s)),t[K]&&this.rs.delete(this.ns),s.es(t)}}const he=()=>{};class oe{constructor(t,{os:s,ls:i,cs:e,us:r=!1,Us:n=!0}={}){this.ds=t,this.zt=s||he,this.W=i||he,this.tt=e,this.fs=r,this.ps=n?Hs:he,this[ws]()}get[k](){return this.Lt?this.Lt[k]:""}[ws](){this.it=new xs(this.W,this.tt),this.Ms=this.ys(),this.Ms.next()}*flush(){this.dt=!0;for(let t=this.Ms.next();t.value;t=this.Ms.next())yield t.value;this.dt=!1,this[ws]()}*ws(t){for(let s=this.Ms.next(t);s.value;s=this.Ms.next())yield s.value}parseAll(t){return[...this.ws(t),...this.flush()]}*ys(){if(this.ds.match(/aac/))this.Lt=new _i(this,this.it,this.zt);else if(this.ds.match(/mpeg/))this.Lt=new gi(this,this.it,this.zt);else if(this.ds.match(/flac/))this.Lt=new ji(this,this.it,this.zt);else{if(!this.ds.match(/ogg/))throw Error("Unsupported Codec "+mimeType);this.Lt=new ne(this,this.it,this.zt)}for(this.gs=0,this.Ys=0,this.Ts=0,this.bs=0,this.As=0,this.Os=void 0,this.vs=new Uint8Array(0);;){const t=yield*this.Lt[Ms]();t&&(yield t)}}*[ns](t=0,s=0){let i;for(;this.vs[L]<=t+s;){if(i=yield,this.dt)return this.vs[ct](s);i&&(this.Ts+=i[L],this.vs=$s(this.vs,i))}return this.vs[ct](s)}[hs](t){this.Ys+=t,this.vs=this.vs[ct](t)}[os](t){this.Os=t[D][Kt],t[D][O]=t[J]>0?8*Math.round(t[I][L]/t[J]):0,t[$t]=this.gs++,t[is]=this.bs,t[rs]=this.As,t[es]=this.As/this.Os*1e3,t[C]=this.ps(t[I]),this.it[ms](t[D][O],t[es]),this.bs+=t[I][L],this.As+=t[Rt]}[as](t){if(t[S]){if(t[K]){let s=t[Rt];t[S].forEach((t=>{const i=t[Rt];s0?s:0,t[J]=t[Rt]/t[D][Kt]*1e3),s-=i,this[os](t)}))}else t[Rt]=0,t[S].forEach((s=>{t[Rt]+=s[Rt],this[os](s)}));t[J]=t[Rt]/this.Os*1e3||0,t[rs]=this.As,t[es]=this.As/this.Os*1e3||0,t[is]=this.bs}else this[os](t)}Bs(t,s){if(this.fs){const i=[`${k}: ${this[k]}`,"inputMimeType: "+this.ds,"readPosition: "+this.Ys,"totalBytesIn: "+this.Ts,`${is}: ${this.bs}`],e=Math.max(...i.map((t=>t[L])));s.push("--stats--"+"-".repeat(e-9),...i,"-".repeat(e)),t("codec-parser",s.reduce(((t,s)=>t+"\n "+s),""))}}[ls](...t){this.Bs(console.warn,t)}[cs](...t){this.Bs(console.error,t)}}const ae=S,le=I,ce=D,ue=K,Ue=dt,de=ft,fe=rs;function pe(t){function s(){}for(var i=new Uint8Array(123),e=25;e>=0;--e)i[48+e]=52+e,i[65+e]=e,i[97+e]=26+e;var r,n;i[43]=62,i[47]=63,pe.M||Object.defineProperty(pe,"M",{get:()=>String.raw`dynEncode01a33fc84f8dïoØå§ä³¨s¢þéõ?§šæ—ƒQ¬·ñì>_•å”è£Mí'…ËÏÊí çåzmòeúaݐ§¢é,šî= 9z…ó¡= $.JõT¬K„'¨®ç ƒä“Ó·ßé‘àäà(u¾ŽÃ÷¯ÃìÍH¶3KQtíŒ;Çø=}ÉóX=}Çã»°£)½SÉVy{oEqûUHhéì8÷7ó[Ÿ”¼ˆiÖ¨A2º»ƒÈ(ä+Ú»‰Ðé*7šç}ìÏց@ü€¿À¿B;?=}A?>ýÿûüÿ~{xÎ#†ë5X.]J +=Mi=M°UH +˜5šâ’ª±ÀéOmrn¿¯2Ljª•˜{• ÝájÔֆ ±Û©bŸÕé)j{èüül8üàJr/¡™¨‘‡²Ýþ^UÜàÈO6܅jÙ5èâ×að1º€HH=M2Û6íÊóI̧[TÜïÚÉ)„ÁW|âßHeF,l Ì¥ 'ž0Äb8ÏK“ß è!Œe‘€J +vÑz–Œ& WrnV "5Êñ ýkwP”4Ãp¨‘¸RAx[p¼Ïóƒ;š7>ÃÑþ¨VU?°Rˆ›q9~ò‰Q”ڃw‡I=}­žœ• f›òÔ·rñ¾ª¸gðx7QE5-±®M߀ãl–?£Á•ãÃE óØ{ËÒÂÌ@µ –z5fñ‘}.;¾ê%Mi‡‰_³ZU@å.ɂñ‰î¾Þ€m„Ät†×¢. ,ä²BB;朤‘äûûZ_¡V)Œ‡ŒªAUµ¾BfÈéŸ Ò&§¦$¢Š»ôåÀk£z‹(Ÿ_zܟ^r>†ï ¾bˆ>ÁŽð/ªÄDTçQŽlÄIÒ°Q}:8_þŽ!@ßvñ!œOö +\”\ebVpȜ±Ö~\¥NÐ'eŸBœb·#ÈN¥ŸY ßà#W´0a]¼!þ½\n×ØT¿¿‡¶çÉS­îäx7óÎ6ñI-ììùpfåh¸Çú,cµÔeiÂeic ÓÂçˆ#ê²up¹aÛÝb0¼þ7–Ÿ™Ü”>F3ÞÔTþñfkï±bxö”€„öfٍ†ˆ±…6H„”ΟÊß6 šÒ°ÂyV¶Á?»‰‚@?{¨Q¥+=}¥±ÿԓÌá9%û!>Âì&¸Õ@Ó„Uùq÷?ñqt˜¿“çIU+÷g‚y+5sä +¼¬åí• GÖ®‡S1Kƒ;…B\©™f‹hX˜d)ºÐ¿²Uw ûûX1ƒ5°Ò1„LÁ”-Œ;j= piN:}îºB¯ÅÉwXtô§¶¸3Œy¶¯oJáàLž¸jÎn®În -Š¸ýûÄàsT ½ÎòÓÄes ´{OsèÚÎþ´ƒÇ“å9SekF†‰TV³úŽK-”š÷WE¾OÔ +µR½‹ø*ٞvVèJ°§†¼Å¤ªàCŠœsr²^Õvü3ããÔ¯/´ Poü|$ RÞ§KuÉ#þ‰[ªß{¦ÑVú>ý>Ôws~~š9ž=Mz¶-ږ•hiò>ñ²1ždüÿ!ü>ý>í¾¿ñ赙À ž/«~yæ¨Êwór„b0©ì!ˆ ~°»Ïžøj§Ý#ß88š÷AlÛ¦3¹ÇS8“oK:xÜ×'dAkÉÜ<É;–)3ÀbÐ{í«Û5?þ +ÈNøRÙᾙ¹/+ß>ۏ¾6åô}mzQ|p÷Mž¼ðjÑí©;2½&Ì#g×g|/[k*Zõ8ZvãXƒçàF–ª¯a*÷«ª+V,\¨rÏâ'É:G-àëˆW£óÿ‡ˆîŸ‚8rpÿ]k€=Mîéû|]´$Î"’îá“VìDŽ_d%~m¢>aj%U6¨^8"žb ]¥®}l†ì­ïèÈfõ lÔ֋çÝÜIÃqÜ;ñ‘°[‚ÙåTàÆä>í•÷™õ{¯oí½3*iú•D¿gÔæÁ@sÙ Ñèځ=MÉkáÑüçuêÕÙðw¨ À ³Fô~{ï_µ9Ѭ5,}í5×0ÿ>_6l*{îò)¯GjE7(aôrÃbôÚj˜Ç½ T°ÜÃÄgk;ß_߇Â֍ûÄRZðùÒ¸§=MX*gê[ÉXÚ©^uN„~u~® +:Õ_NøW‰ëP\^WpÀttØ÷2ÿ2wTØï2þ2v6y6;V˜ÌۆI÷?ªê„̶^&>&í£F]VBfŒ¨Tße|þîõ¹ù±úÁ$˜]ö wá†yƒÏV.îbÁۂŠÆ.Þð¡ØۆïtnZ$þ:—KÌòñӘð?«Ÿ»…±l“ⶠ+SӀÿZ·ƒ©'7 +s%»4äcL+øÈ{ +^ÑKCU¨n9ðÑ~g³/rӆV$ +[cÉ6 &›(¿ô‚qðx ú’Æ6ÞYSÇO×Èò{ ’-L;áèÚÆUhk(öyžÄ„è7´Þ1CY˜¤Dèé׃40,ä$Em9†¦S£"¨ü“ÇkU€ô¹ŠË UgÎ{>%[2\ösiUîçÓ.œÀ¨ãôÂÏûÇ~që¤ +˜$¼À&*ãhæM#Ïî8å#ûûU@·I‡§a†Âú[Hc°cŠ¥öém¶«è䪪ˆ#÷‡ˆñg;ß¾óºš/9í? g~ïB9¨'Süß.›),‡gi±Æèzåëf¹,Èâ^k¿|Ð= ”ÿÉUvˆñÚÍÖـ"&•|ª[Å¢lŽy‚D¸ÖÏñI´QCÑWõȉà°zÈ2_Ǹß(ËÒ¹pi}çkU̇-PV$MÍ)}éžD×q¹{¤aä†.|í+/ýºIë¸××I¥^bü½ö?Ñ/Æ°uCH¥g±•‚|¹MÞ#L²„ææûºÿ 'œîA-÷B¿7<ޙԭ 9ì&Ô¢fÓ1EãÈ/ cE%5ÙO‡£.uK~¨¸;Ëíô°ÿu7uRö¦×³…®= °~£3€0Èö‡ˆpI ìx‚ûŸ)þÏXËyey„o I%Ùý°ðà8­Kð!9¡ƒ‰C£'Ý Y0¶±Ú}îùÛÆze"ߦ[ÌM…ˆ÷qAš?¬;QW–et„ bW¬ýÛ)aW–et„+*˜¾­j¥h8Î +ÉëÎ +~øqù|ô*= DÑW©â +q'$iÇùçÆ®sç4|¶¢USæK|cÅÀ(46?µŠƒ#ËM0÷rYNAP÷r¦á«Ò×{²¶ÁØäpg´e—Ý|¸ìH=MïmÿOn@óå+(÷Ð MI3“ìñÈó倝Óz*^,áÿJ²Úz* [Òíxê|Žfp˜„ûÂûûBŒf4þs*þs*ö [ñ‘bG²ÐnjÄ%Àßñ«Zù\è¬è ‘ K-ÚÈ®”Û“×ΏVyT­´1˜bØüJÅZÕüJÅÚ=}›<ó´nul/6|@{æÔî½àb|é ª³½wTŒAª³uêÀ.¸šNvΘ‘æSUL-÷h›rH7ÙV +VÕ-pL¿ã.PÒ¿êÃÿqÎÁE­k…ÜŒ¦ÙÇéÙ²—l¥(t³p–OYúHp’cÖ¸ó„æÞy5½¶ÎÕ9Ȍ³˜³²ô³2§'6Š­´É‘»_9Ɏ^¿Ï«;ÙËa­&rb—f±_ZØÀª%#ŽÎh?̑;zÀVš‰j¿Ž2lúꋆGÂ^hì +ÊÀþߌðT†Gximü1Oå®&¥ïߗµe‰cË/9/ÍN͟ê¤MÎü´M +ƒ•]Fökj®òJ¤C©K•'îO§•GiÆb6ô¡ØfÒéþ‚h°¶˜À= µfŠaG€Hߵэ¬Ãà ÖO¥*–Ýh·s-#ýtúø*³D¡S6(t,ÀF0(´¡†¿nƒ,Ùádý˜Y@²íۄâÀnhé9ÿ{~@øJèT\†VåԞOó¢üdr턦ür… +¨& +ÝJB¸ŸV%tr­QžóӞO—Våâ SBi¾ÿڐçܘÄ6OLi.p·Å(›Õ“xD¨ +D¨¼¬ ؍ª¼L9¯¨ÌšÓn¤° BªbêtÓ«óÚ;[K°èî¦AÀ—Ο™0ý'ð§|ÌÒÌ÷´rq½ó ̎µazûû8œm´Ê/ŸœV:È&®¬ØÌZ& Uk£‡r¿Ãî9>ÊR‡rѤçśz"ÈBw&!Aúÿ’‘üd˜–&ù¤º¤ûë©ÿ?þlâSwÉ£kl¾2ž9²bÏáz«–­®k€(Ȫ-Ðgýuäƪa­ß÷Ðî5A3*®ÖÖ»­·G‚V@øb1r# éof:&z:ryG~qb˜f“ÜVš\Q°%¿¦cœåþ„¤6á0n"՘a•Õ:¬®{ ™$îN³ºüÜ~=}Ą6¬ÁÛÏÓ¥Y¬ŒÆ€m‚šÝÜÀ,ØAà64æ0kÐÇižL#=MMôk%9ÿ[þ|Ä[Á<0¯ ý¥þÖváÐ\yí¬-zÌOï1ä@ ¤†ÙÙ®»…ÏÈïõ¯•j¢×ì”=}G›þÈÌûû¢r5·5¥„ƒ×ZíõÅä֔þ&žRX*ƒü°Q:ýBÖ.ùžkô){©Ô™B­>´MLZØî’Rf," ŸÊ⟢¢p¦Ò"ìÖ!¡o4•ºÕ††z0ŸŠÎÆm0'$¦g,ˆžòߖö k†bßì°qºU‰L?R©@c‹4¯Öçî쐁 U ú˜Û‹(ZEO DXzÄC=}°×D$ãÞ)é]S²œÄz¿¾ß‚ÝEL·kÍMVañ„%FJ +4ôñ=Mچ™fÒ¶‡AÉÂíÁ|…Ô¤joÁÏ3ÜV5íÇ-:5rKÜ[uò¦\ŽÀÜ]3ނµÂ«âQÙúх åô=}*´TLß8Åî7>Â'±„:LCdh úÕe÷͏M73ëFrԉmÝР“†ÿÀ’ÓM|"6d‡@O…¹‘cs‚Z¡g%n’B³ý£UMŒKÅÖ0Ý8ÒõÏu·ø¶g͜¡ñš¾€ÚÓN Š0þR)h= †þ‘P{nøQ€I3Åß314™’ÐT‘= Ìy”Åy¾–l܅= ÚÃiUCg´WœQ(ŠÁ$^])Ù⑥þ 2­Û·>å˜ms&b¼úªèôQ'Yè¨FüyIr1ýÎmaî0' ÇÈýªÿ’#}^W_W}2QjAÂ*ϐšO¾“rûÿ +Dñöëß_\Z= Â)¡# ú„⟡]ôö¯öx1ÓȒ6γ5_x}']Ö+—ü\c°”O×ì9¯g_³Šd‘óai"©[9ûЀC¹^\:R¢ìŵ‡ýrt‡q׉Çܹ–‰'ÆY[7lÅ4ÓtÒ¡SÛà -W~ üx¯d…ãG@fýÉOsó–Í@O¹ g.æ ,ŒHåÑ?_w‰Š•XÜi~ZS(E¶²ü×¹RJ=M¹Å_=Mø˜ÑL^ålZcþ‹ëÙõðÛà„¸‚õ/ð±Üzé/™whW:ÍÐFÔ #ÉG´ÂÈWŸ²ÿÌM+ínríî#ÌDoñ•„L}ª.–ñ¸ŠçpƒÑ}Ê YW’õ]jãN¬k¸Áç÷F€Lã äªÇÔ)üõ¤ùæÈð} +æ® õ9~%žñõª÷èþæutµØî «ï‚h w3ZyVÖfÛÓÖ/fOP= =M»Ô4ßýa3‘øœ¿„‡$±äšFY\ò[¬)¢Rø¼‘fلO ü71w¿ŠæZlý֋° +ÓÚ? .)fsnW®Æù–«Iò‡Í?Uñš¥A1ƒ¢7+_꼉ßÝÙâÕЦ]s¿îs¿ðS9šÓšŽú ÞWLs_Iu™=M¨6ÛèÝë§bCgт {F¼©¦¶ÌKDZüMv•)Fº»ý»è eI ÏÚëÆ*$&Ù轔Öe´XSX×øØê½ñ4 ÍàG+ôgÒ  ÈVæT[å^~×?|#K·ÇlLÎØi;ùV'j÷œ0ðÀók—=MîAxyvšJbÞà0ŒVHÈA€¤M¸;O¸‘/(SÔ«¦üÆ3؍kU´Jf³)óg»1W¾‚lÄë§1ŠTõù݇’†d%=MaPu™í(pD\0Þ0;7àe“(ÙД´¬µ o6˪@L$Žë¸Ç×cL›Jß¼Òó,]þ&5µÒ‚&ñ´…tÉvâPŠx XŽÔ šÔ8ç‹ÖHëKÊ0]f ê8-rüºªå±­¼(óåНµÒ3äóOôIø—Áþìj# = —bF%4»XîÛð«!@$¹@Bl‘ý’U@O‘EDç/ }òªT3Á$È%nJµ’Æž„[gÊóÀ;=M5»Ã:_ÿq¿BßÀ¥1æ-e ×D¦»6*„Û¿×_ +ÔQ’¦sá0Ž¸êw—Š]ÂÕÌ6Y£>3CëxâF4!y'Èw†±Y¾ŽžñÕõ0ww‹*·ÕX•3ógg5^/’S–Z.´‚ËÆK†9éÓm"Ž}bŽ}âV|‰þPê¬t¤]pbŠ=M»tJ= ^¼-ÄÞ˜=}žWȼ"¾ix=}žØW.¢µ}d=}žÜôwŸ·}S‰!/þ·KÂãŽys}ؚ±Wwþ¿0—˜&)” +±}Èóðí×=M© ~šÜPAŠ9Z†”ƒ*Sό؜ñÑMN·c¶Hï–ëŠB¹]h_þq^&Z=}* „’! ÓœÿÉÊìíƒv‰™“×®>‹BŸŸ²Å2!´4œp_ÊݛÕ!©diŽtÓ7Ȳ¶–®â.;Ù1Ðëb¡º÷ñF"inˆ/­­¯YNÓ(ÐÿÄ<š–›(ÓC–9~õ-­"‹§7LQ‡<1Œ¢‡­ŸAäHÕ«´Dî‹ù–‘PŠ€= ñc{?ýW:Í;Ԃ]cán¿˜¼üÍJŸ£)™Glú!¯dئ:PNÂg½ÍŽ^–JÑjÅ^¿6f(ÄA?anD(°Hsn +$R§Ärkx÷ò­ÅáwۍÈo]?!$"A""÷ð lÄ–ä¾qLô;±óðŒýó;^ð=M,±ð(&²ÀMªªÍü"Kb(6tÒevö&h„ÌD}ÔeŒ¼<}TÑØõnzÞª 7º}óì.$¦‰„1Vå Ç=}5Mþü²!ìm¹™¼6ˆj¦š€›ƒDƒ©èÒ·e § ‚"ŠGœÑÜ%ɶÒÏYa[Jðe#¥ïÔ/;}¿:óöª +¨ÓGÄ< 3mN¢¥¶«Ÿ°XقK—Þ°2ÞŹð¤d|9c¹õ.“J3¼«+™|°*Oôž‘ æï1²„/½©°„ˆ¬·³'´öÛ~ö|õJÛOi¹Ê·û† Ø<¦í>;°HÜVßÒ= &XÀîŽ15 ¦ðöƒÊ0ÊÀùl†=}¯~ñkÄÁ’41qø?ùÕºÏO,K,N¥‘EPÕ§v4‰Íøþú•³¥Êˆ‹k+*5­çr#1DÛ<窣…´¯|{Ù1¬‰ÇÆIje¥Yàkadž°–ÓÊ 3$AßzŽHÇ·Åö­Ë6·Uœl þq5!¢×“EGm*°¥þ6¶ÔùWøJéWÅN$p õ}ÙÕ/}°•,+:Ù +µ'ãŸã²_‰6U˜Á|á÷*c»\ÆU,g*ðÜÆl1ud™ 8¯à“-y÷I ŒÌxÉü.ù†e=Mɔ=Mk«?<çNd2o:Sò°ÑXtÅÝjVZTÃïÎòê;èXúQÉ6ØØ91Ï=M1èpî®Å(è(P I³p¾[Ÿy)$ì$ö®…K÷„¥{®!nP‘Úvä6œÐ’ÈVþCr¶>èqvÉ2ÇtDd@«=M¤c¶ç¨·íi«5A‰›,¸Ôfª/ْX¬‚š×ƒò*2® å¸oô +{ë.»Üy½Ct EâaúÅç¶Gtœd‡nòÔQº5Ñ66/Ë1=}wk*—l$¡J_!JÄ©m,v›À„p£re /7P$Ç.6TAE%8Ō7RÓ]Vú¨µpžPßGOëüâëüÂGO2GO2HO2GO2=Mëe›HI@Kgg,p^›OSü5ÏÆyˤ˜&.‰+&Adëg=MÿšŸ‘O[¦çŒÀ‘mƒØa% É­V­8=MûŽPNfýú’‰0uÝ'|!·‚ÉñjŒÖañ÷eWÂÏÍø4M;ȅ0 À'ú4¨àª¦~F>Dïo6¼.r]“gO:¦]§½„”Xhg†õ(Ýۂ†š‰@´¨¯ß£éD˜üÄF§ƒÃ»y©õŽ@€= ´LM‰ô‚¯[y‡B3솆ÿºw•K)¢w¹ÆFY=MäՉñsÏGBGˆ'÷@Ki=Md¥”Ck¤­3v»Õ=M÷N®fºŠÍ;Çà“³8MG>†Œ(’pÅ ²fÌ ŒÇ$‡€î2Ô.ÿ8ˆ…doÿ£©æ.oŒÏóSÛpX¡ ێzÉw%šUµ¹ÍîԭہMÁ†5fg +ûîBÚþdŸâõ´ñŠB­,ײc‘ÒŽ Pþq×wŠÀ²©Ã= BOµ%DىϪðõ™üQqÀ5 +ÀRÃgèˈ‰øÅ7IÑÜ" eŸø;âqæÞ±g&:ã'sÆk®¨ÏíLàôoªH'÷:'E÷df5*îx= £ñlí®F$«wmٓõîUT¬—»™åÕHFÔ]ò&÷*$Þ)Ê<{\‘ΘÍ?Çâ›V¹"œpžAn·{‘²Îbu¾âaÍ«ªáéĊ9z_KW´ûS§%í ©BÆÝ®¿µt&ƒdùë³ïú7ô£ NÎ'ð µÅ©ïz0´™î¦êUtâKΣ¤=MdTrzU8vM[§óѳ±I„[‚ý¢wIÃÑyn·QÔÝUæµöېðÀ¶{}IC°¶"ë®ó ß›ƒ^vèZ\y}׳BE6’°Èʊ’вJQ$-9Çê~>t‰m w¿²ˆŠ¦¨®®(|nÈÛp».„ÛTÀ^æ©É6•:ݽ獲=}÷ ÕjÛ¼Œ!ÙñI¯Ž.y_ŒüØ5ku–á"P/qžÕ¡>FˆÕëfâ=Mg4‘_’q|= lrö™RCD‘žö™zê]ÚæšKN4_©vÚè}ò͜p[üÊãᮍÓʃ.ÆiñC˜ÿêÀž}2&[»ïmá­rÍ=}ĺ2x>ÄÂéèÖ{ÝÎæ—íǶáN!|Äώd[?9èH^ù—®µ;Z\º¬yI‡ì²p>œÚ¾POŽ?@†º“ý\zþ}53)¡ÐÁÍç6 O#¤ˆáÊcËc£ûÀ¨Û¥Û2¤y£ûVBر«£Š›_ÅcpF£–¤ƒŸËc=M¬ƒ¢g£(þf!yÛãO“í#·ƒm£ºÞñ#Ñ£ï:£áÛ©¢næâ¿ã#/àÁyÏW²C ‡'՟X؈%¦)Ü p¹€ü˜CQõãÓÛ}~¯$OîLàHJ¸cø:«7í­döº¥ºXJæ9Ô÷ÜÀ›ëé0þ“õÕÒÈkîщȺ–õK,þ‰H‡í‘3:?77nóŽKÔæÈÊÖ÷*¯Õw¼=Moøllÿ8#N5£ØÔQ]Vóú1(=}•®ëdɌüŽ×üNihó.ˆF¹Uø†bg…³n ûæyª(…âïþ¨5꯯;Þ_ï «Ö­&tÊBƒ¨Å|’ø ö×P = 4o™Q…”&@²ªÞ= Ê—;·iª*[€/³‰<“{O +ӊ(Ӄ &;Õ8 „8üÂÓoC“ý¢€¸ë€ÓQž;ÖËÖÒß؎Ä)¯Ï«fqF¹ÀÆ1È>›'ô&9(T•j²õÚÙ¡%¸&ù(”F" ”–0†cÿ2S s +{“¦O¦>©Y'®ë=McsԁØÞ©ú;ò}›°1¯‡û{VH!t;¬OÃ?½‡Ü¶q £Î eÃpHXzÿÞ¿žýxÓê¬ P‡\šM'È¿…ë9þÿ„}‚#Î'́ƒ}”÷»é¥¾åzt僵´„ÈAú.C„\}!iÔjÛAڌ¶¾;’ðOŸ ÞÉ(àp’ø;åòXCy¹JùŒÛ51J.Nòvô.=M@ƒo”g1f”ë+³­1 +kË;´«ô7À® Eˆ»¹éôäxT/½1¸xâ{Û¹ûÝysäzü°>;‰{e«j'S†ßMqÊØ>ÔÏzöp‰ýP³5=MX= :¸Š[ð1·u1ºkĒÌï¬v+FÎoŒÍ0Ûçs•2Eî§tävòÐÒ×8Õ/ ž3ùŽ»¤.\i8“{Ô#¤)eÎç³^Hšòtéæ»e½¶g፻¶^À¤g4xŽ³©3èô;¸¹-Ks—Á%ÌÂ>Ð= /³Åas8,}F9ÔRšrsh¿Ø³ú1jé ]Oš+E¶™ÛM94”%k’˜H4v|ß‚ͱÎØÑLN ¤0ãÀØjj®0 i+òwÝeD 缸¶ëûº?k1Zp½r¡ ¢ÍV=}OHV+?®r7šâÔúTÃ\´æ~ÓY^‘É\9<„¹ a§ñ$‘î;òîâ3öuJ?­"ã¡Ãoœ3ÿeKJŠ}T^f[ÞÖQõø|R÷©ìȌĎ랰Y8¦}òþr5IPò„8/0x¼v‰SP—|IëÞ(æ.ɇÕéH#2廗[_¯ÈHÇ·y”-1“c’©ÈQËàH‹(DÛËvšìR Œ„£Ú"/u¡D$uDT˜Â%Þûµ«HÝ>f·!Ô0ŠŸL‡3¼m!_“À÷4{Çýàrá©-¯ú”Êðÿ(jˆè€‹²ÅÎÃÌĖUÒ±T§#i(9í97­öºÛïH¥v•%!ßOWª·Ä~ãÀ½<€A iŽ¶…/%Ýز1PŒÂé Ú/¨Ueiñ$ÛÚOw±·Ü9C±0o»>ôí±ã¥PuÔµ·Ü=}C±0o»ãУ¶åËgí…éð£"}3£Éx{F"S^¼±b^Ù v„wsõ×ý½cë=}P£i,Ðx' S¶¿£aDŠçH‚Oó>.ü,LœD…º‚Lý.œ6Іm…™¹ÿS~©'È3>§,à:FAú4{vìÆùHèâ~ëAú$çpq¬…%=}AúÐûV©¼rf9Ø y’Ñ0\î«ï= ©Hܓ‰±(äâ°6^€ÏOнڀ/}KŒZXÊ]w˜Òbþ/U}Ôn$q2èÚ3¡ˆdüzbP®µPÔ0‰Õ˞í6¡LK¢oЃE¬= Îèt¬ZóÉk+= ¬˜ý À²‚­qAå¬'þä²'þì[¶'2ã[6'㛯'Ӗ›v{Uj˜²^¸¹îŒ,¹<ªJm=MÖ¸ʎ5,ró±Â.Ó=}txHë2ÿë'±: ò>A6Ü3ÚȖùaÈÐ=M%Œmٌ$UÀ°²åœ4“ä ÝÞÇ8èðSæ\ö>qâ¯}ÑxO…üx͒¼É¦;çÒgÿ;»D.úâoÆì:Ñq|Š¨m}'¤@nÍ +Ác[)•Ôph¦ýI”Á­×Åà+(w9¥¨ìGkÁ,Í òש%t’°gX C°C€ ©}½g3¿´‹„Û±F£îÔòêÖú™¼ ÔlÝÂÓª±†FOkéûT•b–l›SOÀ"4²äqǽbê¥,ß*i\ô;S€‘FÀÿž$ªAÉÞF¸l”UKŸÑIè$u¾Oå]É×ʴ̊Œ´Tö>[çƒû ³Ü™¦dÍO =}¿fW,u&Gâþø¦ì>N=}ù»F‰…½.Ö]MÌÔ¡‘c·»vTø02ƃM1†«Mø°=MöÙr /*‚R +ÙÔ ä +\.ô¦Î0ƾ¸êÅé#îmQ‹k;ÞbUä€Jrr ý¬È˜ ¯Mo†,ܲìºBë®N­™äè $*{$ô²ùn]/!§¶­!ª ¢OÖ³©oIz¤4Áeîô[&ãvÃÉÎ{HÍë©Ò\Îú4¥¥ß£»‹œ±WðNÕÔs{BµN+Z‚,ôToI5yhÐ}naO,dèDqU È0q¶œÍRÝÒ4LÜ2¾á{å¬Ï]<º† +}QÅÿ«^pY½ŸŒ.ÓÖv•UÓ\)Œ›ƒ³ I’®ÖŠ¹ q̬vÔ­ "8w¾ñ +I°ÅîHõøì˜úÝwܤßi‹%aƒ0B*;Ó´±ï5Û|ƒK´ú¥²IéëÕ!¾úÆURD՟J7žFEz\û.*zlîAԓ¼…£·”Vä)•«zp!V[á»DBÿx³Ãœ‚Â%:WŽÄËÙ¦ˆ6ó{³Ûyµ2ã ~Ó= !°'c¥‹þóí1ÀëÚ2ÓG„«¦š[ÖÞm3Má0j»)†ÃæÃæMª¼Û]ŠÂ +“1œ½W¬ŸµAEçRè̵·×GÃ;ƒK£ø‹àÇê=}pöÄá²kéâ@§oÎDEÂÈ«™F¡U …v¨bò^ÄÏ×í*Y¿KÝÛގã=}ÆÊ<MâH¡·Ç˜ØßÃ.JpÀ)ñ*,Ë)ШŸÏݘk0-<Òq™ ÿd‘¤7¸¥ƒù¥…W'B.2WKà§Ìëz_و +Žäñ!J^žÇÀf Õ‹Ÿ£…ìµÜ¡ÓÅë Äî€öÉò¥Òimu³Ô(ÌB邒€"‘—,ßà"]!í»1ƒ§=MèCf/WrëF,O(ÄCC1Å*U$J\ŠìV]•AÁ†ò¬ÑÜ'‡Héô2Z>,©ï‰¶Hö¥VڀCJAuĞÿ“ÔKG”;Ë5Þ¿*ðÚûB{½ rèJK+”ˆÿ zþ âÏÔx½†ãõ'»ÞL+0¶Á¯²¸cšG‰:ù=  + +´æVüK¾ C0‚ÎSý‘4Å0= ší⠒-~Šˆ¥ mÒRU…ì8c¹sž\E²¼ïû n¦¸]͈60ÐÃù/Æìâ$Å}}#üÄ°^;¥ŠøKBÍùe…æ!™Ö ˆ lB9Zþ O>£ñop!= Ö)T]ŽÒ"•>(Š¡üâ>?–¾ !zöù†þá›Ta–\‡8 LI¾ºM‹Ä¼ÈÍ%Iãù끞Âz†^Úb{½æ@å@ j¯®[ÖrŸ’Åñú%®d‚m‹FvãüÓÇ},/3ÓÎr¾k:†>Dx²tÁ7_ÔfŸ²ÖJ¿=}òޑÕ|AõEÒ*ù"O& }¥Hˆ0çôWùØ!… +Çs®zã4‘æœr„ ŽPÅgû›lâɝøÑ@ þ~Ê°¶¨ú’퍾Y YÓ·¿~a…²ÆÛіS,‘|Œ6ól\ŸÌ—PË_Vy†Îù ±J¥½„ræΕùìT®G[ù‰BnWôËieºNúûi¨°×@S¤••‘ˆaýP?ÒdçùN:"°”þÅÿŸ[òœp™dÄPÞ02Ùâ¾Þ†אŸŸw +ðƒAŒ, (–<´£é8oŽå¥’ ++»«4D‡¬Ø¥C¹À»ÍÒ°9KÓp*ÖB´¦£¶ÑDfœ’Eƒt8ÔÎÍY˜0ÍEW¢?Ÿ >ø¸ãè#Ûº?b҈®íq¯~Èëî·õ;œ‡î¼P£x~v/Ç!eÌ·5“Šî4_7ÕÊòÄÕËuPÔmN{ô~Ò:!%ªõ±Fc3ÑHüµç°ÅF)wf8—('¬Dc=}ƄH'"må/Á­£7p|© Ò  =}TÍ}œ¨6†jÐáèÔÝyh¸È¬Ôz®1ô2âô«+ùÏ$Ý 0±Á™ +­j›Œ–P–¶™\GB¬žÖ¾šOÂÖù¨½¨¸$%EX,=}ÉÓ(GAӓ=}8Ž%ÅÓmÎ= •Û@2=MÖõ“Ézr¹ý»Z+ïuûGï;ï&#ÇüüH]X•ååd¨r¯Œ*É՞ñéx&*¯ÕX¸ç7NO k™CaàOB„zrSEs®8·Œþ{:4G= —æô‚«Ò„éå©#EÜu]õßºSÑÍ£ðÙs¨G6ú‘!óñ‰gÔ" ÎLiý¦Qð +¤º,DÃ'óö¼Gâ{ü>Á’¬¹(¯â2©ë£ЄèïDI+Àgï k7iï8¥ؔ“í3ÿð(—èsnĨÀ†Ï•êª¦ßHAu-/ë¦ÜX'mÞ=MÎçnKk fõMÓ<–ùŒ +͍ÆEÒ̚®fÌóV\È!”ÓñQq¹^4SyáèÏ-=}<¹×3ýy À’ ·ðmå6·¡­MI¾<Vrº2F}Õ²jAŠ¿«Êðå„w°F+i×?_˜}AÒð(ûï~wÖìzW|Ô]ÇA¥ˆ³l<@gúæ©GŸNà­ß·v›´Ósx)™<›ýޙƒóAЗ|d4hÐ\k +'Î6­óbö¶Eaó-”œdcóöçšë)<7*ãkcëÌ·ãk·ۄ¤ £·q¬²þŒ?Á2ÿ²m †>L š”ú=MxoèÌìŒÎº?€LŽ=M¬V·Â÷¢ñ÷¢0<èäÇå“Áü—ðxîG5,ñi¤Á×׿±\rˆx\.)¿À¾c{žùÀYKž$öGÍmÓa°ÿ)sJÒCÓØw‡øè²1yÞ±µü·æ«wê /¤"+œÅL‰œýÓª*¤.ÄxȂkâw%¦6…eºå¿æÃ.|„sƒ!-07ê¿#ð¸s*IY±'UZ¬@®óõ¦L·Î¢S&k@>øþ8g{O qèª ³ÄE&õ#«CIþóö‘HL)Cd±äbãûÁ úb¾àÇóQòOõ »¿Ç‘|c>/ã—˜H–û7».\ZiéÊÌÔÐ1syìæjƒÓ¼–Ô¤•dŸ—A·Ä;ïpÜÀãזìW7˜€·[~yäÔ=}é3Õ0¡ÀX¾Óqä@>Ä{°÷¯ÕøÃ=}Cã×ÿH»B»ÕB=MåÛ¬o=}ó'Cä®ö +'=}=}¦M…ÞÖ0Ts*he–óÁÃtÛVXÑÔSB+¹f}=}9”íÍþgҚ&ucõ›m6~ + ÀH÷ý:Q¼BÍ)³’#Ì'žDDšI,ˆ¨pDIºUŠ=Mѯ ±w'A¾ì¤ì4K+÷ò¤ˆ¤Û·&æ{«§ô‰:|U®õ"ûÿ~S+Yɋ¶±Z•˜|á,NÐoGIöçJ€-°º úIÉ8·Ù­®¡¹'_,È +Z±LORŠü Vpêh«RÜ IÀÑ¥o騋y㵤†æº ±dÒ@T¨àNۋ¶fòn×ÕçYӄ} Ö¶Ûø° ]_¤€ ¶ˆn ¥š†* °Þú¦=M/ ^N©òߌEŒ®Ý†ZÕs´ +1Wޔ.«:àÛ¶UMÖ'ø*TM̱ö딤Ïv]zœ‡t'I„5=}¶þ‰^cˆì^Q‡Ô—ÃÏöv;ïÂ-rŸ¯" ;»º»1è«[&@»R=M]-„*àç½µ×µä7כ@ ‹¼=}'ÀáŸæÄÃú‹\Näe-^ö•ìý¨8§pöè H ð£º&ËÆdt#Àȁñ²²w5kÊ_^RÓþ%c}ç:—DŠ6ƒN¹ø-+Nuº·‰cºY\kÔp]Ž´"É»K[¬‰=M 0Õÿ‘ÖÖ ×½¦)Dδ{Ôºõ´šÍm7º©l¸<ÞÎdú*Y@ Ž+ÔG;Aº5*L?¬/Ðý˜3ŽšUïUÇkh¬è£Q1 Ó~§ÏççŽ,i¹Åõxs£îþÀPû÷ÀoʑD6¬Ý= È¼DýMË34²C Š^‡¸¾£±¹hÁéKñ€˜ózŽ–¤/StÓ¹weP—ͱÆBů0²Í7ñ1ôfãËßúp[^pô’Ü8Ì2÷It0²‡>Â.Ì46bà†­/”YÀ–=}ŒáånӒ‘ÜûôQɹcœ$dJ´d*+©ytç¾ìVY1´©eo?s;’þÓ|i}kÀëöH‚§‡ZõFÜN(µŸâ¾Ì/C‡B,\¡g®E= z¦G ʁ\ÙZN¡ñ{:w”WQ½%zÎôÆýˆ:XNü®l2¾þï- €¼âë*6_E.²Ö>†¯§Ñ²«lÕ bo”ÿŠ›T¼=Mô¡¥5»Dðs‰ìz”7÷,Ç?]¸vŒÿ±v[Òð­Òù)h?/Xði³Ù¦î7Áš%Ë&ü\×/–Ò6@³xÈ7=}<ÂOR'ŸrJ!3ueh¼#H+[¶Ð!ã¢Ö¼È³ˆ¶»½±_Þ½‰÷Œywñ&C§&Aþ¦bÞe?Ä´jãÍÿ•µÁÇfø¶«ÜèEÀŒöñ(ÀâèèéÝw¼ ¦%(Ó?{Žò¥˜kŠÄ/©yxÓÂ;Š·•æ„74‰Ö5ٍ®jëËÊҍ>#g¬ûkMJOŸËHIÉuTä‚(tZr»“_‚§U‰¥_wßڂGNE‚m e(|¨Š“,=MYz»¿Ù™I*‡èf/k]i jÿ&rpP;~ß]û4Èv¹HCa,Jy1”Y+LÙT((CÀV‰ÙS‰ý1Ð8ÞnÊÉÆ<ÌòÎ'¹&ìT…̸BÖarÄÿîˆÝÇ°¼9“°¨2¬ø—îÛ½³q;Ô5rë\“ù?€ÆÍâ²x©çè v‡÷BA©GE)ãà×›AõüP‡ÌÂe÷jIÔ鈁4pèUv=} þ¾‘¬œ;/ùç4ìôdzóÃÐ&³urÐÙòˆònUmh+ÍlÝEí¶m„¥åó!ë¹gK€áQ¹Š…t­jR…ª÷ÃÊ2Œíd¿bm’ËrÝÎíY­_»o-o½;úÞÔ +DSfí,Lú«&ÂûöW’'€K¨Òâ­IÌ_B†zQh^9šF˵éW:=}ïì×-²ÏðÑær€–c€üù¬Ñ/ԗÃDEù´“i¼QP4%Úíö”ð]¡åŠa–E×òg$€ éÇbÇìUbÔ¯Â×£¦Ã£c™lê¥õ3)yÉØïnÿš—Ùïnÿš—Ùïnÿš—ÙïnB°M]ù£)DÀˆñc±[^ŸÍÜ2ÃÌ8 +v†±l8‹22)vß îóÝÏ?xÎÄwêÚËéÂx÷ù…"¨xÆÑëÞ-ϒ-ü^Çgæ,r‰x"Վ2ípÔ±­Y}QË&¶g + oñÛ²[K(ý ™â8¬—Z¢‡Ò¸Î&\@¿®Å„úÊ Ü‚ª9ƞ÷.8‹VâöémÏ8pO{ÜT1Oâ‘p¬Ïj=M9Â=  *7ɲÐÖñ튕ý} µŠŒº-‰VžSlTüuŠ";M·y +jƹÿn±1=Mꁄ& OŒÛ½‡íf· •â‡T09*ÂD9qôq¾—ž/‡ŽatŠ6x…‚¥”u»™=M²–$€“r&áÛ߁¿fœ †¸{¤[Q ¾ß|±*‰q'¢<Üݐ¥ |‘ {ƒ06ô¡ëM±e0Á«Ì,£œéj}û›*Ksåʤ¶THiý°}xã-¹Ê]ﱅ;+là1gR¿ÎܙŸ‰€g”²*ïY£ÝiÍh+hém{OÿˆJ^:SUú4óˆÉe~ìo‡ÎèDö]ûÁœ÷xDZ¼}4è9±ޜǙ‰= ²î\+ÈzR +Y²šV¡Ÿ¯îv= l}aûiÍ>t(= iWƒæÊÝJØFfM· úCát¶ ;¦¨u<„éQHó–wƒ]=}¯uÚôõZ‡ ƒ£(2òD[]öØ.™‡ti¸Ë9âDÀ®t=}"átnPèwŸ{òý<øòb= >dÎóª&°ƒ·% šY;Úf·‚P]ƒ^ ²Ë®„,a+±½«ß» Š)deë'‡ýe+µ•¯’0ä~I”« .Ø 6ô ݸP"ñj5–Vó‘†#¹0T󐯔.Îïêpêö3ªMúDxÉÂєæZ£Ï Î«¨Z%„Š½-@Òf“ï§õÚç”fË÷wçHÏmð…3~³*w:ÍÀ-jñš§WÙñ' űûM0ä¹½;wƒ\©j=M„7Gh ~ýŸ94ï…[Bk¾j4¶¿FR7Š[ƒK͇»üddNÜ'1î°¿™ð¿¡ìmÇð¢x¡j/øù9n/Ož‚kXAš,Ì.íÌÀ-7-† efzñeTòΨ–öŒ%,î$’˜ÂdHîÊT!Kÿo¾ʑƒÒ±0ûÏ!_Vô_s”3{o¡_ûX“1Ɯ@[֘:ÖbÈÎSf* +ŒŽªÕ‚tiÛYÍ©n€Ø2Ð諾R °ÈîüzÂN<ìZÐÏŒÁ™W¢´™GÌ&ø¼Z ‡TjZ’U°¨HvÙÕO3ØrŸh¥éÙTc“9—= ¤H›XIIטú-v.qéšJo+dw +Œ«}?QCöHçI†¡Éz·Þsϝ8ˆë„‘– ºÝ¡È;9‡èt'ö¬„ˆ¥]Ž\']ùÑJ#xÎìØЌá‚ãœnYsÑY&ŸðÒ’ÆŽ"±4PvÔM¾=}éÝ)ÊLt¼Õ;ìÔ<Üw‘“¸}a˜½ý.éÐ= ê¼®Átêöu“º×=Mt¾mÿ™$ÑOå(¾"óqµ}“-ìNG”Š=MŒwH©U™5^o­ ¬Ô뺕 ‹©¾CÔŸý=}ú¾¯*±À=Mz´’K։m^eX +ם®Ôøàԑð»Ôf,=  OÀ#I\&ƒâw¥¦=}°ä2êæTö14AÆsL‚ˇÁ09O“YØ݌«ëÞÌ$¶äx£ /(‡[€?£†ÜÙ+.ÇRìSŸ×¼¡Ñös™„÷;TŒû" ©I‹r%@rÏmTj6Ü+=}.Ql1˜q¬L@3×h¸´¬~â²vQpj›²‘óùcõz®-ف»‚dªQTws²Ú½ŸsRsÂê©cŒçÃiO¯%RÓ¯®ä«¯(*ݯTFftLÓ¿ÖZé—;ëß ¿¬YË­.^èÆÖƽ·¦h»Gï.(–æ,¿Q‡h¢ ¸ï²Mø² ‹?Î+j—4¬Ë8# BµS÷ÅÑÒí'f ç›ófcô°j=M§¹ëzy½Ë×»7C¤H S™H©9Ýý{°x….= ¹€…Xs~LhHÏп ô•î.É¿Ñ Û_§1?Œ¿½ò1®ô¿nºwPŠ‹>otØ(FÏjŒn¿¬ZÛ¿Á{âŠû”9æ™<†Œ‚1Ј¿Ê"í‚NÛyx'w÷zûÙûØ×…{È š*fòãò•øõÌ 3ŸœRTÒ$ OUÿ G "Þúôž@üM}À¸þ9I/Kõ™= õŒ¡Å| +ö$UèÊ<“ùÊOéÑ;T¶—ž®(Z¹®À7>'úž±¬‡šåžíÄÒìêÿsNP›õæïpÁÇaaÌ1ÂÖäoVAÈ1íºF',1p[›Ñ\;XP QZð5Yú¯ï7!íOyr´"ȺNÅÂ-ºa·€žÏ½qѶþ xAœ±‘eaôòØWÂÎoYY êSÞ ­‰Ô®OI= °.¢Ü(àÌ@p¡x|íòyø£vR² +î÷,Œ¥ùú= ;НY?X¢U5È:R°ÙTۜÙo +ºÞÒOÞkU‰Áüúv{·-pb1 o 2ŽÒVjRTaZ<&Ÿ¤ö‹ˆÖ”ُp¾yŠxêùžˆ¾~zóo/úÓVüxˆ}‚oÇçé¤@þópÀíKòîç´Ðý4¢ Ù‡a^àð2ë‰v^s²õ‘ìsB}a—_£Ü¢ñ=}mÄ×Uìñ4ÉF ëÂη8—f(tF¨Kèm- æþòIR¶JupˆÖ‹€|Wbfÿ…Aq'V÷äÆ¥_ uÀâÕ9ªô“1óØ+G^»íN÷ôè[=}5ÍÛ0më:›TüíÐþÒJ¶Òú3v„ÇM-è}bzóôJ×Eàðn~ë9ÞÙv*KPÖ Þ\°ìà0vE…àg’’ÈF6žLŠ9&õ ;U_2uS jlcÝ8K݀ %Y×ÞèêÍñö|JV‡A=}CvºV̄—è=}ŸÕ|BîÿHØ>QöBXÚ ðu]^Ñ€BùÐë0ŸÔ‰œ—çþã= œ=MƒÒl„½U›Ð(Ò ò@ùGÑÎâö“=}RGV„Þ= ÿëYº6ŒAõ•€ñ²ú33•.uÕMk—ï°¨ytd?‚™íÆ\™*¡ÅffRpƒ›= Üq  $ò(Д_몾-ÿE*ȝ»õ#Þh) '9èi{f§ZaXeÒPô¡T°_®žzÓ–ßu¤‘>%€+á@³6€¼Æq$æ=Múßâs°Šêl]Á+ü™ºIəç ûÒߖ°PæÂ~=}4EÒA±*\@žæê£ú±ãdj$Ëbâ« Ò;ƅ#¨ÁR½/ÔÔæ3†Ý·»â¯ÚªmÔpە¢À1¼œÆ˜oë¯{ß­¬tF4Ünµ)ü„N4¥²aÌSœ-ØÏZÎ4ÁÑCqé' )∯J–«•ðã'š»ç2¿®N †‘¡Û7¾2²A¶So…_žœÚa}:i¹0ÉåRhÇ@'ù.ÊæOÀ5¾“ß­õÆJE^hח¢×°ÚZñêF€¯=}$¤Ê EFžÏ ؾªV +¦!™“Ž#Qü±;†Ôª€˜‰ÅÃÑ =}ÆY8ÞåXy¬*ۆiÀ +/“ä<ÎÙhU› p°âÀŠÄCÁßx–”}kÀ¨~€ÔFbªI?—cHʉe 5ºÂ„qïßmš)F= ²_– óÜfº©š cy²úR›Äë„2ÀŒ¡;¹#0þ¥ƒQÂ+ïøÃ"²ç¾*ÃWr°e.€·/È°d¼%ÖÚæÃZ«h'xDKÏ°h;LÓò¬fü= —¯jl?—Ú0c›ƒ«»‰èÃTÇ©çÅÓÞµèéô‹Œµ¨&ôëP5QFYÕ½°œt{}ЩøÁԋÇ©hÔkÀµ.,Tëq+h@UûÁ¿* ¤Sâ·*Ғ†ƒsè(FÖø›WåÝÖÿùDðH­é¦†ô†¿2ŠN…4ÔÁ=}uïA#±6¶“ÌÙ¤ +šÊ€ §gyÇÃKúÅeÊÉÅÌÏ´ü>¶D6@+3š,K=MQi!=Mç{M´Rii¸=M·Áôƕ)½•Ò=M—I$ö²°Î×óryÃÍç&ön׳6Ø "]ásÖ.©ÎŽHÐi˜xSå®8@¹¹–WS¬z…åЕ٠ԋ#¹ÐòÔÊò®VjýÌ ÐOíXûÿR(&Áêé1ðàܗÏÛ¯Ðܙ1„[â<&àjòÚ11x¿²…Ûq1”nÜwÛßÚw‡žÜ·êÜ­vÛ B‰óÛ‡ kˆ;"&|À1‹ª¿&A¿ÐƒKd•é­ž1†—êÌaÒuž¿"ë-ÛíîÛmÛ¥¡ˆKQƒ“œha5FO-fK)FðÐê6‡üÀjq1ÌbÜíǍ©Ì_ÇW4ÆÕ[,ÆôõÆÔ¢fÒôìYëÕÇúȜ5²5Åì(GýõÒ 7× ‚¢¢ë P½€\4xj~\ùä(ïTC :ÅÞDëtœU<$o|ýt8˜z2Œy1ž®OhÕ +2ñm/ˆR¯Þˆvî¡m‡.8ÀÙ̈z±Ì†oÖ8qΑ͒=  R_HêóÞW¸}'˜³ÉX׺=}ý¬ìžÉ«®2pµ½©«¸¹„%†ÑW"SÿÛI^ñË÷¶‘lš¬vž¿º¥ +A¹]m´‰›‚³]qÇo2ȗ”è;PͺÍÀ¨ ”GZa[!{¢Æ«Á£f£#Ã#pY~Ÿ>¾X~Y~Y~Y8C€^ZtVf Ž.æÇJ%·ªrt4N—žÀ½Îãú%BvS¢Þ]5 8]: Hà"üËM;>uÛ'Œqá ýÌQë*œø,ðï6í,Ök3±Z>u—¼Î½9XF¸°ñˆFÞ¬ºöÝæ£@@²ÄÎBë}m¼êéz5 ~i¯Õ@kDP&(GÜôéF¾=M‹–Xéƒ F’½>ÀCl"÷6Úð\.l^·œú#–=M«˜Pèðt©[jéƒÙŸ–|,Ê!C½aªձfô_>â$i† +3•œß)ØÑ$ژÍÑQa,>‘ãl°{[‹ÄM»AC̆Ü1°¾b‘¶ñ¨!hðŸ'dÂ÷Ô# À®*UF2(¾pœÔõÌ'¦™ƒ9å{à܋RögnüÈ °Mƒ J½oýדRü®‘P݃y&¢+¤º¾fVÌáÂÚ*§ü–¿³X(X<à×EÀtw¯r0K]Š¤´äÒ+[žCMd²ñž¦4žÚ»‚ÀæRÆ¿íúEëÄ©Þ­†cß´î6ÔýA-~ÚÕ3A¨r<¿·V‡†ìäÄ ‘8ÕC¯Zñ÷ÅeQ½Ec|£Š= p{ƒ{­¢vÀó¬%y6g:˜†Ór³Ÿ90%|¿š‘ò¤0֛NÙ2¨%ƒ¤Cu§£cYzY""‘yY~Y ~Y~YÚVMBÛÊÇ;ÂÇ, S×ÒnÓÈô9Zvˆ\œý$=}ýè-yÍVnü(P¦xë\Fñå<©Îz˜ér^²¶•\âmU¦L]ß«P-dˑ½mugÏÀdƒ#4ûÒ½08n»r½ê@€ ñBë9€Ç=M ñ„Cn÷׺ðŠ9¢¯)Ñ@h3'|ÿ‚Ô:\–û¤A5.[¢!Ô¢éæú$?ýWˆ=MV’5Ñ&ø—¼=McèPH ÒF˜­é˜hêzxÏ~U¹1ÿ \$ÝPð»9‰€NPo€qc_À{â~h0\[ù[º–Zž4xÝkžæÏÚße‡ðj;N%æaʔ_=}üöqµø1ªbÒS~È9š= eigNÿÀ^Øڌù^pwFÛ[ÑFʂ†Km z‚Šu¦Ù[àgŸjÆ‚ ï•DÊûQ- ‰Ö…ªß +[›®mnÓØ¡Èø‘R» ›=}[º ]—9ú‚”h)o¢#‹2ÿõžg-‘ò_L›/ñ}º™*HyŒ¾È)‚Ô¢¦˜žâtÜ¢.o bl{“*h"4?¢2춰ÁgÂømÈï~ej­ö=}oSî×ÊÛo%<á9WÛýDp€âً YžÎÞ%Á}–I¦²ÒÝ5u,Þ*?ÜV~¨nÐQïþŠézw˜àÛDŒ,…ÅÒ=MŠv)²ZɞÕ_ÂmF <Øß#ò&¦<àëHad¯¸e´Xóm8f›P»q֜«oÆ :1…]÷×6Èó7+Hb¿h…¹hFÐíCPÊ4‡AÇu5´˜GSÿ7->Ë°¦T¯=}hÕ¬·reýžÊl¿õGô:l†Cá¨OøËG÷T+ÚmhOóÐ#Ìp½‡˜ÑÊ= ¨| ÎL½û(—3=Mi°N˜+ý1MfïàȆ½»ÙT4Ð6>ÞX¼=Mò­ù„ï.Fq§¨\ƒ^y(ò9QËI[UH@¾~\tžP¾pÍ,a‡ñÿ/ªZÓud6¶ÖßÜud.a= _›•m®ž—ñVÚ{ªŽøá络×e:؂œ†jBî!/“j@â(ɤÓÅ#Ž¥K¯g ÃR¥&˵g£p-¨–•ìÓqŒÄû¯„[Ëù墽m>õËÜ© fë>¹iœbWK°ŠtŒ7´A´då0ëe=MżÕ5$‘ôÛï1EzšË¹êZâ=}ayÔ¯½½&z.»iÇhÕ ðÏô†;Î0t(ÛÕ= …üØÔA؆lrï˜)§9É5Ïìi<çiÝʄ×ŬtvǕF5ÔÒ¼n‚l ‡JÓö­Ž]GuRÄ8Ò*õtÕî†åZןÒG´„7q*$Œç‚íÊgÞ&ŽÆÖ³ßoƒúãɦjU‰ìÉà&VØá®0Jü°mIŽ[Ýám (±Òꇉ±<‘\Â3îgHÿù|‡Tð8ê˜tßٌŠVKÙÂBPœwXÑÃË^#X®®ÛŸa#A·÷ÄjRºõþg¯ü´•àè_úï>±oÐi‡èÔ¥’µÙ™Ñ„4µñÌÈÑR7MHûßÎH2þ¼àø«:4€E¿R›y2̊hé®Íø÷dn¸/÷d¬^íù×÷…[]5gZ8•KåÏNåYT­€òø·ú&E=}f¾N˜D=}ðÁØ;ë=MSþöfh:Ø;ÞwuHI9\®=MÜ"J9è)»‰w„Ôa1:ʎ+òûàò]z†[TAQR<€c„E©Éð=MCpL©ïý×ÈC´ìÆáî½\V´pÉW=}ûwF,þ=}{™C,£àÄ”å?¬<= ék‰å‡ýÅQç-[R³ÔT+Š:èßÈ /2;>øqò·ÆÝà †ÞԖïțÉìó:ó_çe~®µ¿¡í‹Çù17n HþÈȉM7ap÷Ýl›;ÈfX2¯€HÕ9B8”ŸN/Î GTY,‡OAÏÊ:?¨²‡oNÃpød=}ï¨Þ^Ìórù“ b% ò·? JÇlèìr×ÈèÈÉΔ}Ig”)5.â8[>K«®øtE÷è2aÍ9oøÔR­F^ÍM¢Ÿ‚ç0ôS=}D¨=M9öÖ-½ð=M­r¢¢0½@±€»—2¤#X¦­¥Ë;ºwYÎMñ~Y€N€}YPCY~Y¢É^üf79)ámÖ°ÖÙ»ý@Ùß=Mk¼Tî\úgõb)ê.¼lÝjÕ&j¬n5ª9íâ϶ÛÑ +ËŒ ø‚WN†³j˜ü1¿Â±ÝÕdžۼ”7=}nÖEGJÀr0™AٍjÕЕ¿‚ƒÌ{vŒMJò™BApT¦Ôv©‡®ÇÇ[ CNc;$œ&¦ޅce$*¦Br§Ñ€±¯!¸›˜Æóá)sÅ<óÔ.“RCÓ½„äØĶÄê„D’„lÄz¿Do­Ä‚©„‹„xÈĊàDgîÄ~º„ŒâÄgõÉô•JúM‰÷í¸ù…9óÙúó­zõiÚù™XôqøY—ö/ËlêÍöÊÍÒ Í ¹ÌùÌLyÌòYͶšÍl1̈́/“U•9•D¡(Ն= õ>•BÐ#¼Õ¯FÓ?~i7U~YŽqY~Y~Y +M¡z“›‘ž„AKö»×Òµýº¦Ð+*]Êä¼öDVŒ”= ±p-%Šé<•F…èó45ËðܗQ5žMFs9©Ëôöw]Èý{¹À+ñèžEÜ ó6¤Ë™³WÛmؽPÁ*ÅïåøJEôÖs]| ‚ßWÄýY§˜1-Påbyj’'ÙäLYFÄÞt8€Ëqá÷…#Áå 2CäjóR¶KtÌ7š/ŠBæÊqFºô-n z¸zæjRÞ"¶Ð= (å€äx’jàžá-³ˆ'MàéPACòô2 +Kfwƒ¨Í¡µH(¥béJe¾÷„Эš±Z)’ôk² Qœ+±ýLò‹/8Ÿ/™þ‰Òqþ‹RK(ÀTǂóÊÞ ôaFMÙfû?ÂK_°Y™wŸçOT°V¸Aý“Ë$Uùn}û¾Ö,PZ{ñ~È^šTàZú™q៝! ha|š"a–" ¢= ÂC†D]Ÿ©ý£H¢×N)®ÙòmdÙaŒàڑš?ÚcÚÎcÆÛD¥ýÛ= ¥/Ûï‡QۆHxÛjÆ£ÜKºÜ)8ÓÜ YîÜãj ܪ‡&Ü ÿ7ÜboHÜ©Ø[Üä8nÜ ‚Üà˜Ü[§d¦#»ë·¨S}Y¾–‚|OP~Y~Y~Y8GO ÁBZÖ°(ftA® (^oҝúÊ Ô¢š¶>ÃgQ¹ÍU¶=}o‰;´þWY²ÂÜր‚ û#Ë.Œ,ay¼ïüF+Tƒ½ùYb@àë½AÖ/b¨,>QƑrþ‹R*^ Š^¦7L/a9ADÑÿIʌÚl02ôp0B ’Bד¤ˆ ¢?7t<‰R‡Ÿ42IºçŒ?ÏÀqöɆµQsI[´ µáåiRϋ#>°ýññúÝz‡ì²\ŸKÔ+-àeŒ^»=MÞ4ëÎIõìXÑ.a¸ˆ6ú ¬ €ôì¢QNÊbžÐgÐvìMÜ × !'OÉ r߄”›¿þ(W,ØsÑþ2Œ‹ð{Œ\¸øYޓ>x_X~*¦ªD¿§)¸j”~—ÌÛ@ߪ: +º”:„¸;º*¡~Ûc²2õ«:ñŸ£ÒB4ܘ¾×§¢åê¢b‹· «0ˆò4”¥Ñڂƒóxõž/Q^¿[Úm06´Ÿ“ôµéqK5éh 7ø%VK­¥§xCÄK$EýÓ:täa]Á­o¯ˆ 'î¬ÉsMÕ&¢'¨™ü†¢’4f 2p‰1{>„/q¼úk‚—ãXCºI¦ sۍª­gGéÓqø'…“œ«7Îé„𯗑hæjÉ´"Òîä±½Ùù vB|k2nh"Z®Cºÿ§ŽH›Ð_¿”Ke °ÝAzf_^´n7ý™ãÞyèeø² ¹S³ÈòꓘۗFÊDÃß&V:ŠDtZ+È%ƒ¤S­££CY~™nY|±Â|YÔ~Y~Y^kàü†y®P¼ ›“_ÒòNžu£Ý%©•€u¯*Ó…ÓIaÀñ’Æ”´/…ÿ  ¥÷iÕK¿–¸ÊÓLŜÍ6õâ(Ùdי˜A$~<ÿBÛ>Hé+ÿÚ2d– Ä x.›–¬z +ÏF|ܵŠùE€S­NR›S!À^uy¶—Æö¹ êo¹Ù+Yu\Þ5sºnڐˆ’j“uäi/ào”‹Æÿ/8*ò³â‡·^Fñ–ƒ–üAÛrh<º Ñ= g°jÎ02Ê!Y§h°5«8éõþ9F‡Œõ´„õªLµóEi:ó°¹ý ”—†¯‚ˆpØĎ²+ÔÿB-²²3”3cª2‹ÎoÿpÊoúmã( +'nßêø¨˜µÒÜҔ-bµR”4&b—þ/‡ÄR—AdÂ žÆH…òϝ<bcZR/t¡é+ŒÑÞ¡ÃošÊ¶E"T֖ڞΡSK†ÒÈ梖]ÙPÎÛ_êºd¨àÁ̎Ƙg#|b°ZØ;ÔE¶Þðt> 1 P¨nòý…Ih—yÿYSäÐe9N8oÁ„#šÍêy?…ac¼¢ÑŸ¯èY0DßTh6·ÌÒ]væ DÒÍF Ì|Ác8ãџ®… ӆ^åSþ´i,GaèÚ×5Žôïÿ¾&aåÏà—…û=}¹r5Ô,WÀì…z.©œJS꽺ë +&Ó&å:ïÇýUS;æSúšßG^•Ì|ükIŠè?²Ò ŠKõýq:ÄuÑÊO[%e8ø'®N´ªysÕU1úŽÜ ycE9éŚØVˆ®èPK +vN±åvÞ¼ÜD>£¯¥¤£™?~_Ä~ûQÐ~V~qØ~Yþ¢*¤o­½#€$@Ó«žCä[â;@6*ƒ»Ù'ªò)Û»…)ĕÛúº2‰«¹Í1gfËA82ep×^š/äM¯‰q¥?ÞÒkîäÄ}¥'ë Å/{¥´_Uç“óºè^»ô7^1艍Û;ÛA:†´9>c“P¶Ü‚ß´:ìo5†i߂juÀžT³à#„¤ÁG“fÄ/²Âii´Ž2ƒ¿·P×à1}}¶_½µ‚/6+^?užvëÁàfr=œu_’3éʉÏP9ŠSÁ> ºK>´(y..a'(xIb_åˆDN¯?Ò&R¯LU«]†'íÒàðm(I•¹dZ< *¾Ò‘u"—Á¨î’Ög¦ºâV¢æÓ'm.jo۔'‘8ò<ě¯ˆ +,qý*ºß4ì*oÎåG6ݎ°îªaÈEƒÐq¤’ëSr9ò œ4ªù¼Н,krB¡'6 +õâÆWž®r!DtúOðaêã1¶Â‡[sË*E/ßìL•~FãgÒ¨AÑöçõ4híO8ú…Jµ18´Ìói‹[­µ„ͯ~EíX^͘Vx³Ôó†{ _áKV_è@k>½qxã;É*eØ\_ø®°ÒЉVn÷>û´ÀÁ̋S]úª„Ê]/Ow‰Èà1HXBÔä ×@*¤p–¯,ÔØÇóo+çÆ©½Æ˜m»>© ×d҂'Jðü¼m[€ /˜Ú|©Ñ;†]c¥ôî®WÉýUën5O4ù{ YåT~-RòPÔOXɗ]°F­[Äîñ5ÐZ±{Ä» ê7[à‰âôý†#->¦Y®¿ìXm÷ÊŒÞôΏo®¸ +ɱđF®É€Ñ_‘mVéúá‚fQ0N‘Ïqêø}&äLÁK”/Êè^= ±™åä>ºb= ^dªÂŸú›uŠ…n4(!›|TyÚ!; †‡‡’¯Ø›ñ[{²ïØ"“üƒÊ7"Åڟºù"´Ú“Ú¥Â!DŠÚ¢ žÂ_B¡úvÍŸfO™Âú’›VauBlÚ¥³Ï°ãçÉ3\($]·g.Ã!?® ùÓU +åëﮢlóõ5æ\ϯ„gÓ%²*–ØÑ?ªÆû¹¶d[ 4/1-ç·vÅE{[Þ=}Ît‹/ÄÐÇ)|Þ¶¿îa÷¿*&…+5/Š ß赬«ëaçż¡,‹-Êqâ,H…l¯šòI=}·U¡H3çÍl¢õlÆ0I" «,JVqâÀ¼”¯/ Ök·r ãɲÈU«²kaÙM$|쉓ÓË*½LÿÁ©ŠuXà²83ß ’oÊÃ×Â|¨«)º“ÄòÅ­üaZ+kş™¸–Ä];fªí;¾þå’dõU†íœ[¯~'Õw29–ÑL?ªjÎ3ðLƒelíGv¡¢¸ŠÕM[ÏppO=MÁBN„ ñ°=Mº=MÔrNh–õÀĨLJTKAôU°oÌ#Ž0ë:ڕ— ¶ý8ð[€ÉM]}óu1øîÞâA³zyät.ñýÝݼ•]®t‘ÑIb Ú΁šSYb*˜ÂüÞS28BžûÛ[B žô›2D£+&¤c nYz]:Ö!oY8Ô~Y>€pYþvt…ú)¹ Wë®,AÙêUW,=Ms y´°‹3FæF±dj ÕwˆQÑ,f¼ÿ:þé'‰ŽÔ'Ážñ‹DEòù$áXƘ|€OrÞ¶¦®°³1ÕCõcµöæ1¸½• 7Ä}½æ¿o/«ÍÕÅ!W´ /k×ÖÉVk»d Øi›<<ezôÉÿú>S€w7”(IWÁí'}7òÉ ÒÓF’ëÖå=}p[ñaÜÄÆo áñF¹oäðö®¯2XClc¥P¿®ÚûŽS¨<9ÏkW‡PȜªÐF _Ìÿ’p4ºçªœÓT@²2¹›³!n*ñqaï6›UEÒÊòœtg2ÖÜ!P˜‘â"–ÆԁBZ= Ÿëñ©èTR·– +ètŽå·ô‰tp1I]Õ½.t/Àpš#»G¢jS ¯Zqg¿.Ïd&”}³.„vûQiÔò¹êœ›ÛÀ.F‰¿b††Œ}àAFî…T_¼òQ¥€­¶KLðCê¥ ‚Çó´3+žb,ÿ@?ë0Ý´ª@Ç ÈɁÆ,Qî5{à,²ùl[‰È¶<BÈFŠ««ãc(á¥]Òº“„)#±ù×¾O©æ¡ý‹²Ív»ÿ3é>m×µÚI”ˆ½î?u´·JKÝ@{pŒ/"?q¸Š¯oîÕ«Plé´2ÖSq‡ñôÉÖNÕì~;l<ª<·ÞTÜâ®fDüRpEj@ύOVLnmI¢U9 +F"Ð>°I܇H‰sà*'œÜ/Þ>fÜ@ÿ!j‡…sѺŠL\»ÀnˆqŠÿ¹¨‰ôÑr†Œ+ß]o†mVßŕŒ;rĜü˜šz–üýã¢7¥…^· + ¤ >®šX£èóÄ(ßÍgþÄA2­Y΅ú ´=}èwÒËe¢ï´¾! ûÔ°mñ0ËéÔQ2-”YÐdÍF' +àíûàJ§<]'ú틍mèÌ¡ØHWýþ톘õɼ8ÔÕQ/ÑPn+Àúi†wàÌfkQ?¤Œˆ?ù1ho519ö—Q?ÿš­å®Í›yR%°®ÍËâüdXÒ¸·œ­üý͇|ęî('A¸µŸæ+ø#+ވŠ¯¸4_ïg„VŅ"+;‹Ò‰õ<»@Ä¿:+TâЉjºÔ½¬èµžîûàò%ž¬¬¦‚ì{ŒÅˆ97ҀG;͈máÌîAëôûl›5ÇFUX/ºÆ5ôi­ÜÞ凳m<Óç14¿öX?h’‡›Üλ:Qƒê¨Ñ†¸«YÌk^HÃè, K5N¸í½©Ì?R•ôÈËlUôÔÓìh7¢÷o ót[í(•O­jr͙[¡;?¥ˆ­#»ý~Y^àXP pP~Y~Y~†ì•¾ª0Þ{º3/¦’骆QÜû•~deñ)zu5_6¸>@7_„qÂÊB^˂èêdèO.Q¾÷= Å™òºŽU^Lnpb>Ef€—ÿˆ  üڊá[\=}qf4-Á ™s\2*{–à/â‹Ät¶²D'y¹™J,:ÒU:r†_ƒxÈÒaÒ… —ÔM52@WŒˆuÂ^š›Û zj4"á9‰•Fw•6nŽ +jãâø¹œükr:ê!íi®sÝ#Q¦×šªËßÛcŽè¤IÀ­ó—ô#%Çp¶GæPÃFä9š®U3ü%‹Z&7Ÿ¸‡=M‰³$íÄZ²ôx±Ôõ+p¾å?ܺ…>³~6)¼üÛï= ©›fû¦™_;"ò;ôÚf›¹‰ÿ]«Šíê{}ßeÓÔåp„´ÁÏ1ÃÀ+’ñ'MâƗnÃS]/cD‰¥ª§$¸æ¨Ï·Ë^úƒm°¤šº$nLçí¸¶,Ù³ü…¸|€êr4>ç?¸Ì¢å‡ ÿ,±,8Ç ÆÔÿ9{Ø¥,þ^Çñÿ4û“ñe6ûÉ <xUY:¼Cmÿ»Ñ6DïTÕ8Ñn·"Æ6Ï$eˆ¿­æÎ͇LS×O3!#%Õæ ©(~Ê·áß+ŒÂ­ÚöNOÌOÅwõìxì$I5[í¢͊YMÇßNõ‡,½†Ê8… Øõ·t[ôöª0µ-i™d½è + /C”;éŸ^½â·ìE6à:q2•Ýª=}‹»Á@7€I1yì[ójZð +ˆ @~²×È֛;nƒÿ& 0°½\¯A<©}&êV°=MÓ» gƒc°&ª¯jÙ7‡ë6,xð½ZÕŽÚŒv€‡žË¶Šß6¾ðÂÔì"fG“Ž;¡ºJT@rè® +.’НL¹Â©ûW?ÔLhœ¹Âòýga”ŽPhfûÙþu{ûœùS|ycI=MÊ>ø%ðEÙPi{¯>V@p™ Ù>Ñ{o F U̶Òm ôˆ2µZå7‘˜F ÂHóË-bþ7tfEÏ?™B#%¦.¤ƒ|YžL~Ùâ6}Y~Y~YXÔBjÓ7DjÏæ€ø)7^¯Úñ½×Ÿ•?Ÿ^92aXכjUÃ@ˆýnÐâwT‚{•Ênh¤9<†ÐxŠüû¼]~•xÌ9–òÞ¡"nôŽ®êr‚¿öÛÉ ¯Í ÷t4Fa†HI1¼@¿\©Û0‡?;ae”eÙê™f1)º¿¦’É¡Ašïjv’î2 p6Ñ\ŠÉr‹ŸAWßÇ“¬¹ßò–¿‡4AÄVßÖ9‰ퟒ–܈Ì"p–fÆra:¥°‚®_”øC~R$Š5©MG²or¸÷דhãdÝ$MµKxÍóQÖ#c +F¦jJ)§ž$WN¦Zɪ¥ªñ¨Õ°¯= Â[›ÿ‡ŠÚÆèá1[Æ!2Wð½44uÜÅ¢¹-ÒÀ<ùØõ_!‡9é=}X-ß|Èõ^nSkÚ¶Å8 +é©Ñ-OÿÀÜ_È!‡Tk–4œÚÅ@Âé­áÒ_™)ӊ¦Dƒ:elÂ(m"¬ž6¬Œu¬ V¬J–¬‚ºº­:ºG]sPaÓã'áp(ِ(=M€(× (º*®Îi¬˜J¬’p¶iÒ¸¡üÎïÅTê û{훝5ó‰Is˜$ӎ¼–nm$Zµ¡DUˆ®qšír‚7-¢ÍâHó1HøÝô¡kPOËK‡ÏDOÒJGMM/KPß8MI FŽG}öœJb5K5 W•¢çˆNŒmö8.7ÄÎ7uŽ7ZË®ÍșÎú2˕;„££å.‹Z~ylY~nY~Y~Yr]v0#b~$i2ޝèªu= ®}B,Ö.«â-Eb¬¢ÐÉè³NF-@Tg›êµTÅH»BñWæ·oÑ¡qÆñ·³ --Hg\E”ø0“ùêzóKL[xõ‡ÊIýߌÅu™·P-ܦh”D…xë”~Û´ 5ëÓðgBÈEp¶bϵr:-ÆÎh/XE|é4ƒ{ÄI’´è±'–t¢[+ݓ@¶¬Ò(}N…b>EŽÀ†akû¯ÉÑa·Ô-mÂgsroIÒp˜oºâ;¢"ٔ!Öl¡¯–¶¢"¶Ô5œÉM\¾€-ijØ°µ;7,p–G ä­öÐXœÜ@ü9d·Æw ÔÀUªÿÑvÒ2œábŒõsßÐ͸Öþí;KHð>U ò–Èöa-¼öp¿N´XðM]Iå †)„= Tüw×Áþ=}&Pp$YdòVñ ñêÖWV €x7µš×B˜Ù*;ô ¥r£¶óƒÁ°Ø *>ÎÆïrôÉq»VOÌÞá›A³ßðÕBñÔJ=}rJ*¿Öo†<þe‚ù>\T€ß~á×‘ْԐ°á™¨@ӒÚÂìZª3\f£#fÐz»u…~™9 i|±V~Y~~ +~y6pR]›"¼"’(W™ò™ûšha‹pF˜‰±=Mút?¶[¢v;bOèQ”jþqs6¢Ün¢Vò.Á·=M¡î(ô„ivGÒÓû:q.ـÛýú +7é@dUû= ýJáç P­¶×ÝɝHð5EA 3흘ÕÕ¼6M¼vÍp¿K3Q–%ý¼‘ªÄWxX򫔻 ¦D×qyi舿À@FgvËú:ŠÕ ×t= Ê5M‰þ¾N[ê½x®ø9(Ó%(ycûy(‚7õö¾’lçyAšÇ¶Ë2‹i»¹U@®_Ç'%ȑàPŒpëIT'¿ŠÝrœénj7³ËRKì¶Ýs0¤¯ß6;hÅ9T1P„³ÊÛj¸2jߊ°Â›o!”2óe,Å)µìÉ8×ÕkÇ>¿lÆB¥­äj*s–¤à£ןt.Õ£1£¢+®Ø:kdØóŒàÙZš?ÙэÙB~Y ~Y~Y~À®)±…}ŽdŸë¼%‹¡ŸX¼q ÜÆüÎÖ-5at+"ÁnwMkß=}ãqç‚?oj—ÌËB)‰7‘q‡ö”Ïà*9\k«o +m›(+‹ÑÅ" µ9§Ðˆ…˜ˆ_Kþdî”øÿ_)¸¡Ì\^ÁLa°oÕ'…tÐ×ø2m’~,xѷ׃’,= ÿ‘}jÇ^¦ßág”Üê“òÜm(†ßÞµXTJT.à&= eÜwRƒ|îoÒ= /R ø1Ÿ\1vL>/?>X¸2²œ¡´*òá‹U +{¯!¤èÒ¯!pۖZÿ3rRrÂ4]–¼d†\Z˜Þ.9ŸÇ=Mm±¢îzâIŸ +þ.£Ê¾¨ÜÒg,ÝYy,Ó\75©ÔÏ=}h\zÑd+Áì/ªìV G¯1¶üÝö±L蕷Qôp±èAÂùå˜%ÕQš÷+NíoØ%ˆwTÙsãoü6î„ýïotÉCô**Ƙ üCrr@©×ÿׇi¾Æ¿h0ŒÔÙ +CÌr•p³ÖêaȍžP3 pÞ´¾±þ{ÕÍy1#ÉosäÊGÝÖï|(²aQg÷[Ô=}ªz±ŕd®Æ ¿… »‹*¡ "¡â°ƒ_ ö…%«»µe&€D×!¯†FøÛèh´¿=}Â(up 5÷»?¿nEì”_3c©(ç‰ÈÉtàÜ(+NL+ ITÔÒ@‹È<ÿ 8è_ÙÞ]3â?êMáÕ®{SO+æB-ܵóeY¬ï= ñ4 ¨&MÛH=}–½šwõTAF¹° ¯ ŖÖÆ¿þûÝI0°r}ü¼wd›¨·¢Œi×^*Ηtò³ß£é¤££·Y~‰òzU~Y>~Y„ ~فžï'@àōfmþ \ÓaÂP´ »˜LâΩ?Ú# ½¦¼!³ç©mÓ9ò)“óÿv*•ë»ý*)V= ‚«qž0C‡ëMú0…œËQ<2ɕi»ÏI2HæÛ9«˜¯ÝàA#t¶Ëò;#_Ÿço2ï “l1>/V·/2ñƒK ‡ÉðX=}rqp7<‡ +qS”Ïo‘qi Œ¿Yxq6jÿOaoæäÓBUD®“ìüã2qåÒEœ·>º¸W'ðUî|¼9ÿX?¡áÎk3ûleÖN˛3È ÂD÷ +*¼2.eî2J»<àZqŸ$“ˆîµa†Lz/µ_„…Zïÿ›±d‡š‡² ãæzªy ‡ätʅuá5“(usR»"Æ}”Þñ¢cքª² ‡gò™ŸEòƒÒ/Y ‰&zGÙ+4Åilx…¯³J<§®Ç3ûÏlî썺ët Éh1œu<í– A¯ +ïÚò9öür:(\¿Îºm–cõA—h­ŸYôƒqèaÝË5Sý,Qíï}Koëúdßó¨$ã8L4MÏÝOivçØmòNÃ÷ê‰M©™œ½¯C,8ÉZ^𮀒}¯ÀK&6?±­†ÔxtH 1ÁRO˜ûaéB¼+‘Ùcß}#J¯¼?k+Þé¿KÕeŠ@ÔZèï³k; _Ì9©IÏþéTN¼eÀ‰+g; O¨ð\¹§âTÇOx5ÔÎA0T _$Øî‹’fÔôþµõ´bjn=MÞwb{öàw$}±«¹ÞUvv4úž?뢎g*^q¿‰%[®ý¶ÿ¼„-’éگŀ“[ƒñ¢Gâû„lýæòÑO”eØw.= Š_¼ù‰pCÒἈ.4,Ò—/Â6RœYBË,£ﮇ;öÃÚè&Sì²t.uª'³E¾å‘=}óyé(…Ð/šðß3®ê§¸á´ܸlA•ë›¸h6LtÇ^疋¯þ­{™Ø9z¶†k/†Šdq¸g–¥)6µ¼Š5+’4Ç×î5S8ïx/·‘JӄÍPXL/7¢fhÈ"´)¢è‘y⚟æô’âÜþ'¡Ò}~ש0î +DÝB1 +sZݦ"\ï:4·6hEê|[¯l„(±Z±‰Åø9îaÁr:‰VÍÙBò­Û×E³*åyBËELQ+xiτG¼ùÏð~ ]÷;÷Ðf” Õ mu~ÅnZ¶U/Ô6&áÜçÒn‚äANæ‡úÁ¨Â¨…ÉËS“H¥M„-ïBF+šÚèÉÎTHµîÇ7üÿKoQm_÷ödHä(j÷3ÕöbÍ!z÷œ‘Mi|t=MIi¡ó‘oôê*Ý(Œ½¿ÿJä#_ɊÎ،ÞKì#4¹}= ýkÿxåxð¾zT}w_w G±i.;ÆO.þaњYŽUëö2"þ˜ ÜJêB&áVê‹œLṄ©/ÿ#/SÄ•°,| +E1´rÝ/[!l+ªQi+/ÚižPÔ&†ðau'üöaù<ՒKÌè9 ±ÙfŸ4¼yD‰'ÑÓJg%àè¹»VE4Èé¢ý“1È ¤ùgrTe0î$Ø´O ÕW âÙkXDÖs9B<ÅêTÀ-ª=Mr= $™_2ÿ'¦ÄîÀ»Îkj=Mêñݕn,œ?k"Š'ö-Öý>?tsdIn(w¾Ñïc8 +ÿ춆íL¾˜êsXŠ™ëY_ +UªnÚón62àA›”õSºµ.= »Ì0ø@ÚzrÖrp*aLáן—DFs:,ª ܈*eËâ=MœΰmY&+D⾪›vžwBO[£Ezª3O¼ë Ѩ•Ûß+C8äOú±iNÆ;–Ú&œâÛ'“HÄ»Ì'Es½-•˜óO¦fë¿i÷\×*6 Ð?Ž¤´wÒ1ãîá5nÐ4Ï= Ál;CËéÏ0I×~Fœ!Î=}kS»9R/dûÐ98àTgß+賶j4˜Ïs, +…¢”ïÁr‡§‘òc{×41´, 3ë!µ²ÉÔ|á$‰C¯qbq! É&™ +u:hClüϳm‰Ù}:U ­k„‰U¿w€Bn' +\gI‰D= Ê2Ryœ_;;rÞä¤ÕبÿÑCàK3ήsÍl#Åÿ‚·Ñ^;¤*.,Ìd¬ÕÕHëY:Eb·B›Õ½Z:TpE¿X¬ˆŸÒKãGY%lúΓ°N‡†]홻÷Ôç¸ÆbùÔIO=}(ŠNÜ´ó&›M½5=MüÖG¹FòXÏËQfŽÀL +}-mW¾«¼u#ŽJ©ßí½,ázëã¶îúؔZ<'„p}/è®JÒXs¿}-ˆ)ù¾Z¾Ž¨OQ +ŠPiÃbV&§~ñ¹ñ’çýI.¢]]3!yh%oµ1Ɗx–*„#’åW›YPX‡‚Y0rnY–M|Y~Y~ib†æapڟ‰ j¡z¿a¶•‹ª¸Üâû÷/þa·oµ +}ìñm+FÁËñ JÛ~ÙìC˜ã%äƬA +îóÜø5ªêÇ µ:çú5œ5›R6…d̉¼ë4AÄ(y ‘¿5 .;×v GŒ4IP¯üëz:ÄÊæ)mlU—À5Q[Ï^ uÉ.lB·žlFB_m¡ìwWÏâ™.‚õb‹±›hVQw-¡‰ˆ†‚¯; éXƒÚ>‰k4!ý±T‚±:Fã±2P•+b5Š%@ßE¸•oûEcƒ¨=}ø¸K0úC!WÅ@¥èiôç{æ´ä6ŲzËDê,ç¦ÈÉÎ]Õij8Œ7ô‰+ÕA m+ôä H­ö÷óQóaSÍYúø|NDíì5ÍU†x{ã0}Â=MûM”[†rºø +o¶-Ðw¬Ñùj$©ýºØ3útƒú_©­×t|N,€Úðe= ØÌv…ÉÐßy…H(¹™hý×Ðs žÈ‡÷XÌîs ’ÛÀOšŽÓöï*B!ݟxH&‡â]ïQ.Q0ÑE¸]g®Ž”…]Á–W˜+ìvæ-á^2ŒÖåùBgó /©˜œ[f#.’°{ˆ=Mcé¦‰RØi âÙØDÄΉ¾TE´ +÷08 'ye²½vÈ/ 3ÔҞ/”{=Meðے%æ= ¬¶z;•A̜ÉI?Ï×Èa¼žÑ<´H i|ÖíÊ=}–”+ÜVo”­ØŠ‰3Ü6ü³™t%’Á¹XwÉîõAû lz­îQ-ûTž)¸N˜P;>hG|y/à +pÛIÉûV _°>±|ëm)Äٟ½WdJÐhÂ<ˆ nLÙþ·èë" jÞÞAú~´aeÁ„Þ™+¼~öør|¨±'*I¦A ±@‰ëƒìê1mÞ5º†kŽÔñïáƒ'6'¶º&@³½eJÖ²âÜVn<• +¢„€îº±Û]Ób(™ØQGàhne¸6Õú79]Äf0r©ožv–´b‡1%)Þ) ‘[ð–Ô7ª°­Áï.šjòÁÁ™çòi6wòÉ2“…wÁÒw"ô»ƒh)!Òg6 t>p v¢R²šž3„f„ÉÂ%ڛUŽLÒ¤YaP”È8Âú‘žô‘*ç<Â.矬[ŒrðÆ"i¹†TÓ#z¥;R¾ãý£m¥ÜÔ3ܽ$·J¨…Ûà«TÖäÿ÷±å×Ì+l6& áÁïIÿÓdTdÛ1®d›«=}UÄËê)CÛÍ·ˆ D ë)·½-= ó»¤%Óõ"'ôº»i;dÓù Ûja)–}Ò¿fµYêӗÔ%p´_‹-c!îÇ°’ÅœjÆ5r4矾hoÚôß0ÅCÈ-|"ꖉ× ñt-i¯Bj“Ä)M»QP2ȘìÏʏ,N0ˆ›}ÛõÁhhÉ1UÛP1ŠR*” ýhVTÍA‹8¬^BcËn§͵ÛXÅ4A^,û;Êaß4tn6“^6g¾VÇÙ9ÈôÊ5/ ;ÉV\×uìqLñÁËu4,gWÑIAeãX.X p‹ ¢œ5x^\Atð˜OÁëV*üào?~.„ˆùŒ—…?vn™œ 'ÿ†+Âl ÿý{òd˜!¾—öøsr6h¦× ¢£R0© Ò½ƒ= “Ã@Úªœ•Jî©ÊÕ玐Ä;°ôÙg&ˆf7À‰=}hӌ¸fûq³µ7¡ÎÇûëŒP3ãè볎ÑÇ»4ÄÇ{|ÄÇ֎Ò$‰b§¢ Á#/ñޜJY™‘N~YÙ~Y4@}Ù¹XŸé’í洙äÅ=Mñ³”n©´¾q-[žõ'ºö^[;B¾.üÞûoX,o>g7ÞÒI’ÔÖ¿µ±:3“],'“ó¬XÊî»]üe?®µ±= 4“oÌhøí­pG½ÉˆBÌõù4…E7ŠHû€Õ-99tS\/¤f/<Íhù¼*UʆVþ1V/?%Ї÷ ññŽ ©IˆŸ@Ð +}ÜÎà­Y:ôE(%n‚ÌÛðd^W¥è1¥–ª¨%CÇ=}DÇîÈèaúõ=M]5Õ87pôõ„&5-%--¼ÍmZ÷ô™¸¼vø7k÷ôËêè•&-CCi4Dé~õpŠ’wß>I‰ýpŒØނNb¡½I9t“ê®°= bvs=})/W)Y©|°Z€ý±7yU[\9â* âønZþXÛUWßNbîj—õݝÙvô!;±n·Àzڎû äj²÷Ô8wD,Aüæ—;GÊYìr@¹= uvlÃ÷ãƦ¶ª¼Kàd#&$p +¯"cØK+4D°/ç©»ÜÙykƒXé'öéáØutåkg%]É͗Ø7,Nï;1>û—kç)oT }wՖKJ<’¡ÚFû —Ö1ž KЧõ¹‰ùV³ y‚¹ß.Ðï{ä~eÎRFù]ùUDF8mbþüÞr- +Z8‚Qü\ÎUôÖ ü¾]YÙ]¢’ᄀÙ©ˆ}ۗd)úSvN/@o‰7fwB +m Þ:r~¬= Yvt‘Ôª:¾Ý²ó"?&bzÝëB““,¦d‹Gý¤Ê¦=MÞ.[lÉŽªÚŠJ^Ü8Ënp™ZyÝàoЄ²‚°•s_*Žß‡âˆd“wfæ&cdŸ¥¬¯ŽÌóŽâ¤¢õ$*ª§Y¹›ð‘Hw.aE:†= /ŸˆN +4šUØzŸÁÂêywê +2¦¶—û’æ}juJáͼ ‡‰švb9Âüò↢˜¶ÿ… +|!â(œ|Ë°óÕ¿\£(~©û#c/£†u¤Çü¤a¬3²õQû3¨°%kžªŒÛÝk™8ä¿ê&—_Â>Í'Ñ´Eüˆ³Þ)[–+ßå—{Áô+N’æۀ=M7¯–†Ó.ª)ÜàÙo~x_jfžÓï®ð'dl«ÆMç;vÌe=}‚ÅB¶„ƒ™«ÊÆ?„OÎmLµô1×-Uã7ðEÏý¸ŸtËâ2uì¸F=MßéEõ¯ *»\âjûÚÖiB<Ô½h«a,z¹ +4Û Žhl‚Êq€¢†o½J„$ÛuþyíµW«É³4!n§¸)Ê[ßÌds°¬WJ¶o5Ã2álißìÕMÈ|tܬbÊìrìõ5ÈÜì’5Ÿë”O - ˜ö™ìÄ/ëÔ -¶žöçI»ÇqfÑ"ÁW»³ª£C¹»-!Ö~™V€lY~Y~Y~Y^ÝµËøìï$v§PµkÿCf¶$¨¢-?lǕÈZë}=}Å\],÷BÏu&kSVÅv,Ï0ÐTä7{ùó +à,= ÈÙp3û\ø‘È,ԒÈÇ3LRl·ÑÉÆ×9œ#o0ÜÕm—\Éö•VïUÇ­zï(ŒÈ¸M×öëÛû„s(q·U÷ۜøDÕ8g1m=}uÍèþK½EuDmҞ÷©õ,˜û0¢0á×áWs Û÷†å0ž× €u›^阇ݎ¿@¢m‹÷=MDÖ+qv¨Ý@‰Ú¹ x\ß1Zf7GÑ"þÑðî[¿Å™ŒÞnˆ…ù:Ϻýb|·~†îÙ²ÒBêN=}Á–]?¾’”Ž=M2Ïjß­à—K¢*ò2wáB| 9X“üÖ{ +€ßBxÞ ¹”<¡ +û_#±õãX¥¤w±ëÐƒ˜'#= N¦i¿®KÓÀÂÄZõ(ï˜åm7¬œVkM$Ä8Š'~™b»…_¬ÜµÎE=My+ª\Æ=}ú.|ÄE|‹+žîÆÍÂ+ÛÎe›½ ó¿£{«#Ãû~Y^<ƒwY~Y~Y~YÿÔÐ#’è¦÷Õ¥Oµƒúb£o£†Úª[Ù㕺¤/»sÒ¶OΦÚà+u½U±(-–Duñ ¼Ýa(A&—pÁGhÃM© táë04ä'h䕐°µ’3jÂ%í³Q³Ø%ÄUy«”K+œFæ÷½Å„¡³Þ' —Ìç?ç9‰±¶­(\õÆï6ñ2±v ;že_´‰hjÓضéÛ=}Îå„'”xÆ_Œ³ä¿¸}…«ò™çËÐ垚´yi¶9Ãæè¤= -ãJY¥v*¬>Ò*c6.¥¬ç,ȵ֖¢ÐƵh¸œÿ‡l£4–ÖèYµ<ýGf¶´ˆRë}×µ2.ëO÷ÈýØ3kvö…qç,TNÇmÂ9þƒº,o,Y‡94&ÕºNlw Ò[ïX¨Õ +k§ÒmOÌ6ß)åJ¯­Šîˇٸ]ÚùÛþÄ¡·¨0e“Æ­’Ë_žE3ÄTíÛZíæ÷ùø<ùló8˜øY b +øÙßøü™úý=M0$(Ø=}l½í0Øa1tÛ]çŸÁ0mú×õ_tÛ¶ö +ãé@EÈ»Ý ½Œ‹HVE1UõŠ•¤@}Ú‘= ¢¢†½ÿqÃ:Ô{ ¾G=MsN2dXl©(ù¾—à…Iä52©ñß64üð™8Ô +>¢VÉ$áÉXÊ>ü՟Clw¾É–>Ï/ÔÒVhwõ¹fð.Ñ0Ï=MšW«ïSë^…. úÏé_YS{Çñ_KðhÉ">î@]1Uì\s x¾q|?† Y\;dqŠۋóUMfy±Ô©Ü×?„S@æ5F±ÞÏ ‹“ßQîQÏÑXî\/ØÿÙ\‚pȍû:¯.-¬AôB];b—‡Á4_ÁȔkù|Æî2º ß1ï”;\mFˆ$¢Ø2ÂRàYêš ByÊ +B®%òš½áŒ~œÀq—\VqJ|´BzÚ ý= šµNµxÖ÷… tí·5ÎÔ¡Â&…£Ãç£çt~Y| ~Y~Y~Y€“n³väCmÓ$lV¨‘³kïcbÐӞ&c\»Å"u-ÒÏõF]+R.— ÒÕ+k7<ÅÖy,ïâÏՔ)k3ZÅÀFí LÇmˆ:ëøü…PÇTZ8g“¡µJëgÌRçzîµüBî?ÐtÝTïo¿ÕVnk‡ÃVx:Ìv ~ <%®¹4ìõI–<ÎÂÆW;­&vÍÿÍK3QM%PËoÀdžÎç>Eó(%[êD–¨(Tò·¹¡óûºþ 8ÀhøYwõüMoCÕ+ín¼ÍØzKáC•ŒUm¡ŠÍf!NwëG´È>iY5½ðŽ ÇWØÙw Ó÷†Œ¯0×EÁs»!üƉ0¤b×áÊs”U‹?ËQ6Z9qÓæŠÞ@&]ñx|\办@%ŠêÝa-Ü@d~%©ôM»Ç5¯õXÓëv~ÈÛ&›®°¡Ù!oƒ—ð&ø¯©èÕ45=}l•E7l-ÝÉ$5M&lTäɐJ=}ÇüU:ì˜VÉz‘>[BïAéZ«öüptK_h©¹|ß.Ä@Б²XËáf“Í.Öϵ@ZKšÓ%"Y{µf‰!Í>‹U8ẐcIDU¬*{×@ †QS4|÷ÞöƒAð5²Ù’EÛ¿ð‰ÓÐ*&úmÄú* +]fŸÙ±åâ*k¶¿9ÒKX|„l´*Az¿…_;—vÄèß:lŒ…¹ŒötˆÆ:an=}qÑÔ)] vÿ9ÐZfHsÌ:yZ¹a\“zˆúå2¯<àm¸”³M'%ê*sFþz+À‰t!]êSeF”ñ2ÕJßu€™›™}†oÂ2ܬ=}—lþkŠèèB¨0=}á¢ÝÏ¼‡öUr há@Z›ç܍֕MòŸ +áÆaè©Wò¸Öúã(u¤=M¨ø¦=MY¯;uփyk#V¥‡ø¤F¨ß¸“‹ùã/z¤ü"ª7,ºõÊ+7ÒçÒºTæ§ÆGéŽ3…= æu0±œÞ·iM3^åA­LÎǁN36âf¢¯9¦[¸ô³#V~YŽrYy^ª||Y~Y~ّûBê¯-óË(d ©æ.¾L CLäÆnƒô¦;d~L©‘õ&*þ¯½¿Ô{|Æ&äB¯èÓl6cGò6æœïÅ:ØÌþjGþ6HalœáÉBê<Ç;5HìŒÀÉx1>w= ¹…JÉØa'Æü‡ð 4Ï&hR¹ÚSû~óÎ.}AèE¹:êû/@ô!éÙ0Ý}vÙ,©}ۆpT,U}Iiñ>ôj±Xœ¡{ÉnÊ>}„Àÿ*ÔLÀ¹ˆ{ÿ¸*f0åd2{s‚»*V¿?¸±8ZÜGᅓ™Efqž± ‚Ý“~„ê:Øìý,÷süü:-XX”:€ÿ*\Ÿ>ƒuAn~xÑP]¿Þ‰5†-n“*њ‚\D"lã¯2FìàE™KócFÊÁÎ=Mÿ=M‰”€“ë}hƂã2-àr• aFˆ¹2 ªàA–Ë~ƚ®2'àáè“ܾz +ôÍÂ@€J÷´B¸ŸsžŒ6f™\yxJ¢ÃB—†™o• [Šl ÂcŠ~<ó€ðB2ò oòáú¢œ70¸SÛüãgo¤Ð•ªOÎÀ“JýãHi¤f}ª¿±¥!š­kàÏCœG#¤–¥¹O­{VЃuD#ꊥ­›—ÏgB¥Ÿ®»öÄL +éd_%aȨ0M«UÚ³Ð{Š«©¶Óˇ2´O;Ä _ç“ += äl†%.:§À‘¬= · Í›½EîAÈ6×pÇÜ7ú5PGçlF5PÇfÐlhq5G ÈðéíÉï4¿<Ҝ_í5 >GŸäì^Ö5zȆÁì‰_8ϞÄü¸ìTÅQ­hwo-S­bGEè- иZ¯híHs ·è)ÌáòóO7•~8 ª7‘Ê8¡:7Z8´ò%!N—žI R×,=M70 +íçîßlo/Î wÎ +ÇNRÏ wŒ 猎 +×Âç?ÏB· ÿü W€} ›!†r”CÒ§¢)t‘D˜Hô•6T•:´Ü%vÍ)VÖ$¶ÆLvÓPªAqV_ñ]ñ–UqoMqT]qJIñEñtñæ²é2 ò9qyÏyQù¹I‘)¿Ý@–)h¤}±Ã©EX~Y~þ~Ya€ÇX~Y~YžÂ/*-:¥a¸ÃŸF£š©{›Ôã¢B¤m*ç,ƒÛ¾€ÔÅaF jj1œ|¿–܁ƒ»i4Y-ê8i1~P¿PÝÜ—WŽßkô"7†—çê¡<1(®¿ù§yޙg€ºWލ{i”’UF‡jƒê1 ÒÀâÛu¢w¬‰¼³yV×-Š rFçABÌàôÕµˆ“Gp’lÿw6H/ÊöòMýA›°à„þáZ–|ŽßVž¥æ߸êµò•_?„|ׂ†9•Q˜üTnv“Cʅ¬r9A©úàb ᕇŒÜ™öš>Š”Âòjóež«å:‹en[åVÇeH÷å”/eå/årÅe(5å)­åb=MeœÝå…iåN9em™äbQå½Ê׍Æï»Ç¿»Ä_ÁÊg?͇<ÐwýËѯÎo{ÏÏ~ÌÒâ͏ßÀgº&Ÿœ‰{îD~DqúĂÄñ«ˆûˆë=MïHÈõˆöÍ©HþÙÈÁˆ!äÔ(Õm.-m{íY]m|éí>¹mBYm[qí…AmÕô՚öy°±…4m•í5Ìm'íkžítÊ-_÷yaö‘ ùÅ¢÷•¡ö½(՝(ډçÔYj×qhÖÁÈÙáIÓ¡IØeÙŇÓʼnØe¸Õ%ºÖa8Õ7ÚQøÔ±w×9zÖéØÙÝWÓmWØ5ÕáÖ±ª/, ׋ÇÂßÁϽ×Ag<??‹¥Æõ†ŸíÆSq+Z|{Y€Kajc‹w+m;që|û€kjû Ã‹šw;šu+œq»Ÿl››p ›~Û·OÚ åš ë›ß/>¢¯9¦»¸ã³'V~YŽrY~_@~Y~YYqVò6Ò=}åÏ¢1Šk5{tÒ\†=Mꋯ1uü¿fÛ±‡΃ëúgôZ'¼j)­1ø¿â=Mۅw‡ ‹KswtWHFþjƒ11ÀvÝ šo8bªœ¢Ó22¯½Š˜É  9ZBŠ+Vk”L†íjIX14¾À°ZÝՒŸ|†Û!cÔ¡+F}¬ê/Ö1nŠÀÒÞíÿŸ_ˆû rôšDƇöj}º1M¿B‚ÞÉ"‘"ܽŸAF¾ æ¼„f¼öŽ”F½–»,…»V†¾Ô¶¾5¼äõ<ŠºéÃ&ôÑ.TÜ^´ÊZtÚBVC4N+Ôa[”G74J?ÔUEœA»ì»P¾Ž¼’½½<=}½þ».þ^é'ñédQÁŽï +ß7´34Kô'ôWt?ÔEÔ-T]T9TQT"$ T‚n/¦Î0€/pŽ0¸>/|þ0tÞ/^0 ž/Uª0Ïê/ j0²Ê0 +/8Š0¤:/½ú0wÚ/Z/Æ0¤2àՅàؑßډ_Ս_ØE"Óñ"•Ù0â/êb/¬"0ŸähFƒË4ÄOÛ¶W0Çå踖E.?Tg,ÛE”ßD‹AçŸðÉ)I·„u+Ԍç'/áV«4ð[¿…ÑtÅR[9·ÒÇÙ·¹”-,$ÈgvõEüTE_«üì×QÅù¶4- Xhy]Åç¦ôH4;€çß=MÉuY·þ.XhŽ™ÅðÊtW.;xðÿ‹Ä%š¹|žo,µÞ©+côKzÀÑm/·Pê.ÄhŸ”žç U«ï¸ÂI.ÃVçgÜÅqß4$ëXëGþÅÕϖ(ë^íGÿƵP¶Ôڛ]Ú,â>h~P…qJ{_þoŽ’âËíÀ¹L2-3jèƒ'{íïßÆý@¶œÑ+«:gnhøt]Ëö'[Ðñ´‘,­¤R–ó?Ç)á´(A,ÒrhM:E„´œP{šñW¢Ã"µªâ.yèG’v²ô :›—þïŸÎÕ¨Œr,C  ¿_â‚å— +K¡Ç­vB˜žö‹âš³¨k$¨ó×ñ}Y~Y~Y~Y~Y~ º’ÉŠ×îb=Mž!ªu©y=}©xj Ž(sfŒ >*ye +þ(vŒ +>éwn ét´ .é’9J9ÙX9 GAYþߐ Ðå^2¶|?ç6;÷JRpNR@6õn=}ýÎ;iá†W™¯JZ¾Û&Àk~c< !¹ðù@Ù"ÞÅJˆu¼‰T>ÛRáØBQØbéUCáS3_(CÍê–˜8z†±ÎD"ÐLzvˆÉÏFNÏN ÏzÐ~ ‘­Qúì¶üüªýèöûx”xßrþf˜ÜIYQX1 +ONÞOJw‘Ñ=MZU!šÆrt{Ÿ=}‹ü>Œ÷>^Ҟ=}¶Zw$YU>ür>^0ùvþG@9ôzþ_¦ÀpM6 j@àöº^*^=M^n9ÿŠ¾Z*ñ\JžH²wžáŠýÂÐ ֌ +Q ØFâZÀ ٝ‚ÿ&X<½ƒãæ€Öê) Ú*BÆ_Z4¡7iü¶Ÿ9Æ¿R°‘Óq /ÚÆ “®ïwGñalA-q4„¡v–ž4Øf:;Ùv¿WfT +>ÀV‰›˜ÿŠ<Šr¼Ö‚‚CZxµHpŊV­fhÜ:!;\o¯9ÇüSåî_õÆl_ø1<_iÿy]± zi˜aúӎ0QðYðQî>p‰HäAî9P®°YÜâfZØlNlPîáèð•ÖݐR‡´ç}Ž?ÇuÌRÇ != Ôܱ›!kóŽíaæ!Ç2!º|2 &ìNäeA2+j>‚ñ[±rKLáæö÷…Œ>j•.i\ÈúÌKæ—ýõ„_’0º×R_C/™à4ќÑ\å¹À—·áô„-³M;&gy舿lWt \åM¾Qh¸õ‹Gž1§ýŒ1¿Å5 ]ľ› 1Ù?¼ßÄ= !]ºê«JFQqA4ùò€(ŸDLÑoñ¶ñþ$,ÿÅUi]Õ6[ëPüé/ãòoBA‰ÐlWz˜Ç›cÒ¶=M®Ù—¤^·±º±ùô>né7i/9Z•çÉüô3à³ð_Ãóö˽÷PÖ]÷ÃÝ¡ ßýyÄ¿ÉiF”@ Âý0eèS¡¤7aâ¬= ›A$weZó‚šr4…ÚWT$-‚؅RnpÛvj¶ÚXŒÁ+= :«ß‰ù«›_¶qn¿#†:0jž*†· +ßA»ŒgR¯Ní= P{SÂò>9'¢ÛA$ +Š™ŠÛ"eÚ?ùèÈQ|éõÓmï- –ànüìŠj¤‡ñÒä?NåkZp@돣Õ]= Û¼ÔßAç5ݚú´†þksž¬7ç=MrqÎF5^&A6ژa4Zâ·}OV49IqsÆrÐqQ£]t͋\aÄWfƒñ×Ul£ÝwÛAMre 0é”ð Ê@T +¸À3= (QJH5‹ƒi¼wp!6©ø"ñâaŸí= ÑÎOKB4¨÷ÕVÀîàûœæ¹í£>œMath.atan(t),a:t=>Math.cos(t),d:t=>Math.exp(t),e:t=>Math.log(t),f:(t,s)=>Math.pow(t,s),c:t=>Math.sin(t),g:(t,s,i)=>r.copyWithin(t,s,s+i),h(t){r.length,(()=>{throw"OOM"})()}}};this.u=s=>{t.u(pe,s)},this.U=()=>t.U(pe),this.instantiate=()=>(this.U().then((t=>WebAssembly.instantiate(t,d))).then((t=>{const i=t.exports;var e;h=i.k,o=i.l,a=i.m,l=i.n,c=i.o,u=i.p,U=i.q,e=(n=i.i).buffer,r=new Uint8Array(e),(t=>{t.j()})(i),s()})),this.ready=new Promise((t=>{s=t})).then((()=>{this.I=n.buffer,this.V=o,this.free=U,this.Fs=h,this._s=a,this.Vs=l,this.ks=c,this.Ss=u})),this)}function Me(){return this.qs=()=>(new this.Hs).instantiate(this.$s,this.Cs).then((t=>{this.Is=t,this.js=this.Is._(this.Js,Uint8Array),this.xs=!0,this.Ps=this.Is._(1,Uint32Array),this.Ds=this.Is._(1,Uint32Array),this.Es=this.Is._(1,Uint32Array),this.Os=this.Is._(1,Uint32Array),this.Ns=this.Is._(1,Uint32Array),this.Zs=this.Is._(256,Uint32Array),this.zs=this.Is._(1,Int32Array),this.gs=0,this.Ks=0,this.Qs=0,this.Rs=this.Is.M.Fs(this.js.H,this.Ps.H,this.Ds.H,this.Es.H,this.Os.H,this.Ns.H,this.Zs.H,this.zs.H,256)})),Object.defineProperty(this,"ready",{enumerable:!0,get:()=>this.Gs}),this.reset=()=>(this.free(),this.qs()),this.free=()=>{this.Is.M.Ss(this.Rs),this.Is.free()},this.sendSetupHeader=t=>{this.js.C.set(t),this.Ps.C[0]=t.length,this.Is.M._s(this.Rs,this.xs),this.xs=!1},this.initDsp=()=>{this.Is.M.Vs(this.Rs)},this.decodePackets=t=>{let s=[],i=0,e=[];for(let r=0;r{if("vorbis"!==t)throw Error("@wasm-audio-decoders/ogg-vorbis does not support this codec "+t)},new r,this.qs(),this[ye](Me)}qs(){this.Ls=!0,this.Ws=0,this.ut=new oe("audio/ogg",{os:this.zt,Us:!1})}[ye](t){if(this.Rs){const t=this.Rs;t.ready.then((()=>t.free()))}this.Rs=new t,this.Gs=this.Rs.ready}get ready(){return this.Gs}async reset(){return this.qs(),this.Rs.reset()}free(){this.Rs.free()}async ti(t){const s=[];for(let r=0;rt[le])))}const i=await this.Rs.decodePackets(s);this.Ws+=i.samplesDecoded;const e=t[t.length-1];if(e&&e[ue]){const t=this.Ws-e[fe];if(t>0){for(let s=0;s= 1", - true: [ - { - type: "setValue", - name: "item:yellowKey", - operator: "-=", - value: "1", - }, - { - type: "setValue", - name: "status:money", - operator: "+=", - value: "10", - }, - ], - false: ["\t[商人,trader]你没有黄钥匙!"], - }, - ], - }, - { - text: "蓝钥匙(50金币)", - color: [0, 0, 255, 1], - action: [ - { - type: "if", - condition: "item:blueKey >= 1", - true: [ - { - type: "setValue", - name: "item:blueKey", - operator: "-=", - value: "1", - }, - { - type: "setValue", - name: "status:money", - operator: "+=", - value: "50", - }, - ], - false: ["\t[商人,trader]你没有蓝钥匙!"], - }, - ], - }, - { - text: "离开", - action: [ - { - type: "exit", - }, - ], - }, - ], - }, - ], - }, - ], - chapter0: [ - { - type: "playBgm", - name: "Crawler.mp3", - keep: true, - }, - { - type: "setText", - time: 50, - }, - { - type: "changebg", - img1: "", - memory1: false, - img2: "", - memory2: false, - time: 30, - style: "引入", - }, - { - type: "over", - text: "人生不如意事,十常居七八。", - image: "", - memory: false, - time: 50, - hidetime: 30, - sound: "", - textColor: [255, 255, 255, 1], - boldColor: [0, 0, 0, 1], - font: "bold 48px Verdana", - }, - { - type: "over", - text: "世间的万物皆被装缀着不公的色彩。", - image: "", - memory: false, - time: 50, - hidetime: 30, - sound: "", - textColor: [255, 255, 255, 1], - boldColor: [0, 0, 0, 1], - font: "bold 48px Verdana", - }, - { - type: "over", - text: "没错,就像——", - image: "", - memory: false, - time: 50, - hidetime: 30, - sound: "", - textColor: [255, 255, 255, 1], - boldColor: [0, 0, 0, 1], - font: "bold 48px Verdana", - }, - { - type: "over", - text: "十几年前的那一天,", - image: "", - memory: false, - time: 50, - hidetime: 30, - sound: "", - textColor: [255, 255, 255, 1], - boldColor: [0, 0, 0, 1], - font: "bold 48px Verdana", - }, - { - type: "over", - text: "在都市的角落,同许多的生命共同消逝一般。", - image: "", - memory: false, - time: 50, - hidetime: 30, - sound: "", - textColor: [255, 255, 255, 1], - boldColor: [0, 0, 0, 1], - font: "bold 48px Verdana", - }, - { - type: "over", - text: "没错,就像——", - image: "", - memory: false, - time: 50, - hidetime: 30, - sound: "", - textColor: [255, 255, 255, 1], - boldColor: [0, 0, 0, 1], - font: "bold 48px Verdana", - }, - { - type: "over", - text: "十几年前的那天起以来,", - image: "", - memory: false, - time: 50, - hidetime: 30, - sound: "", - textColor: [255, 255, 255, 1], - boldColor: [0, 0, 0, 1], - font: "bold 48px Verdana", - }, - { - type: "over", - text: "无数的生命被那无法逃脱的污泥囚禁一样。", - image: "", - memory: false, - time: 50, - hidetime: 30, - sound: "", - textColor: [255, 255, 255, 1], - boldColor: [0, 0, 0, 1], - font: "bold 48px Verdana", - }, - { - type: "over", - text: "人生不如意事,十常居七八。", - image: "", - memory: false, - time: 50, - hidetime: 30, - sound: "", - textColor: [255, 255, 255, 1], - boldColor: [0, 0, 0, 1], - font: "bold 48px Verdana", - }, - { - type: "over", - text: "世间的万物皆被装缀着不公的色彩。", - image: "", - memory: false, - time: 50, - hidetime: 30, - sound: "", - textColor: [255, 255, 255, 1], - boldColor: [0, 0, 0, 1], - font: "bold 48px Verdana", - }, - { - type: "over", - text: "没错,就像——", - image: "", - memory: false, - time: 50, - hidetime: 30, - sound: "", - textColor: [255, 255, 255, 1], - boldColor: [0, 0, 0, 1], - font: "bold 48px Verdana", - }, - { - type: "over", - text: "如今,这一天。", - image: "", - memory: false, - time: 50, - hidetime: 30, - sound: "", - textColor: [255, 255, 255, 1], - boldColor: [0, 0, 0, 1], - font: "bold 48px Verdana", - }, - { - type: "changebg", - img1: "", - memory1: false, - img2: "other_0001.webp", - memory2: false, - time: 30, - style: "场景切换", - }, - { - type: "cgtext", - bg: "other_0001.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "这些天,街道不曾下雨。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "other_0001.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "所以,那浸湿地面的,定是那些女孩们流落的鲜血无疑。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "other_0001.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "我蹲在充斥着铁锈味般恶臭的小巷中,悠闲地如是想着。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "changebg", - img1: "other_0001.webp", - memory1: false, - img2: "bg_3563.webp", - memory2: false, - time: 30, - style: "场景切换", - }, - { - type: "cgtext", - bg: "bg_3563.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "扑哧。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3563.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "耳旁再次响起象征着某个女孩子死去的声音。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3563.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "再一次——", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3563.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "再一次。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3563.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "女子们被肢解成单纯的肉块。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3563.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "我任由流下的血浸满全身,屏住自己的呼吸。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3563.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "祈求自己能拥有从猎人手中逃脱的幸运。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3563.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "扑哧。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "changebg", - img1: "bg_3563.webp", - memory1: false, - img2: "other_0002.webp", - memory2: false, - time: 30, - style: "场景切换", - }, - { - type: "cgtext", - bg: "other_0002.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "直到刚才,我们还坐在去往娼馆的马车的路上。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "other_0002.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "而在这之中的某些人,已经不在这个世上了。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "other_0002.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "不,应该把“某些”换成“几乎所有”才更为恰当吧。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "other_0002.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "恐怕,不久之后我也会变成小巷中血腥的装饰品。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "other_0002.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "我是为了得到这种死法,才辛苦苟活至今的吗?", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "other_0002.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "来个人告诉我啊——", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "other_0002.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "谁都好。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "other_0002.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "来人啊!!", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "changebg", - img1: "other_0002.webp", - memory1: false, - img2: "other_0001.webp", - memory2: false, - time: 30, - style: "场景切换", - }, - { - type: "cgtext", - bg: "other_0001.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "少女", - time: 30, - wait: 1000, - sound: "aiy010000010.mp3", - text: "「呃······!?」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "changebg", - img1: "other_0001.webp", - memory1: false, - img2: "other_0003.webp", - memory2: false, - time: 30, - style: "场景切换", - }, - { - type: "cgtext", - bg: "other_0003.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "漆黑的物体充斥了我的整个视野", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "other_0003.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "我很快意识到,那是只很大的脚。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "changebg", - img1: "other_0003.webp", - memory1: false, - img2: "", - memory2: false, - time: 30, - style: "场景切换", - }, - { - type: "cgtext", - bg: "", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "必须要出声求救。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "changebg", - img1: "", - memory1: false, - img2: "other_0003.webp", - memory2: false, - time: 30, - style: "场景切换", - }, - { - type: "cgtext", - bg: "other_0003.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "可是,耳中却只能听到自己的牙关不停交战的声音。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "other_0003.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 50, - wait: 1000, - sound: "", - text: "我是如此的无助。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "changebg", - img1: "other_0003.webp", - memory1: false, - img2: "", - memory2: false, - time: 30, - style: "场景切换", - }, - { - type: "cgtext", - bg: "", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "逃跑也好,道歉也罢。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "就连抬头看一眼将要杀掉我的人的面孔都做不到。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "少女", - time: 30, - wait: 2000, - sound: "aiy010000020.mp3", - text: "「······被杀」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "会被杀。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "会被杀!!", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "来自内心深处的冰冷预感,渐渐地在体内蔓延开来。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "少女", - time: 30, - wait: 1000, - sound: "aiy010000030.mp3", - text: "「不,不要······」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "playBgm", - name: "Blind_Alley.mp3", - keep: true, - }, - { - type: "changebg", - img1: "", - memory1: false, - img2: "bg_6004.webp", - memory2: false, - time: 30, - style: "场景切换", - }, - { - type: "cgtext", - bg: "bg_6004.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "浮游都市,《诺瓦斯·艾蒂尔》。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_6004.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "《特别受灾地区》——", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_6004.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "通称,《牢狱》", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_6004.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "是被险峻的峭壁环绕,与世隔绝的,都市的最底部。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_6004.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "年轻人", - time: 30, - wait: 1000, - sound: "aiy710000010.mp3", - text: "「放开我!」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_6004.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "年轻人", - time: 30, - wait: 1000, - sound: "aiy710000020.mp3", - text: "「我只是在帮那个女人而已!」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "changebg", - img1: "bg_6004.webp", - memory1: false, - img2: "other_0004.webp", - memory2: false, - time: 30, - style: "场景切换", - }, - { - type: "cgtext", - bg: "other_0004.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "年轻人", - time: 30, - wait: 1000, - sound: "aiy710000030.mp3", - text: "「你们没听到吗!?」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "other_0004.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "年轻人", - time: 30, - wait: 1000, - sound: "aiy710000040.mp3", - text: "「她是被受骗才会被卖到娼馆来的」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "other_0004.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "年轻人", - time: 30, - wait: 1000, - sound: "aiy710000050.mp3", - text: "「用肮脏的手段把钱借给她父母的,就是你们这些家伙吧!?」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "changebg", - img1: "other_0004.webp", - memory1: false, - img2: "bg_3601.webp", - memory2: false, - time: 30, - style: "场景切换", - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "年轻人", - time: 30, - wait: 1000, - sound: "aiy710000060.mp3", - text: "「给我说些什么啊」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "凯伊姆", - time: 30, - wait: 1000, - sound: "aiy310000010.mp3", - text: "「这些话等到了娼馆再说吧」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "凯伊姆", - time: 30, - wait: 1000, - sound: "aiy310000020.mp3", - text: "「我来抓你,只是受雇于人而已」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "changebg", - img1: "bg_3601.webp", - memory1: false, - img2: "bg_3531.webp", - memory2: false, - time: 30, - style: "场景切换", - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "我走进娼馆《莉莉乌姆》的接待室。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "正在桌旁整理账簿的奥兹停下手头的工作,抬起头向我看来。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "奥兹", - time: 30, - wait: 1000, - sound: "aiy350000010.mp3", - text: "「这不是凯伊姆先生吗,辛苦了」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "奥兹", - time: 30, - wait: 1000, - sound: "aiy350000020.mp3", - text: "「委托已经完成了吗?」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "凯伊姆", - time: 30, - wait: 1000, - sound: "aiy310000030.mp3", - text: "「啊啊,是这家伙没错吧」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "奥兹用只要接触到就能杀人般的眼神在男人脸上搜过。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "奥兹", - time: 30, - wait: 1000, - sound: "aiy350000030.mp3", - text: "「没错,就是这个人」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "凯伊姆", - time: 30, - wait: 1000, - sound: "aiy310000040.mp3", - text: "「是么」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "年轻人", - time: 30, - wait: 1000, - sound: "aiy710000070.mp3", - text: "「你,你们要对我做什么」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "奥兹", - time: 30, - wait: 1000, - sound: "aiy350000040.mp3", - text: "「······」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "奥兹用一个眼神,就让男人闭上了嘴。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "然后,向我这边转过身来。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "奥兹", - time: 30, - wait: 1000, - sound: "aiy350000050.mp3", - text: "「抱歉啊,总是麻烦你去做这些无聊的事」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "奥兹", - time: 30, - wait: 1000, - sound: "aiy350000060.mp3", - text: "「都怪我们这边的年轻人太没用」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "凯伊姆", - time: 30, - wait: 1000, - sound: "aiy310000050.mp3", - text: "「客套话就免了」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "奥兹", - time: 30, - wait: 1000, - sound: "aiy350000070.mp3", - text: "「这还真是失礼了」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "奥兹", - time: 30, - wait: 1000, - sound: "aiy350000080.mp3", - text: "「喂,来个人」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "光头男人", - time: 30, - wait: 1000, - sound: "aiy820000010.mp3", - text: "「是」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "奥兹", - time: 30, - wait: 1000, - sound: "aiy350000090.mp3", - text: "「凯伊姆先生做完工作回来了」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "光头男人", - time: 30, - wait: 1000, - sound: "aiy820000020.mp3", - text: "「是,是,那个······」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "奥兹", - time: 30, - wait: 1000, - sound: "aiy350000100.mp3", - text: "「我是要你拿些酒来,这个蠢材!」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "喀!", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "奥兹扔出的烟灰缸砸中了手下的额头。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "鲜血四溅。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "凯伊姆", - time: 30, - wait: 1000, - sound: "aiy310000060.mp3", - text: "「不用这么麻烦」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "凯伊姆", - time: 30, - wait: 1000, - sound: "aiy310000070.mp3", - text: "「我接下来要去《菲诺列塔》」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "奥兹", - time: 30, - wait: 1000, - sound: "aiy350000110.mp3", - text: "「喔唷」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "奥兹", - time: 30, - wait: 1000, - sound: "aiy350000120.mp3", - text: "「既然如此,我就不留您在这里喝难饮的劣质酒了」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "奥兹斜眼看着正捂住额头呻吟的手下,轻描淡写地说道。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "凯伊姆", - time: 30, - wait: 1000, - sound: "aiy310000080.mp3", - text: "「用这些钱去买药」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "我将几枚铜钱仍在那个手下的身前。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "奥兹", - time: 30, - wait: 1000, - sound: "aiy350000130.mp3", - text: "「凯伊姆先生,不用对他们这么好」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "凯伊姆", - time: 30, - wait: 1000, - sound: "aiy310000090.mp3", - text: "「无妨」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "凯伊姆", - time: 30, - wait: 1000, - sound: "aiy310000100.mp3", - text: "「话说回来,那个要落跑的女人呢?」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "奥兹", - time: 30, - wait: 1000, - sound: "aiy350000140.mp3", - text: "「我把她交给那些年轻人了,现在应该正在体会人生的严苛吧」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "奥兹", - time: 30, - wait: 1000, - sound: "aiy350000150.mp3", - text: "「正好,趁此机会凯伊姆先生也来享受一番如何?」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "年轻人", - time: 30, - wait: 1000, - sound: "aiy710000080.mp3", - text: "「你,你们这些家伙,要对她做什么!?」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "咣!", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "奥兹给了他一拳。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "一击即倒。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "喀,咚,咯!", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "奥兹毫不留情地向男人的脸上踩去。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "年轻人", - time: 30, - wait: 1000, - sound: "aiy710000090.mp3", - text: "「咕······呃咳······」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "折断的牙齿伴着血泡被吐出。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "这份白色在鲜红色的液体中格外显眼。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "年轻人", - time: 30, - wait: 1000, - sound: "aiy710000100.mp3", - text: "「你们以为做出这种事······卫兵会坐视不理吗······」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "奥兹", - time: 30, - wait: 1000, - sound: "aiy350000160.mp3", - text: "「啊啊,不会坐视不理的」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "奥兹", - time: 30, - wait: 1000, - sound: "aiy350000170.mp3", - text: "「应该会拿出你的钱包,和我们商量如何瓜分吧」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "年轻人", - time: 30, - wait: 1000, - sound: "aiy710000110.mp3", - text: "「那,那种事······」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "这在牢狱是理所当然的事。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "奥兹", - time: 30, - wait: 2000, - sound: "aiy350000180.mp3", - text: "「怎么,头一回来牢狱么?」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "男人点了点头。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "奥兹", - time: 30, - wait: 1000, - sound: "aiy350000190.mp3", - text: "「为了被骗的女人而来到牢狱,真是个规矩人啊」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "奥兹", - time: 30, - wait: 1000, - sound: "aiy350000200.mp3", - text: "「······前提是,被骗的人不是你」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "年轻人", - time: 30, - wait: 1000, - sound: "aiy710000120.mp3", - text: "「你说······我被骗了?」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "年轻人", - time: 30, - wait: 1000, - sound: "aiy710000130.mp3", - text: "「那,那是怎么回事!?」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "奥兹", - time: 30, - wait: 1000, - sound: "aiy350000210.mp3", - text: "「不用急,今天晚上会好好告诉你的」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "奥兹抓起男人的脸。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "为引诱客人的怜悯之心而装纯,是娼妇的惯用手段。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "双亲被骗而借钱,结果作为抵押而将自己卖到这里,这是典型的说法。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "如果只是头脑发热而成为常客也就罢了,这次的男人热血过头,居然想出了要带女人私奔的计划。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "虽然女人半开玩笑地予以拒绝,但不知天高地厚的这家伙还是拉着她逃跑了。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "不过,想要逃脱追击本来就是不可能的任务。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "但即便如此,这种事情还是会一再的出现。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "说谎的女人和被骗的男人。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "在娼馆街,这是令人看到生厌的日常的风景。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "凯伊姆", - time: 30, - wait: 1000, - sound: "aiy310000110.mp3", - text: "「我要走了」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "奥兹", - time: 30, - wait: 1000, - sound: "aiy350000220.mp3", - text: "「好的,下次再麻烦您」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "奥兹", - time: 30, - wait: 1000, - sound: "aiy350000230.mp3", - text: "「之后吉克先生会将谢礼交给您的」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "凯伊姆", - time: 30, - wait: 1000, - sound: "aiy310000120.mp3", - text: "「啊啊」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "我背向奥兹走出娼馆。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "凯伊姆", - time: 30, - wait: 1000, - sound: "", - text: "「······?」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "changebg", - img1: "bg_3531.webp", - memory1: false, - img2: "bg_3601.webp", - memory2: false, - time: 30, - style: "场景切换", - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "从远方传来微弱的歌声。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "是关卡广场的方向。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "对了。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "今天有觐见圣女的仪式。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "当代的圣女伊莲——", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "俗称《盲眼之圣女》,据说即使在历代的圣女中,人气也是数一数二的。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "广场上的人估计相当多吧。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "虽然我也想去看看她长什么样,不过要在人潮中挤来挤去就免了。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "还是老老实实去菲诺列塔喝烧酒吧。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "正当我这样想着的时候,一个身影自小巷的那头走来。", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "changebg", - img1: "bg_3601.webp", - memory1: false, - img2: "bg_3531.webp", - memory2: false, - time: 30, - style: "场景切换", - }, - { - type: "cgtext", - bg: "bg_3531.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "凯伊姆", - time: 30, - wait: 1000, - sound: "", - text: "「艾莉斯」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "changebg", - img1: "bg_3531.webp", - memory1: false, - img2: "", - memory2: false, - time: 30, - style: "引出", - }, - { - type: "comment", - text: "好多立绘,先更这点(吐槽一下)", - }, - ], - chapter01: [ - { - type: "changebg", - img1: "", - memory1: false, - img2: "bg_3601.webp", - memory2: false, - time: 30, - style: "引入", - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "face_020106.webp", - px: -300, - }, - name: "艾莉斯", - time: 30, - wait: 1000, - sound: "", - text: "「啊,凯伊姆」", - bodyList: [ - { - name: "", - px: 100, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "face_020141.webp", - px: -300, - }, - name: "艾莉斯", - time: 30, - wait: 1000, - sound: "", - text: "「正好,我还想要去找你呢」", - bodyList: [ - { - name: "tati_020141.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "face_020157.webp", - px: -300, - }, - name: "艾莉斯", - time: 30, - wait: 1000, - sound: "", - text: "「没想到凯伊姆会主动出现······这是命运吗?」", - bodyList: [ - { - name: "tati_020157.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "凯伊姆", - time: 30, - wait: 1000, - sound: "", - text: "「显然不是吧」", - bodyList: [ - { - name: "tati_020157.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "face_020107.webp", - px: -300, - }, - name: "艾莉斯", - time: 30, - wait: 1000, - sound: "", - text: "「啊,是么」", - bodyList: [ - { - name: "tati_020107.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "艾莉斯挑了挑整齐的双眉,微微地哼了一声。", - bodyList: [ - { - name: "tati_020107.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "虽然是个相当引人注目的美人,但她这个将亲切儿子丢入无底深渊的性格,为自己扣了不少的分", - bodyList: [ - { - name: "tati_020107.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "给人印象最深的,就是那潭水般的双瞳。", - bodyList: [ - { - name: "tati_020107.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "", - time: 30, - wait: 1000, - sound: "", - text: "在漆黑的瞳孔中,完全看不出感情的波动。", - bodyList: [ - { - name: "tati_020107.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "face_020157.webp", - px: -300, - }, - name: "艾莉斯", - time: 30, - wait: 1000, - sound: "", - text: "「喜欢我的眼睛吗?」", - bodyList: [ - { - name: "tati_020157.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "face_020157.webp", - px: -300, - }, - name: "艾莉斯", - time: 30, - wait: 1000, - sound: "", - text: "「如果想要的话就给你吧?」", - bodyList: [ - { - name: "tati_020157.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "凯伊姆", - time: 30, - wait: 1000, - sound: "", - text: "「用不着」", - bodyList: [ - { - name: "tati_020157.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "face_020111.webp", - px: -300, - }, - name: "艾莉斯", - time: 30, - wait: 1000, - sound: "", - text: "「阿拉,可惜」", - bodyList: [ - { - name: "tati_020111.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "凯伊姆", - time: 30, - wait: 1000, - sound: "", - text: "「那么,找我有什么事」", - bodyList: [ - { - name: "tati_020111.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "face_020101.webp", - px: -300, - }, - name: "艾莉斯", - time: 30, - wait: 1000, - sound: "", - text: "「梅尔特的钱好像被偷了」", - bodyList: [ - { - name: "tati_020101.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "凯伊姆", - time: 30, - wait: 1000, - sound: "", - text: "「钱被偷了?都几岁了还这么没用」", - bodyList: [ - { - name: "tati_020101.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "face_020107.webp", - px: -300, - }, - name: "艾莉斯", - time: 30, - wait: 1000, - sound: "", - text: "「不要对我说啊」", - bodyList: [ - { - name: "tati_020107.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "凯伊姆", - time: 30, - wait: 1000, - sound: "", - text: "「那家伙,该不会说要让我去抓那个小偷吧?」", - bodyList: [ - { - name: "tati_020107.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "face_020157.webp", - px: -300, - }, - name: "艾莉斯", - time: 30, - wait: 1000, - sound: "", - text: "「就是这样」", - bodyList: [ - { - name: "tati_020157.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "凯伊姆", - time: 30, - wait: 1000, - sound: "", - text: "「笨蛋吗」", - bodyList: [ - { - name: "tati_020157.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "凯伊姆", - time: 30, - wait: 1000, - sound: "", - text: "「如果是小钱的话,就当做是买个教训吧」", - bodyList: [ - { - name: "tati_020157.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "face_020125.webp", - px: -300, - }, - name: "艾莉斯", - time: 30, - wait: 1000, - sound: "", - text: "「说起来,被盗的是这个月的上纳金」", - bodyList: [ - { - name: "tati_020125.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "凯伊姆", - time: 30, - wait: 1000, - sound: "", - text: "「你说什么?」", - bodyList: [ - { - name: "tati_020125.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "face_020121.webp", - px: -300, - }, - name: "艾莉斯", - time: 30, - wait: 1000, - sound: "", - text: "「用这些钱买教训,也太过奢侈了呢」", - bodyList: [ - { - name: "tati_020121.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "凯伊姆", - time: 30, - wait: 1000, - sound: "", - text: "「知道了,我去找」", - bodyList: [ - { - name: "tati_020121.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "凯伊姆", - time: 30, - wait: 1000, - sound: "", - text: "「小偷的特征呢」", - bodyList: [ - { - name: "tati_020121.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "face_020105.webp", - px: -300, - }, - name: "艾莉斯", - time: 30, - wait: 1000, - sound: "", - text: "「男孩子」", - bodyList: [ - { - name: "tati_020105.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "face_020103.webp", - px: -300, - }, - name: "艾莉斯", - time: 30, - wait: 1000, - sound: "", - text: "「······而且,背后有翅膀」", - bodyList: [ - { - name: "tati_020103.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "face_020141.webp", - px: -300, - }, - name: "艾莉斯", - time: 30, - wait: 1000, - sound: "", - text: "「虽然姑且是藏在身后,但是仔细观察的话是很明显的」", - bodyList: [ - { - name: "tati_020141.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "凯伊姆", - time: 30, - wait: 1000, - sound: "", - text: "「羽化病吗」", - bodyList: [ - { - name: "tati_020141.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "face_020105.webp", - px: -300, - }, - name: "艾莉斯", - time: 30, - wait: 1000, - sound: "", - text: "「那些人可是毫不留情的,所以即使是为了那个孩子,也要赶快抓到他」", - bodyList: [ - { - name: "tati_020105.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "凯伊姆", - time: 30, - wait: 1000, - sound: "", - text: "「注意到他逃窜的方向了吗?」", - bodyList: [ - { - name: "tati_020105.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "face_020105.webp", - px: -300, - }, - name: "艾莉斯", - time: 30, - wait: 1000, - sound: "", - text: "「广场那边」", - bodyList: [ - { - name: "tati_020105.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "face_020107.webp", - px: -300, - }, - name: "艾莉斯", - time: 30, - wait: 1000, - sound: "", - text: "「虽然刚才《不蚀金锁》的人去追了,不过多半是······」", - bodyList: [ - { - name: "tati_020107.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "凯伊姆", - time: 30, - wait: 1000, - sound: "", - text: "「偏偏还是广场吗」", - bodyList: [ - { - name: "tati_020107.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "face_020141.webp", - px: -300, - }, - name: "艾莉斯", - time: 30, - wait: 1000, - sound: "", - text: "「今天是觐见圣女大人的日子」", - bodyList: [ - { - name: "tati_020145.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "凯伊姆", - time: 30, - wait: 1000, - sound: "", - text: "「我知道」", - bodyList: [ - { - name: "tati_020145.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "cgtext", - bg: "bg_3601.webp", - memory: false, - WindowSkin: false, - head: { - name: "", - px: -300, - }, - name: "凯伊姆", - time: 30, - wait: 1000, - sound: "", - text: "「尽量找找看就好」", - bodyList: [ - { - name: "tati_020145.webp", - px: 600, - filter: false, - }, - ], - }, - { - type: "changebg", - img1: "bg_3601.webp", - memory1: false, - img2: "", - memory2: false, - time: 30, - style: "引出", - }, - ], - chapter02: null, - chapter03: null, - chapter04: null, - chapter05: null, - 强制横屏: [ - { - type: "if", - condition: "((!main.replayChecking )&&(!core.isReplaying()))", - true: [ - { - type: "if", - condition: - '((screen.orientation || {}).type ||\n screen.mozOrientation ||\n screen.msOrientation!=="landscape-primary")', - true: [ - { - type: "if", - condition: "(!core.platform.isPC)", - true: [ - { - type: "confirm", - default: true, - text: "手机用户横屏体验更佳,是否切换", - yes: [ - { - type: "function", - function: - "function(){\ncore.triggerFullscreen(true)\n}", - }, - ], - no: [], - }, - ], - }, - ], - }, - ], - }, - ], - }, - CommonEventTemplate: { - 检测音乐如果没有开启则系统提示开启: [ - { - type: "if", - condition: "!core.musicStatus.bgmStatus", - true: ["\t[系统提示]你当前音乐处于关闭状态,本塔开音乐游戏效果更佳"], - false: [], - }, - ], - 仿新新魔塔一次性商人: [ - { - type: "if", - condition: "switch:A", - true: [ - "\t[行商,trader]\b[this]这是购买我的道具后我给玩家的提示。", - { - type: "comment", - text: "下一条指令可视情况使用或不使用", - }, - { - type: "hide", - remove: true, - time: 250, - loc: [[]], - }, - ], - false: [ - { - type: "confirm", - text: "我有3把黄钥匙,\n你出50金币就卖给你。", - yes: [ - { - type: "if", - condition: "status:money>=50", - true: [ - { - type: "setValue", - name: "status:money", - operator: "-=", - value: "50", - }, - { - type: "setValue", - name: "item:yellowKey", - operator: "+=", - value: "3", - }, - { - type: "playSound", - name: "确定", - stop: true, - }, - { - type: "setValue", - name: "switch:A", - value: "true", - }, - ], - false: [ - { - type: "playSound", - name: "操作失败", - }, - "\t[行商,trader]\b[this]你的金币不足!", - ], - }, - ], - no: [], - }, - ], - }, - ], - 全地图选中一个点: [ - { - type: "comment", - text: "全地图选中一个点,需要用鼠标或触屏操作", - }, - { - type: "setValue", - name: "temp:X", - value: "status:x", - }, - { - type: "setValue", - name: "temp:Y", - value: "status:y", - }, - { - type: "tip", - text: "再次点击闪烁位置确认", - }, - { - type: "while", - condition: "true", - data: [ - { - type: "drawSelector", - image: "winskin.webp", - code: 1, - x: "32*temp:X", - y: "32*temp:Y", - width: 32, - height: 32, - }, - { - type: "wait", - }, - { - type: "if", - condition: "(flag:type === 1)", - true: [ - { - type: "if", - condition: "((temp:X===flag:x)&&(temp:Y===flag:y))", - true: [ - { - type: "break", - n: 1, - }, - ], - }, - { - type: "setValue", - name: "temp:X", - value: "flag:x", - }, - { - type: "setValue", - name: "temp:Y", - value: "flag:y", - }, - ], - }, - ], - }, - { - type: "drawSelector", - code: 1, - }, - { - type: "comment", - text: "流程进行到这里可以对[X,Y]点进行处理,比如", - }, - { - type: "closeDoor", - id: "yellowDoor", - loc: ["temp:X", "temp:Y"], - }, - ], - 多阶段Boss战斗: [ - { - type: "comment", - text: "多阶段boss,请直接作为战后事件使用", - }, - { - type: "setValue", - name: "switch:A", - operator: "+=", - value: "1", - }, - { - type: "switch", - condition: "switch:A", - caseList: [ - { - case: "1", - action: [ - { - type: "setBlock", - number: "redSlime", - loc: [[]], - }, - "\t[2阶段boss,redSlime]\b[this]你以为你已经打败我了吗?没听说过史莱姆有九条命吗?", - ], - }, - { - case: "2", - action: [ - { - type: "setBlock", - number: "blackSlime", - loc: [[]], - }, - "\t[3阶段boss,blackSlime]\b[this]不能消灭我的,只会让我更强大!", - ], - }, - { - case: "3", - action: [ - { - type: "setBlock", - number: "slimelord", - loc: [[]], - }, - "\t[4阶段boss,slimelord]\b[this]我还能打!", - ], - }, - { - case: "4", - action: ["\t[4阶段boss,slimelord]我一定会回来的!"], - }, - ], - }, - ], - 光标修改: [ - { - type: "changeMouse", - icon: "sword0", - div: "gameGroup", - translate: [0, 0], - scale: [1, 1], - angle: 0, - px: 0, - py: 0, - }, - { - type: "removeMouse", - div: "gameGroup", - }, - ], - 添加弹幕: [ - { - type: "addPop", - value: "这段话将在游戏中以弹幕显示", - px: 32, - py: 32, - color: [255, 0, 0, 1], - boldColor: [0, 0, 0, 1], - left: false, - jump: false, - time: 60, - show: 30, - font: "16px Verdana", - speed: 1, - }, - ], - }, -}; +var events_c12a15a8_c380_4b28_8144_256cba95f760 = +{ + "commonEvent": { + "加点事件": [ + { + "type": "comment", + "text": "通过传参,flag:arg1 表示当前应该的加点数值" + }, + { + "type": "choices", + "choices": [ + { + "text": "攻击+${1*flag:arg1}", + "action": [ + { + "type": "setValue", + "name": "status:atk", + "operator": "+=", + "value": "1*flag:arg1" + } + ] + }, + { + "text": "防御+${2*flag:arg1}", + "action": [ + { + "type": "setValue", + "name": "status:def", + "operator": "+=", + "value": "2*flag:arg1" + } + ] + }, + { + "text": "生命+${200*flag:arg1}", + "action": [ + { + "type": "setValue", + "name": "status:hp", + "operator": "+=", + "value": "200*flag:arg1" + } + ] + } + ] + } + ], + "回收钥匙商店": [ + { + "type": "comment", + "text": "此事件在全局商店中被引用了(全局商店keyShop)" + }, + { + "type": "comment", + "text": "解除引用前勿删除此事件" + }, + { + "type": "comment", + "text": "玩家在快捷列表(V键)中可以使用本公共事件" + }, + { + "type": "while", + "condition": "1", + "data": [ + { + "type": "choices", + "text": "\t[商人,trader]你有多余的钥匙想要出售吗?", + "choices": [ + { + "text": "黄钥匙(10金币)", + "color": [ + 255, + 255, + 0, + 1 + ], + "action": [ + { + "type": "if", + "condition": "item:yellowKey >= 1", + "true": [ + { + "type": "setValue", + "name": "item:yellowKey", + "operator": "-=", + "value": "1" + }, + { + "type": "setValue", + "name": "status:money", + "operator": "+=", + "value": "10" + } + ], + "false": [ + "\t[商人,trader]你没有黄钥匙!" + ] + } + ] + }, + { + "text": "蓝钥匙(50金币)", + "color": [ + 0, + 0, + 255, + 1 + ], + "action": [ + { + "type": "if", + "condition": "item:blueKey >= 1", + "true": [ + { + "type": "setValue", + "name": "item:blueKey", + "operator": "-=", + "value": "1" + }, + { + "type": "setValue", + "name": "status:money", + "operator": "+=", + "value": "50" + } + ], + "false": [ + "\t[商人,trader]你没有蓝钥匙!" + ] + } + ] + }, + { + "text": "离开", + "action": [ + { + "type": "exit" + } + ] + } + ] + } + ] + } + ], + "chapter0": [ + { + "type": "playBgm", + "name": "Crawler.opus", + "keep": true + }, + { + "type": "setText", + "time": 50 + }, + { + "type": "changebg", + "img1": "", + "memory1": false, + "img2": "", + "memory2": false, + "time": 30, + "style": "引入" + }, + { + "type": "over", + "text": "人生不如意事,十常居七八。", + "image": "", + "memory": false, + "time": 50, + "hidetime": 30, + "sound": "", + "textColor": [ + 255, + 255, + 255, + 1 + ], + "boldColor": [ + 0, + 0, + 0, + 1 + ], + "font": "bold 48px Verdana" + }, + { + "type": "over", + "text": "世间的万物皆被装缀着不公的色彩。", + "image": "", + "memory": false, + "time": 50, + "hidetime": 30, + "sound": "", + "textColor": [ + 255, + 255, + 255, + 1 + ], + "boldColor": [ + 0, + 0, + 0, + 1 + ], + "font": "bold 48px Verdana" + }, + { + "type": "over", + "text": "没错,就像——", + "image": "", + "memory": false, + "time": 50, + "hidetime": 30, + "sound": "", + "textColor": [ + 255, + 255, + 255, + 1 + ], + "boldColor": [ + 0, + 0, + 0, + 1 + ], + "font": "bold 48px Verdana" + }, + { + "type": "over", + "text": "十几年前的那一天,", + "image": "", + "memory": false, + "time": 50, + "hidetime": 30, + "sound": "", + "textColor": [ + 255, + 255, + 255, + 1 + ], + "boldColor": [ + 0, + 0, + 0, + 1 + ], + "font": "bold 48px Verdana" + }, + { + "type": "over", + "text": "在都市的角落,同许多的生命共同消逝一般。", + "image": "", + "memory": false, + "time": 50, + "hidetime": 30, + "sound": "", + "textColor": [ + 255, + 255, + 255, + 1 + ], + "boldColor": [ + 0, + 0, + 0, + 1 + ], + "font": "bold 48px Verdana" + }, + { + "type": "over", + "text": "没错,就像——", + "image": "", + "memory": false, + "time": 50, + "hidetime": 30, + "sound": "", + "textColor": [ + 255, + 255, + 255, + 1 + ], + "boldColor": [ + 0, + 0, + 0, + 1 + ], + "font": "bold 48px Verdana" + }, + { + "type": "over", + "text": "十几年前的那天起以来,", + "image": "", + "memory": false, + "time": 50, + "hidetime": 30, + "sound": "", + "textColor": [ + 255, + 255, + 255, + 1 + ], + "boldColor": [ + 0, + 0, + 0, + 1 + ], + "font": "bold 48px Verdana" + }, + { + "type": "over", + "text": "无数的生命被那无法逃脱的污泥囚禁一样。", + "image": "", + "memory": false, + "time": 50, + "hidetime": 30, + "sound": "", + "textColor": [ + 255, + 255, + 255, + 1 + ], + "boldColor": [ + 0, + 0, + 0, + 1 + ], + "font": "bold 48px Verdana" + }, + { + "type": "over", + "text": "人生不如意事,十常居七八。", + "image": "", + "memory": false, + "time": 50, + "hidetime": 30, + "sound": "", + "textColor": [ + 255, + 255, + 255, + 1 + ], + "boldColor": [ + 0, + 0, + 0, + 1 + ], + "font": "bold 48px Verdana" + }, + { + "type": "over", + "text": "世间的万物皆被装缀着不公的色彩。", + "image": "", + "memory": false, + "time": 50, + "hidetime": 30, + "sound": "", + "textColor": [ + 255, + 255, + 255, + 1 + ], + "boldColor": [ + 0, + 0, + 0, + 1 + ], + "font": "bold 48px Verdana" + }, + { + "type": "over", + "text": "没错,就像——", + "image": "", + "memory": false, + "time": 50, + "hidetime": 30, + "sound": "", + "textColor": [ + 255, + 255, + 255, + 1 + ], + "boldColor": [ + 0, + 0, + 0, + 1 + ], + "font": "bold 48px Verdana" + }, + { + "type": "over", + "text": "如今,这一天。", + "image": "", + "memory": false, + "time": 50, + "hidetime": 30, + "sound": "", + "textColor": [ + 255, + 255, + 255, + 1 + ], + "boldColor": [ + 0, + 0, + 0, + 1 + ], + "font": "bold 48px Verdana" + }, + { + "type": "changebg", + "img1": "", + "memory1": false, + "img2": "other_0001.webp", + "memory2": false, + "time": 30, + "style": "场景切换" + }, + { + "type": "cgtext", + "bg": "other_0001.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "这些天,街道不曾下雨。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "other_0001.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "所以,那浸湿地面的,定是那些女孩们流落的鲜血无疑。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "other_0001.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "我蹲在充斥着铁锈味般恶臭的小巷中,悠闲地如是想着。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "changebg", + "img1": "other_0001.webp", + "memory1": false, + "img2": "bg_3563.webp", + "memory2": false, + "time": 30, + "style": "场景切换" + }, + { + "type": "cgtext", + "bg": "bg_3563.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "扑哧。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3563.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "耳旁再次响起象征着某个女孩子死去的声音。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3563.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "再一次——", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3563.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "再一次。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3563.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "女子们被肢解成单纯的肉块。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3563.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "我任由流下的血浸满全身,屏住自己的呼吸。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3563.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "祈求自己能拥有从猎人手中逃脱的幸运。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3563.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "扑哧。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "changebg", + "img1": "bg_3563.webp", + "memory1": false, + "img2": "other_0002.webp", + "memory2": false, + "time": 30, + "style": "场景切换" + }, + { + "type": "cgtext", + "bg": "other_0002.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "直到刚才,我们还坐在去往娼馆的马车的路上。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "other_0002.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "而在这之中的某些人,已经不在这个世上了。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "other_0002.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "不,应该把“某些”换成“几乎所有”才更为恰当吧。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "other_0002.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "恐怕,不久之后我也会变成小巷中血腥的装饰品。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "other_0002.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "我是为了得到这种死法,才辛苦苟活至今的吗?", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "other_0002.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "来个人告诉我啊——", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "other_0002.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "谁都好。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "other_0002.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "来人啊!!", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "changebg", + "img1": "other_0002.webp", + "memory1": false, + "img2": "other_0001.webp", + "memory2": false, + "time": 30, + "style": "场景切换" + }, + { + "type": "cgtext", + "bg": "other_0001.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "少女", + "time": 30, + "wait": 1000, + "sound": "aiy010000010.opus", + "text": "「呃······!?」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "changebg", + "img1": "other_0001.webp", + "memory1": false, + "img2": "other_0003.webp", + "memory2": false, + "time": 30, + "style": "场景切换" + }, + { + "type": "cgtext", + "bg": "other_0003.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "漆黑的物体充斥了我的整个视野", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "other_0003.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "我很快意识到,那是只很大的脚。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "changebg", + "img1": "other_0003.webp", + "memory1": false, + "img2": "", + "memory2": false, + "time": 30, + "style": "场景切换" + }, + { + "type": "cgtext", + "bg": "", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "必须要出声求救。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "changebg", + "img1": "", + "memory1": false, + "img2": "other_0003.webp", + "memory2": false, + "time": 30, + "style": "场景切换" + }, + { + "type": "cgtext", + "bg": "other_0003.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "可是,耳中却只能听到自己的牙关不停交战的声音。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "other_0003.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 50, + "wait": 1000, + "sound": "", + "text": "我是如此的无助。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "changebg", + "img1": "other_0003.webp", + "memory1": false, + "img2": "", + "memory2": false, + "time": 30, + "style": "场景切换" + }, + { + "type": "cgtext", + "bg": "", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "逃跑也好,道歉也罢。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "就连抬头看一眼将要杀掉我的人的面孔都做不到。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "少女", + "time": 30, + "wait": 2000, + "sound": "aiy010000020.opus", + "text": "「······被杀」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "会被杀。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "会被杀!!", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "来自内心深处的冰冷预感,渐渐地在体内蔓延开来。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "少女", + "time": 30, + "wait": 1000, + "sound": "aiy010000030.opus", + "text": "「不,不要······」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "playBgm", + "name": "Blind_Alley.opus", + "keep": true + }, + { + "type": "changebg", + "img1": "", + "memory1": false, + "img2": "bg_6004.webp", + "memory2": false, + "time": 30, + "style": "场景切换" + }, + { + "type": "cgtext", + "bg": "bg_6004.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "浮游都市,《诺瓦斯·艾蒂尔》。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_6004.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "《特别受灾地区》——", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_6004.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "通称,《牢狱》", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_6004.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "是被险峻的峭壁环绕,与世隔绝的,都市的最底部。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_6004.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "年轻人", + "time": 30, + "wait": 1000, + "sound": "aiy710000010.opus", + "text": "「放开我!」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_6004.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "年轻人", + "time": 30, + "wait": 1000, + "sound": "aiy710000020.opus", + "text": "「我只是在帮那个女人而已!」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "changebg", + "img1": "bg_6004.webp", + "memory1": false, + "img2": "other_0004.webp", + "memory2": false, + "time": 30, + "style": "场景切换" + }, + { + "type": "cgtext", + "bg": "other_0004.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "年轻人", + "time": 30, + "wait": 1000, + "sound": "aiy710000030.opus", + "text": "「你们没听到吗!?」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "other_0004.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "年轻人", + "time": 30, + "wait": 1000, + "sound": "aiy710000040.opus", + "text": "「她是被受骗才会被卖到娼馆来的」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "other_0004.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "年轻人", + "time": 30, + "wait": 1000, + "sound": "aiy710000050.opus", + "text": "「用肮脏的手段把钱借给她父母的,就是你们这些家伙吧!?」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "changebg", + "img1": "other_0004.webp", + "memory1": false, + "img2": "bg_3601.webp", + "memory2": false, + "time": 30, + "style": "场景切换" + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "年轻人", + "time": 30, + "wait": 1000, + "sound": "aiy710000060.opus", + "text": "「给我说些什么啊」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "aiy310000010.opus", + "text": "「这些话等到了娼馆再说吧」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "aiy310000020.opus", + "text": "「我来抓你,只是受雇于人而已」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "changebg", + "img1": "bg_3601.webp", + "memory1": false, + "img2": "bg_3531.webp", + "memory2": false, + "time": 30, + "style": "场景切换" + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "我走进娼馆《莉莉乌姆》的接待室。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "正在桌旁整理账簿的奥兹停下手头的工作,抬起头向我看来。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "奥兹", + "time": 30, + "wait": 1000, + "sound": "aiy350000010.opus", + "text": "「这不是凯伊姆先生吗,辛苦了」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "奥兹", + "time": 30, + "wait": 1000, + "sound": "aiy350000020.opus", + "text": "「委托已经完成了吗?」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "aiy310000030.opus", + "text": "「啊啊,是这家伙没错吧」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "奥兹用只要接触到就能杀人般的眼神在男人脸上搜过。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "奥兹", + "time": 30, + "wait": 1000, + "sound": "aiy350000030.opus", + "text": "「没错,就是这个人」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "aiy310000040.opus", + "text": "「是么」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "年轻人", + "time": 30, + "wait": 1000, + "sound": "aiy710000070.opus", + "text": "「你,你们要对我做什么」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "奥兹", + "time": 30, + "wait": 1000, + "sound": "aiy350000040.opus", + "text": "「······」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "奥兹用一个眼神,就让男人闭上了嘴。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "然后,向我这边转过身来。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "奥兹", + "time": 30, + "wait": 1000, + "sound": "aiy350000050.opus", + "text": "「抱歉啊,总是麻烦你去做这些无聊的事」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "奥兹", + "time": 30, + "wait": 1000, + "sound": "aiy350000060.opus", + "text": "「都怪我们这边的年轻人太没用」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "aiy310000050.opus", + "text": "「客套话就免了」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "奥兹", + "time": 30, + "wait": 1000, + "sound": "aiy350000070.opus", + "text": "「这还真是失礼了」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "奥兹", + "time": 30, + "wait": 1000, + "sound": "aiy350000080.opus", + "text": "「喂,来个人」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "光头男人", + "time": 30, + "wait": 1000, + "sound": "aiy820000010.opus", + "text": "「是」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "奥兹", + "time": 30, + "wait": 1000, + "sound": "aiy350000090.opus", + "text": "「凯伊姆先生做完工作回来了」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "光头男人", + "time": 30, + "wait": 1000, + "sound": "aiy820000020.opus", + "text": "「是,是,那个······」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "奥兹", + "time": 30, + "wait": 1000, + "sound": "aiy350000100.opus", + "text": "「我是要你拿些酒来,这个蠢材!」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "喀!", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "奥兹扔出的烟灰缸砸中了手下的额头。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "鲜血四溅。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "aiy310000060.opus", + "text": "「不用这么麻烦」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "aiy310000070.opus", + "text": "「我接下来要去《菲诺列塔》」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "奥兹", + "time": 30, + "wait": 1000, + "sound": "aiy350000110.opus", + "text": "「喔唷」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "奥兹", + "time": 30, + "wait": 1000, + "sound": "aiy350000120.opus", + "text": "「既然如此,我就不留您在这里喝难饮的劣质酒了」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "奥兹斜眼看着正捂住额头呻吟的手下,轻描淡写地说道。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "aiy310000080.opus", + "text": "「用这些钱去买药」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "我将几枚铜钱仍在那个手下的身前。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "奥兹", + "time": 30, + "wait": 1000, + "sound": "aiy350000130.opus", + "text": "「凯伊姆先生,不用对他们这么好」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "aiy310000090.opus", + "text": "「无妨」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "aiy310000100.opus", + "text": "「话说回来,那个要落跑的女人呢?」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "奥兹", + "time": 30, + "wait": 1000, + "sound": "aiy350000140.opus", + "text": "「我把她交给那些年轻人了,现在应该正在体会人生的严苛吧」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "奥兹", + "time": 30, + "wait": 1000, + "sound": "aiy350000150.opus", + "text": "「正好,趁此机会凯伊姆先生也来享受一番如何?」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "年轻人", + "time": 30, + "wait": 1000, + "sound": "aiy710000080.opus", + "text": "「你,你们这些家伙,要对她做什么!?」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "咣!", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "奥兹给了他一拳。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "一击即倒。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "喀,咚,咯!", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "奥兹毫不留情地向男人的脸上踩去。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "年轻人", + "time": 30, + "wait": 1000, + "sound": "aiy710000090.opus", + "text": "「咕······呃咳······」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "折断的牙齿伴着血泡被吐出。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "这份白色在鲜红色的液体中格外显眼。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "年轻人", + "time": 30, + "wait": 1000, + "sound": "aiy710000100.opus", + "text": "「你们以为做出这种事······卫兵会坐视不理吗······」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "奥兹", + "time": 30, + "wait": 1000, + "sound": "aiy350000160.opus", + "text": "「啊啊,不会坐视不理的」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "奥兹", + "time": 30, + "wait": 1000, + "sound": "aiy350000170.opus", + "text": "「应该会拿出你的钱包,和我们商量如何瓜分吧」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "年轻人", + "time": 30, + "wait": 1000, + "sound": "aiy710000110.opus", + "text": "「那,那种事······」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "这在牢狱是理所当然的事。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "奥兹", + "time": 30, + "wait": 2000, + "sound": "aiy350000180.opus", + "text": "「怎么,头一回来牢狱么?」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "男人点了点头。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "奥兹", + "time": 30, + "wait": 1000, + "sound": "aiy350000190.opus", + "text": "「为了被骗的女人而来到牢狱,真是个规矩人啊」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "奥兹", + "time": 30, + "wait": 1000, + "sound": "aiy350000200.opus", + "text": "「······前提是,被骗的人不是你」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "年轻人", + "time": 30, + "wait": 1000, + "sound": "aiy710000120.opus", + "text": "「你说······我被骗了?」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "年轻人", + "time": 30, + "wait": 1000, + "sound": "aiy710000130.opus", + "text": "「那,那是怎么回事!?」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "奥兹", + "time": 30, + "wait": 1000, + "sound": "aiy350000210.opus", + "text": "「不用急,今天晚上会好好告诉你的」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "奥兹抓起男人的脸。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "为引诱客人的怜悯之心而装纯,是娼妇的惯用手段。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "双亲被骗而借钱,结果作为抵押而将自己卖到这里,这是典型的说法。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "如果只是头脑发热而成为常客也就罢了,这次的男人热血过头,居然想出了要带女人私奔的计划。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "虽然女人半开玩笑地予以拒绝,但不知天高地厚的这家伙还是拉着她逃跑了。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "不过,想要逃脱追击本来就是不可能的任务。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "但即便如此,这种事情还是会一再的出现。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "说谎的女人和被骗的男人。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "在娼馆街,这是令人看到生厌的日常的风景。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "aiy310000110.opus", + "text": "「我要走了」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "奥兹", + "time": 30, + "wait": 1000, + "sound": "aiy350000220.opus", + "text": "「好的,下次再麻烦您」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "奥兹", + "time": 30, + "wait": 1000, + "sound": "aiy350000230.opus", + "text": "「之后吉克先生会将谢礼交给您的」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "aiy310000120.opus", + "text": "「啊啊」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "我背向奥兹走出娼馆。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "aiy310000130.opus", + "text": "「······?」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "changebg", + "img1": "bg_3531.webp", + "memory1": false, + "img2": "bg_3601.webp", + "memory2": false, + "time": 30, + "style": "场景切换" + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "从远方传来微弱的歌声。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "是关卡广场的方向。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "对了。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "今天有觐见圣女的仪式。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "当代的圣女伊莲——", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "俗称《盲眼之圣女》,据说即使在历代的圣女中,人气也是数一数二的。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "广场上的人估计相当多吧。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "虽然我也想去看看她长什么样,不过要在人潮中挤来挤去就免了。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "还是老老实实去菲诺列塔喝烧酒吧。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "正当我这样想着的时候,一个身影自小巷的那头走来。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "changebg", + "img1": "bg_3601.webp", + "memory1": false, + "img2": "bg_3531.webp", + "memory2": false, + "time": 30, + "style": "场景切换" + }, + { + "type": "cgtext", + "bg": "bg_3531.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "aiy310000140.opus", + "text": "「艾莉斯」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "changebg", + "img1": "bg_3531.webp", + "memory1": false, + "img2": "", + "memory2": false, + "time": 30, + "style": "引出" + }, + { + "type": "comment", + "text": "好多立绘,先更这点(吐槽一下)" + } + ], + "chapter01": [ + { + "type": "changebg", + "img1": "", + "memory1": false, + "img2": "bg_3601.webp", + "memory2": false, + "time": 30, + "style": "引入" + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_020106.webp", + "px": -300 + }, + "name": "艾莉斯", + "time": 30, + "wait": 1000, + "sound": "aiy020000005.opus", + "text": "「啊,凯伊姆」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_020141.webp", + "px": -300 + }, + "name": "艾莉斯", + "time": 30, + "wait": 1000, + "sound": "aiy020000010.opus", + "text": "「正好,我还想要去找你呢」", + "bodyList": [ + { + "name": "tati_020141.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_020157.webp", + "px": -300 + }, + "name": "艾莉斯", + "time": 30, + "wait": 1000, + "sound": "aiy020000020.opus", + "text": "「没想到凯伊姆会主动出现······这是命运吗?」", + "bodyList": [ + { + "name": "tati_020157.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "aiy310000150.opus", + "text": "「显然不是吧」", + "bodyList": [ + { + "name": "tati_020157.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_020107.webp", + "px": -300 + }, + "name": "艾莉斯", + "time": 30, + "wait": 1000, + "sound": "aiy020000030.opus", + "text": "「啊,是么」", + "bodyList": [ + { + "name": "tati_020107.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "艾莉斯挑了挑整齐的双眉,微微地哼了一声。", + "bodyList": [ + { + "name": "tati_020107.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "虽然是个相当引人注目的美人,但她这个将亲切儿子丢入无底深渊的性格,为自己扣了不少的分", + "bodyList": [ + { + "name": "tati_020107.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "给人印象最深的,就是那潭水般的双瞳。", + "bodyList": [ + { + "name": "tati_020107.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "在漆黑的瞳孔中,完全看不出感情的波动。", + "bodyList": [ + { + "name": "tati_020107.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_020157.webp", + "px": -300 + }, + "name": "艾莉斯", + "time": 30, + "wait": 1000, + "sound": "aiy020000040.opus", + "text": "「喜欢我的眼睛吗?」", + "bodyList": [ + { + "name": "tati_020157.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_020157.webp", + "px": -300 + }, + "name": "艾莉斯", + "time": 30, + "wait": 1000, + "sound": "aiy020000050.opus", + "text": "「如果想要的话就给你吧?」", + "bodyList": [ + { + "name": "tati_020157.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "aiy310000160.opus", + "text": "「用不着」", + "bodyList": [ + { + "name": "tati_020157.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_020111.webp", + "px": -300 + }, + "name": "艾莉斯", + "time": 30, + "wait": 1000, + "sound": "aiy020000060.opus", + "text": "「阿拉,可惜」", + "bodyList": [ + { + "name": "tati_020111.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "aiy310000170.opus", + "text": "「那么,找我有什么事」", + "bodyList": [ + { + "name": "tati_020111.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_020101.webp", + "px": -300 + }, + "name": "艾莉斯", + "time": 30, + "wait": 1000, + "sound": "aiy020000070.opus", + "text": "「梅尔特的钱好像被偷了」", + "bodyList": [ + { + "name": "tati_020101.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "aiy310000180.opus", + "text": "「钱被偷了?都几岁了还这么没用」", + "bodyList": [ + { + "name": "tati_020101.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_020107.webp", + "px": -300 + }, + "name": "艾莉斯", + "time": 30, + "wait": 1000, + "sound": "aiy020000080.opus", + "text": "「不要对我说啊」", + "bodyList": [ + { + "name": "tati_020107.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "aiy310000190.opus", + "text": "「那家伙,该不会说要让我去抓那个小偷吧?」", + "bodyList": [ + { + "name": "tati_020107.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_020157.webp", + "px": -300 + }, + "name": "艾莉斯", + "time": 30, + "wait": 1000, + "sound": "aiy020000090.opus", + "text": "「就是这样」", + "bodyList": [ + { + "name": "tati_020157.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "aiy310000200.opus", + "text": "「笨蛋吗」", + "bodyList": [ + { + "name": "tati_020157.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "aiy310000210.opus", + "text": "「如果是小钱的话,就当做是买个教训吧」", + "bodyList": [ + { + "name": "tati_020157.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_020125.webp", + "px": -300 + }, + "name": "艾莉斯", + "time": 30, + "wait": 1000, + "sound": "aiy020000100.opus", + "text": "「说起来,被盗的是这个月的上纳金」", + "bodyList": [ + { + "name": "tati_020125.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "aiy310000220.opus", + "text": "「你说什么?」", + "bodyList": [ + { + "name": "tati_020125.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_020121.webp", + "px": -300 + }, + "name": "艾莉斯", + "time": 30, + "wait": 1000, + "sound": "aiy020000110.opus", + "text": "「用这些钱买教训,也太过奢侈了呢」", + "bodyList": [ + { + "name": "tati_020121.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "aiy310000230.opus", + "text": "「知道了,我去找」", + "bodyList": [ + { + "name": "tati_020121.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "aiy310000240.opus", + "text": "「小偷的特征呢」", + "bodyList": [ + { + "name": "tati_020121.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_020105.webp", + "px": -300 + }, + "name": "艾莉斯", + "time": 30, + "wait": 1000, + "sound": "aiy020000120.opus", + "text": "「男孩子」", + "bodyList": [ + { + "name": "tati_020105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_020103.webp", + "px": -300 + }, + "name": "艾莉斯", + "time": 30, + "wait": 1000, + "sound": "aiy020000130.opus", + "text": "「······而且,背后有翅膀」", + "bodyList": [ + { + "name": "tati_020103.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_020141.webp", + "px": -300 + }, + "name": "艾莉斯", + "time": 30, + "wait": 1000, + "sound": "aiy020000140.opus", + "text": "「虽然姑且是藏在身后,但是仔细观察的话是很明显的」", + "bodyList": [ + { + "name": "tati_020141.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "aiy310000250.opus", + "text": "「羽化病吗」", + "bodyList": [ + { + "name": "tati_020141.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_020105.webp", + "px": -300 + }, + "name": "艾莉斯", + "time": 30, + "wait": 1000, + "sound": "aiy020000150.opus", + "text": "「那些人可是毫不留情的,所以即使是为了那个孩子,也要赶快抓到他」", + "bodyList": [ + { + "name": "tati_020105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "aiy310000260.opus", + "text": "「注意到他逃窜的方向了吗?」", + "bodyList": [ + { + "name": "tati_020105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_020105.webp", + "px": -300 + }, + "name": "艾莉斯", + "time": 30, + "wait": 1000, + "sound": "aiy020000160.opus", + "text": "「广场那边」", + "bodyList": [ + { + "name": "tati_020105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_020107.webp", + "px": -300 + }, + "name": "艾莉斯", + "time": 30, + "wait": 1000, + "sound": "aiy020000170.opus", + "text": "「虽然刚才《不蚀金锁》的人去追了,不过多半是······」", + "bodyList": [ + { + "name": "tati_020107.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "aiy310000280.opus", + "text": "「偏偏还是广场吗」", + "bodyList": [ + { + "name": "tati_020107.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_020141.webp", + "px": -300 + }, + "name": "艾莉斯", + "time": 30, + "wait": 1000, + "sound": "aiy020000180.opus", + "text": "「今天是觐见圣女大人的日子」", + "bodyList": [ + { + "name": "tati_020145.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "aiy310000290.opus", + "text": "「我知道」", + "bodyList": [ + { + "name": "tati_020145.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3601.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "aiy310000300.opus", + "text": "「尽量找找看就好」", + "bodyList": [ + { + "name": "tati_020145.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "changebg", + "img1": "bg_3601.webp", + "memory1": false, + "img2": "", + "memory2": false, + "time": 30, + "style": "引出" + } + ], + "chapter02": [ + { + "type": "changebg", + "img1": "", + "memory1": false, + "img2": "bg_3561.webp", + "memory2": false, + "time": 30, + "style": "引入" + }, + { + "type": "cgtext", + "bg": "bg_3561.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "不蚀金锁成员", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「凯伊姆先生,凯伊姆先生」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3561.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "不蚀金锁成员", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「您已经和艾莉斯大夫见过面了吗?」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3561.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「啊啊,所以才会追过来的」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3561.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「看到小偷了吗?」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3561.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "不蚀金锁成员", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「没有,他向广场那边逃了过去,今天这么拥挤,我们也只能放弃了」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3561.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "不蚀金锁成员", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「不过,我也只是刚好在店里所以才追了过去,并不是受人所托」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3561.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "不蚀金锁成员", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「我已经准备撤退了」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3561.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "不蚀金锁成员", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「凯伊姆先生还要继续追吗?」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3561.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「啊啊」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3561.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "做完情报交换之后,我跟男人道别。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "changebg", + "img1": "bg_3561.webp", + "memory1": false, + "img2": "bg_3021.webp", + "memory2": false, + "time": 30, + "style": "场景切换" + }, + { + "type": "cgtext", + "bg": "bg_3021.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「和我想的一样啊······」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3021.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "在牢狱中最大的广场上,聚集着看不到尽头的人群。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3021.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "就算是来参见圣女祈祷,这人数也太多了点吧。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3021.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "自然,我也找不到逃跑的孩子。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3021.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "是混杂到人群中了吧。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3021.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "如果已经从广场上脱身了的话,就更难发现了。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3021.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "只好赌他还在这里了。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "changebg", + "img1": "bg_3021.webp", + "memory1": false, + "img2": "bg_0000.png", + "memory2": false, + "time": 30, + "style": "场景切换" + }, + { + "type": "cgtext", + "bg": "bg_0000.png", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "我先移动到了一个视野良好的地方。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_0000.png", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "从这里,一眼就可以看到人群的变化。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_0000.png", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "广场还是沸腾起来。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "changebg", + "img1": "bg_0000.png", + "memory1": false, + "img2": "bg_3021.webp", + "memory2": false, + "time": 30, + "style": "场景切换" + }, + { + "type": "comment", + "text": "这个神官草莓说是特效不是立绘,标记!" + }, + { + "type": "cgtext", + "bg": "bg_3021.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "抬头望去,原来是在天台之上出现了一个人影", + "bodyList": [ + { + "name": "tati_440101.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3021.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "但是,与周围的期待不同,现身的是一名中年的神官。", + "bodyList": [ + { + "name": "tati_440101.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3021.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "骂声四溢。", + "bodyList": [ + { + "name": "tati_440101.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3021.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "神官则是笑着摆正衣领", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3021.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_440101.webp", + "px": -300 + }, + "name": "神官", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「从现在开始,举行谒见的仪式」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3021.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_440105.webp", + "px": -300 + }, + "name": "神官", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「在参见那位大人之前,我希望牢狱的诸位再次思考这个《诺瓦斯·艾蒂尔》存在的意义······」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3021.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_440101.webp", + "px": -300 + }, + "name": "神官", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「初代圣女伊莲大人,便是也难怪这崇高的祈祷之力,令《诺瓦斯·艾蒂尔》浮在空中,拯救了我们的祖先」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3021.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_440110.webp", + "px": -300 + }, + "name": "神官", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「这之后的几百年来,传承了初代大人力量的历代圣女伊莲大人,让这里留在了空中」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3021.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_440101.webp", + "px": -300 + }, + "name": "神官", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「这座都市是被圣女大人守护的人类最后的圣域,而我们则是被选召的虔诚的信徒」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3021.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_440102.webp", + "px": -300 + }, + "name": "神官", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「怀着对圣女的感激祈祷吧,感谢圣女伊莲吧!并献上祈祷!」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "comment", + "text": "这里是音效,打个标签" + }, + { + "type": "changebg", + "img1": "bg_3021.webp", + "memory1": false, + "img2": "bg_3026.webp", + "memory2": false, + "time": 30, + "style": "场景切换" + }, + { + "type": "comment", + "text": "这里有一堆描述不知道加不加..." + }, + { + "type": "changebg", + "img1": "bg_3026.webp", + "memory1": false, + "img2": "eve_030101.webp", + "memory2": false, + "time": 30, + "style": "场景切换" + }, + { + "type": "cgtext", + "bg": "eve_030101.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_030102.webp", + "px": -300 + }, + "name": "圣女", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「不忘感谢与祈祷,神才会拯救我们」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "eve_030101.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_030101.webp", + "px": -300 + }, + "name": "圣女", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「与我一起,向审虔诚地祈祷吧」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "comment", + "text": "这里是人声音效,打个标签" + }, + { + "type": "cgtext", + "bg": "eve_030101.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "广场上欢声雷动。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "eve_030101.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "圣女没有回应喧嚣的人声,而是静静地合上双眼面向广场。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "eve_030101.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "虽然感觉有些冷淡,但总比像个傻瓜似的笑着向这群人挥手要强。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "eve_030101.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "她掌握着这条街道,还有在这条街上生活的人的命运。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "eve_030101.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "比起揽得人气,她更想要为了街道的继续存在而献出全力。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "eve_030101.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "也是为了不让《大崩落》的惨剧再度发生。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "eve_030101.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "十几年前的那场悲剧。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "eve_030101.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "虽然在我脑海中的记忆已经相当模糊,但哪怕只是稍有触及,不快的感觉都会在胸口蔓延开。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3021.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「······」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "eve_030101.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "这时我才想起,现在不是我在这里看圣女的时候。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "comment", + "text": "这里是人声音效,打个标签" + }, + { + "type": "cgtext", + "bg": "eve_030101.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "女声", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「——っ!?」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "changebg", + "img1": "eve_030101.webp", + "memory1": false, + "img2": "bg_3021.webp", + "memory2": false, + "time": 30, + "style": "场景切换" + }, + { + "type": "cgtext", + "bg": "bg_3021.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "围观的女人", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「羽,羽化病人!?」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3021.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "围观的中年人", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「喂,谁去叫下羽狩」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3021.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "惊慌的观众", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「你这家伙不要靠近我,要是传染了可怎么办」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3021.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "粗鲁的观众", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「你这小鬼赶快滚开」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3021.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「接下来」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "changebg", + "img1": "bg_3021.webp", + "memory1": false, + "img2": "bg_3026.webp", + "memory2": false, + "time": 30, + "style": "场景切换" + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_030107.webp", + "px": -300 + }, + "name": "圣女", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「发生什么事了?看上去似乎很嘈杂」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_130104.webp", + "px": -300 + }, + "name": "随从", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「似乎是某个人逃跑了······具体的我也不是很清楚」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_440103.webp", + "px": -300 + }, + "name": "神官", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「圣女大人,继续待在天台上可能会出事,请您先回到室内吧」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_030145.webp", + "px": -300 + }, + "name": "圣女", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「不用在意我,比起那个,我更关心究竟发生了什么事」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_440107.webp", + "px": -300 + }, + "name": "神官", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「对不起,我真的不知道」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_030145.webp", + "px": -300 + }, + "name": "圣女", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「······是吗」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_320101.webp", + "px": -300 + }, + "name": "男", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「恕我僭越,请准许我说明情况」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_320105.webp", + "px": -300 + }, + "name": "男", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「在来觐见的人群中出现了《羽化病》的患者」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_320101.webp", + "px": -300 + }, + "name": "男", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「围观的人群因而产生了骚动」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_320102.webp", + "px": -300 + }, + "name": "男", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「现在,《防疫局》已经派遣了部队。我想不久之后,他们就会安静下来了」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_030124.webp", + "px": -300 + }, + "name": "圣女", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「羽化病······」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_320107.webp", + "px": -300 + }, + "name": "男", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「怎么了?」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_030125.webp", + "px": -300 + }, + "name": "圣女", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「没什么」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_030141.webp", + "px": -300 + }, + "name": "圣女", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「辛苦了,你的名字是?」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_320102.webp", + "px": -300 + }, + "name": "男", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「属下是在防疫局任职的,鲁基乌斯· 迪斯·米利尤」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_440102.webp", + "px": -300 + }, + "name": "神官", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「噢噢,阁下就是鲁基乌斯卿吗,我听说过你的传闻」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_440109.webp", + "px": -300 + }, + "name": "神官", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「阁下是在工作上相当出色的人呢」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_320101.webp", + "px": -300 + }, + "name": "鲁基乌斯", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「不敢当」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_320108.webp", + "px": -300 + }, + "name": "鲁基乌斯", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「话说回来,这次是属下警备工作的失职。让圣女大人见到这不成体统的一面,请您见谅」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_030145.webp", + "px": -300 + }, + "name": "圣女", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「即使是目不见物的我,也能感受到聚集于此的民众数量之多。警备工作难以展开也在情理之中」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_320101.webp", + "px": -300 + }, + "name": "鲁基乌斯", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「属下不胜惶恐」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_320102.webp", + "px": -300 + }, + "name": "鲁基乌斯", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「接下来属下还要回到工作岗位上,在这里就先告退了」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_030101.webp", + "px": -300 + }, + "name": "圣女", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「鲁基乌斯先生」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_320101.webp", + "px": -300 + }, + "name": "鲁基乌斯", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「属下在」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_030105.webp", + "px": -300 + }, + "name": "圣女", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「你是怎样看待羽狩的工作的呢?」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_440106.webp", + "px": -300 + }, + "name": "神官", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「圣,圣女大人」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_320101.webp", + "px": -300 + }, + "name": "鲁基乌斯", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「防疫局的工作是国王陛下赐予的重要职务。属下非常荣幸能够为这个都市的繁荣尽一份微薄之力」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_440102.webp", + "px": -300 + }, + "name": "神官", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「不,不亏是鲁基乌斯卿,相当优秀的想法」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_030125.webp", + "px": -300 + }, + "name": "圣女", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「是吗。辛苦你了」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_130124.webp", + "px": -300 + }, + "name": "随从", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「圣女大人······」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_320102.webp", + "px": -300 + }, + "name": "鲁基乌斯", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「······」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3026.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_320101.webp", + "px": -300 + }, + "name": "鲁基乌斯", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「那么,属下就回岗位去了」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "changebg", + "img1": "bg_3026.webp", + "memory1": false, + "img2": "", + "memory2": false, + "time": 30, + "style": "引出" + }, + { + "type": "comment", + "text": "下一场景是追捕羽化病少年...做个标记" + } + ], + "chapter03": [ + { + "type": "changebg", + "img1": "", + "memory1": false, + "img2": "bg_3801.webp", + "memory2": false, + "time": 30, + "style": "引入" + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "从羽化病的少年纷乱的足音中,可以听得出相当的疲劳。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "显然,他并没有想到我会捷足先登吧。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "少年惶恐地回头看了一眼后,微微露出安心的表情,双手拄在膝盖上。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「辛苦你了」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「稀!?」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「逃到贫民区是个不错的想法」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「你,你是,羽狩吗?」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「不是」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「什,什么啊······混蛋,不要吓我啊」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「我对令你受惊这件事致以歉意」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「作为回报,麻烦你把从店里偷的钱交出来吧」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「钱?你在说什么」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「你要找的腰上的东西,掉在你身后了」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「哎?」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "comment", + "text": "画面上下抖动一下,cy" + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「呃呀」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「你······你这混蛋」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「······」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「把偷的钱交出来」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「我不知道你在······咕」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "comment", + "text": "画面上下抖动一下,cy" + }, + { + "type": "comment", + "text": "下面这个弹幕说翻译有误,是“就是我偷的,谁会给你这种人”,我也没看过日文原文不太晓得,先cy" + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「你,你说是我偷的······有什么证据吗」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「你还挺倔的啊」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「不过,给我听好了」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「你偷的那些钱,是要上缴给《不蚀金锁》的上纳金」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「而且,钱的主人是从前和吉克颇有渊源的女人」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「吉克?」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「他是《不蚀金锁》的主人,这么说你就明白了吧」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「哎?哎?怎么会······」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「再问你一遍,钱在哪里?」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「是,是,是,在我的怀里」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「你没有擅自拿掉一部分吧」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「是,是的」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「那,那个,您是《不蚀金锁》的人吗?」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「算是吧」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「我什么都可以做,请您一定要帮帮我」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「抱歉,我并没有兴趣去帮助他人」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「我什么······什么,都会做的······」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「我一直都是生活在下层的」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「可是,不知何时染上了羽化病······背后长出了翅膀······」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「被寄宿工作的店赶了出来,只得流落到牢狱这里」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「因为独自实在是饿的不行了,所以才会偷这些钱的」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「我明明没有做任何坏事······为什么······会遇到这种事······」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「谁知道」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「呜······呜呜······接下来,要对我做什么?」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「我要把你带到组织那里」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「怎,怎么这样」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「不过,那样做的前提是你不是羽化病人」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「组织也没有笨到把羽化病人招待到家里的程度」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「那么,是要放我逃走吗?」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「我要让你学到教训」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "comment", + "text": "画面上下抖动一下,cy" + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「如果换做是组织的制裁,至少要有断条胳膊的觉悟」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「你的运气不错」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「唔······啊,是的······」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「滚」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「非常感谢」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「唔啊!?」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "comment", + "text": "画面上下抖动一下,cy" + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430103.webp", + "px": -300 + }, + "name": "男", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「到这里就结束了,羽化病人」", + "bodyList": [ + { + "name": "tati_430103.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430105.webp", + "px": -300 + }, + "name": "男", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「确认他的翅膀」", + "bodyList": [ + { + "name": "tati_430105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "趁还没有被卷入麻烦的事情之前,赶快离开这里吧", + "bodyList": [ + { + "name": "tati_430105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "changebg", + "img1": "bg_3801.webp", + "memory1": false, + "img2": "bg_0000.png", + "memory2": false, + "time": 30, + "style": "场景切换" + }, + { + "type": "changebg", + "img1": "bg_0000.png", + "memory1": false, + "img2": "bg_3801.webp", + "memory2": false, + "time": 30, + "style": "场景切换" + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430106.webp", + "px": -300 + }, + "name": "羽狩的队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「那边的那个人」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「······有什么事?」", + "bodyList": [ + { + "name": "tati_430101.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430101.webp", + "px": -300 + }, + "name": "羽狩的队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「可以稍微让我问几句话吗」", + "bodyList": [ + { + "name": "tati_430101.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「······」", + "bodyList": [ + { + "name": "tati_430101.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「啊啊,无妨」", + "bodyList": [ + { + "name": "tati_430101.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430102.webp", + "px": -300 + }, + "name": "羽狩的队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「感谢您的合作」", + "bodyList": [ + { + "name": "tati_430102.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430102.webp", + "px": -300 + }, + "name": "", + "time": 0, + "wait": 2000, + "sound": "", + "text": "队长殷勤地致以谢礼。", + "bodyList": [ + { + "name": "tati_430102.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430102.webp", + "px": -300 + }, + "name": "", + "time": 0, + "wait": 2000, + "sound": "", + "text": "而在他的眼前,少年的衣服已经被他的补下们扯破。", + "bodyList": [ + { + "name": "tati_430102.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430102.webp", + "px": -300 + }, + "name": "", + "time": 0, + "wait": 2000, + "sound": "", + "text": "在瘦骨嶙峋的裸露后背上,长有纯白的羽翼。", + "bodyList": [ + { + "name": "tati_430102.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430102.webp", + "px": -300 + }, + "name": "红发的羽狩", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「副队长,确认翅膀的持有了」", + "bodyList": [ + { + "name": "", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430105.webp", + "px": -300 + }, + "name": "羽狩的副队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「保护他」", + "bodyList": [ + { + "name": "tati_430105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「不要······请原谅,我······」", + "bodyList": [ + { + "name": "tati_430105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430102.webp", + "px": -300 + }, + "name": "羽狩的副队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「我们只是要带你去治愈院治疗羽化病,不是什么应该感到害怕的事情」", + "bodyList": [ + { + "name": "tati_430102.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「可是,可是」", + "bodyList": [ + { + "name": "tati_430102.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430102.webp", + "px": -300 + }, + "name": "羽狩的副队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「没关系的」", + "bodyList": [ + { + "name": "tati_430102.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「······哥,哥哥」", + "bodyList": [ + { + "name": "tati_430102.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430105.webp", + "px": -300 + }, + "name": "羽狩的副队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「你是羽化病人的亲属吗?」", + "bodyList": [ + { + "name": "tati_430105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「只是路人而已」", + "bodyList": [ + { + "name": "tati_430105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「顺带一提,我也没有打算找你们的麻烦」", + "bodyList": [ + { + "name": "tati_430105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430101.webp", + "px": -300 + }, + "name": "羽狩的副队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「前几天,有个和你说了同样的话的人,在我们背向他的瞬间对我们发动了袭击」", + "bodyList": [ + { + "name": "tati_430101.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430108.webp", + "px": -300 + }, + "name": "羽狩的副队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「我的一个部下就此永久失去了半截胳膊」", + "bodyList": [ + { + "name": "tati_430108.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「我表示同情」", + "bodyList": [ + { + "name": "tati_430108.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「我马上就会消失的,这样就没问题了吧?」", + "bodyList": [ + { + "name": "tati_430108.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430102.webp", + "px": -300 + }, + "name": "羽狩的副队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「嘛,不要这么慌张」", + "bodyList": [ + { + "name": "tati_430102.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "副队长看着羽化的少年。", + "bodyList": [ + { + "name": "tati_430102.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430105.webp", + "px": -300 + }, + "name": "羽狩的副队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「你与这个人是什么关系?没有被他殴打吗?」", + "bodyList": [ + { + "name": "tati_430105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「没,没有」", + "bodyList": [ + { + "name": "tati_430105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430102.webp", + "px": -300 + }, + "name": "羽狩的副队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「如何对我们保持合作,你就可以在治愈院得到优先的治疗」", + "bodyList": [ + { + "name": "tati_430102.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「······」", + "bodyList": [ + { + "name": "tati_430102.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「那个人,是《不蚀金锁》的组织成员······」", + "bodyList": [ + { + "name": "tati_430102.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "羽化病患少年", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「突然说让我拿出钱来,我刚一拒绝他就打我」", + "bodyList": [ + { + "name": "tati_430102.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430105.webp", + "px": -300 + }, + "name": "羽狩的副队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「原来如此······」", + "bodyList": [ + { + "name": "tati_430105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430107.webp", + "px": -300 + }, + "name": "羽狩的副队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「那位少年说你是《不蚀金锁》的一员,不知此事是否属实?」", + "bodyList": [ + { + "name": "tati_430107.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「当然不是」", + "bodyList": [ + { + "name": "tati_430107.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「我只是从那里接受工作而已,并不是他们的成员」", + "bodyList": [ + { + "name": "tati_430107.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430105.webp", + "px": -300 + }, + "name": "羽狩的副队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「你的意思是说,少年在说谎吗?」", + "bodyList": [ + { + "name": "tati_430105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「啊啊」", + "bodyList": [ + { + "name": "tati_430105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「如果你们和组织有关系的话,只要问问我是不是那里的成员就能明白事实了吧」", + "bodyList": [ + { + "name": "tati_430105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430107.webp", + "px": -300 + }, + "name": "羽狩的副队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「就算我去询问,也无法从他们那里得到事实」", + "bodyList": [ + { + "name": "tati_430107.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430108.webp", + "px": -300 + }, + "name": "羽狩的副队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「《不蚀金锁》的那些人一向都不对我们合作,我对此深感困扰」", + "bodyList": [ + { + "name": "tati_430108.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「真是辛苦啊」", + "bodyList": [ + { + "name": "tati_430108.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430102.webp", + "px": -300 + }, + "name": "羽狩的副队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「说的是啊」", + "bodyList": [ + { + "name": "tati_430102.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430105.webp", + "px": -300 + }, + "name": "羽狩的副队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「其实,砍下我部下胳膊的似乎也是组织的成员呢」", + "bodyList": [ + { + "name": "tati_430105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430102.webp", + "px": -300 + }, + "name": "羽狩的副队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「无需如此警戒,我只是想在看守所向你咨询一些事情而已」", + "bodyList": [ + { + "name": "tati_430102.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430105.webp", + "px": -300 + }, + "name": "羽狩的副队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「如果能够知晓牢狱与组织的事情,我们也可以尽可能地对更多的羽化病人进行保护」", + "bodyList": [ + { + "name": "tati_430105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430102.webp", + "px": -300 + }, + "name": "羽狩的副队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「那和整条街道的和平也是紧密相关的吧?」", + "bodyList": [ + { + "name": "tati_430102.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「我知道,你们有逮捕干扰狩猎羽化病人的权力」", + "bodyList": [ + { + "name": "tati_430102.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「但是,我没有对你们做出任何干扰,为什么要对我如此纠缠不休呢」", + "bodyList": [ + { + "name": "tati_430102.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430105.webp", + "px": -300 + }, + "name": "羽狩的副队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「那些话,我们会在看守所对你详细说明的」", + "bodyList": [ + { + "name": "tati_430105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「······」", + "bodyList": [ + { + "name": "tati_430105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "在这里起争执的话,就会被羽狩加害。", + "bodyList": [ + { + "name": "tati_430105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "就算能从这里脱身,今后只要碰面就会产生纠纷也是摆明的事情。", + "bodyList": [ + { + "name": "tati_430105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "就算逃跑,也没有好的结果。", + "bodyList": [ + { + "name": "tati_430105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "正当我想要打圆场的时候,刚才的气氛一瞬间产生了转变。", + "bodyList": [ + { + "name": "tati_430105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "发生了什么事······", + "bodyList": [ + { + "name": "tati_430105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_050101.webp", + "px": -300 + }, + "name": "??", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「我认为,那位先生是正确的」", + "bodyList": [ + { + "name": "tati_430105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "耳边突然响起了一个能够将这阴暗的气息一扫而空的声音", + "bodyList": [ + { + "name": "tati_430105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "羽狩们一起回头。", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "而在他们视线的焦点处,", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "伫立着一位女性。", + "bodyList": [ + { + "name": "tati_050101.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "在端正的容颜下,代表着强烈意志的双眉十分显眼。", + "bodyList": [ + { + "name": "tati_050101.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "身体的柔软与紧紧包裹在其身上的御兽支付,两者显得十分的不搭配。", + "bodyList": [ + { + "name": "tati_050101.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "我还是第一次看到女性的羽狩。", + "bodyList": [ + { + "name": "tati_050101.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430105.webp", + "px": -300 + }, + "name": "羽狩的副队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「队长,这是获得《不蚀金锁》情报的好机会」", + "bodyList": [ + { + "name": "tati_050101.webp", + "px": 200, + "filter": false + }, + { + "name": "tati_430105.webp", + "px": 1000, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430141.webp", + "px": -300 + }, + "name": "羽狩的队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「兰格副队长,就算是为了获得情报,也不能做出恫吓的发言啊」", + "bodyList": [ + { + "name": "tati_050141.webp", + "px": 200, + "filter": false + }, + { + "name": "tati_430105.webp", + "px": 1000, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430106.webp", + "px": -300 + }, + "name": "兰格副队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「我并没有打算去恫吓他······」", + "bodyList": [ + { + "name": "tati_050141.webp", + "px": 200, + "filter": false + }, + { + "name": "tati_430106.webp", + "px": 1000, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_050221.webp", + "px": -300 + }, + "name": "羽狩的队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「告诉我那个被砍掉胳膊的队员的名字」", + "bodyList": [ + { + "name": "tati_050221.webp", + "px": 200, + "filter": false + }, + { + "name": "tati_430106.webp", + "px": 1000, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_050223.webp", + "px": -300 + }, + "name": "羽狩的队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「我会去探望他的」", + "bodyList": [ + { + "name": "tati_050223.webp", + "px": 200, + "filter": false + }, + { + "name": "tati_430106.webp", + "px": 1000, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430104.webp", + "px": -300 + }, + "name": "兰格副队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「那个是······」", + "bodyList": [ + { + "name": "tati_050223.webp", + "px": 200, + "filter": false + }, + { + "name": "tati_430104.webp", + "px": 1000, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_050101.webp", + "px": -300 + }, + "name": "羽狩的队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「我知道,你一直在为有所收获而努力工作」", + "bodyList": [ + { + "name": "tati_050101.webp", + "px": 200, + "filter": false + }, + { + "name": "tati_430106.webp", + "px": 1000, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_050105.webp", + "px": -300 + }, + "name": "羽狩的队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「但是,正因为我们的工作是为民众提供帮助」", + "bodyList": [ + { + "name": "tati_050105.webp", + "px": 200, + "filter": false + }, + { + "name": "tati_430106.webp", + "px": 1000, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_050103.webp", + "px": -300 + }, + "name": "羽狩的队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「所以就更不能损害人与人之间的信赖」", + "bodyList": [ + { + "name": "tati_050103.webp", + "px": 200, + "filter": false + }, + { + "name": "tati_430106.webp", + "px": 1000, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_430105.webp", + "px": -300 + }, + "name": "兰格副队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「我会铭记在心」", + "bodyList": [ + { + "name": "tati_050103.webp", + "px": 200, + "filter": false + }, + { + "name": "tati_430105.webp", + "px": 1000, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_050101.webp", + "px": -300 + }, + "name": "羽狩的队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「这位先生,我的部下失礼了」", + "bodyList": [ + { + "name": "tati_050101.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「只要不对我再来一次就好」", + "bodyList": [ + { + "name": "tati_050101.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_050126.webp", + "px": -300 + }, + "name": "羽狩的队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「请稍等」", + "bodyList": [ + { + "name": "tati_050126.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「有什么事?」", + "bodyList": [ + { + "name": "tati_050126.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_050101.webp", + "px": -300 + }, + "name": "羽狩的队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「我想确认一件事」", + "bodyList": [ + { + "name": "tati_050101.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_050105.webp", + "px": -300 + }, + "name": "羽狩的队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「你真的不是《不蚀金锁》的成员吗?」", + "bodyList": [ + { + "name": "tati_050105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「真的」", + "bodyList": [ + { + "name": "tati_050105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「如果我说是的话,你有什么打算?」", + "bodyList": [ + { + "name": "tati_050105.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_050143.webp", + "px": -300 + }, + "name": "羽狩的队长", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「我听过传闻,说他们是用依靠暴力而得的钱在生活」", + "bodyList": [ + { + "name": "tati_050143.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「······这样啊」", + "bodyList": [ + { + "name": "tati_050143.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3801.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 30, + "wait": 1000, + "sound": "", + "text": "「如果能有收获就好了啊」", + "bodyList": [ + { + "name": "tati_050143.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "changebg", + "img1": "bg_3801.webp", + "memory1": false, + "img2": "", + "memory2": false, + "time": 30, + "style": "引出" + } + ], + "chapter04": [ + { + "type": "changebg", + "img1": "", + "memory1": false, + "img2": "bg_3512.webp", + "memory2": false, + "time": 30, + "style": "引入" + }, + { + "type": "changebg", + "img1": "bg_3512.webp", + "memory1": false, + "img2": "bg_3522.webp", + "memory2": false, + "time": 30, + "style": "场景切换" + }, + { + "type": "changebg", + "img1": "bg_3522.webp", + "memory1": false, + "img2": "bg_3602.webp", + "memory2": false, + "time": 30, + "style": "场景切换" + }, + { + "type": "changebg", + "img1": "bg_3602.webp", + "memory1": false, + "img2": "bg_3551.webp", + "memory2": false, + "time": 30, + "style": "场景切换" + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120122.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「欢迎光临」", + "bodyList": [ + { + "name": "", + "px": 100, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120101.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「辛苦了」", + "bodyList": [ + { + "name": "tati_120101.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120107.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「抱歉,又拜托给你了个这么麻烦的工作」", + "bodyList": [ + { + "name": "tati_120107.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「没什么,比想象中完成的更容易」", + "bodyList": [ + { + "name": "tati_120107.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120112.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「那就好」", + "bodyList": [ + { + "name": "tati_120112.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120102.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「这是我的一点谢意」", + "bodyList": [ + { + "name": "tati_120102.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「味道有些变化啊」", + "bodyList": [ + { + "name": "tati_120102.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120107.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「啊,被发现了?」", + "bodyList": [ + { + "name": "tati_120107.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120111.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「最近,没能到手什么好的原料呢」", + "bodyList": [ + { + "name": "tati_120111.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「去拜托吉克如何?」", + "bodyList": [ + { + "name": "tati_120111.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120127.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「话是这么说,但是总不能用店里采购的这种小事去麻烦他吧······」", + "bodyList": [ + { + "name": "tati_120127.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「那希望你也不要来麻烦我」", + "bodyList": [ + { + "name": "tati_120127.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120112.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「那 是 两 码 事」", + "bodyList": [ + { + "name": "tati_120112.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120113.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「再说,凯伊姆是靠着工作来生活的吧」", + "bodyList": [ + { + "name": "tati_120113.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120113.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「而且,自己的钱被偷了这么害羞的事,向凯伊姆意外的其他人都说不出口」", + "bodyList": [ + { + "name": "tati_120113.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「反正,也已经传到吉克的耳朵里了」", + "bodyList": [ + { + "name": "tati_120113.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120112.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「这是面子问题啊,面子问题」", + "bodyList": [ + { + "name": "tati_120112.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「嘛,算了」", + "bodyList": [ + { + "name": "tati_120101.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「这样就好了吧?」", + "bodyList": [ + { + "name": "tati_120101.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120121.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「这是钱包呢」", + "bodyList": [ + { + "name": "tati_120121.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120102.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「嗯,东西没少」", + "bodyList": [ + { + "name": "tati_120102.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120111.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「太好啦—这个月的上纳金,我可全部都放在里面了呢」", + "bodyList": [ + { + "name": "tati_120111.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120113.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「如果没有找到的话,说不定就又会被送到娼馆里了呢」", + "bodyList": [ + { + "name": "tati_120113.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「在那边不是来钱更快吗?」", + "bodyList": [ + { + "name": "tati_120113.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120106.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「阿拉,你是在说我还能有魅力吗?」", + "bodyList": [ + { + "name": "tati_120106.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「这是客套话而已」", + "bodyList": [ + { + "name": "tati_120106.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120113.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「欺负人」", + "bodyList": [ + { + "name": "tati_120113.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "comment", + "text": "弹个脑崩" + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120122.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「总而言之,今天帮大忙了」", + "bodyList": [ + { + "name": "tati_120122.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120107.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「谢礼嘛······」", + "bodyList": [ + { + "name": "tati_120107.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「就记在账单上吧」", + "bodyList": [ + { + "name": "tati_120107.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120112.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「了解—盛谢惠顾了哦?」", + "bodyList": [ + { + "name": "tati_120112.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 0, + "wait": 2000, + "sound": "", + "text": "喀啷喀啷", + "bodyList": [ + { + "name": "", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 0, + "wait": 2000, + "sound": "", + "text": "门铃响起", + "bodyList": [ + { + "name": "", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 0, + "wait": 2000, + "sound": "", + "text": "喧哗瞬间安静下来。", + "bodyList": [ + { + "name": "", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 0, + "wait": 2000, + "sound": "", + "text": "进来的人是吉克。", + "bodyList": [ + { + "name": "tati_340101.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 0, + "wait": 2000, + "sound": "", + "text": "是掌控着牢狱的组织之一,《不蚀金锁》的头目。", + "bodyList": [ + { + "name": "tati_340101.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 0, + "wait": 2000, + "sound": "", + "text": "不仅组织的成员,就连店内一般的客人也对他以注目礼表示敬意。", + "bodyList": [ + { + "name": "tati_340101.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_340102.webp", + "px": -300 + }, + "name": "吉克", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「各位继续吧」", + "bodyList": [ + { + "name": "tati_340102.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 0, + "wait": 2000, + "sound": "", + "text": "仿佛停滞的时钟重新转动了一般,店内恢复了热闹的气氛。", + "bodyList": [ + { + "name": "tati_340102.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_340101.webp", + "px": -300 + }, + "name": "吉克", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「抱歉,今天拜托你去做了无聊的工作」", + "bodyList": [ + { + "name": "tati_340101.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「不用介意」", + "bodyList": [ + { + "name": "tati_340101.webp", + "px": 600, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 0, + "wait": 2000, + "sound": "", + "text": "吉克轻轻点了点头,在我右边坐了下来", + "bodyList": [ + { + "name": "tati_z340101.webp", + "px": -200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「逃跑的男人怎么样了?」", + "bodyList": [ + { + "name": "tati_z340101.webp", + "px": -200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_340104.webp", + "px": -300 + }, + "name": "吉克", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「嗯?已经不在这个世上了」", + "bodyList": [ + { + "name": "tati_z340104.webp", + "px": -200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_340107.webp", + "px": -300 + }, + "name": "吉克", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「有什么想要知道的事吗?」", + "bodyList": [ + { + "name": "tati_z340107.webp", + "px": -200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「不,没什么」", + "bodyList": [ + { + "name": "tati_z340107.webp", + "px": -200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_340108.webp", + "px": -300 + }, + "name": "吉克", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「那个无聊的家伙,完全没有趣味呢」", + "bodyList": [ + { + "name": "tati_z340108.webp", + "px": -200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_340114.webp", + "px": -300 + }, + "name": "吉克", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「真希望他也替我负责清扫的部下也考虑考虑」", + "bodyList": [ + { + "name": "tati_z340114.webp", + "px": -200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「真是灾难啊」", + "bodyList": [ + { + "name": "tati_z340114.webp", + "px": -200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_340102.webp", + "px": -300 + }, + "name": "吉克", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「比起那个,我听说了哦。你去追羽化病人了啊」", + "bodyList": [ + { + "name": "tati_z340102.webp", + "px": -200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「消息真灵通」", + "bodyList": [ + { + "name": "tati_z340102.webp", + "px": -200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_340104.webp", + "px": -300 + }, + "name": "吉克", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「梅尔特也注意点」", + "bodyList": [ + { + "name": "tati_z340104.webp", + "px": -200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_340107.webp", + "px": -300 + }, + "name": "吉克", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「你丢钱已经不是一回两回了」", + "bodyList": [ + { + "name": "tati_z340107.webp", + "px": -200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120132.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「好的—我会注意的。」", + "bodyList": [ + { + "name": "tati_z340104.webp", + "px": -200, + "filter": false + }, + { + "name": "tati_120132.webp", + "px": 1200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120101.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「吉克还是平常的点单吧」", + "bodyList": [ + { + "name": "tati_z340102.webp", + "px": -200, + "filter": false + }, + { + "name": "tati_120101.webp", + "px": 1200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120121.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「凯伊姆要再来一杯吗?」", + "bodyList": [ + { + "name": "tati_z340102.webp", + "px": -200, + "filter": false + }, + { + "name": "tati_120121.webp", + "px": 1200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 0, + "wait": 2000, + "sound": "", + "text": "我们用眼神点头示意后,梅尔特开始准备起酒来。", + "bodyList": [ + { + "name": "tati_z340102.webp", + "px": -200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "", + "time": 0, + "wait": 2000, + "sound": "", + "text": "悠然地吐出眼圈后,吉克取出一个纸包放在柜台上。", + "bodyList": [ + { + "name": "tati_z340102.webp", + "px": -200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_340101.webp", + "px": -300 + }, + "name": "吉克", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「这是抓捕逃跑男人的报酬」", + "bodyList": [ + { + "name": "tati_z340101.webp", + "px": -200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「下次有什么事再告诉我」", + "bodyList": [ + { + "name": "tati_z340101.webp", + "px": -200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120102.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「来,久等了」", + "bodyList": [ + { + "name": "tati_z340101.webp", + "px": -200, + "filter": false + }, + { + "name": "tati_120102.webp", + "px": 1200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「话说回来梅尔特,为什么会被那种孩子偷到钱?」", + "bodyList": [ + { + "name": "tati_z340101.webp", + "px": -200, + "filter": false + }, + { + "name": "tati_120102.webp", + "px": 1200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_340102.webp", + "px": -300 + }, + "name": "吉克", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「让我猜猜看」", + "bodyList": [ + { + "name": "tati_z340102.webp", + "px": -200, + "filter": false + }, + { + "name": "tati_120102.webp", + "px": 1200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_340110.webp", + "px": -300 + }, + "name": "吉克", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「是那个吧,看某个特立独行的男人入迷了,所以就有了空隙?」", + "bodyList": [ + { + "name": "tati_z340110.webp", + "px": -200, + "filter": false + }, + { + "name": "tati_120102.webp", + "px": 1200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120113.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「可惜—」", + "bodyList": [ + { + "name": "tati_z340110.webp", + "px": -200, + "filter": false + }, + { + "name": "tati_120113.webp", + "px": 1200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120101.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「事实恰恰相反,是那家伙一直在纠缠我」", + "bodyList": [ + { + "name": "tati_z340101.webp", + "px": -200, + "filter": false + }, + { + "name": "tati_120101.webp", + "px": 1200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「完全把你当成新进的女佣了么」", + "bodyList": [ + { + "name": "tati_z340101.webp", + "px": -200, + "filter": false + }, + { + "name": "tati_120101.webp", + "px": 1200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120121.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「我从前可是很有名的,不会被当成这种下人吧」", + "bodyList": [ + { + "name": "tati_z340101.webp", + "px": -200, + "filter": false + }, + { + "name": "tati_120121.webp", + "px": 1200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120132.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「······而且,我没法对对我这么钟情的人发火啊」", + "bodyList": [ + { + "name": "tati_z340101.webp", + "px": -200, + "filter": false + }, + { + "name": "tati_120132.webp", + "px": 1200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_340106.webp", + "px": -300 + }, + "name": "凯伊姆&吉克", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「你傻啊」", + "bodyList": [ + { + "name": "tati_z340106.webp", + "px": -200, + "filter": false + }, + { + "name": "tati_120132.webp", + "px": 1200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_340112.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「异口同声呢,不亏是兄弟」", + "bodyList": [ + { + "name": "tati_z340106.webp", + "px": -200, + "filter": false + }, + { + "name": "tati_120112.webp", + "px": 1200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「别用这种称呼,怪恶心的」", + "bodyList": [ + { + "name": "tati_z340106.webp", + "px": -200, + "filter": false + }, + { + "name": "tati_120112.webp", + "px": 1200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_340108.webp", + "px": -300 + }, + "name": "吉克", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「说得没错」", + "bodyList": [ + { + "name": "tati_z340108.webp", + "px": -200, + "filter": false + }, + { + "name": "tati_120112.webp", + "px": 1200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_340105.webp", + "px": -300 + }, + "name": "吉克", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「······说起来······」", + "bodyList": [ + { + "name": "tati_z340105.webp", + "px": -200, + "filter": false + }, + { + "name": "tati_120112.webp", + "px": 1200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120107.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「怎么了?」", + "bodyList": [ + { + "name": "tati_z340105.webp", + "px": -200, + "filter": false + }, + { + "name": "tati_120107.webp", + "px": 1200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_340107.webp", + "px": -300 + }, + "name": "吉克", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「有件事我一直很在意,我和凯伊姆,哪个是哥哥啊?」", + "bodyList": [ + { + "name": "tati_z340107.webp", + "px": -200, + "filter": false + }, + { + "name": "tati_120107.webp", + "px": 1200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "", + "px": -300 + }, + "name": "凯伊姆", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「你也说这么无聊的话题」", + "bodyList": [ + { + "name": "tati_z340107.webp", + "px": -200, + "filter": false + }, + { + "name": "tati_120107.webp", + "px": 1200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_340103.webp", + "px": -300 + }, + "name": "吉克", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「不,这是很重要的事情」", + "bodyList": [ + { + "name": "tati_z340103.webp", + "px": -200, + "filter": false + }, + { + "name": "tati_120107.webp", + "px": 1200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_340101.webp", + "px": -300 + }, + "name": "吉克", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「梅尔特,事实是怎么样的?」", + "bodyList": [ + { + "name": "tati_z340101.webp", + "px": -200, + "filter": false + }, + { + "name": "tati_120107.webp", + "px": 1200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120113.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「啊~是怎么样的呢~」", + "bodyList": [ + { + "name": "tati_z340105.webp", + "px": -200, + "filter": false + }, + { + "name": "tati_120113.webp", + "px": 1200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_120112.webp", + "px": -300 + }, + "name": "梅尔特", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「我忘记了」", + "bodyList": [ + { + "name": "tati_z340105.webp", + "px": -200, + "filter": false + }, + { + "name": "tati_120112.webp", + "px": 1200, + "filter": false + } + ] + }, + { + "type": "cgtext", + "bg": "bg_3551.webp", + "memory": false, + "WindowSkin": false, + "head": { + "name": "face_340107.webp", + "px": -300 + }, + "name": "吉克", + "time": 0, + "wait": 2000, + "sound": "", + "text": "「骗人」", + "bodyList": [ + { + "name": "tati_z340107.webp", + "px": -200, + "filter": false + }, + { + "name": "tati_120112.webp", + "px": 1200, + "filter": false + } + ] + } + ], + "chapter05": null, + "强制横屏": [ + { + "type": "if", + "condition": "((!main.replayChecking )&&(!core.isReplaying()))", + "true": [ + { + "type": "if", + "condition": "((screen.orientation || {}).type ||\n screen.mozOrientation ||\n screen.msOrientation!==\"landscape-primary\")", + "true": [ + { + "type": "if", + "condition": "(!core.platform.isPC)", + "true": [ + { + "type": "confirm", + "default": true, + "text": "手机用户横屏体验更佳,是否切换", + "yes": [ + { + "type": "function", + "function": "function(){\ncore.triggerFullscreen(true)\n}" + } + ], + "no": [] + } + ] + } + ] + } + ] + } + ] + }, + "CommonEventTemplate": { + "检测音乐如果没有开启则系统提示开启": [ + { + "type": "if", + "condition": "!core.musicStatus.bgmStatus", + "true": [ + "\t[系统提示]你当前音乐处于关闭状态,本塔开音乐游戏效果更佳" + ], + "false": [] + } + ], + "仿新新魔塔一次性商人": [ + { + "type": "if", + "condition": "switch:A", + "true": [ + "\t[行商,trader]\b[this]这是购买我的道具后我给玩家的提示。", + { + "type": "comment", + "text": "下一条指令可视情况使用或不使用" + }, + { + "type": "hide", + "remove": true, + "time": 250, + "loc": [ + [] + ] + } + ], + "false": [ + { + "type": "confirm", + "text": "我有3把黄钥匙,\n你出50金币就卖给你。", + "yes": [ + { + "type": "if", + "condition": "status:money>=50", + "true": [ + { + "type": "setValue", + "name": "status:money", + "operator": "-=", + "value": "50" + }, + { + "type": "setValue", + "name": "item:yellowKey", + "operator": "+=", + "value": "3" + }, + { + "type": "playSound", + "name": "确定", + "stop": true + }, + { + "type": "setValue", + "name": "switch:A", + "value": "true" + } + ], + "false": [ + { + "type": "playSound", + "name": "操作失败" + }, + "\t[行商,trader]\b[this]你的金币不足!" + ] + } + ], + "no": [] + } + ] + } + ], + "全地图选中一个点": [ + { + "type": "comment", + "text": "全地图选中一个点,需要用鼠标或触屏操作" + }, + { + "type": "setValue", + "name": "temp:X", + "value": "status:x" + }, + { + "type": "setValue", + "name": "temp:Y", + "value": "status:y" + }, + { + "type": "tip", + "text": "再次点击闪烁位置确认" + }, + { + "type": "while", + "condition": "true", + "data": [ + { + "type": "drawSelector", + "image": "winskin.webp", + "code": 1, + "x": "32*temp:X", + "y": "32*temp:Y", + "width": 32, + "height": 32 + }, + { + "type": "wait" + }, + { + "type": "if", + "condition": "(flag:type === 1)", + "true": [ + { + "type": "if", + "condition": "((temp:X===flag:x)&&(temp:Y===flag:y))", + "true": [ + { + "type": "break", + "n": 1 + } + ] + }, + { + "type": "setValue", + "name": "temp:X", + "value": "flag:x" + }, + { + "type": "setValue", + "name": "temp:Y", + "value": "flag:y" + } + ] + } + ] + }, + { + "type": "drawSelector", + "code": 1 + }, + { + "type": "comment", + "text": "流程进行到这里可以对[X,Y]点进行处理,比如" + }, + { + "type": "closeDoor", + "id": "yellowDoor", + "loc": [ + "temp:X", + "temp:Y" + ] + } + ], + "多阶段Boss战斗": [ + { + "type": "comment", + "text": "多阶段boss,请直接作为战后事件使用" + }, + { + "type": "setValue", + "name": "switch:A", + "operator": "+=", + "value": "1" + }, + { + "type": "switch", + "condition": "switch:A", + "caseList": [ + { + "case": "1", + "action": [ + { + "type": "setBlock", + "number": "redSlime", + "loc": [ + [] + ] + }, + "\t[2阶段boss,redSlime]\b[this]你以为你已经打败我了吗?没听说过史莱姆有九条命吗?" + ] + }, + { + "case": "2", + "action": [ + { + "type": "setBlock", + "number": "blackSlime", + "loc": [ + [] + ] + }, + "\t[3阶段boss,blackSlime]\b[this]不能消灭我的,只会让我更强大!" + ] + }, + { + "case": "3", + "action": [ + { + "type": "setBlock", + "number": "slimelord", + "loc": [ + [] + ] + }, + "\t[4阶段boss,slimelord]\b[this]我还能打!" + ] + }, + { + "case": "4", + "action": [ + "\t[4阶段boss,slimelord]我一定会回来的!" + ] + } + ] + } + ], + "光标修改": [ + { + "type": "changeMouse", + "icon": "sword0", + "div": "gameGroup", + "translate": [ + 0, + 0 + ], + "scale": [ + 1, + 1 + ], + "angle": 0, + "px": 0, + "py": 0 + }, + { + "type": "removeMouse", + "div": "gameGroup" + } + ], + "添加弹幕": [ + { + "type": "addPop", + "value": "这段话将在游戏中以弹幕显示", + "px": 32, + "py": 32, + "color": [ + 255, + 0, + 0, + 1 + ], + "boldColor": [ + 0, + 0, + 0, + 1 + ], + "left": false, + "jump": false, + "time": 60, + "show": 30, + "font": "16px Verdana", + "speed": 1 + } + ] + } +} \ No newline at end of file diff --git a/project/floors/street01.js b/project/floors/street01.js index 61dd725..dceac7f 100644 --- a/project/floors/street01.js +++ b/project/floors/street01.js @@ -29,7 +29,7 @@ main.floors.street01= "6,11": [ { "type": "insert", - "name": "chapter01" + "name": "chapter04" } ], "4,11": [ @@ -118,7 +118,7 @@ main.floors.street01= [110118,110118,200096,110116,110020, 0,200014, 0, 0, 0, 0, 0,110125], [ 92, 0, 0,110124, 0,201, 0, 0,110125,110122,110122,110122,110122], [ 0, 0, 0,110118,110118,202,110118,110118,110122, 0, 0, 0, 94], - [130170, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [130170, 0, 0, 0, 71, 35, 0, 0, 0, 0, 0, 0, 0], [130178, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,130168,130169], [130225,130169,130169,130169,130169,130170,110122,110122,130168,130169,130169,130224,130177] ], diff --git a/project/floors/yiqu8.js b/project/floors/yiqu8.js index 3174759..18bb1e8 100644 --- a/project/floors/yiqu8.js +++ b/project/floors/yiqu8.js @@ -1,29 +1,29 @@ main.floors.yiqu8= { -"floorId": "yiqu8", -"title": "主塔 8 层", -"name": "8", -"width": 13, -"height": 13, -"canFlyTo": true, -"canFlyFrom": true, -"canUseQuickShop": true, -"images": [], -"ratio": 1, -"defaultGround": "grass2", -"firstArrive": [], -"eachArrive": [], -"parallelDo": "", -"events": {}, -"changeFloor": {}, -"beforeBattle": {}, -"afterBattle": {}, -"afterGetItem": {}, -"afterOpenDoor": {}, -"autoEvent": {}, -"cannotMove": {}, -"cannotMoveIn": {}, -"map": [ + "floorId": "yiqu8", + "title": "主塔 8 层", + "name": "8", + "width": 13, + "height": 13, + "canFlyTo": true, + "canFlyFrom": true, + "canUseQuickShop": true, + "images": [], + "ratio": 1, + "defaultGround": "grass2", + "firstArrive": [], + "eachArrive": [], + "parallelDo": "", + "events": {}, + "changeFloor": {}, + "beforeBattle": {}, + "afterBattle": {}, + "afterGetItem": {}, + "afterOpenDoor": {}, + "autoEvent": {}, + "cannotMove": {}, + "cannotMoveIn": {}, + "map": [ [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], @@ -38,4 +38,16 @@ main.floors.yiqu8= [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ], + "bgmap": [ + +], + "fgmap": [ + +], + "bg2map": [ + +], + "fg2map": [ + +] } \ No newline at end of file diff --git a/project/functions.js b/project/functions.js index 0a2927d..ed051d3 100644 --- a/project/functions.js +++ b/project/functions.js @@ -1152,26 +1152,27 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = }, "getStatusLabel": function (name) { - // 返回某个状态英文名的对应中文标签,如atk -> 攻击,def -> 防御等。 - // 请注意此项仅影响 libs/ 下的内容(如绘制怪物手册、数据统计等) - // 自行定义的(比如获得道具效果)中用到的“攻击+3”等需要自己去对应地方修改 + // 返回某个状态英文名的对应中文标签,如atk -> 攻击,def -> 防御等。 + // 请注意此项仅影响 libs/ 下的内容(如绘制怪物手册、数据统计等) + // 自行定义的(比如获得道具效果)中用到的“攻击+3”等需要自己去对应地方修改 - return { - name: "名称", - lv: "等级", - hpmax: "生命上限", - hp: "生命", - manamax: "魔力上限", - mana: "魔力", - atk: "攻击", - def: "防御", - mdef: "护盾", - money: "金币", - exp: "经验", - point: "加点", - steps: "步数", - }[name] || name; - }, + return { + name: "名称", + lv: "等级", + hpmax: "生命上限", + hp: "生命", + manamax: "魔力上限", + mana: "魔力", + atk: "攻击", + def: "防御", + mdef: "法强", + speed: "速度", + money: "金币", + exp: "经验", + point: "加点", + steps: "步数", + } [name] || name; +}, "triggerDebuff": function (action, type) { // 毒衰咒效果的获得与解除 // action:获得还是解除;'get'表示获得,'remove'表示解除 @@ -1230,8 +1231,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = } }, "updateStatusBar": function () { - //更新属性映射 - core.updateStatus() // 更新状态栏 core.ui.statusBar.update(); // 更新阻激夹域的伤害值 diff --git a/project/images/LOGO.webp b/project/images/LOGO.webp new file mode 100644 index 0000000..890e5fd Binary files /dev/null and b/project/images/LOGO.webp differ diff --git a/project/images/bg_0000.png b/project/images/bg_0000.png new file mode 100644 index 0000000..dec8909 Binary files /dev/null and b/project/images/bg_0000.png differ diff --git a/project/images/bg_3021.webp b/project/images/bg_3021.webp new file mode 100644 index 0000000..c87f60b Binary files /dev/null and b/project/images/bg_3021.webp differ diff --git a/project/images/bg_3026.webp b/project/images/bg_3026.webp new file mode 100644 index 0000000..8bd0aa3 Binary files /dev/null and b/project/images/bg_3026.webp differ diff --git a/project/images/bg_3028.webp b/project/images/bg_3028.webp new file mode 100644 index 0000000..28fb42c Binary files /dev/null and b/project/images/bg_3028.webp differ diff --git a/project/images/bg_3512.webp b/project/images/bg_3512.webp new file mode 100644 index 0000000..9feaa2f Binary files /dev/null and b/project/images/bg_3512.webp differ diff --git a/project/images/bg_3522.webp b/project/images/bg_3522.webp new file mode 100644 index 0000000..da43179 Binary files /dev/null and b/project/images/bg_3522.webp differ diff --git a/project/images/bg_3561.webp b/project/images/bg_3561.webp new file mode 100644 index 0000000..96a778b Binary files /dev/null and b/project/images/bg_3561.webp differ diff --git a/project/images/bg_3602.webp b/project/images/bg_3602.webp new file mode 100644 index 0000000..19c22f8 Binary files /dev/null and b/project/images/bg_3602.webp differ diff --git a/project/images/bg_3801.webp b/project/images/bg_3801.webp new file mode 100644 index 0000000..57849f5 Binary files /dev/null and b/project/images/bg_3801.webp differ diff --git a/project/images/face_030101.webp b/project/images/face_030101.webp new file mode 100644 index 0000000..46c41ed Binary files /dev/null and b/project/images/face_030101.webp differ diff --git a/project/images/face_030102.webp b/project/images/face_030102.webp new file mode 100644 index 0000000..c2b5ac7 Binary files /dev/null and b/project/images/face_030102.webp differ diff --git a/project/images/face_030103.webp b/project/images/face_030103.webp new file mode 100644 index 0000000..d314fca Binary files /dev/null and b/project/images/face_030103.webp differ diff --git a/project/images/face_030104.webp b/project/images/face_030104.webp new file mode 100644 index 0000000..6175ca9 Binary files /dev/null and b/project/images/face_030104.webp differ diff --git a/project/images/face_030105.webp b/project/images/face_030105.webp new file mode 100644 index 0000000..9935bfa Binary files /dev/null and b/project/images/face_030105.webp differ diff --git a/project/images/face_030107.webp b/project/images/face_030107.webp new file mode 100644 index 0000000..1c87a84 Binary files /dev/null and b/project/images/face_030107.webp differ diff --git a/project/images/face_030121.webp b/project/images/face_030121.webp new file mode 100644 index 0000000..a04c087 Binary files /dev/null and b/project/images/face_030121.webp differ diff --git a/project/images/face_030122.webp b/project/images/face_030122.webp new file mode 100644 index 0000000..19801ae Binary files /dev/null and b/project/images/face_030122.webp differ diff --git a/project/images/face_030123.webp b/project/images/face_030123.webp new file mode 100644 index 0000000..0fd9160 Binary files /dev/null and b/project/images/face_030123.webp differ diff --git a/project/images/face_030124.webp b/project/images/face_030124.webp new file mode 100644 index 0000000..ac6e273 Binary files /dev/null and b/project/images/face_030124.webp differ diff --git a/project/images/face_030125.webp b/project/images/face_030125.webp new file mode 100644 index 0000000..48eb565 Binary files /dev/null and b/project/images/face_030125.webp differ diff --git a/project/images/face_030127.webp b/project/images/face_030127.webp new file mode 100644 index 0000000..5bd993b Binary files /dev/null and b/project/images/face_030127.webp differ diff --git a/project/images/face_030129.webp b/project/images/face_030129.webp new file mode 100644 index 0000000..b71b74f Binary files /dev/null and b/project/images/face_030129.webp differ diff --git a/project/images/face_030131.webp b/project/images/face_030131.webp new file mode 100644 index 0000000..6faf82e Binary files /dev/null and b/project/images/face_030131.webp differ diff --git a/project/images/face_030132.webp b/project/images/face_030132.webp new file mode 100644 index 0000000..6d02061 Binary files /dev/null and b/project/images/face_030132.webp differ diff --git a/project/images/face_030141.webp b/project/images/face_030141.webp new file mode 100644 index 0000000..db4120e Binary files /dev/null and b/project/images/face_030141.webp differ diff --git a/project/images/face_030142.webp b/project/images/face_030142.webp new file mode 100644 index 0000000..bf889f3 Binary files /dev/null and b/project/images/face_030142.webp differ diff --git a/project/images/face_030143.webp b/project/images/face_030143.webp new file mode 100644 index 0000000..7d23764 Binary files /dev/null and b/project/images/face_030143.webp differ diff --git a/project/images/face_030144.webp b/project/images/face_030144.webp new file mode 100644 index 0000000..b53077e Binary files /dev/null and b/project/images/face_030144.webp differ diff --git a/project/images/face_030145.webp b/project/images/face_030145.webp new file mode 100644 index 0000000..3c55682 Binary files /dev/null and b/project/images/face_030145.webp differ diff --git a/project/images/face_050101.webp b/project/images/face_050101.webp new file mode 100644 index 0000000..10d4b8c Binary files /dev/null and b/project/images/face_050101.webp differ diff --git a/project/images/face_050102.webp b/project/images/face_050102.webp new file mode 100644 index 0000000..5c97cde Binary files /dev/null and b/project/images/face_050102.webp differ diff --git a/project/images/face_050103.webp b/project/images/face_050103.webp new file mode 100644 index 0000000..0d3d811 Binary files /dev/null and b/project/images/face_050103.webp differ diff --git a/project/images/face_050104.webp b/project/images/face_050104.webp new file mode 100644 index 0000000..0767d99 Binary files /dev/null and b/project/images/face_050104.webp differ diff --git a/project/images/face_050105.webp b/project/images/face_050105.webp new file mode 100644 index 0000000..21a2fe5 Binary files /dev/null and b/project/images/face_050105.webp differ diff --git a/project/images/face_050106.webp b/project/images/face_050106.webp new file mode 100644 index 0000000..8a3bc4e Binary files /dev/null and b/project/images/face_050106.webp differ diff --git a/project/images/face_050107.webp b/project/images/face_050107.webp new file mode 100644 index 0000000..f838238 Binary files /dev/null and b/project/images/face_050107.webp differ diff --git a/project/images/face_050108.webp b/project/images/face_050108.webp new file mode 100644 index 0000000..d330016 Binary files /dev/null and b/project/images/face_050108.webp differ diff --git a/project/images/face_050111.webp b/project/images/face_050111.webp new file mode 100644 index 0000000..e192d48 Binary files /dev/null and b/project/images/face_050111.webp differ diff --git a/project/images/face_050112.webp b/project/images/face_050112.webp new file mode 100644 index 0000000..ec560a3 Binary files /dev/null and b/project/images/face_050112.webp differ diff --git a/project/images/face_050113.webp b/project/images/face_050113.webp new file mode 100644 index 0000000..344da43 Binary files /dev/null and b/project/images/face_050113.webp differ diff --git a/project/images/face_050116.webp b/project/images/face_050116.webp new file mode 100644 index 0000000..1cea83d Binary files /dev/null and b/project/images/face_050116.webp differ diff --git a/project/images/face_050121.webp b/project/images/face_050121.webp new file mode 100644 index 0000000..1ae1b7b Binary files /dev/null and b/project/images/face_050121.webp differ diff --git a/project/images/face_050122.webp b/project/images/face_050122.webp new file mode 100644 index 0000000..b7b6467 Binary files /dev/null and b/project/images/face_050122.webp differ diff --git a/project/images/face_050123.webp b/project/images/face_050123.webp new file mode 100644 index 0000000..1e7c47a Binary files /dev/null and b/project/images/face_050123.webp differ diff --git a/project/images/face_050124.webp b/project/images/face_050124.webp new file mode 100644 index 0000000..fc5e21f Binary files /dev/null and b/project/images/face_050124.webp differ diff --git a/project/images/face_050125.webp b/project/images/face_050125.webp new file mode 100644 index 0000000..a5651ae Binary files /dev/null and b/project/images/face_050125.webp differ diff --git a/project/images/face_050126.webp b/project/images/face_050126.webp new file mode 100644 index 0000000..1f1d570 Binary files /dev/null and b/project/images/face_050126.webp differ diff --git a/project/images/face_050127.webp b/project/images/face_050127.webp new file mode 100644 index 0000000..ea1297d Binary files /dev/null and b/project/images/face_050127.webp differ diff --git a/project/images/face_050128.webp b/project/images/face_050128.webp new file mode 100644 index 0000000..8a191f7 Binary files /dev/null and b/project/images/face_050128.webp differ diff --git a/project/images/face_050129.webp b/project/images/face_050129.webp new file mode 100644 index 0000000..571b5ac Binary files /dev/null and b/project/images/face_050129.webp differ diff --git a/project/images/face_050130.webp b/project/images/face_050130.webp new file mode 100644 index 0000000..056379e Binary files /dev/null and b/project/images/face_050130.webp differ diff --git a/project/images/face_050131.webp b/project/images/face_050131.webp new file mode 100644 index 0000000..5a51170 Binary files /dev/null and b/project/images/face_050131.webp differ diff --git a/project/images/face_050132.webp b/project/images/face_050132.webp new file mode 100644 index 0000000..25d18fe Binary files /dev/null and b/project/images/face_050132.webp differ diff --git a/project/images/face_050134.webp b/project/images/face_050134.webp new file mode 100644 index 0000000..837fdd5 Binary files /dev/null and b/project/images/face_050134.webp differ diff --git a/project/images/face_050135.webp b/project/images/face_050135.webp new file mode 100644 index 0000000..a96d4db Binary files /dev/null and b/project/images/face_050135.webp differ diff --git a/project/images/face_050136.webp b/project/images/face_050136.webp new file mode 100644 index 0000000..0812a79 Binary files /dev/null and b/project/images/face_050136.webp differ diff --git a/project/images/face_050137.webp b/project/images/face_050137.webp new file mode 100644 index 0000000..38e6649 Binary files /dev/null and b/project/images/face_050137.webp differ diff --git a/project/images/face_050141.webp b/project/images/face_050141.webp new file mode 100644 index 0000000..04ac926 Binary files /dev/null and b/project/images/face_050141.webp differ diff --git a/project/images/face_050142.webp b/project/images/face_050142.webp new file mode 100644 index 0000000..adf6280 Binary files /dev/null and b/project/images/face_050142.webp differ diff --git a/project/images/face_050143.webp b/project/images/face_050143.webp new file mode 100644 index 0000000..ee524ca Binary files /dev/null and b/project/images/face_050143.webp differ diff --git a/project/images/face_050144.webp b/project/images/face_050144.webp new file mode 100644 index 0000000..8df7199 Binary files /dev/null and b/project/images/face_050144.webp differ diff --git a/project/images/face_050145.webp b/project/images/face_050145.webp new file mode 100644 index 0000000..63b24ee Binary files /dev/null and b/project/images/face_050145.webp differ diff --git a/project/images/face_050146.webp b/project/images/face_050146.webp new file mode 100644 index 0000000..bf2f02b Binary files /dev/null and b/project/images/face_050146.webp differ diff --git a/project/images/face_050147.webp b/project/images/face_050147.webp new file mode 100644 index 0000000..fa89346 Binary files /dev/null and b/project/images/face_050147.webp differ diff --git a/project/images/face_050148.webp b/project/images/face_050148.webp new file mode 100644 index 0000000..8b615eb Binary files /dev/null and b/project/images/face_050148.webp differ diff --git a/project/images/face_050150.webp b/project/images/face_050150.webp new file mode 100644 index 0000000..46e228a Binary files /dev/null and b/project/images/face_050150.webp differ diff --git a/project/images/face_050151.webp b/project/images/face_050151.webp new file mode 100644 index 0000000..5bab333 Binary files /dev/null and b/project/images/face_050151.webp differ diff --git a/project/images/face_050152.webp b/project/images/face_050152.webp new file mode 100644 index 0000000..3d2954f Binary files /dev/null and b/project/images/face_050152.webp differ diff --git a/project/images/face_050201.webp b/project/images/face_050201.webp new file mode 100644 index 0000000..12dd2ff Binary files /dev/null and b/project/images/face_050201.webp differ diff --git a/project/images/face_050202.webp b/project/images/face_050202.webp new file mode 100644 index 0000000..0114c03 Binary files /dev/null and b/project/images/face_050202.webp differ diff --git a/project/images/face_050203.webp b/project/images/face_050203.webp new file mode 100644 index 0000000..fbaff96 Binary files /dev/null and b/project/images/face_050203.webp differ diff --git a/project/images/face_050204.webp b/project/images/face_050204.webp new file mode 100644 index 0000000..2c256b4 Binary files /dev/null and b/project/images/face_050204.webp differ diff --git a/project/images/face_050205.webp b/project/images/face_050205.webp new file mode 100644 index 0000000..7df8178 Binary files /dev/null and b/project/images/face_050205.webp differ diff --git a/project/images/face_050206.webp b/project/images/face_050206.webp new file mode 100644 index 0000000..96ae26d Binary files /dev/null and b/project/images/face_050206.webp differ diff --git a/project/images/face_050210.webp b/project/images/face_050210.webp new file mode 100644 index 0000000..abed1e3 Binary files /dev/null and b/project/images/face_050210.webp differ diff --git a/project/images/face_050212.webp b/project/images/face_050212.webp new file mode 100644 index 0000000..0f59bfe Binary files /dev/null and b/project/images/face_050212.webp differ diff --git a/project/images/face_050213.webp b/project/images/face_050213.webp new file mode 100644 index 0000000..564bd98 Binary files /dev/null and b/project/images/face_050213.webp differ diff --git a/project/images/face_050214.webp b/project/images/face_050214.webp new file mode 100644 index 0000000..169a477 Binary files /dev/null and b/project/images/face_050214.webp differ diff --git a/project/images/face_050215.webp b/project/images/face_050215.webp new file mode 100644 index 0000000..b1df32f Binary files /dev/null and b/project/images/face_050215.webp differ diff --git a/project/images/face_050216.webp b/project/images/face_050216.webp new file mode 100644 index 0000000..15ffca8 Binary files /dev/null and b/project/images/face_050216.webp differ diff --git a/project/images/face_050221.webp b/project/images/face_050221.webp new file mode 100644 index 0000000..1ae1b7b Binary files /dev/null and b/project/images/face_050221.webp differ diff --git a/project/images/face_050222.webp b/project/images/face_050222.webp new file mode 100644 index 0000000..b7b6467 Binary files /dev/null and b/project/images/face_050222.webp differ diff --git a/project/images/face_050223.webp b/project/images/face_050223.webp new file mode 100644 index 0000000..1e7c47a Binary files /dev/null and b/project/images/face_050223.webp differ diff --git a/project/images/face_050224.webp b/project/images/face_050224.webp new file mode 100644 index 0000000..fc5e21f Binary files /dev/null and b/project/images/face_050224.webp differ diff --git a/project/images/face_050225.webp b/project/images/face_050225.webp new file mode 100644 index 0000000..a5651ae Binary files /dev/null and b/project/images/face_050225.webp differ diff --git a/project/images/face_050226.webp b/project/images/face_050226.webp new file mode 100644 index 0000000..1f1d570 Binary files /dev/null and b/project/images/face_050226.webp differ diff --git a/project/images/face_050229.webp b/project/images/face_050229.webp new file mode 100644 index 0000000..571b5ac Binary files /dev/null and b/project/images/face_050229.webp differ diff --git a/project/images/face_050230.webp b/project/images/face_050230.webp new file mode 100644 index 0000000..056379e Binary files /dev/null and b/project/images/face_050230.webp differ diff --git a/project/images/face_050232.webp b/project/images/face_050232.webp new file mode 100644 index 0000000..25d18fe Binary files /dev/null and b/project/images/face_050232.webp differ diff --git a/project/images/face_050234.webp b/project/images/face_050234.webp new file mode 100644 index 0000000..837fdd5 Binary files /dev/null and b/project/images/face_050234.webp differ diff --git a/project/images/face_050235.webp b/project/images/face_050235.webp new file mode 100644 index 0000000..a96d4db Binary files /dev/null and b/project/images/face_050235.webp differ diff --git a/project/images/face_050237.webp b/project/images/face_050237.webp new file mode 100644 index 0000000..38e6649 Binary files /dev/null and b/project/images/face_050237.webp differ diff --git a/project/images/face_050241.webp b/project/images/face_050241.webp new file mode 100644 index 0000000..04ac926 Binary files /dev/null and b/project/images/face_050241.webp differ diff --git a/project/images/face_050242.webp b/project/images/face_050242.webp new file mode 100644 index 0000000..adf6280 Binary files /dev/null and b/project/images/face_050242.webp differ diff --git a/project/images/face_050243.webp b/project/images/face_050243.webp new file mode 100644 index 0000000..ee524ca Binary files /dev/null and b/project/images/face_050243.webp differ diff --git a/project/images/face_050244.webp b/project/images/face_050244.webp new file mode 100644 index 0000000..8df7199 Binary files /dev/null and b/project/images/face_050244.webp differ diff --git a/project/images/face_050245.webp b/project/images/face_050245.webp new file mode 100644 index 0000000..63b24ee Binary files /dev/null and b/project/images/face_050245.webp differ diff --git a/project/images/face_050246.webp b/project/images/face_050246.webp new file mode 100644 index 0000000..bf2f02b Binary files /dev/null and b/project/images/face_050246.webp differ diff --git a/project/images/face_050249.webp b/project/images/face_050249.webp new file mode 100644 index 0000000..2f77e72 Binary files /dev/null and b/project/images/face_050249.webp differ diff --git a/project/images/face_050250.webp b/project/images/face_050250.webp new file mode 100644 index 0000000..46e228a Binary files /dev/null and b/project/images/face_050250.webp differ diff --git a/project/images/face_050252.webp b/project/images/face_050252.webp new file mode 100644 index 0000000..3d2954f Binary files /dev/null and b/project/images/face_050252.webp differ diff --git a/project/images/face_050301.webp b/project/images/face_050301.webp new file mode 100644 index 0000000..8ed9e9c Binary files /dev/null and b/project/images/face_050301.webp differ diff --git a/project/images/face_050302.webp b/project/images/face_050302.webp new file mode 100644 index 0000000..dc5c9db Binary files /dev/null and b/project/images/face_050302.webp differ diff --git a/project/images/face_050303.webp b/project/images/face_050303.webp new file mode 100644 index 0000000..993e16a Binary files /dev/null and b/project/images/face_050303.webp differ diff --git a/project/images/face_050304.webp b/project/images/face_050304.webp new file mode 100644 index 0000000..8be3448 Binary files /dev/null and b/project/images/face_050304.webp differ diff --git a/project/images/face_050305.webp b/project/images/face_050305.webp new file mode 100644 index 0000000..caeaa80 Binary files /dev/null and b/project/images/face_050305.webp differ diff --git a/project/images/face_050306.webp b/project/images/face_050306.webp new file mode 100644 index 0000000..f84a944 Binary files /dev/null and b/project/images/face_050306.webp differ diff --git a/project/images/face_050307.webp b/project/images/face_050307.webp new file mode 100644 index 0000000..908a9bf Binary files /dev/null and b/project/images/face_050307.webp differ diff --git a/project/images/face_050308.webp b/project/images/face_050308.webp new file mode 100644 index 0000000..d716999 Binary files /dev/null and b/project/images/face_050308.webp differ diff --git a/project/images/face_050309.webp b/project/images/face_050309.webp new file mode 100644 index 0000000..3c7799f Binary files /dev/null and b/project/images/face_050309.webp differ diff --git a/project/images/face_050310.webp b/project/images/face_050310.webp new file mode 100644 index 0000000..47ff979 Binary files /dev/null and b/project/images/face_050310.webp differ diff --git a/project/images/face_050311.webp b/project/images/face_050311.webp new file mode 100644 index 0000000..5302cd3 Binary files /dev/null and b/project/images/face_050311.webp differ diff --git a/project/images/face_050313.webp b/project/images/face_050313.webp new file mode 100644 index 0000000..797d3d1 Binary files /dev/null and b/project/images/face_050313.webp differ diff --git a/project/images/face_050314.webp b/project/images/face_050314.webp new file mode 100644 index 0000000..5e80e7d Binary files /dev/null and b/project/images/face_050314.webp differ diff --git a/project/images/face_050315.webp b/project/images/face_050315.webp new file mode 100644 index 0000000..c663bef Binary files /dev/null and b/project/images/face_050315.webp differ diff --git a/project/images/face_050316.webp b/project/images/face_050316.webp new file mode 100644 index 0000000..1d359df Binary files /dev/null and b/project/images/face_050316.webp differ diff --git a/project/images/face_050317.webp b/project/images/face_050317.webp new file mode 100644 index 0000000..4dce220 Binary files /dev/null and b/project/images/face_050317.webp differ diff --git a/project/images/face_050321.webp b/project/images/face_050321.webp new file mode 100644 index 0000000..533f0ea Binary files /dev/null and b/project/images/face_050321.webp differ diff --git a/project/images/face_050322.webp b/project/images/face_050322.webp new file mode 100644 index 0000000..5a03bc7 Binary files /dev/null and b/project/images/face_050322.webp differ diff --git a/project/images/face_050323.webp b/project/images/face_050323.webp new file mode 100644 index 0000000..dd02280 Binary files /dev/null and b/project/images/face_050323.webp differ diff --git a/project/images/face_050324.webp b/project/images/face_050324.webp new file mode 100644 index 0000000..4faa9a0 Binary files /dev/null and b/project/images/face_050324.webp differ diff --git a/project/images/face_050325.webp b/project/images/face_050325.webp new file mode 100644 index 0000000..a0378a5 Binary files /dev/null and b/project/images/face_050325.webp differ diff --git a/project/images/face_050326.webp b/project/images/face_050326.webp new file mode 100644 index 0000000..8d23302 Binary files /dev/null and b/project/images/face_050326.webp differ diff --git a/project/images/face_050327.webp b/project/images/face_050327.webp new file mode 100644 index 0000000..5350f93 Binary files /dev/null and b/project/images/face_050327.webp differ diff --git a/project/images/face_050328.webp b/project/images/face_050328.webp new file mode 100644 index 0000000..75b8723 Binary files /dev/null and b/project/images/face_050328.webp differ diff --git a/project/images/face_050329.webp b/project/images/face_050329.webp new file mode 100644 index 0000000..35f592d Binary files /dev/null and b/project/images/face_050329.webp differ diff --git a/project/images/face_050330.webp b/project/images/face_050330.webp new file mode 100644 index 0000000..9256890 Binary files /dev/null and b/project/images/face_050330.webp differ diff --git a/project/images/face_050331.webp b/project/images/face_050331.webp new file mode 100644 index 0000000..9d6e3fe Binary files /dev/null and b/project/images/face_050331.webp differ diff --git a/project/images/face_050332.webp b/project/images/face_050332.webp new file mode 100644 index 0000000..1ef6645 Binary files /dev/null and b/project/images/face_050332.webp differ diff --git a/project/images/face_050333.webp b/project/images/face_050333.webp new file mode 100644 index 0000000..f4c7896 Binary files /dev/null and b/project/images/face_050333.webp differ diff --git a/project/images/face_050334.webp b/project/images/face_050334.webp new file mode 100644 index 0000000..7bbeeda Binary files /dev/null and b/project/images/face_050334.webp differ diff --git a/project/images/face_050335.webp b/project/images/face_050335.webp new file mode 100644 index 0000000..0c4208e Binary files /dev/null and b/project/images/face_050335.webp differ diff --git a/project/images/face_050336.webp b/project/images/face_050336.webp new file mode 100644 index 0000000..1d36bf1 Binary files /dev/null and b/project/images/face_050336.webp differ diff --git a/project/images/face_050337.webp b/project/images/face_050337.webp new file mode 100644 index 0000000..8ecf407 Binary files /dev/null and b/project/images/face_050337.webp differ diff --git a/project/images/face_050338.webp b/project/images/face_050338.webp new file mode 100644 index 0000000..afed9a4 Binary files /dev/null and b/project/images/face_050338.webp differ diff --git a/project/images/face_050341.webp b/project/images/face_050341.webp new file mode 100644 index 0000000..825cd77 Binary files /dev/null and b/project/images/face_050341.webp differ diff --git a/project/images/face_050342.webp b/project/images/face_050342.webp new file mode 100644 index 0000000..f9f8384 Binary files /dev/null and b/project/images/face_050342.webp differ diff --git a/project/images/face_050343.webp b/project/images/face_050343.webp new file mode 100644 index 0000000..5854061 Binary files /dev/null and b/project/images/face_050343.webp differ diff --git a/project/images/face_050344.webp b/project/images/face_050344.webp new file mode 100644 index 0000000..2e67cd9 Binary files /dev/null and b/project/images/face_050344.webp differ diff --git a/project/images/face_050345.webp b/project/images/face_050345.webp new file mode 100644 index 0000000..9a58f26 Binary files /dev/null and b/project/images/face_050345.webp differ diff --git a/project/images/face_050346.webp b/project/images/face_050346.webp new file mode 100644 index 0000000..27a2a09 Binary files /dev/null and b/project/images/face_050346.webp differ diff --git a/project/images/face_050347.webp b/project/images/face_050347.webp new file mode 100644 index 0000000..d937b33 Binary files /dev/null and b/project/images/face_050347.webp differ diff --git a/project/images/face_050348.webp b/project/images/face_050348.webp new file mode 100644 index 0000000..f8bb7f7 Binary files /dev/null and b/project/images/face_050348.webp differ diff --git a/project/images/face_050349.webp b/project/images/face_050349.webp new file mode 100644 index 0000000..59992cd Binary files /dev/null and b/project/images/face_050349.webp differ diff --git a/project/images/face_050350.webp b/project/images/face_050350.webp new file mode 100644 index 0000000..27d1e0e Binary files /dev/null and b/project/images/face_050350.webp differ diff --git a/project/images/face_050351.webp b/project/images/face_050351.webp new file mode 100644 index 0000000..b9da1fc Binary files /dev/null and b/project/images/face_050351.webp differ diff --git a/project/images/face_050352.webp b/project/images/face_050352.webp new file mode 100644 index 0000000..0eacd03 Binary files /dev/null and b/project/images/face_050352.webp differ diff --git a/project/images/face_050353.webp b/project/images/face_050353.webp new file mode 100644 index 0000000..75cc486 Binary files /dev/null and b/project/images/face_050353.webp differ diff --git a/project/images/face_050441.webp b/project/images/face_050441.webp new file mode 100644 index 0000000..04ac926 Binary files /dev/null and b/project/images/face_050441.webp differ diff --git a/project/images/face_050442.webp b/project/images/face_050442.webp new file mode 100644 index 0000000..adf6280 Binary files /dev/null and b/project/images/face_050442.webp differ diff --git a/project/images/face_050443.webp b/project/images/face_050443.webp new file mode 100644 index 0000000..ee524ca Binary files /dev/null and b/project/images/face_050443.webp differ diff --git a/project/images/face_050446.webp b/project/images/face_050446.webp new file mode 100644 index 0000000..bf2f02b Binary files /dev/null and b/project/images/face_050446.webp differ diff --git a/project/images/face_050447.webp b/project/images/face_050447.webp new file mode 100644 index 0000000..fa89346 Binary files /dev/null and b/project/images/face_050447.webp differ diff --git a/project/images/face_050451.webp b/project/images/face_050451.webp new file mode 100644 index 0000000..5bab333 Binary files /dev/null and b/project/images/face_050451.webp differ diff --git a/project/images/face_050452.webp b/project/images/face_050452.webp new file mode 100644 index 0000000..3d2954f Binary files /dev/null and b/project/images/face_050452.webp differ diff --git a/project/images/face_120101.webp b/project/images/face_120101.webp new file mode 100644 index 0000000..bc440ef Binary files /dev/null and b/project/images/face_120101.webp differ diff --git a/project/images/face_120102.webp b/project/images/face_120102.webp new file mode 100644 index 0000000..d88d401 Binary files /dev/null and b/project/images/face_120102.webp differ diff --git a/project/images/face_120103.webp b/project/images/face_120103.webp new file mode 100644 index 0000000..b1a6b80 Binary files /dev/null and b/project/images/face_120103.webp differ diff --git a/project/images/face_120104.webp b/project/images/face_120104.webp new file mode 100644 index 0000000..1b676d7 Binary files /dev/null and b/project/images/face_120104.webp differ diff --git a/project/images/face_120105.webp b/project/images/face_120105.webp new file mode 100644 index 0000000..a90ab21 Binary files /dev/null and b/project/images/face_120105.webp differ diff --git a/project/images/face_120106.webp b/project/images/face_120106.webp new file mode 100644 index 0000000..c9dc845 Binary files /dev/null and b/project/images/face_120106.webp differ diff --git a/project/images/face_120108.webp b/project/images/face_120108.webp new file mode 100644 index 0000000..ca624d5 Binary files /dev/null and b/project/images/face_120108.webp differ diff --git a/project/images/face_120111.webp b/project/images/face_120111.webp new file mode 100644 index 0000000..880953f Binary files /dev/null and b/project/images/face_120111.webp differ diff --git a/project/images/face_120112.webp b/project/images/face_120112.webp new file mode 100644 index 0000000..90c5083 Binary files /dev/null and b/project/images/face_120112.webp differ diff --git a/project/images/face_120113.webp b/project/images/face_120113.webp new file mode 100644 index 0000000..f012da0 Binary files /dev/null and b/project/images/face_120113.webp differ diff --git a/project/images/face_120121.webp b/project/images/face_120121.webp new file mode 100644 index 0000000..3a5a791 Binary files /dev/null and b/project/images/face_120121.webp differ diff --git a/project/images/face_120122.webp b/project/images/face_120122.webp new file mode 100644 index 0000000..17087be Binary files /dev/null and b/project/images/face_120122.webp differ diff --git a/project/images/face_120123.webp b/project/images/face_120123.webp new file mode 100644 index 0000000..bb97d21 Binary files /dev/null and b/project/images/face_120123.webp differ diff --git a/project/images/face_120124.webp b/project/images/face_120124.webp new file mode 100644 index 0000000..2208131 Binary files /dev/null and b/project/images/face_120124.webp differ diff --git a/project/images/face_120125.webp b/project/images/face_120125.webp new file mode 100644 index 0000000..2aa827b Binary files /dev/null and b/project/images/face_120125.webp differ diff --git a/project/images/face_120126.webp b/project/images/face_120126.webp new file mode 100644 index 0000000..b48d08c Binary files /dev/null and b/project/images/face_120126.webp differ diff --git a/project/images/face_120127.webp b/project/images/face_120127.webp new file mode 100644 index 0000000..997d46f Binary files /dev/null and b/project/images/face_120127.webp differ diff --git a/project/images/face_120128.webp b/project/images/face_120128.webp new file mode 100644 index 0000000..97208ac Binary files /dev/null and b/project/images/face_120128.webp differ diff --git a/project/images/face_120131.webp b/project/images/face_120131.webp new file mode 100644 index 0000000..610ca15 Binary files /dev/null and b/project/images/face_120131.webp differ diff --git a/project/images/face_120132.webp b/project/images/face_120132.webp new file mode 100644 index 0000000..3c0e085 Binary files /dev/null and b/project/images/face_120132.webp differ diff --git a/project/images/face_130101.webp b/project/images/face_130101.webp new file mode 100644 index 0000000..181b18e Binary files /dev/null and b/project/images/face_130101.webp differ diff --git a/project/images/face_130102.webp b/project/images/face_130102.webp new file mode 100644 index 0000000..c2d4499 Binary files /dev/null and b/project/images/face_130102.webp differ diff --git a/project/images/face_130103.webp b/project/images/face_130103.webp new file mode 100644 index 0000000..5c14feb Binary files /dev/null and b/project/images/face_130103.webp differ diff --git a/project/images/face_130104.webp b/project/images/face_130104.webp new file mode 100644 index 0000000..37a7ca6 Binary files /dev/null and b/project/images/face_130104.webp differ diff --git a/project/images/face_130105.webp b/project/images/face_130105.webp new file mode 100644 index 0000000..e8a31dd Binary files /dev/null and b/project/images/face_130105.webp differ diff --git a/project/images/face_130106.webp b/project/images/face_130106.webp new file mode 100644 index 0000000..0658862 Binary files /dev/null and b/project/images/face_130106.webp differ diff --git a/project/images/face_130107.webp b/project/images/face_130107.webp new file mode 100644 index 0000000..2e88e47 Binary files /dev/null and b/project/images/face_130107.webp differ diff --git a/project/images/face_130108.webp b/project/images/face_130108.webp new file mode 100644 index 0000000..32e28b1 Binary files /dev/null and b/project/images/face_130108.webp differ diff --git a/project/images/face_130109.webp b/project/images/face_130109.webp new file mode 100644 index 0000000..4f87b11 Binary files /dev/null and b/project/images/face_130109.webp differ diff --git a/project/images/face_130110.webp b/project/images/face_130110.webp new file mode 100644 index 0000000..d16f85b Binary files /dev/null and b/project/images/face_130110.webp differ diff --git a/project/images/face_130111.webp b/project/images/face_130111.webp new file mode 100644 index 0000000..fa141f4 Binary files /dev/null and b/project/images/face_130111.webp differ diff --git a/project/images/face_130112.webp b/project/images/face_130112.webp new file mode 100644 index 0000000..bdbb1fb Binary files /dev/null and b/project/images/face_130112.webp differ diff --git a/project/images/face_130113.webp b/project/images/face_130113.webp new file mode 100644 index 0000000..b5c4f3f Binary files /dev/null and b/project/images/face_130113.webp differ diff --git a/project/images/face_130121.webp b/project/images/face_130121.webp new file mode 100644 index 0000000..c5024f1 Binary files /dev/null and b/project/images/face_130121.webp differ diff --git a/project/images/face_130122.webp b/project/images/face_130122.webp new file mode 100644 index 0000000..a97578e Binary files /dev/null and b/project/images/face_130122.webp differ diff --git a/project/images/face_130123.webp b/project/images/face_130123.webp new file mode 100644 index 0000000..3595d7e Binary files /dev/null and b/project/images/face_130123.webp differ diff --git a/project/images/face_130124.webp b/project/images/face_130124.webp new file mode 100644 index 0000000..4ce2fdf Binary files /dev/null and b/project/images/face_130124.webp differ diff --git a/project/images/face_130125.webp b/project/images/face_130125.webp new file mode 100644 index 0000000..8c6790b Binary files /dev/null and b/project/images/face_130125.webp differ diff --git a/project/images/face_130126.webp b/project/images/face_130126.webp new file mode 100644 index 0000000..3d9c572 Binary files /dev/null and b/project/images/face_130126.webp differ diff --git a/project/images/face_130127.webp b/project/images/face_130127.webp new file mode 100644 index 0000000..7eff9ba Binary files /dev/null and b/project/images/face_130127.webp differ diff --git a/project/images/face_130128.webp b/project/images/face_130128.webp new file mode 100644 index 0000000..9286671 Binary files /dev/null and b/project/images/face_130128.webp differ diff --git a/project/images/face_130129.webp b/project/images/face_130129.webp new file mode 100644 index 0000000..b63370c Binary files /dev/null and b/project/images/face_130129.webp differ diff --git a/project/images/face_130130.webp b/project/images/face_130130.webp new file mode 100644 index 0000000..37a0caf Binary files /dev/null and b/project/images/face_130130.webp differ diff --git a/project/images/face_130131.webp b/project/images/face_130131.webp new file mode 100644 index 0000000..a7c34c8 Binary files /dev/null and b/project/images/face_130131.webp differ diff --git a/project/images/face_130132.webp b/project/images/face_130132.webp new file mode 100644 index 0000000..41d2160 Binary files /dev/null and b/project/images/face_130132.webp differ diff --git a/project/images/face_130201.webp b/project/images/face_130201.webp new file mode 100644 index 0000000..8428c50 Binary files /dev/null and b/project/images/face_130201.webp differ diff --git a/project/images/face_130202.webp b/project/images/face_130202.webp new file mode 100644 index 0000000..12f397b Binary files /dev/null and b/project/images/face_130202.webp differ diff --git a/project/images/face_130203.webp b/project/images/face_130203.webp new file mode 100644 index 0000000..47a4336 Binary files /dev/null and b/project/images/face_130203.webp differ diff --git a/project/images/face_130204.webp b/project/images/face_130204.webp new file mode 100644 index 0000000..8e826ff Binary files /dev/null and b/project/images/face_130204.webp differ diff --git a/project/images/face_130205.webp b/project/images/face_130205.webp new file mode 100644 index 0000000..d78ff3c Binary files /dev/null and b/project/images/face_130205.webp differ diff --git a/project/images/face_130206.webp b/project/images/face_130206.webp new file mode 100644 index 0000000..88ae09f Binary files /dev/null and b/project/images/face_130206.webp differ diff --git a/project/images/face_130207.webp b/project/images/face_130207.webp new file mode 100644 index 0000000..f2b7e46 Binary files /dev/null and b/project/images/face_130207.webp differ diff --git a/project/images/face_130208.webp b/project/images/face_130208.webp new file mode 100644 index 0000000..80c45d1 Binary files /dev/null and b/project/images/face_130208.webp differ diff --git a/project/images/face_130209.webp b/project/images/face_130209.webp new file mode 100644 index 0000000..968938d Binary files /dev/null and b/project/images/face_130209.webp differ diff --git a/project/images/face_130211.webp b/project/images/face_130211.webp new file mode 100644 index 0000000..91cd1ff Binary files /dev/null and b/project/images/face_130211.webp differ diff --git a/project/images/face_130212.webp b/project/images/face_130212.webp new file mode 100644 index 0000000..bacab45 Binary files /dev/null and b/project/images/face_130212.webp differ diff --git a/project/images/face_130213.webp b/project/images/face_130213.webp new file mode 100644 index 0000000..2277d0c Binary files /dev/null and b/project/images/face_130213.webp differ diff --git a/project/images/face_130221.webp b/project/images/face_130221.webp new file mode 100644 index 0000000..3527add Binary files /dev/null and b/project/images/face_130221.webp differ diff --git a/project/images/face_130222.webp b/project/images/face_130222.webp new file mode 100644 index 0000000..5244eac Binary files /dev/null and b/project/images/face_130222.webp differ diff --git a/project/images/face_130223.webp b/project/images/face_130223.webp new file mode 100644 index 0000000..eeea6dd Binary files /dev/null and b/project/images/face_130223.webp differ diff --git a/project/images/face_130224.webp b/project/images/face_130224.webp new file mode 100644 index 0000000..6aaf352 Binary files /dev/null and b/project/images/face_130224.webp differ diff --git a/project/images/face_130225.webp b/project/images/face_130225.webp new file mode 100644 index 0000000..d59cbe4 Binary files /dev/null and b/project/images/face_130225.webp differ diff --git a/project/images/face_130226.webp b/project/images/face_130226.webp new file mode 100644 index 0000000..465ecd7 Binary files /dev/null and b/project/images/face_130226.webp differ diff --git a/project/images/face_130227.webp b/project/images/face_130227.webp new file mode 100644 index 0000000..c9b80f0 Binary files /dev/null and b/project/images/face_130227.webp differ diff --git a/project/images/face_130228.webp b/project/images/face_130228.webp new file mode 100644 index 0000000..ab9a7e0 Binary files /dev/null and b/project/images/face_130228.webp differ diff --git a/project/images/face_130229.webp b/project/images/face_130229.webp new file mode 100644 index 0000000..28a8d6d Binary files /dev/null and b/project/images/face_130229.webp differ diff --git a/project/images/face_130230.webp b/project/images/face_130230.webp new file mode 100644 index 0000000..e350061 Binary files /dev/null and b/project/images/face_130230.webp differ diff --git a/project/images/face_130231.webp b/project/images/face_130231.webp new file mode 100644 index 0000000..7646d12 Binary files /dev/null and b/project/images/face_130231.webp differ diff --git a/project/images/face_320101.webp b/project/images/face_320101.webp new file mode 100644 index 0000000..125a136 Binary files /dev/null and b/project/images/face_320101.webp differ diff --git a/project/images/face_320102.webp b/project/images/face_320102.webp new file mode 100644 index 0000000..c4f770e Binary files /dev/null and b/project/images/face_320102.webp differ diff --git a/project/images/face_320103.webp b/project/images/face_320103.webp new file mode 100644 index 0000000..0bb5290 Binary files /dev/null and b/project/images/face_320103.webp differ diff --git a/project/images/face_320104.webp b/project/images/face_320104.webp new file mode 100644 index 0000000..69f8d08 Binary files /dev/null and b/project/images/face_320104.webp differ diff --git a/project/images/face_320105.webp b/project/images/face_320105.webp new file mode 100644 index 0000000..583df87 Binary files /dev/null and b/project/images/face_320105.webp differ diff --git a/project/images/face_320106.webp b/project/images/face_320106.webp new file mode 100644 index 0000000..e35e192 Binary files /dev/null and b/project/images/face_320106.webp differ diff --git a/project/images/face_320107.webp b/project/images/face_320107.webp new file mode 100644 index 0000000..cf1e0b0 Binary files /dev/null and b/project/images/face_320107.webp differ diff --git a/project/images/face_320108.webp b/project/images/face_320108.webp new file mode 100644 index 0000000..9d6178a Binary files /dev/null and b/project/images/face_320108.webp differ diff --git a/project/images/face_320109.webp b/project/images/face_320109.webp new file mode 100644 index 0000000..17dff8d Binary files /dev/null and b/project/images/face_320109.webp differ diff --git a/project/images/face_320121.webp b/project/images/face_320121.webp new file mode 100644 index 0000000..e78fb80 Binary files /dev/null and b/project/images/face_320121.webp differ diff --git a/project/images/face_320122.webp b/project/images/face_320122.webp new file mode 100644 index 0000000..53e5827 Binary files /dev/null and b/project/images/face_320122.webp differ diff --git a/project/images/face_320123.webp b/project/images/face_320123.webp new file mode 100644 index 0000000..03d4a51 Binary files /dev/null and b/project/images/face_320123.webp differ diff --git a/project/images/face_320124.webp b/project/images/face_320124.webp new file mode 100644 index 0000000..27d82a7 Binary files /dev/null and b/project/images/face_320124.webp differ diff --git a/project/images/face_320125.webp b/project/images/face_320125.webp new file mode 100644 index 0000000..ae2783c Binary files /dev/null and b/project/images/face_320125.webp differ diff --git a/project/images/face_320127.webp b/project/images/face_320127.webp new file mode 100644 index 0000000..4835679 Binary files /dev/null and b/project/images/face_320127.webp differ diff --git a/project/images/face_340101.webp b/project/images/face_340101.webp new file mode 100644 index 0000000..1eaf8fd Binary files /dev/null and b/project/images/face_340101.webp differ diff --git a/project/images/face_340102.webp b/project/images/face_340102.webp new file mode 100644 index 0000000..49d188e Binary files /dev/null and b/project/images/face_340102.webp differ diff --git a/project/images/face_340103.webp b/project/images/face_340103.webp new file mode 100644 index 0000000..da0a15f Binary files /dev/null and b/project/images/face_340103.webp differ diff --git a/project/images/face_340104.webp b/project/images/face_340104.webp new file mode 100644 index 0000000..6355dba Binary files /dev/null and b/project/images/face_340104.webp differ diff --git a/project/images/face_340105.webp b/project/images/face_340105.webp new file mode 100644 index 0000000..b92a56a Binary files /dev/null and b/project/images/face_340105.webp differ diff --git a/project/images/face_340106.webp b/project/images/face_340106.webp new file mode 100644 index 0000000..4e785ff Binary files /dev/null and b/project/images/face_340106.webp differ diff --git a/project/images/face_340107.webp b/project/images/face_340107.webp new file mode 100644 index 0000000..3c10a9d Binary files /dev/null and b/project/images/face_340107.webp differ diff --git a/project/images/face_340108.webp b/project/images/face_340108.webp new file mode 100644 index 0000000..f61f0f5 Binary files /dev/null and b/project/images/face_340108.webp differ diff --git a/project/images/face_340109.webp b/project/images/face_340109.webp new file mode 100644 index 0000000..ea81797 Binary files /dev/null and b/project/images/face_340109.webp differ diff --git a/project/images/face_340110.webp b/project/images/face_340110.webp new file mode 100644 index 0000000..4d3f3a1 Binary files /dev/null and b/project/images/face_340110.webp differ diff --git a/project/images/face_340111.webp b/project/images/face_340111.webp new file mode 100644 index 0000000..88a5708 Binary files /dev/null and b/project/images/face_340111.webp differ diff --git a/project/images/face_340112.webp b/project/images/face_340112.webp new file mode 100644 index 0000000..d3f11ec Binary files /dev/null and b/project/images/face_340112.webp differ diff --git a/project/images/face_340113.webp b/project/images/face_340113.webp new file mode 100644 index 0000000..f548732 Binary files /dev/null and b/project/images/face_340113.webp differ diff --git a/project/images/face_340114.webp b/project/images/face_340114.webp new file mode 100644 index 0000000..756c346 Binary files /dev/null and b/project/images/face_340114.webp differ diff --git a/project/images/face_340115.webp b/project/images/face_340115.webp new file mode 100644 index 0000000..47615b8 Binary files /dev/null and b/project/images/face_340115.webp differ diff --git a/project/images/face_430101.webp b/project/images/face_430101.webp new file mode 100644 index 0000000..1e769d8 Binary files /dev/null and b/project/images/face_430101.webp differ diff --git a/project/images/face_430102.webp b/project/images/face_430102.webp new file mode 100644 index 0000000..f147014 Binary files /dev/null and b/project/images/face_430102.webp differ diff --git a/project/images/face_430103.webp b/project/images/face_430103.webp new file mode 100644 index 0000000..93a9925 Binary files /dev/null and b/project/images/face_430103.webp differ diff --git a/project/images/face_430104.webp b/project/images/face_430104.webp new file mode 100644 index 0000000..9c9cb04 Binary files /dev/null and b/project/images/face_430104.webp differ diff --git a/project/images/face_430105.webp b/project/images/face_430105.webp new file mode 100644 index 0000000..a24dee1 Binary files /dev/null and b/project/images/face_430105.webp differ diff --git a/project/images/face_430106.webp b/project/images/face_430106.webp new file mode 100644 index 0000000..b5cfa7e Binary files /dev/null and b/project/images/face_430106.webp differ diff --git a/project/images/face_430107.webp b/project/images/face_430107.webp new file mode 100644 index 0000000..75d9b5e Binary files /dev/null and b/project/images/face_430107.webp differ diff --git a/project/images/face_430108.webp b/project/images/face_430108.webp new file mode 100644 index 0000000..48f8965 Binary files /dev/null and b/project/images/face_430108.webp differ diff --git a/project/images/face_440101.webp b/project/images/face_440101.webp new file mode 100644 index 0000000..37539c6 Binary files /dev/null and b/project/images/face_440101.webp differ diff --git a/project/images/face_440102.webp b/project/images/face_440102.webp new file mode 100644 index 0000000..96b1027 Binary files /dev/null and b/project/images/face_440102.webp differ diff --git a/project/images/face_440103.webp b/project/images/face_440103.webp new file mode 100644 index 0000000..76c6b72 Binary files /dev/null and b/project/images/face_440103.webp differ diff --git a/project/images/face_440104.webp b/project/images/face_440104.webp new file mode 100644 index 0000000..0092336 Binary files /dev/null and b/project/images/face_440104.webp differ diff --git a/project/images/face_440105.webp b/project/images/face_440105.webp new file mode 100644 index 0000000..536aff5 Binary files /dev/null and b/project/images/face_440105.webp differ diff --git a/project/images/face_440106.webp b/project/images/face_440106.webp new file mode 100644 index 0000000..7e53532 Binary files /dev/null and b/project/images/face_440106.webp differ diff --git a/project/images/face_440107.webp b/project/images/face_440107.webp new file mode 100644 index 0000000..a0e9fa5 Binary files /dev/null and b/project/images/face_440107.webp differ diff --git a/project/images/face_440108.webp b/project/images/face_440108.webp new file mode 100644 index 0000000..fa6aeab Binary files /dev/null and b/project/images/face_440108.webp differ diff --git a/project/images/face_440109.webp b/project/images/face_440109.webp new file mode 100644 index 0000000..f9713c4 Binary files /dev/null and b/project/images/face_440109.webp differ diff --git a/project/images/face_440110.webp b/project/images/face_440110.webp new file mode 100644 index 0000000..a5a91c8 Binary files /dev/null and b/project/images/face_440110.webp differ diff --git a/project/images/tati_050101.webp b/project/images/tati_050101.webp new file mode 100644 index 0000000..7e7b8bd Binary files /dev/null and b/project/images/tati_050101.webp differ diff --git a/project/images/tati_050101a.webp b/project/images/tati_050101a.webp new file mode 100644 index 0000000..261a3f1 Binary files /dev/null and b/project/images/tati_050101a.webp differ diff --git a/project/images/tati_050101y.webp b/project/images/tati_050101y.webp new file mode 100644 index 0000000..26fef52 Binary files /dev/null and b/project/images/tati_050101y.webp differ diff --git a/project/images/tati_050102.webp b/project/images/tati_050102.webp new file mode 100644 index 0000000..519308e Binary files /dev/null and b/project/images/tati_050102.webp differ diff --git a/project/images/tati_050102y.webp b/project/images/tati_050102y.webp new file mode 100644 index 0000000..46a5f3d Binary files /dev/null and b/project/images/tati_050102y.webp differ diff --git a/project/images/tati_050103.webp b/project/images/tati_050103.webp new file mode 100644 index 0000000..f655203 Binary files /dev/null and b/project/images/tati_050103.webp differ diff --git a/project/images/tati_050103a.webp b/project/images/tati_050103a.webp new file mode 100644 index 0000000..4d1a43b Binary files /dev/null and b/project/images/tati_050103a.webp differ diff --git a/project/images/tati_050103y.webp b/project/images/tati_050103y.webp new file mode 100644 index 0000000..243883a Binary files /dev/null and b/project/images/tati_050103y.webp differ diff --git a/project/images/tati_050104.webp b/project/images/tati_050104.webp new file mode 100644 index 0000000..8894735 Binary files /dev/null and b/project/images/tati_050104.webp differ diff --git a/project/images/tati_050104a.webp b/project/images/tati_050104a.webp new file mode 100644 index 0000000..4d58e4a Binary files /dev/null and b/project/images/tati_050104a.webp differ diff --git a/project/images/tati_050105.webp b/project/images/tati_050105.webp new file mode 100644 index 0000000..df6359e Binary files /dev/null and b/project/images/tati_050105.webp differ diff --git a/project/images/tati_050105a.webp b/project/images/tati_050105a.webp new file mode 100644 index 0000000..49f7c84 Binary files /dev/null and b/project/images/tati_050105a.webp differ diff --git a/project/images/tati_050105y.webp b/project/images/tati_050105y.webp new file mode 100644 index 0000000..3df3405 Binary files /dev/null and b/project/images/tati_050105y.webp differ diff --git a/project/images/tati_050106.webp b/project/images/tati_050106.webp new file mode 100644 index 0000000..86dc7c8 Binary files /dev/null and b/project/images/tati_050106.webp differ diff --git a/project/images/tati_050106y.webp b/project/images/tati_050106y.webp new file mode 100644 index 0000000..728f894 Binary files /dev/null and b/project/images/tati_050106y.webp differ diff --git a/project/images/tati_050107.webp b/project/images/tati_050107.webp new file mode 100644 index 0000000..354acde Binary files /dev/null and b/project/images/tati_050107.webp differ diff --git a/project/images/tati_050107a.webp b/project/images/tati_050107a.webp new file mode 100644 index 0000000..08e5d3d Binary files /dev/null and b/project/images/tati_050107a.webp differ diff --git a/project/images/tati_050107y.webp b/project/images/tati_050107y.webp new file mode 100644 index 0000000..a46ed5b Binary files /dev/null and b/project/images/tati_050107y.webp differ diff --git a/project/images/tati_050110.webp b/project/images/tati_050110.webp new file mode 100644 index 0000000..ad26d10 Binary files /dev/null and b/project/images/tati_050110.webp differ diff --git a/project/images/tati_050111.webp b/project/images/tati_050111.webp new file mode 100644 index 0000000..1956c65 Binary files /dev/null and b/project/images/tati_050111.webp differ diff --git a/project/images/tati_050111a.webp b/project/images/tati_050111a.webp new file mode 100644 index 0000000..ab59b9e Binary files /dev/null and b/project/images/tati_050111a.webp differ diff --git a/project/images/tati_050111y.webp b/project/images/tati_050111y.webp new file mode 100644 index 0000000..14012b2 Binary files /dev/null and b/project/images/tati_050111y.webp differ diff --git a/project/images/tati_050112.webp b/project/images/tati_050112.webp new file mode 100644 index 0000000..7752e4a Binary files /dev/null and b/project/images/tati_050112.webp differ diff --git a/project/images/tati_050113y.webp b/project/images/tati_050113y.webp new file mode 100644 index 0000000..2636fb3 Binary files /dev/null and b/project/images/tati_050113y.webp differ diff --git a/project/images/tati_050116.webp b/project/images/tati_050116.webp new file mode 100644 index 0000000..cba90ef Binary files /dev/null and b/project/images/tati_050116.webp differ diff --git a/project/images/tati_050116a.webp b/project/images/tati_050116a.webp new file mode 100644 index 0000000..48e2c94 Binary files /dev/null and b/project/images/tati_050116a.webp differ diff --git a/project/images/tati_050116y.webp b/project/images/tati_050116y.webp new file mode 100644 index 0000000..a3d1fa5 Binary files /dev/null and b/project/images/tati_050116y.webp differ diff --git a/project/images/tati_050117.webp b/project/images/tati_050117.webp new file mode 100644 index 0000000..153d707 Binary files /dev/null and b/project/images/tati_050117.webp differ diff --git a/project/images/tati_050121.webp b/project/images/tati_050121.webp new file mode 100644 index 0000000..0acc15b Binary files /dev/null and b/project/images/tati_050121.webp differ diff --git a/project/images/tati_050121a.webp b/project/images/tati_050121a.webp new file mode 100644 index 0000000..a802414 Binary files /dev/null and b/project/images/tati_050121a.webp differ diff --git a/project/images/tati_050121y.webp b/project/images/tati_050121y.webp new file mode 100644 index 0000000..cc5f03d Binary files /dev/null and b/project/images/tati_050121y.webp differ diff --git a/project/images/tati_050122.webp b/project/images/tati_050122.webp new file mode 100644 index 0000000..0ce76a0 Binary files /dev/null and b/project/images/tati_050122.webp differ diff --git a/project/images/tati_050122y.webp b/project/images/tati_050122y.webp new file mode 100644 index 0000000..3acdec6 Binary files /dev/null and b/project/images/tati_050122y.webp differ diff --git a/project/images/tati_050123.webp b/project/images/tati_050123.webp new file mode 100644 index 0000000..eb60f3a Binary files /dev/null and b/project/images/tati_050123.webp differ diff --git a/project/images/tati_050123a.webp b/project/images/tati_050123a.webp new file mode 100644 index 0000000..d2a7a6b Binary files /dev/null and b/project/images/tati_050123a.webp differ diff --git a/project/images/tati_050123y.webp b/project/images/tati_050123y.webp new file mode 100644 index 0000000..347ee03 Binary files /dev/null and b/project/images/tati_050123y.webp differ diff --git a/project/images/tati_050124.webp b/project/images/tati_050124.webp new file mode 100644 index 0000000..d7a8298 Binary files /dev/null and b/project/images/tati_050124.webp differ diff --git a/project/images/tati_050124a.webp b/project/images/tati_050124a.webp new file mode 100644 index 0000000..b2931cf Binary files /dev/null and b/project/images/tati_050124a.webp differ diff --git a/project/images/tati_050124y.webp b/project/images/tati_050124y.webp new file mode 100644 index 0000000..9ea35ee Binary files /dev/null and b/project/images/tati_050124y.webp differ diff --git a/project/images/tati_050125.webp b/project/images/tati_050125.webp new file mode 100644 index 0000000..ceeff74 Binary files /dev/null and b/project/images/tati_050125.webp differ diff --git a/project/images/tati_050125a.webp b/project/images/tati_050125a.webp new file mode 100644 index 0000000..f847625 Binary files /dev/null and b/project/images/tati_050125a.webp differ diff --git a/project/images/tati_050125y.webp b/project/images/tati_050125y.webp new file mode 100644 index 0000000..18d2682 Binary files /dev/null and b/project/images/tati_050125y.webp differ diff --git a/project/images/tati_050126.webp b/project/images/tati_050126.webp new file mode 100644 index 0000000..245c05b Binary files /dev/null and b/project/images/tati_050126.webp differ diff --git a/project/images/tati_050126y.webp b/project/images/tati_050126y.webp new file mode 100644 index 0000000..2b5f2b6 Binary files /dev/null and b/project/images/tati_050126y.webp differ diff --git a/project/images/tati_050127.webp b/project/images/tati_050127.webp new file mode 100644 index 0000000..19850d9 Binary files /dev/null and b/project/images/tati_050127.webp differ diff --git a/project/images/tati_050127a.webp b/project/images/tati_050127a.webp new file mode 100644 index 0000000..e3f69ce Binary files /dev/null and b/project/images/tati_050127a.webp differ diff --git a/project/images/tati_050128.webp b/project/images/tati_050128.webp new file mode 100644 index 0000000..179fbaf Binary files /dev/null and b/project/images/tati_050128.webp differ diff --git a/project/images/tati_050131.webp b/project/images/tati_050131.webp new file mode 100644 index 0000000..509ddfd Binary files /dev/null and b/project/images/tati_050131.webp differ diff --git a/project/images/tati_050131a.webp b/project/images/tati_050131a.webp new file mode 100644 index 0000000..58406d2 Binary files /dev/null and b/project/images/tati_050131a.webp differ diff --git a/project/images/tati_050131y.webp b/project/images/tati_050131y.webp new file mode 100644 index 0000000..92dbc60 Binary files /dev/null and b/project/images/tati_050131y.webp differ diff --git a/project/images/tati_050132.webp b/project/images/tati_050132.webp new file mode 100644 index 0000000..6a25ddd Binary files /dev/null and b/project/images/tati_050132.webp differ diff --git a/project/images/tati_050134.webp b/project/images/tati_050134.webp new file mode 100644 index 0000000..f1ea445 Binary files /dev/null and b/project/images/tati_050134.webp differ diff --git a/project/images/tati_050134y.webp b/project/images/tati_050134y.webp new file mode 100644 index 0000000..f09f864 Binary files /dev/null and b/project/images/tati_050134y.webp differ diff --git a/project/images/tati_050135.webp b/project/images/tati_050135.webp new file mode 100644 index 0000000..adab376 Binary files /dev/null and b/project/images/tati_050135.webp differ diff --git a/project/images/tati_050135y.webp b/project/images/tati_050135y.webp new file mode 100644 index 0000000..1266015 Binary files /dev/null and b/project/images/tati_050135y.webp differ diff --git a/project/images/tati_050136.webp b/project/images/tati_050136.webp new file mode 100644 index 0000000..a1a40d6 Binary files /dev/null and b/project/images/tati_050136.webp differ diff --git a/project/images/tati_050137.webp b/project/images/tati_050137.webp new file mode 100644 index 0000000..ca1fefc Binary files /dev/null and b/project/images/tati_050137.webp differ diff --git a/project/images/tati_050137y.webp b/project/images/tati_050137y.webp new file mode 100644 index 0000000..d536486 Binary files /dev/null and b/project/images/tati_050137y.webp differ diff --git a/project/images/tati_050141.webp b/project/images/tati_050141.webp new file mode 100644 index 0000000..a94ba95 Binary files /dev/null and b/project/images/tati_050141.webp differ diff --git a/project/images/tati_050141a.webp b/project/images/tati_050141a.webp new file mode 100644 index 0000000..57f3957 Binary files /dev/null and b/project/images/tati_050141a.webp differ diff --git a/project/images/tati_050141y.webp b/project/images/tati_050141y.webp new file mode 100644 index 0000000..e3df30e Binary files /dev/null and b/project/images/tati_050141y.webp differ diff --git a/project/images/tati_050142.webp b/project/images/tati_050142.webp new file mode 100644 index 0000000..499b32a Binary files /dev/null and b/project/images/tati_050142.webp differ diff --git a/project/images/tati_050142a.webp b/project/images/tati_050142a.webp new file mode 100644 index 0000000..93f43c9 Binary files /dev/null and b/project/images/tati_050142a.webp differ diff --git a/project/images/tati_050142y.webp b/project/images/tati_050142y.webp new file mode 100644 index 0000000..3e84bc5 Binary files /dev/null and b/project/images/tati_050142y.webp differ diff --git a/project/images/tati_050143.webp b/project/images/tati_050143.webp new file mode 100644 index 0000000..8244d15 Binary files /dev/null and b/project/images/tati_050143.webp differ diff --git a/project/images/tati_050143a.webp b/project/images/tati_050143a.webp new file mode 100644 index 0000000..9d7e93a Binary files /dev/null and b/project/images/tati_050143a.webp differ diff --git a/project/images/tati_050143y.webp b/project/images/tati_050143y.webp new file mode 100644 index 0000000..f7e03e0 Binary files /dev/null and b/project/images/tati_050143y.webp differ diff --git a/project/images/tati_050144.webp b/project/images/tati_050144.webp new file mode 100644 index 0000000..6ebae4b Binary files /dev/null and b/project/images/tati_050144.webp differ diff --git a/project/images/tati_050144a.webp b/project/images/tati_050144a.webp new file mode 100644 index 0000000..e0a932a Binary files /dev/null and b/project/images/tati_050144a.webp differ diff --git a/project/images/tati_050144y.webp b/project/images/tati_050144y.webp new file mode 100644 index 0000000..1beb0d4 Binary files /dev/null and b/project/images/tati_050144y.webp differ diff --git a/project/images/tati_050145.webp b/project/images/tati_050145.webp new file mode 100644 index 0000000..705ea09 Binary files /dev/null and b/project/images/tati_050145.webp differ diff --git a/project/images/tati_050145y.webp b/project/images/tati_050145y.webp new file mode 100644 index 0000000..e5e3e82 Binary files /dev/null and b/project/images/tati_050145y.webp differ diff --git a/project/images/tati_050146.webp b/project/images/tati_050146.webp new file mode 100644 index 0000000..2cc72ed Binary files /dev/null and b/project/images/tati_050146.webp differ diff --git a/project/images/tati_050146y.webp b/project/images/tati_050146y.webp new file mode 100644 index 0000000..1df3fe3 Binary files /dev/null and b/project/images/tati_050146y.webp differ diff --git a/project/images/tati_050147.webp b/project/images/tati_050147.webp new file mode 100644 index 0000000..ae5953d Binary files /dev/null and b/project/images/tati_050147.webp differ diff --git a/project/images/tati_050147y.webp b/project/images/tati_050147y.webp new file mode 100644 index 0000000..a2bf1c2 Binary files /dev/null and b/project/images/tati_050147y.webp differ diff --git a/project/images/tati_050151.webp b/project/images/tati_050151.webp new file mode 100644 index 0000000..867f631 Binary files /dev/null and b/project/images/tati_050151.webp differ diff --git a/project/images/tati_050151a.webp b/project/images/tati_050151a.webp new file mode 100644 index 0000000..0a6b036 Binary files /dev/null and b/project/images/tati_050151a.webp differ diff --git a/project/images/tati_050151y.webp b/project/images/tati_050151y.webp new file mode 100644 index 0000000..30399ac Binary files /dev/null and b/project/images/tati_050151y.webp differ diff --git a/project/images/tati_050152.webp b/project/images/tati_050152.webp new file mode 100644 index 0000000..fa61d27 Binary files /dev/null and b/project/images/tati_050152.webp differ diff --git a/project/images/tati_050152y.webp b/project/images/tati_050152y.webp new file mode 100644 index 0000000..d56f1f1 Binary files /dev/null and b/project/images/tati_050152y.webp differ diff --git a/project/images/tati_050201.webp b/project/images/tati_050201.webp new file mode 100644 index 0000000..126c435 Binary files /dev/null and b/project/images/tati_050201.webp differ diff --git a/project/images/tati_050201a.webp b/project/images/tati_050201a.webp new file mode 100644 index 0000000..5964960 Binary files /dev/null and b/project/images/tati_050201a.webp differ diff --git a/project/images/tati_050201y.webp b/project/images/tati_050201y.webp new file mode 100644 index 0000000..be1adf8 Binary files /dev/null and b/project/images/tati_050201y.webp differ diff --git a/project/images/tati_050202.webp b/project/images/tati_050202.webp new file mode 100644 index 0000000..fd9311d Binary files /dev/null and b/project/images/tati_050202.webp differ diff --git a/project/images/tati_050202a.webp b/project/images/tati_050202a.webp new file mode 100644 index 0000000..935244c Binary files /dev/null and b/project/images/tati_050202a.webp differ diff --git a/project/images/tati_050202y.webp b/project/images/tati_050202y.webp new file mode 100644 index 0000000..a15791f Binary files /dev/null and b/project/images/tati_050202y.webp differ diff --git a/project/images/tati_050203.webp b/project/images/tati_050203.webp new file mode 100644 index 0000000..4b0d2fc Binary files /dev/null and b/project/images/tati_050203.webp differ diff --git a/project/images/tati_050203y.webp b/project/images/tati_050203y.webp new file mode 100644 index 0000000..64c6173 Binary files /dev/null and b/project/images/tati_050203y.webp differ diff --git a/project/images/tati_050204a.webp b/project/images/tati_050204a.webp new file mode 100644 index 0000000..199883d Binary files /dev/null and b/project/images/tati_050204a.webp differ diff --git a/project/images/tati_050204y.webp b/project/images/tati_050204y.webp new file mode 100644 index 0000000..4d7672c Binary files /dev/null and b/project/images/tati_050204y.webp differ diff --git a/project/images/tati_050205.webp b/project/images/tati_050205.webp new file mode 100644 index 0000000..f58e1e1 Binary files /dev/null and b/project/images/tati_050205.webp differ diff --git a/project/images/tati_050205a.webp b/project/images/tati_050205a.webp new file mode 100644 index 0000000..549877e Binary files /dev/null and b/project/images/tati_050205a.webp differ diff --git a/project/images/tati_050205y.webp b/project/images/tati_050205y.webp new file mode 100644 index 0000000..6351984 Binary files /dev/null and b/project/images/tati_050205y.webp differ diff --git a/project/images/tati_050206.webp b/project/images/tati_050206.webp new file mode 100644 index 0000000..cd51e96 Binary files /dev/null and b/project/images/tati_050206.webp differ diff --git a/project/images/tati_050206a.webp b/project/images/tati_050206a.webp new file mode 100644 index 0000000..4435f23 Binary files /dev/null and b/project/images/tati_050206a.webp differ diff --git a/project/images/tati_050206y.webp b/project/images/tati_050206y.webp new file mode 100644 index 0000000..0b9a04b Binary files /dev/null and b/project/images/tati_050206y.webp differ diff --git a/project/images/tati_050210y.webp b/project/images/tati_050210y.webp new file mode 100644 index 0000000..2504e2c Binary files /dev/null and b/project/images/tati_050210y.webp differ diff --git a/project/images/tati_050215.webp b/project/images/tati_050215.webp new file mode 100644 index 0000000..adefc64 Binary files /dev/null and b/project/images/tati_050215.webp differ diff --git a/project/images/tati_050216.webp b/project/images/tati_050216.webp new file mode 100644 index 0000000..4fd50a0 Binary files /dev/null and b/project/images/tati_050216.webp differ diff --git a/project/images/tati_050221.webp b/project/images/tati_050221.webp new file mode 100644 index 0000000..6ed3bde Binary files /dev/null and b/project/images/tati_050221.webp differ diff --git a/project/images/tati_050221a.webp b/project/images/tati_050221a.webp new file mode 100644 index 0000000..683f2a6 Binary files /dev/null and b/project/images/tati_050221a.webp differ diff --git a/project/images/tati_050221y.webp b/project/images/tati_050221y.webp new file mode 100644 index 0000000..3984fe1 Binary files /dev/null and b/project/images/tati_050221y.webp differ diff --git a/project/images/tati_050222.webp b/project/images/tati_050222.webp new file mode 100644 index 0000000..3aac4c8 Binary files /dev/null and b/project/images/tati_050222.webp differ diff --git a/project/images/tati_050222a.webp b/project/images/tati_050222a.webp new file mode 100644 index 0000000..c3facb0 Binary files /dev/null and b/project/images/tati_050222a.webp differ diff --git a/project/images/tati_050222y.webp b/project/images/tati_050222y.webp new file mode 100644 index 0000000..522e0e6 Binary files /dev/null and b/project/images/tati_050222y.webp differ diff --git a/project/images/tati_050223.webp b/project/images/tati_050223.webp new file mode 100644 index 0000000..3f3151e Binary files /dev/null and b/project/images/tati_050223.webp differ diff --git a/project/images/tati_050224a.webp b/project/images/tati_050224a.webp new file mode 100644 index 0000000..3e3f828 Binary files /dev/null and b/project/images/tati_050224a.webp differ diff --git a/project/images/tati_050224y.webp b/project/images/tati_050224y.webp new file mode 100644 index 0000000..e647df5 Binary files /dev/null and b/project/images/tati_050224y.webp differ diff --git a/project/images/tati_050225.webp b/project/images/tati_050225.webp new file mode 100644 index 0000000..59c7c5c Binary files /dev/null and b/project/images/tati_050225.webp differ diff --git a/project/images/tati_050225a.webp b/project/images/tati_050225a.webp new file mode 100644 index 0000000..2bc0246 Binary files /dev/null and b/project/images/tati_050225a.webp differ diff --git a/project/images/tati_050225y.webp b/project/images/tati_050225y.webp new file mode 100644 index 0000000..6ff5676 Binary files /dev/null and b/project/images/tati_050225y.webp differ diff --git a/project/images/tati_050226.webp b/project/images/tati_050226.webp new file mode 100644 index 0000000..efd597a Binary files /dev/null and b/project/images/tati_050226.webp differ diff --git a/project/images/tati_050226a.webp b/project/images/tati_050226a.webp new file mode 100644 index 0000000..c652554 Binary files /dev/null and b/project/images/tati_050226a.webp differ diff --git a/project/images/tati_050229.webp b/project/images/tati_050229.webp new file mode 100644 index 0000000..a0915ef Binary files /dev/null and b/project/images/tati_050229.webp differ diff --git a/project/images/tati_050230y.webp b/project/images/tati_050230y.webp new file mode 100644 index 0000000..ac60ecf Binary files /dev/null and b/project/images/tati_050230y.webp differ diff --git a/project/images/tati_050232a.webp b/project/images/tati_050232a.webp new file mode 100644 index 0000000..e55f89b Binary files /dev/null and b/project/images/tati_050232a.webp differ diff --git a/project/images/tati_050234a.webp b/project/images/tati_050234a.webp new file mode 100644 index 0000000..3186bef Binary files /dev/null and b/project/images/tati_050234a.webp differ diff --git a/project/images/tati_050237.webp b/project/images/tati_050237.webp new file mode 100644 index 0000000..e56f654 Binary files /dev/null and b/project/images/tati_050237.webp differ diff --git a/project/images/tati_050241.webp b/project/images/tati_050241.webp new file mode 100644 index 0000000..97d09ab Binary files /dev/null and b/project/images/tati_050241.webp differ diff --git a/project/images/tati_050241a.webp b/project/images/tati_050241a.webp new file mode 100644 index 0000000..710adc3 Binary files /dev/null and b/project/images/tati_050241a.webp differ diff --git a/project/images/tati_050241y.webp b/project/images/tati_050241y.webp new file mode 100644 index 0000000..60df1c1 Binary files /dev/null and b/project/images/tati_050241y.webp differ diff --git a/project/images/tati_050242.webp b/project/images/tati_050242.webp new file mode 100644 index 0000000..cb969b8 Binary files /dev/null and b/project/images/tati_050242.webp differ diff --git a/project/images/tati_050242a.webp b/project/images/tati_050242a.webp new file mode 100644 index 0000000..070640d Binary files /dev/null and b/project/images/tati_050242a.webp differ diff --git a/project/images/tati_050242y.webp b/project/images/tati_050242y.webp new file mode 100644 index 0000000..e5c4840 Binary files /dev/null and b/project/images/tati_050242y.webp differ diff --git a/project/images/tati_050243.webp b/project/images/tati_050243.webp new file mode 100644 index 0000000..4371e03 Binary files /dev/null and b/project/images/tati_050243.webp differ diff --git a/project/images/tati_050243y.webp b/project/images/tati_050243y.webp new file mode 100644 index 0000000..d87f357 Binary files /dev/null and b/project/images/tati_050243y.webp differ diff --git a/project/images/tati_050244a.webp b/project/images/tati_050244a.webp new file mode 100644 index 0000000..4ba656b Binary files /dev/null and b/project/images/tati_050244a.webp differ diff --git a/project/images/tati_050244y.webp b/project/images/tati_050244y.webp new file mode 100644 index 0000000..a710959 Binary files /dev/null and b/project/images/tati_050244y.webp differ diff --git a/project/images/tati_050245.webp b/project/images/tati_050245.webp new file mode 100644 index 0000000..e8a0755 Binary files /dev/null and b/project/images/tati_050245.webp differ diff --git a/project/images/tati_050245a.webp b/project/images/tati_050245a.webp new file mode 100644 index 0000000..ef94266 Binary files /dev/null and b/project/images/tati_050245a.webp differ diff --git a/project/images/tati_050245y.webp b/project/images/tati_050245y.webp new file mode 100644 index 0000000..2b86e8b Binary files /dev/null and b/project/images/tati_050245y.webp differ diff --git a/project/images/tati_050252.webp b/project/images/tati_050252.webp new file mode 100644 index 0000000..192f1ae Binary files /dev/null and b/project/images/tati_050252.webp differ diff --git a/project/images/tati_050252y.webp b/project/images/tati_050252y.webp new file mode 100644 index 0000000..7b55af9 Binary files /dev/null and b/project/images/tati_050252y.webp differ diff --git a/project/images/tati_050301.webp b/project/images/tati_050301.webp new file mode 100644 index 0000000..e0a5682 Binary files /dev/null and b/project/images/tati_050301.webp differ diff --git a/project/images/tati_050301a.webp b/project/images/tati_050301a.webp new file mode 100644 index 0000000..598ab9f Binary files /dev/null and b/project/images/tati_050301a.webp differ diff --git a/project/images/tati_050301y.webp b/project/images/tati_050301y.webp new file mode 100644 index 0000000..1cf7669 Binary files /dev/null and b/project/images/tati_050301y.webp differ diff --git a/project/images/tati_050302.webp b/project/images/tati_050302.webp new file mode 100644 index 0000000..8eb4f7b Binary files /dev/null and b/project/images/tati_050302.webp differ diff --git a/project/images/tati_050303.webp b/project/images/tati_050303.webp new file mode 100644 index 0000000..561ff6d Binary files /dev/null and b/project/images/tati_050303.webp differ diff --git a/project/images/tati_050303y.webp b/project/images/tati_050303y.webp new file mode 100644 index 0000000..916859e Binary files /dev/null and b/project/images/tati_050303y.webp differ diff --git a/project/images/tati_050304.webp b/project/images/tati_050304.webp new file mode 100644 index 0000000..091d36b Binary files /dev/null and b/project/images/tati_050304.webp differ diff --git a/project/images/tati_050304y.webp b/project/images/tati_050304y.webp new file mode 100644 index 0000000..7587939 Binary files /dev/null and b/project/images/tati_050304y.webp differ diff --git a/project/images/tati_050305.webp b/project/images/tati_050305.webp new file mode 100644 index 0000000..7f6b7e2 Binary files /dev/null and b/project/images/tati_050305.webp differ diff --git a/project/images/tati_050305a.webp b/project/images/tati_050305a.webp new file mode 100644 index 0000000..0266053 Binary files /dev/null and b/project/images/tati_050305a.webp differ diff --git a/project/images/tati_050305y.webp b/project/images/tati_050305y.webp new file mode 100644 index 0000000..7ae4e59 Binary files /dev/null and b/project/images/tati_050305y.webp differ diff --git a/project/images/tati_050306.webp b/project/images/tati_050306.webp new file mode 100644 index 0000000..323b501 Binary files /dev/null and b/project/images/tati_050306.webp differ diff --git a/project/images/tati_050306y.webp b/project/images/tati_050306y.webp new file mode 100644 index 0000000..385c0f1 Binary files /dev/null and b/project/images/tati_050306y.webp differ diff --git a/project/images/tati_050307.webp b/project/images/tati_050307.webp new file mode 100644 index 0000000..b566868 Binary files /dev/null and b/project/images/tati_050307.webp differ diff --git a/project/images/tati_050307a.webp b/project/images/tati_050307a.webp new file mode 100644 index 0000000..f9d248b Binary files /dev/null and b/project/images/tati_050307a.webp differ diff --git a/project/images/tati_050307y.webp b/project/images/tati_050307y.webp new file mode 100644 index 0000000..bc14c5d Binary files /dev/null and b/project/images/tati_050307y.webp differ diff --git a/project/images/tati_050308.webp b/project/images/tati_050308.webp new file mode 100644 index 0000000..18e3096 Binary files /dev/null and b/project/images/tati_050308.webp differ diff --git a/project/images/tati_050309.webp b/project/images/tati_050309.webp new file mode 100644 index 0000000..7ffbd5d Binary files /dev/null and b/project/images/tati_050309.webp differ diff --git a/project/images/tati_050310.webp b/project/images/tati_050310.webp new file mode 100644 index 0000000..5e856aa Binary files /dev/null and b/project/images/tati_050310.webp differ diff --git a/project/images/tati_050311.webp b/project/images/tati_050311.webp new file mode 100644 index 0000000..f186eda Binary files /dev/null and b/project/images/tati_050311.webp differ diff --git a/project/images/tati_050311y.webp b/project/images/tati_050311y.webp new file mode 100644 index 0000000..59af9d8 Binary files /dev/null and b/project/images/tati_050311y.webp differ diff --git a/project/images/tati_050313.webp b/project/images/tati_050313.webp new file mode 100644 index 0000000..4660d8b Binary files /dev/null and b/project/images/tati_050313.webp differ diff --git a/project/images/tati_050314.webp b/project/images/tati_050314.webp new file mode 100644 index 0000000..4bf2a0e Binary files /dev/null and b/project/images/tati_050314.webp differ diff --git a/project/images/tati_050315.webp b/project/images/tati_050315.webp new file mode 100644 index 0000000..0ac2d72 Binary files /dev/null and b/project/images/tati_050315.webp differ diff --git a/project/images/tati_050316.webp b/project/images/tati_050316.webp new file mode 100644 index 0000000..cf4128a Binary files /dev/null and b/project/images/tati_050316.webp differ diff --git a/project/images/tati_050316y.webp b/project/images/tati_050316y.webp new file mode 100644 index 0000000..0b4df60 Binary files /dev/null and b/project/images/tati_050316y.webp differ diff --git a/project/images/tati_050317.webp b/project/images/tati_050317.webp new file mode 100644 index 0000000..3d3ce57 Binary files /dev/null and b/project/images/tati_050317.webp differ diff --git a/project/images/tati_050321.webp b/project/images/tati_050321.webp new file mode 100644 index 0000000..a9a8012 Binary files /dev/null and b/project/images/tati_050321.webp differ diff --git a/project/images/tati_050321a.webp b/project/images/tati_050321a.webp new file mode 100644 index 0000000..002e810 Binary files /dev/null and b/project/images/tati_050321a.webp differ diff --git a/project/images/tati_050321y.webp b/project/images/tati_050321y.webp new file mode 100644 index 0000000..6a8331a Binary files /dev/null and b/project/images/tati_050321y.webp differ diff --git a/project/images/tati_050322.webp b/project/images/tati_050322.webp new file mode 100644 index 0000000..1e7d827 Binary files /dev/null and b/project/images/tati_050322.webp differ diff --git a/project/images/tati_050322y.webp b/project/images/tati_050322y.webp new file mode 100644 index 0000000..3043a92 Binary files /dev/null and b/project/images/tati_050322y.webp differ diff --git a/project/images/tati_050323.webp b/project/images/tati_050323.webp new file mode 100644 index 0000000..9b2a380 Binary files /dev/null and b/project/images/tati_050323.webp differ diff --git a/project/images/tati_050324.webp b/project/images/tati_050324.webp new file mode 100644 index 0000000..ab2f3ce Binary files /dev/null and b/project/images/tati_050324.webp differ diff --git a/project/images/tati_050324a.webp b/project/images/tati_050324a.webp new file mode 100644 index 0000000..ac7fc74 Binary files /dev/null and b/project/images/tati_050324a.webp differ diff --git a/project/images/tati_050324y.webp b/project/images/tati_050324y.webp new file mode 100644 index 0000000..2e579cc Binary files /dev/null and b/project/images/tati_050324y.webp differ diff --git a/project/images/tati_050325.webp b/project/images/tati_050325.webp new file mode 100644 index 0000000..47ef3fb Binary files /dev/null and b/project/images/tati_050325.webp differ diff --git a/project/images/tati_050325a.webp b/project/images/tati_050325a.webp new file mode 100644 index 0000000..2f09eb1 Binary files /dev/null and b/project/images/tati_050325a.webp differ diff --git a/project/images/tati_050325y.webp b/project/images/tati_050325y.webp new file mode 100644 index 0000000..bd791d8 Binary files /dev/null and b/project/images/tati_050325y.webp differ diff --git a/project/images/tati_050326.webp b/project/images/tati_050326.webp new file mode 100644 index 0000000..0e866dc Binary files /dev/null and b/project/images/tati_050326.webp differ diff --git a/project/images/tati_050327.webp b/project/images/tati_050327.webp new file mode 100644 index 0000000..09dd7e9 Binary files /dev/null and b/project/images/tati_050327.webp differ diff --git a/project/images/tati_050327y.webp b/project/images/tati_050327y.webp new file mode 100644 index 0000000..837cbf5 Binary files /dev/null and b/project/images/tati_050327y.webp differ diff --git a/project/images/tati_050328.webp b/project/images/tati_050328.webp new file mode 100644 index 0000000..d8ad714 Binary files /dev/null and b/project/images/tati_050328.webp differ diff --git a/project/images/tati_050329.webp b/project/images/tati_050329.webp new file mode 100644 index 0000000..d8224a3 Binary files /dev/null and b/project/images/tati_050329.webp differ diff --git a/project/images/tati_050331.webp b/project/images/tati_050331.webp new file mode 100644 index 0000000..6a571cf Binary files /dev/null and b/project/images/tati_050331.webp differ diff --git a/project/images/tati_050331y.webp b/project/images/tati_050331y.webp new file mode 100644 index 0000000..86ccedd Binary files /dev/null and b/project/images/tati_050331y.webp differ diff --git a/project/images/tati_050332.webp b/project/images/tati_050332.webp new file mode 100644 index 0000000..f9b0ae2 Binary files /dev/null and b/project/images/tati_050332.webp differ diff --git a/project/images/tati_050333.webp b/project/images/tati_050333.webp new file mode 100644 index 0000000..0134380 Binary files /dev/null and b/project/images/tati_050333.webp differ diff --git a/project/images/tati_050334.webp b/project/images/tati_050334.webp new file mode 100644 index 0000000..2c6a11d Binary files /dev/null and b/project/images/tati_050334.webp differ diff --git a/project/images/tati_050334a.webp b/project/images/tati_050334a.webp new file mode 100644 index 0000000..11c3544 Binary files /dev/null and b/project/images/tati_050334a.webp differ diff --git a/project/images/tati_050335.webp b/project/images/tati_050335.webp new file mode 100644 index 0000000..f92b052 Binary files /dev/null and b/project/images/tati_050335.webp differ diff --git a/project/images/tati_050337.webp b/project/images/tati_050337.webp new file mode 100644 index 0000000..2a4e430 Binary files /dev/null and b/project/images/tati_050337.webp differ diff --git a/project/images/tati_050338.webp b/project/images/tati_050338.webp new file mode 100644 index 0000000..0497a5f Binary files /dev/null and b/project/images/tati_050338.webp differ diff --git a/project/images/tati_050338y.webp b/project/images/tati_050338y.webp new file mode 100644 index 0000000..076f83c Binary files /dev/null and b/project/images/tati_050338y.webp differ diff --git a/project/images/tati_050341.webp b/project/images/tati_050341.webp new file mode 100644 index 0000000..04d340e Binary files /dev/null and b/project/images/tati_050341.webp differ diff --git a/project/images/tati_050341a.webp b/project/images/tati_050341a.webp new file mode 100644 index 0000000..875a3f9 Binary files /dev/null and b/project/images/tati_050341a.webp differ diff --git a/project/images/tati_050341y.webp b/project/images/tati_050341y.webp new file mode 100644 index 0000000..72dba58 Binary files /dev/null and b/project/images/tati_050341y.webp differ diff --git a/project/images/tati_050342.webp b/project/images/tati_050342.webp new file mode 100644 index 0000000..62510c3 Binary files /dev/null and b/project/images/tati_050342.webp differ diff --git a/project/images/tati_050343.webp b/project/images/tati_050343.webp new file mode 100644 index 0000000..5a281c6 Binary files /dev/null and b/project/images/tati_050343.webp differ diff --git a/project/images/tati_050343y.webp b/project/images/tati_050343y.webp new file mode 100644 index 0000000..0604b3f Binary files /dev/null and b/project/images/tati_050343y.webp differ diff --git a/project/images/tati_050344.webp b/project/images/tati_050344.webp new file mode 100644 index 0000000..07ad5a8 Binary files /dev/null and b/project/images/tati_050344.webp differ diff --git a/project/images/tati_050345.webp b/project/images/tati_050345.webp new file mode 100644 index 0000000..a54aecf Binary files /dev/null and b/project/images/tati_050345.webp differ diff --git a/project/images/tati_050345a.webp b/project/images/tati_050345a.webp new file mode 100644 index 0000000..2242854 Binary files /dev/null and b/project/images/tati_050345a.webp differ diff --git a/project/images/tati_050345y.webp b/project/images/tati_050345y.webp new file mode 100644 index 0000000..6df2797 Binary files /dev/null and b/project/images/tati_050345y.webp differ diff --git a/project/images/tati_050346.webp b/project/images/tati_050346.webp new file mode 100644 index 0000000..cbb5b61 Binary files /dev/null and b/project/images/tati_050346.webp differ diff --git a/project/images/tati_050347.webp b/project/images/tati_050347.webp new file mode 100644 index 0000000..4f8265f Binary files /dev/null and b/project/images/tati_050347.webp differ diff --git a/project/images/tati_050348.webp b/project/images/tati_050348.webp new file mode 100644 index 0000000..8ffccb9 Binary files /dev/null and b/project/images/tati_050348.webp differ diff --git a/project/images/tati_050349.webp b/project/images/tati_050349.webp new file mode 100644 index 0000000..3ac485f Binary files /dev/null and b/project/images/tati_050349.webp differ diff --git a/project/images/tati_050351.webp b/project/images/tati_050351.webp new file mode 100644 index 0000000..7b70249 Binary files /dev/null and b/project/images/tati_050351.webp differ diff --git a/project/images/tati_050351y.webp b/project/images/tati_050351y.webp new file mode 100644 index 0000000..d2a0b93 Binary files /dev/null and b/project/images/tati_050351y.webp differ diff --git a/project/images/tati_050352.webp b/project/images/tati_050352.webp new file mode 100644 index 0000000..018c49d Binary files /dev/null and b/project/images/tati_050352.webp differ diff --git a/project/images/tati_050353.webp b/project/images/tati_050353.webp new file mode 100644 index 0000000..0f17f24 Binary files /dev/null and b/project/images/tati_050353.webp differ diff --git a/project/images/tati_050353y.webp b/project/images/tati_050353y.webp new file mode 100644 index 0000000..c422640 Binary files /dev/null and b/project/images/tati_050353y.webp differ diff --git a/project/images/tati_050441.webp b/project/images/tati_050441.webp new file mode 100644 index 0000000..2e7df0f Binary files /dev/null and b/project/images/tati_050441.webp differ diff --git a/project/images/tati_050443.webp b/project/images/tati_050443.webp new file mode 100644 index 0000000..a4189d0 Binary files /dev/null and b/project/images/tati_050443.webp differ diff --git a/project/images/tati_050443y.webp b/project/images/tati_050443y.webp new file mode 100644 index 0000000..4273394 Binary files /dev/null and b/project/images/tati_050443y.webp differ diff --git a/project/images/tati_050445.webp b/project/images/tati_050445.webp new file mode 100644 index 0000000..1a0313e Binary files /dev/null and b/project/images/tati_050445.webp differ diff --git a/project/images/tati_050445a.webp b/project/images/tati_050445a.webp new file mode 100644 index 0000000..a3e4da3 Binary files /dev/null and b/project/images/tati_050445a.webp differ diff --git a/project/images/tati_050445y.webp b/project/images/tati_050445y.webp new file mode 100644 index 0000000..99c60db Binary files /dev/null and b/project/images/tati_050445y.webp differ diff --git a/project/images/tati_050451.webp b/project/images/tati_050451.webp new file mode 100644 index 0000000..6020b87 Binary files /dev/null and b/project/images/tati_050451.webp differ diff --git a/project/images/tati_050451a.webp b/project/images/tati_050451a.webp new file mode 100644 index 0000000..9d970c7 Binary files /dev/null and b/project/images/tati_050451a.webp differ diff --git a/project/images/tati_050452.webp b/project/images/tati_050452.webp new file mode 100644 index 0000000..315d2cb Binary files /dev/null and b/project/images/tati_050452.webp differ diff --git a/project/images/tati_050452y.webp b/project/images/tati_050452y.webp new file mode 100644 index 0000000..6718c6d Binary files /dev/null and b/project/images/tati_050452y.webp differ diff --git a/project/images/tati_120101.webp b/project/images/tati_120101.webp new file mode 100644 index 0000000..b029f25 Binary files /dev/null and b/project/images/tati_120101.webp differ diff --git a/project/images/tati_120101y.webp b/project/images/tati_120101y.webp new file mode 100644 index 0000000..7e62b74 Binary files /dev/null and b/project/images/tati_120101y.webp differ diff --git a/project/images/tati_120102.webp b/project/images/tati_120102.webp new file mode 100644 index 0000000..15fb1ca Binary files /dev/null and b/project/images/tati_120102.webp differ diff --git a/project/images/tati_120102y.webp b/project/images/tati_120102y.webp new file mode 100644 index 0000000..57ea32c Binary files /dev/null and b/project/images/tati_120102y.webp differ diff --git a/project/images/tati_120103.webp b/project/images/tati_120103.webp new file mode 100644 index 0000000..1352df3 Binary files /dev/null and b/project/images/tati_120103.webp differ diff --git a/project/images/tati_120103y.webp b/project/images/tati_120103y.webp new file mode 100644 index 0000000..9af9fc8 Binary files /dev/null and b/project/images/tati_120103y.webp differ diff --git a/project/images/tati_120104.webp b/project/images/tati_120104.webp new file mode 100644 index 0000000..1435e70 Binary files /dev/null and b/project/images/tati_120104.webp differ diff --git a/project/images/tati_120104y.webp b/project/images/tati_120104y.webp new file mode 100644 index 0000000..112259f Binary files /dev/null and b/project/images/tati_120104y.webp differ diff --git a/project/images/tati_120105.webp b/project/images/tati_120105.webp new file mode 100644 index 0000000..40980f7 Binary files /dev/null and b/project/images/tati_120105.webp differ diff --git a/project/images/tati_120105y.webp b/project/images/tati_120105y.webp new file mode 100644 index 0000000..100d3f1 Binary files /dev/null and b/project/images/tati_120105y.webp differ diff --git a/project/images/tati_120106.webp b/project/images/tati_120106.webp new file mode 100644 index 0000000..d9f065d Binary files /dev/null and b/project/images/tati_120106.webp differ diff --git a/project/images/tati_120107.webp b/project/images/tati_120107.webp new file mode 100644 index 0000000..ac25b28 Binary files /dev/null and b/project/images/tati_120107.webp differ diff --git a/project/images/tati_120107y.webp b/project/images/tati_120107y.webp new file mode 100644 index 0000000..baf03db Binary files /dev/null and b/project/images/tati_120107y.webp differ diff --git a/project/images/tati_120108.webp b/project/images/tati_120108.webp new file mode 100644 index 0000000..e33b955 Binary files /dev/null and b/project/images/tati_120108.webp differ diff --git a/project/images/tati_120111.webp b/project/images/tati_120111.webp new file mode 100644 index 0000000..18fcb9f Binary files /dev/null and b/project/images/tati_120111.webp differ diff --git a/project/images/tati_120111y.webp b/project/images/tati_120111y.webp new file mode 100644 index 0000000..8d69d91 Binary files /dev/null and b/project/images/tati_120111y.webp differ diff --git a/project/images/tati_120112.webp b/project/images/tati_120112.webp new file mode 100644 index 0000000..6c662fd Binary files /dev/null and b/project/images/tati_120112.webp differ diff --git a/project/images/tati_120113.webp b/project/images/tati_120113.webp new file mode 100644 index 0000000..01e30af Binary files /dev/null and b/project/images/tati_120113.webp differ diff --git a/project/images/tati_120113y.webp b/project/images/tati_120113y.webp new file mode 100644 index 0000000..e91fd21 Binary files /dev/null and b/project/images/tati_120113y.webp differ diff --git a/project/images/tati_120121.webp b/project/images/tati_120121.webp new file mode 100644 index 0000000..d0ddee1 Binary files /dev/null and b/project/images/tati_120121.webp differ diff --git a/project/images/tati_120121y.webp b/project/images/tati_120121y.webp new file mode 100644 index 0000000..7b2d0e5 Binary files /dev/null and b/project/images/tati_120121y.webp differ diff --git a/project/images/tati_120122.webp b/project/images/tati_120122.webp new file mode 100644 index 0000000..3207f82 Binary files /dev/null and b/project/images/tati_120122.webp differ diff --git a/project/images/tati_120123.webp b/project/images/tati_120123.webp new file mode 100644 index 0000000..7d3d768 Binary files /dev/null and b/project/images/tati_120123.webp differ diff --git a/project/images/tati_120123y.webp b/project/images/tati_120123y.webp new file mode 100644 index 0000000..5b7df9e Binary files /dev/null and b/project/images/tati_120123y.webp differ diff --git a/project/images/tati_120125.webp b/project/images/tati_120125.webp new file mode 100644 index 0000000..8cfd59c Binary files /dev/null and b/project/images/tati_120125.webp differ diff --git a/project/images/tati_120125y.webp b/project/images/tati_120125y.webp new file mode 100644 index 0000000..e7e2fe9 Binary files /dev/null and b/project/images/tati_120125y.webp differ diff --git a/project/images/tati_120126.webp b/project/images/tati_120126.webp new file mode 100644 index 0000000..3e0f874 Binary files /dev/null and b/project/images/tati_120126.webp differ diff --git a/project/images/tati_120127.webp b/project/images/tati_120127.webp new file mode 100644 index 0000000..c010e67 Binary files /dev/null and b/project/images/tati_120127.webp differ diff --git a/project/images/tati_120127y.webp b/project/images/tati_120127y.webp new file mode 100644 index 0000000..020fcf8 Binary files /dev/null and b/project/images/tati_120127y.webp differ diff --git a/project/images/tati_120128.webp b/project/images/tati_120128.webp new file mode 100644 index 0000000..f1de7ab Binary files /dev/null and b/project/images/tati_120128.webp differ diff --git a/project/images/tati_120131.webp b/project/images/tati_120131.webp new file mode 100644 index 0000000..9e88925 Binary files /dev/null and b/project/images/tati_120131.webp differ diff --git a/project/images/tati_120132.webp b/project/images/tati_120132.webp new file mode 100644 index 0000000..f67a394 Binary files /dev/null and b/project/images/tati_120132.webp differ diff --git a/project/images/tati_340101.webp b/project/images/tati_340101.webp new file mode 100644 index 0000000..96724ce Binary files /dev/null and b/project/images/tati_340101.webp differ diff --git a/project/images/tati_340101a.webp b/project/images/tati_340101a.webp new file mode 100644 index 0000000..add8ba2 Binary files /dev/null and b/project/images/tati_340101a.webp differ diff --git a/project/images/tati_340101y.webp b/project/images/tati_340101y.webp new file mode 100644 index 0000000..bb04825 Binary files /dev/null and b/project/images/tati_340101y.webp differ diff --git a/project/images/tati_340102.webp b/project/images/tati_340102.webp new file mode 100644 index 0000000..769f51b Binary files /dev/null and b/project/images/tati_340102.webp differ diff --git a/project/images/tati_340102y.webp b/project/images/tati_340102y.webp new file mode 100644 index 0000000..7b6d59e Binary files /dev/null and b/project/images/tati_340102y.webp differ diff --git a/project/images/tati_340103.webp b/project/images/tati_340103.webp new file mode 100644 index 0000000..2a383eb Binary files /dev/null and b/project/images/tati_340103.webp differ diff --git a/project/images/tati_340103y.webp b/project/images/tati_340103y.webp new file mode 100644 index 0000000..6145491 Binary files /dev/null and b/project/images/tati_340103y.webp differ diff --git a/project/images/tati_340104.webp b/project/images/tati_340104.webp new file mode 100644 index 0000000..9728246 Binary files /dev/null and b/project/images/tati_340104.webp differ diff --git a/project/images/tati_340104y.webp b/project/images/tati_340104y.webp new file mode 100644 index 0000000..5482404 Binary files /dev/null and b/project/images/tati_340104y.webp differ diff --git a/project/images/tati_340105.webp b/project/images/tati_340105.webp new file mode 100644 index 0000000..dd76fb8 Binary files /dev/null and b/project/images/tati_340105.webp differ diff --git a/project/images/tati_340105a.webp b/project/images/tati_340105a.webp new file mode 100644 index 0000000..681610a Binary files /dev/null and b/project/images/tati_340105a.webp differ diff --git a/project/images/tati_340105y.webp b/project/images/tati_340105y.webp new file mode 100644 index 0000000..bad076a Binary files /dev/null and b/project/images/tati_340105y.webp differ diff --git a/project/images/tati_340106.webp b/project/images/tati_340106.webp new file mode 100644 index 0000000..4be5842 Binary files /dev/null and b/project/images/tati_340106.webp differ diff --git a/project/images/tati_340106y.webp b/project/images/tati_340106y.webp new file mode 100644 index 0000000..d9b8110 Binary files /dev/null and b/project/images/tati_340106y.webp differ diff --git a/project/images/tati_340107.webp b/project/images/tati_340107.webp new file mode 100644 index 0000000..6923456 Binary files /dev/null and b/project/images/tati_340107.webp differ diff --git a/project/images/tati_340107y.webp b/project/images/tati_340107y.webp new file mode 100644 index 0000000..05fb151 Binary files /dev/null and b/project/images/tati_340107y.webp differ diff --git a/project/images/tati_340108.webp b/project/images/tati_340108.webp new file mode 100644 index 0000000..46e1ce1 Binary files /dev/null and b/project/images/tati_340108.webp differ diff --git a/project/images/tati_340108y.webp b/project/images/tati_340108y.webp new file mode 100644 index 0000000..a5faccc Binary files /dev/null and b/project/images/tati_340108y.webp differ diff --git a/project/images/tati_340109.webp b/project/images/tati_340109.webp new file mode 100644 index 0000000..7929c9a Binary files /dev/null and b/project/images/tati_340109.webp differ diff --git a/project/images/tati_340109y.webp b/project/images/tati_340109y.webp new file mode 100644 index 0000000..90a58f3 Binary files /dev/null and b/project/images/tati_340109y.webp differ diff --git a/project/images/tati_340110.webp b/project/images/tati_340110.webp new file mode 100644 index 0000000..bc4d976 Binary files /dev/null and b/project/images/tati_340110.webp differ diff --git a/project/images/tati_340110y.webp b/project/images/tati_340110y.webp new file mode 100644 index 0000000..20491bf Binary files /dev/null and b/project/images/tati_340110y.webp differ diff --git a/project/images/tati_340111.webp b/project/images/tati_340111.webp new file mode 100644 index 0000000..e8d251d Binary files /dev/null and b/project/images/tati_340111.webp differ diff --git a/project/images/tati_340111y.webp b/project/images/tati_340111y.webp new file mode 100644 index 0000000..1681178 Binary files /dev/null and b/project/images/tati_340111y.webp differ diff --git a/project/images/tati_340112.webp b/project/images/tati_340112.webp new file mode 100644 index 0000000..2786dcc Binary files /dev/null and b/project/images/tati_340112.webp differ diff --git a/project/images/tati_340112a.webp b/project/images/tati_340112a.webp new file mode 100644 index 0000000..37a492c Binary files /dev/null and b/project/images/tati_340112a.webp differ diff --git a/project/images/tati_340112y.webp b/project/images/tati_340112y.webp new file mode 100644 index 0000000..f20b1e4 Binary files /dev/null and b/project/images/tati_340112y.webp differ diff --git a/project/images/tati_340113.webp b/project/images/tati_340113.webp new file mode 100644 index 0000000..08b5954 Binary files /dev/null and b/project/images/tati_340113.webp differ diff --git a/project/images/tati_340113y.webp b/project/images/tati_340113y.webp new file mode 100644 index 0000000..0316326 Binary files /dev/null and b/project/images/tati_340113y.webp differ diff --git a/project/images/tati_340114.webp b/project/images/tati_340114.webp new file mode 100644 index 0000000..3f7da16 Binary files /dev/null and b/project/images/tati_340114.webp differ diff --git a/project/images/tati_340114y.webp b/project/images/tati_340114y.webp new file mode 100644 index 0000000..ee21221 Binary files /dev/null and b/project/images/tati_340114y.webp differ diff --git a/project/images/tati_340115.webp b/project/images/tati_340115.webp new file mode 100644 index 0000000..f8cd30d Binary files /dev/null and b/project/images/tati_340115.webp differ diff --git a/project/images/tati_430101.webp b/project/images/tati_430101.webp new file mode 100644 index 0000000..82d2e68 Binary files /dev/null and b/project/images/tati_430101.webp differ diff --git a/project/images/tati_430101a.webp b/project/images/tati_430101a.webp new file mode 100644 index 0000000..153d99f Binary files /dev/null and b/project/images/tati_430101a.webp differ diff --git a/project/images/tati_430101y.webp b/project/images/tati_430101y.webp new file mode 100644 index 0000000..fa51d26 Binary files /dev/null and b/project/images/tati_430101y.webp differ diff --git a/project/images/tati_430102.webp b/project/images/tati_430102.webp new file mode 100644 index 0000000..428e27f Binary files /dev/null and b/project/images/tati_430102.webp differ diff --git a/project/images/tati_430102a.webp b/project/images/tati_430102a.webp new file mode 100644 index 0000000..045891a Binary files /dev/null and b/project/images/tati_430102a.webp differ diff --git a/project/images/tati_430102y.webp b/project/images/tati_430102y.webp new file mode 100644 index 0000000..7f0c790 Binary files /dev/null and b/project/images/tati_430102y.webp differ diff --git a/project/images/tati_430103.webp b/project/images/tati_430103.webp new file mode 100644 index 0000000..3328371 Binary files /dev/null and b/project/images/tati_430103.webp differ diff --git a/project/images/tati_430103a.webp b/project/images/tati_430103a.webp new file mode 100644 index 0000000..5954ed6 Binary files /dev/null and b/project/images/tati_430103a.webp differ diff --git a/project/images/tati_430103y.webp b/project/images/tati_430103y.webp new file mode 100644 index 0000000..852203c Binary files /dev/null and b/project/images/tati_430103y.webp differ diff --git a/project/images/tati_430104.webp b/project/images/tati_430104.webp new file mode 100644 index 0000000..63618c6 Binary files /dev/null and b/project/images/tati_430104.webp differ diff --git a/project/images/tati_430105.webp b/project/images/tati_430105.webp new file mode 100644 index 0000000..3b913ca Binary files /dev/null and b/project/images/tati_430105.webp differ diff --git a/project/images/tati_430105a.webp b/project/images/tati_430105a.webp new file mode 100644 index 0000000..62279c2 Binary files /dev/null and b/project/images/tati_430105a.webp differ diff --git a/project/images/tati_430105y.webp b/project/images/tati_430105y.webp new file mode 100644 index 0000000..d2c47f7 Binary files /dev/null and b/project/images/tati_430105y.webp differ diff --git a/project/images/tati_430106.webp b/project/images/tati_430106.webp new file mode 100644 index 0000000..38e047f Binary files /dev/null and b/project/images/tati_430106.webp differ diff --git a/project/images/tati_430106a.webp b/project/images/tati_430106a.webp new file mode 100644 index 0000000..a448e29 Binary files /dev/null and b/project/images/tati_430106a.webp differ diff --git a/project/images/tati_430106y.webp b/project/images/tati_430106y.webp new file mode 100644 index 0000000..3fb8ee5 Binary files /dev/null and b/project/images/tati_430106y.webp differ diff --git a/project/images/tati_430107.webp b/project/images/tati_430107.webp new file mode 100644 index 0000000..5ee8605 Binary files /dev/null and b/project/images/tati_430107.webp differ diff --git a/project/images/tati_430107y.webp b/project/images/tati_430107y.webp new file mode 100644 index 0000000..d8dd713 Binary files /dev/null and b/project/images/tati_430107y.webp differ diff --git a/project/images/tati_430108.webp b/project/images/tati_430108.webp new file mode 100644 index 0000000..088b83f Binary files /dev/null and b/project/images/tati_430108.webp differ diff --git a/project/images/tati_430108a.webp b/project/images/tati_430108a.webp new file mode 100644 index 0000000..5699299 Binary files /dev/null and b/project/images/tati_430108a.webp differ diff --git a/project/images/tati_430108y.webp b/project/images/tati_430108y.webp new file mode 100644 index 0000000..a2a6fc4 Binary files /dev/null and b/project/images/tati_430108y.webp differ diff --git a/project/images/tati_440101.webp b/project/images/tati_440101.webp new file mode 100644 index 0000000..13b1e48 Binary files /dev/null and b/project/images/tati_440101.webp differ diff --git a/project/images/tati_440101y.webp b/project/images/tati_440101y.webp new file mode 100644 index 0000000..2b632ae Binary files /dev/null and b/project/images/tati_440101y.webp differ diff --git a/project/images/tati_440103.webp b/project/images/tati_440103.webp new file mode 100644 index 0000000..5e96a78 Binary files /dev/null and b/project/images/tati_440103.webp differ diff --git a/project/images/tati_440104.webp b/project/images/tati_440104.webp new file mode 100644 index 0000000..0953eba Binary files /dev/null and b/project/images/tati_440104.webp differ diff --git a/project/images/tati_440105.webp b/project/images/tati_440105.webp new file mode 100644 index 0000000..abbd82e Binary files /dev/null and b/project/images/tati_440105.webp differ diff --git a/project/images/tati_440106.webp b/project/images/tati_440106.webp new file mode 100644 index 0000000..e8fe7e5 Binary files /dev/null and b/project/images/tati_440106.webp differ diff --git a/project/images/tati_440108.webp b/project/images/tati_440108.webp new file mode 100644 index 0000000..412223f Binary files /dev/null and b/project/images/tati_440108.webp differ diff --git a/project/images/tati_z340101.webp b/project/images/tati_z340101.webp new file mode 100644 index 0000000..5387c08 Binary files /dev/null and b/project/images/tati_z340101.webp differ diff --git a/project/images/tati_z340102.webp b/project/images/tati_z340102.webp new file mode 100644 index 0000000..e3db89f Binary files /dev/null and b/project/images/tati_z340102.webp differ diff --git a/project/images/tati_z340103.webp b/project/images/tati_z340103.webp new file mode 100644 index 0000000..1850508 Binary files /dev/null and b/project/images/tati_z340103.webp differ diff --git a/project/images/tati_z340104.webp b/project/images/tati_z340104.webp new file mode 100644 index 0000000..1300940 Binary files /dev/null and b/project/images/tati_z340104.webp differ diff --git a/project/images/tati_z340105.webp b/project/images/tati_z340105.webp new file mode 100644 index 0000000..505a09c Binary files /dev/null and b/project/images/tati_z340105.webp differ diff --git a/project/images/tati_z340106.webp b/project/images/tati_z340106.webp new file mode 100644 index 0000000..0911177 Binary files /dev/null and b/project/images/tati_z340106.webp differ diff --git a/project/images/tati_z340107.webp b/project/images/tati_z340107.webp new file mode 100644 index 0000000..2241f44 Binary files /dev/null and b/project/images/tati_z340107.webp differ diff --git a/project/images/tati_z340108.webp b/project/images/tati_z340108.webp new file mode 100644 index 0000000..f4c6f2b Binary files /dev/null and b/project/images/tati_z340108.webp differ diff --git a/project/images/tati_z340109.webp b/project/images/tati_z340109.webp new file mode 100644 index 0000000..7e836f5 Binary files /dev/null and b/project/images/tati_z340109.webp differ diff --git a/project/images/tati_z340110.webp b/project/images/tati_z340110.webp new file mode 100644 index 0000000..61c5610 Binary files /dev/null and b/project/images/tati_z340110.webp differ diff --git a/project/images/tati_z340111.webp b/project/images/tati_z340111.webp new file mode 100644 index 0000000..e7b3efd Binary files /dev/null and b/project/images/tati_z340111.webp differ diff --git a/project/images/tati_z340112.webp b/project/images/tati_z340112.webp new file mode 100644 index 0000000..c46c0c0 Binary files /dev/null and b/project/images/tati_z340112.webp differ diff --git a/project/images/tati_z340113.webp b/project/images/tati_z340113.webp new file mode 100644 index 0000000..2284cda Binary files /dev/null and b/project/images/tati_z340113.webp differ diff --git a/project/images/tati_z340114.webp b/project/images/tati_z340114.webp new file mode 100644 index 0000000..1c1f0dc Binary files /dev/null and b/project/images/tati_z340114.webp differ diff --git a/project/images/tati_z340115.webp b/project/images/tati_z340115.webp new file mode 100644 index 0000000..9a1621c Binary files /dev/null and b/project/images/tati_z340115.webp differ diff --git a/project/items.js b/project/items.js index 05dcc9c..fddc8ac 100644 --- a/project/items.js +++ b/project/items.js @@ -146,7 +146,7 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a = "sword1": { "cls": "equips", "name": "铁剑", - "text": "一把很普通的铁剑", + "text": "一把普通的铁剑", "equip": { "type": 0, "animate": "sword", @@ -224,17 +224,22 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a = "equipCls": "匕首" }, "shield0": { - "cls": "items", + "cls": "equips", "name": "破旧的盾", "text": "一个很破旧的铁盾", "equip": { - "type": 1, + "type": 2, "value": { - "def": 0 + "mdef": -5, + "def": 10 + }, + "percentage": { + "def": 10 } }, "itemEffect": "core.status.hero.def += 0", - "itemEffectTip": ",防御+0" + "itemEffectTip": ",防御+0", + "equipCls": "护具" }, "shield1": { "cls": "equips", diff --git a/project/maps.js b/project/maps.js index 6367155..fc722c6 100644 --- a/project/maps.js +++ b/project/maps.js @@ -1,11 +1,11 @@ var maps_90f36752_8815_4be8_b32b_d7fad1d0542e = { - "1": {"cls":"animates","id":"yellowWall","canBreak":true,"animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.mp3","keys":{}}}, - "2": {"cls":"animates","id":"whiteWall","canBreak":true,"animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.mp3","keys":{}}}, - "3": {"cls":"animates","id":"blueWall","canBreak":true,"animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.mp3","keys":{}}}, + "1": {"cls":"animates","id":"yellowWall","canBreak":true,"animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.opus","keys":{}}}, + "2": {"cls":"animates","id":"whiteWall","canBreak":true,"animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.opus","keys":{}}}, + "3": {"cls":"animates","id":"blueWall","canBreak":true,"animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.opus","keys":{}}}, "4": {"cls":"animates","id":"star","name":"星空"}, "5": {"cls":"animates","id":"lava","name":"岩浆"}, - "6": {"cls":"animates","id":"ice","doorInfo":{"time":160,"openSound":"破冰镐","closeSound":"door.mp3","keys":{"icePickaxe":1}},"animate":1}, + "6": {"cls":"animates","id":"ice","doorInfo":{"time":160,"openSound":"破冰镐","closeSound":"door.opus","keys":{"icePickaxe":1}},"animate":1}, "7": {"cls":"terrains","id":"blueShopLeft"}, "8": {"cls":"terrains","id":"blueShopRight"}, "9": {"cls":"terrains","id":"pinkShopLeft"}, @@ -68,12 +68,12 @@ var maps_90f36752_8815_4be8_b32b_d7fad1d0542e = "71": {"cls":"items","id":"shield0"}, "72": {"cls":"items","id":"skill1"}, "73": {"cls":"items","id":"wand"}, - "81": {"cls":"animates","id":"yellowDoor","trigger":"openDoor","animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.mp3","keys":{"yellowKey":1}},"name":"黄门"}, - "82": {"cls":"animates","id":"blueDoor","trigger":"openDoor","animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.mp3","keys":{"blueKey":1}},"name":"蓝门"}, - "83": {"cls":"animates","id":"redDoor","trigger":"openDoor","animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.mp3","keys":{"redKey":1}},"name":"红门"}, - "84": {"cls":"animates","id":"greenDoor","trigger":"openDoor","animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.mp3","keys":{"greenKey":1}},"name":"绿门"}, - "85": {"cls":"animates","id":"specialDoor","trigger":"openDoor","animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.mp3","keys":{"specialKey":1}},"name":"机关门"}, - "86": {"cls":"animates","id":"steelDoor","trigger":"openDoor","animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.mp3","keys":{"steelKey":1}},"name":"铁门"}, + "81": {"cls":"animates","id":"yellowDoor","trigger":"openDoor","animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.opus","keys":{"yellowKey":1}},"name":"黄门"}, + "82": {"cls":"animates","id":"blueDoor","trigger":"openDoor","animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.opus","keys":{"blueKey":1}},"name":"蓝门"}, + "83": {"cls":"animates","id":"redDoor","trigger":"openDoor","animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.opus","keys":{"redKey":1}},"name":"红门"}, + "84": {"cls":"animates","id":"greenDoor","trigger":"openDoor","animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.opus","keys":{"greenKey":1}},"name":"绿门"}, + "85": {"cls":"animates","id":"specialDoor","trigger":"openDoor","animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.opus","keys":{"specialKey":1}},"name":"机关门"}, + "86": {"cls":"animates","id":"steelDoor","trigger":"openDoor","animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.opus","keys":{"steelKey":1}},"name":"铁门"}, "87": {"cls":"terrains","id":"upFloor","canPass":true}, "88": {"cls":"terrains","id":"downFloor","canPass":true}, "89": {"cls":"animates","id":"portal","canPass":true}, @@ -86,7 +86,7 @@ var maps_90f36752_8815_4be8_b32b_d7fad1d0542e = "102": {"cls":"animates","id":"crystalBottom"}, "103": {"cls":"animates","id":"fire"}, "104": {"cls":"animates","id":"switch"}, - "109": {"cls":"animates","id":"magentaWall","canBreak":true,"animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.mp3","keys":{}}}, + "109": {"cls":"animates","id":"magentaWall","canBreak":true,"animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.opus","keys":{}}}, "121": {"cls":"npcs","id":"man"}, "122": {"cls":"npcs","id":"trader"}, "123": {"cls":"npcs","id":"thief"}, @@ -217,12 +217,12 @@ var maps_90f36752_8815_4be8_b32b_d7fad1d0542e = "316": {"cls":"terrains","id":"sWallTLR","name":"薄墙-上左右","cannotOut":["up","left","right"],"cannotIn":["up","left","right"]}, "317": {"cls":"terrains","id":"sWallTBR","name":"薄墙-上下右","cannotOut":["up","down","right"],"cannotIn":["up","down","right"]}, "318": {"cls":"terrains","id":"sWallTBL","name":"薄墙-上下左","cannotOut":["up","down","left"],"cannotIn":["up","down","left"]}, - "319": {"cls":"npc48","id":"tallYellowDoor","trigger":"openDoor","name":"高黄门","animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.mp3","keys":{"yellowKey":1}}}, - "320": {"cls":"npc48","id":"tallBlueDoor","trigger":"openDoor","name":"高蓝门","animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.mp3","keys":{"blueKey":1}}}, - "321": {"cls":"npc48","id":"tallRedDoor","trigger":"openDoor","name":"高红门","animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.mp3","keys":{"redKey":1}}}, - "322": {"cls":"npc48","id":"tallGreenDoor","trigger":"openDoor","name":"高绿门","animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.mp3","keys":{"greenKey":1}}}, - "323": {"cls":"npc48","id":"tallSpecialDoor","trigger":"openDoor","name":"高机关门","animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.mp3","keys":{"specialKey":1}}}, - "324": {"cls":"npc48","id":"tallSteelDoor","trigger":"openDoor","name":"高铁门","animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.mp3","keys":{"steelKey":1}}}, + "319": {"cls":"npc48","id":"tallYellowDoor","trigger":"openDoor","name":"高黄门","animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.opus","keys":{"yellowKey":1}}}, + "320": {"cls":"npc48","id":"tallBlueDoor","trigger":"openDoor","name":"高蓝门","animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.opus","keys":{"blueKey":1}}}, + "321": {"cls":"npc48","id":"tallRedDoor","trigger":"openDoor","name":"高红门","animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.opus","keys":{"redKey":1}}}, + "322": {"cls":"npc48","id":"tallGreenDoor","trigger":"openDoor","name":"高绿门","animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.opus","keys":{"greenKey":1}}}, + "323": {"cls":"npc48","id":"tallSpecialDoor","trigger":"openDoor","name":"高机关门","animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.opus","keys":{"specialKey":1}}}, + "324": {"cls":"npc48","id":"tallSteelDoor","trigger":"openDoor","name":"高铁门","animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.opus","keys":{"steelKey":1}}}, "325": {"cls":"enemys","id":"keiskeiFairy"}, "326": {"cls":"enemys","id":"tulipFairy"}, "327": {"cls":"enemy48","id":"bearDown"}, diff --git a/project/plugins.js b/project/plugins.js index b1bda83..cd0125a 100644 --- a/project/plugins.js +++ b/project/plugins.js @@ -1,214 +1,226 @@ -var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = -{ - "init": function () { - this._afterLoadResources = function () { - // 本函数将在所有资源加载完毕后,游戏开启前被执行 - core.ui.statusBar.init(); - core.registerEvent("changeMouse", function (data) { - if (!main.replayChecking && !core.isReplaying()) - core.changeMouse( - data.icon, - data.div, - data.translate[0], - data.translate[1], - data.scale[0], - data.scale[1], - data.angel, - data.px, - data.py - ); - core.doAction(); - }); - core.registerEvent("removeMouse", function (data) { - if (!main.replayChecking && !core.isReplaying()) - core.removeMouse(data.div); - core.doAction(); - }); - core.registerEvent("addPop", function (data) { - if (!main.replayChecking && !core.isReplaying()) { - data.value = core.replaceText(data.value); - core.addPop( - data.value, - data.px, - data.py, - data.color, - data.boldColor, - data.left, - data.jump, - data.time, - data.show, - data.font, - data.speed - ); - } - core.doAction(); - }); - core.registerEvent("drawWarning", function (data) { - if (!main.replayChecking && !core.isReplaying()) { - data.text = core.replaceText(data.text); - data.text2 = core.replaceText(data.text2); - core.drawWarning( - data.x, - data.y, - data.size, - data?.text, - data?.text2, - data?.warning - ); - setTimeout(() => core.doAction(), 3100); - } else { - core.doAction(); - } - }); - core.registerEvent("playStereo", function (data) { - if (!main.replayChecking && !core.isReplaying()) - core.playStereo(data.name, data.left, data.right, data.split); - core.doAction(); - }); - core.registerEvent("moveStereo", function (data) { - if (!main.replayChecking && !core.isReplaying()) { - const id = core.playStereo( - data.name, - data.left, - data.right, - data.split - ); - core.moveStereo(id, data.leftTo, data.rightTo, data.time); - } - core.doAction(); - }); - core.registerEvent("over", function (data) { - let image = data.image ?? ""; - let time = data.time ?? 3000; - let sound = data.sound ?? ""; - let textColor = data.textColor ?? "#FFFFFF"; - let boldColor = data.boldColor ?? "#000000"; - let font = data.font ?? "bold 48px Verdana"; - let text = data.text ?? ""; - let hidetime = data.hidetime ?? 100; - if (!main.replayChecking && !core.isReplaying()) { - core.over( - image, - data.memory, - time, - hidetime, - sound, - textColor, - boldColor, - font, - text - ); - } else { - core.doAction(); - } - }); - core.registerEvent("changebg", function (data) { - if (!main.replayChecking && !core.isReplaying()) { - core.changebg( - data.img1, - data.memory1, - data.img2, - data.memory2, - data.time, - data.style - ); - } else { - core.doAction(); - } - }); - core.registerEvent("overlist", function (data) { - if (!main.replayChecking && !core.isReplaying()) { - core.overlist( - data.image, - data.memory, - data.hidetime || 30, - data.list || [{ - text: "", - sound: "", - time: 50, - textColor: "#FFFFFF", - boldColor: "#000000", - font: "bold 48px Verdana", - frame: 0, - }, ] - ); - } else { - core.doAction(); - } - }); - core.registerEvent("op", function (data) { - if (!main.replayChecking && !core.isReplaying()) { - core.openvideo(); - } else { - core.doAction(); - } - }); - core.registerEvent("animationDrawable", function (data) { - if (!main.replayChecking && !core.isReplaying()) { - core.animationDrawable( - data.allFarme, - data.color, - data.globalAlpha, - data.imageList, - data.soundList - ); - } else { - core.doAction(); - } - }); - core.registerEvent("setanimate", function (data) { +var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = { + init: function () { + this._afterLoadResources = function () { + // 本函数将在所有资源加载完毕后,游戏开启前被执行 + core.ui.statusBar.init(); + core.registerEvent("changeMouse", function (data) { + if (!main.replayChecking && !core.isReplaying()) + core.changeMouse( + data.icon, + data.div, + data.translate[0], + data.translate[1], + data.scale[0], + data.scale[1], + data.angel, + data.px, + data.py + ); + core.doAction(); + }); + core.registerEvent("removeMouse", function (data) { + if (!main.replayChecking && !core.isReplaying()) + core.removeMouse(data.div); + core.doAction(); + }); + core.registerEvent("addPop", function (data) { + if (!main.replayChecking && !core.isReplaying()) { + data.value = core.replaceText(data.value); + core.addPop( + data.value, + data.px, + data.py, + data.color, + data.boldColor, + data.left, + data.jump, + data.time, + data.show, + data.font, + data.speed + ); + } + core.doAction(); + }); + core.registerEvent("drawWarning", function (data) { + if (!main.replayChecking && !core.isReplaying()) { + data.text = core.replaceText(data.text); + data.text2 = core.replaceText(data.text2); + core.drawWarning( + data.x, + data.y, + data.size, + data?.text, + data?.text2, + data?.warning + ); + setTimeout(() => core.doAction(), 3100); + } else { + core.doAction(); + } + }); + core.registerEvent("playStereo", function (data) { + if (!main.replayChecking && !core.isReplaying()) + core.playStereo(data.name, data.left, data.right, data.split); + core.doAction(); + }); + core.registerEvent("moveStereo", function (data) { + if (!main.replayChecking && !core.isReplaying()) { + const id = core.playStereo( + data.name, + data.left, + data.right, + data.split + ); + core.moveStereo(id, data.leftTo, data.rightTo, data.time); + } + core.doAction(); + }); + core.registerEvent("over", function (data) { + let image = data.image ?? ""; + let time = data.time ?? 3000; + let sound = data.sound ?? ""; + let textColor = data.textColor ?? "#FFFFFF"; + let boldColor = data.boldColor ?? "#000000"; + let font = data.font ?? "bold 48px Verdana"; + let text = data.text ?? ""; + let hidetime = data.hidetime ?? 100; + if (!main.replayChecking && !core.isReplaying()) { + core.over( + image, + data.memory, + time, + hidetime, + sound, + textColor, + boldColor, + font, + text + ); + } else { + core.doAction(); + } + }); + core.registerEvent("changebg", function (data) { + if (!main.replayChecking && !core.isReplaying()) { + core.changebg( + data.img1, + data.memory1, + data.img2, + data.memory2, + data.time, + data.style + ); + } else { + core.doAction(); + } + }); + core.registerEvent("overlist", function (data) { + if (!main.replayChecking && !core.isReplaying()) { + core.overlist( + data.image, + data.memory, + data.hidetime || 30, + data.list || [ + { + text: "", + sound: "", + time: 50, + textColor: "#FFFFFF", + boldColor: "#000000", + font: "bold 48px Verdana", + frame: 0, + }, + ] + ); + } else { + core.doAction(); + } + }); + core.registerEvent("op", function (data) { + if (!main.replayChecking && !core.isReplaying()) { + core.openvideo(); + } else { + core.doAction(); + } + }); + core.registerEvent("animationDrawable", function (data) { + if (!main.replayChecking && !core.isReplaying()) { + core.animationDrawable( + data.allFarme, + data.color, + data.globalAlpha, + data.imageList, + data.soundList + ); + } else { + core.doAction(); + } + }); + core.registerEvent("setanimate", function (data) { + data.px = data.px ?? 0; + data.py = data.py ?? 0; + core.setanimate( + data.name, + data.px, + data.py, + data.width, + data.height, + data.allFarme, + data.imageList, + data.soundList + ); + core.doAction(); + }); + core.registerEvent("clearanimate", function (data) { + core.plugin.playing.clear(); - data.px = data.px ?? 0; - data.py = data.py ?? 0; - core.setanimate(data.name, data.px, data.py, data.width, data.height, data.allFarme, data.imageList, data.soundList) - core.doAction(); - - - }); - core.registerEvent("clearanimate", function (data) { - core.plugin.playing.clear() - - core.doAction(); - - - }); - core.registerEvent("deleteanimate", function (data) { - core.deleteanimate(data.name) - core.doAction(); - }); - core.registerEvent("playanimate", function (data) { - if (!main.replayChecking && !core.isReplaying()) { - data.x = data.x ?? 0 - data.y = data.y ?? 0 - data.scalex = data.scalex ?? 1 - data.scaley = data.scaley ?? 1 - core.playanimate(data.name, data.x, data.y, data.hero, data.scalex, data.scaley) - core.doAction(); - } else { - core.doAction(); - } - }); - core.registerEvent("cgtext", function (data) { - if (!main.replayChecking && !core.isReplaying()) { - core.ui.cgText.image = data.bg; - core.ui.cgText.memory = data.memory; - core.ui.cgText.head = core.clone(data.head); - core.ui.cgText.name = data.name; - core.ui.cgText.text = data.text; - 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.bodyList = core.clone(data.bodyList); - main.dom.cgText.style.display = "block"; - core.ui.cgText.update(); - } else { - core.doAction(); - } - }); - }; -}, - "drawLight": function () { + core.doAction(); + }); + core.registerEvent("deleteanimate", function (data) { + core.deleteanimate(data.name); + core.doAction(); + }); + core.registerEvent("playanimate", function (data) { + if (!main.replayChecking && !core.isReplaying()) { + data.x = data.x ?? 0; + data.y = data.y ?? 0; + data.scalex = data.scalex ?? 1; + data.scaley = data.scaley ?? 1; + core.playanimate( + data.name, + data.x, + data.y, + data.hero, + data.scalex, + data.scaley + ); + core.doAction(); + } else { + core.doAction(); + } + }); + core.registerEvent("cgtext", function (data) { + if (!main.replayChecking && !core.isReplaying()) { + core.ui.cgText.image = data.bg; + core.ui.cgText.memory = data.memory; + core.ui.cgText.head = core.clone(data.head); + core.ui.cgText.name = data.name; + core.ui.cgText.text = data.text; + 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.bodyList = core.clone(data.bodyList); + main.dom.cgText.style.display = "block"; + core.ui.cgText.update(); + } else { + core.doAction(); + } + }); + }; + }, + drawLight: function () { // 绘制灯光/漆黑层效果。调用方式 core.plugin.drawLight(...) // 【参数说明】 // name:必填,要绘制到的画布名;可以是一个系统画布,或者是个自定义画布;如果不存在则创建 @@ -274,7 +286,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = // 可以在任何地方(如afterXXX或自定义脚本事件)调用函数,方法为 core.plugin.xxx(); }; }, - "shop": function () { + shop: function () { // 【全局商店】相关的功能 // // 打开一个全局商店 @@ -550,7 +562,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = 60 ); }, - "removeMap": function () { + removeMap: function () { // 高层塔砍层插件,删除后不会存入存档,不可浏览地图也不可飞到。 // 推荐用法: // 对于超高层或分区域塔,当在1区时将2区以后的地图删除;1区结束时恢复2区,进二区时删除1区地图,以此类推 @@ -639,7 +651,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = }); }; }, - "fiveLayers": function () { + fiveLayers: function () { // 是否启用五图层(增加背景2层和前景2层) 将__enable置为true即会启用;启用后请保存后刷新编辑器 // 背景层2将会覆盖背景层 被事件层覆盖 前景层2将会覆盖前景层 // 另外 请注意加入两个新图层 会让大地图的性能降低一些 @@ -841,7 +853,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = }; }; }, - "itemShop": function () { + itemShop: function () { // 道具商店相关的插件 // 可在全塔属性-全局商店中使用「道具商店」事件块进行编辑(如果找不到可以在入口方块中找) @@ -1243,7 +1255,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ]); }; }, - "enemyLevel": function () { + enemyLevel: function () { // 此插件将提供怪物手册中的怪物境界显示 // 使用此插件需要先给每个怪物定义境界,方法如下: // 点击怪物的【配置表格】,找到“【怪物】相关的表格配置”,然后在【名称】仿照增加境界定义: @@ -1411,7 +1423,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ); }; }, - "multiHeros": function () { + multiHeros: function () { // 多角色插件 // Step 1: 启用本插件 // Step 2: 定义每个新的角色各项初始数据(参见下方注释) @@ -1565,7 +1577,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = core.setFlag("heroId", toHeroId); // 保存切换到的角色ID }; }, - "heroFourFrames": function () { + heroFourFrames: function () { // 样板的勇士/跟随者移动时只使用2、4两帧,观感较差。本插件可以将四帧全用上。 // 是否启用本插件 @@ -1628,7 +1640,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = return false; }; }, - "routeFixing": function () { + routeFixing: function () { // 是否开启本插件,true 表示启用,false 表示禁用。 var __enable = true; if (!__enable) return; @@ -1752,7 +1764,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = 100 ); }, - "numpad": function () { + numpad: function () { // 样板自带的整数输入事件为白屏弹窗且可以误输入任意非法内容但不支持负整数,观感较差。本插件可以将其美化成仿RM样式,使其支持负整数同时带有音效 // 另一方面,4399等第三方平台不允许使用包括 core.myprompt() 和 core.myconfirm() 在内的弹窗,因此也需要此插件来替代,不然类似生命魔杖的道具就不好实现了 // 关于负整数输入,V2.8.2原生支持其录像的压缩和解压,只是默认的 core.events._action_input() 函数将负数取了绝对值,可以只复写下面的 core.isReplaying() 部分来取消 @@ -2009,7 +2021,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = } }; }, - "sprites": function () { + sprites: function () { // 基于canvas的sprite化,摘编整理自万宁魔塔 // // ---------------------------------------- 第一部分 js代码 (必装) --------------------------------------- // @@ -2213,7 +2225,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = window.Sprite = Sprite; }, - "hotReload": function () { + hotReload: function () { /* ---------- 功能说明 ---------- * 1. 当 libs/ main.js index.html 中的任意一个文件被更改后,会自动刷新塔的页面 @@ -2470,1210 +2482,1212 @@ 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; //横屏画面高度 + 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; //横屏画面高度 - 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 ? - core.getLocalStorage('end') ? 'project/images/winbackgroundVertical.webp' : main.styles.startVerticalBackground || main.styles.startBackground : - core.getLocalStorage('end') ? 'project/images/winbackground.webp' : 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.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.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 (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(); + }; - 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, true); - 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.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.ui._drawViewMaps(core.floorIds.indexOf(core.status.floorId)); - 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, true); + 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.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.ui._drawViewMaps(core.floorIds.indexOf(core.status.floorId)); + 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.ui._drawViewMaps(core.floorIds.indexOf(core.status.floorId)); - 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.ui._drawViewMaps(core.floorIds.indexOf(core.status.floorId)); + 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.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.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`. -}, - "override": function () { + core.control.clearStatusBar = function () { + core.clearMap("outerUI"); + }; + // init() called in `afterLoadResources`. + }, + override: function () { core.statusBar.icons = { floor: 0, name: null, @@ -4023,7 +4037,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ctx.fillText(text, x, y); }; }, - "额外信息": function () { + 额外信息: function () { /* 宝石血瓶左下角显示数值 * 注意!!!不要在道具属性中直接操作flags,使用core.status.hero.flags或core.setFlag系列函数代替! * 需要将 变量:itemDetail改为true才可正常运行 @@ -4180,281 +4194,281 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = } } }, - "编辑器显伤": function () { - // 在此增加新插件 - /////// 用户设置 /////// - // 将__enable置为false将关闭插件 - var __enable = true; - // 魔防攻速之类的属性可以在这里加 ['atk', 'def', 'mdef'] - var heroStatus = ["atk", "def", "mdef", "hp"]; - // saveHero为true 将会把每次造塔测试时的角色数据存下来 否则会读取初始属性 - // 用不着可以关了 节约缓存空间 (虽然根本没多少 还没一个存档大 - // 也可以手动清理 控制台输入core.removeLocalStorage('editorHero')即可 - var saveHero = true; + 编辑器显伤: function () { + // 在此增加新插件 + /////// 用户设置 /////// + // 将__enable置为false将关闭插件 + var __enable = true; + // 魔防攻速之类的属性可以在这里加 ['atk', 'def', 'mdef'] + var heroStatus = ["atk", "def", "mdef", "hp"]; + // saveHero为true 将会把每次造塔测试时的角色数据存下来 否则会读取初始属性 + // 用不着可以关了 节约缓存空间 (虽然根本没多少 还没一个存档大 + // 也可以手动清理 控制台输入core.removeLocalStorage('editorHero')即可 + var saveHero = true; - // 下为具体实现 懒得写注释了 大概就是写HTML然后注册交互 - if (!__enable || main.mode != "editor") return; - core.plugin.initEditorDamage = false; - if (heroStatus.length >= 4 && !editor.isMobile) - editor.dom.mid2.style.top = 650 + 30 * (heroStatus.length - 3) + "px"; - editor.statusRatio = core.getLocalStorage("statusRatio", 1); - editor.saveHero = saveHero; - editor._heroStatus = heroStatus; - editor.dom.mapEdit.appendChild(core.canvas.damage.canvas); - var HTML = - ""; + // 下为具体实现 懒得写注释了 大概就是写HTML然后注册交互 + if (!__enable || main.mode != "editor") return; + core.plugin.initEditorDamage = false; + if (heroStatus.length >= 4 && !editor.isMobile) + editor.dom.mid2.style.top = 650 + 30 * (heroStatus.length - 3) + "px"; + editor.statusRatio = core.getLocalStorage("statusRatio", 1); + editor.saveHero = saveHero; + editor._heroStatus = heroStatus; + editor.dom.mapEdit.appendChild(core.canvas.damage.canvas); + var HTML = + ""; - //if (heroStatus.length >= 4 && !editor.isMobile) editor.dom.mid2.style.top = 650 + 30 * (heroStatus.length - 3) + 'px'; - heroStatus.forEach(function (status) { - var id = status + "set", - id2 = status + "add", - id3 = status + "rec", - id4 = status + "help"; - HTML += - "
"; - }); - document.getElementById("viewportButtons").innerHTML = HTML; - ["set", "add", "rec", "help"].forEach(function (e) { - heroStatus.forEach(function (status) { - editor.dom[status + e] = document.getElementById(status + e); - }); - }); - var _hasItem = core.items.hasItem; - core.items.hasItem = function (itemId) { - if (itemId == "book" && main.mode == "editor") return true; - return _hasItem.call(core.items, itemId); - }; - if (main.mode == "editor") { - var applyList = [ - "getDamageString", - "nextCriticals", - "getEnemyInfo", - "getEnemyValue", - ]; - applyList.forEach(function (name) { - var func = core.enemys[name]; - core.enemys[name] = function () { - var args = - arguments.length === 1 ? - [arguments[0]] : - Array.apply(null, arguments); - if (typeof args[0] == "string") args[0] = core.enemys.enemys[args[0]]; - return func.apply(core.enemys, args); - }; - }); - } + //if (heroStatus.length >= 4 && !editor.isMobile) editor.dom.mid2.style.top = 650 + 30 * (heroStatus.length - 3) + 'px'; + heroStatus.forEach(function (status) { + var id = status + "set", + id2 = status + "add", + id3 = status + "rec", + id4 = status + "help"; + HTML += + "
"; + }); + document.getElementById("viewportButtons").innerHTML = HTML; + ["set", "add", "rec", "help"].forEach(function (e) { + heroStatus.forEach(function (status) { + editor.dom[status + e] = document.getElementById(status + e); + }); + }); + var _hasItem = core.items.hasItem; + core.items.hasItem = function (itemId) { + if (itemId == "book" && main.mode == "editor") return true; + return _hasItem.call(core.items, itemId); + }; + if (main.mode == "editor") { + var applyList = [ + "getDamageString", + "nextCriticals", + "getEnemyInfo", + "getEnemyValue", + ]; + applyList.forEach(function (name) { + var func = core.enemys[name]; + core.enemys[name] = function () { + var args = + arguments.length === 1 + ? [arguments[0]] + : Array.apply(null, arguments); + if (typeof args[0] == "string") args[0] = core.enemys.enemys[args[0]]; + return func.apply(core.enemys, args); + }; + }); + } - ////// 获得勇士属性 ////// - core.control.getStatus = function (name) { - if (!core.status.hero) return null; - if (name == "x" || name == "y" || name == "direction") - return this.getHeroLoc(name); - /*if ( main.mode == 'editor' && !core.hasFlag('__statistics__')) { + ////// 获得勇士属性 ////// + core.control.getStatus = function (name) { + if (!core.status.hero) return null; + if (name == "x" || name == "y" || name == "direction") + return this.getHeroLoc(name); + /*if ( main.mode == 'editor' && !core.hasFlag('__statistics__')) { return data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.firstData.hero[name]; }*/ - return core.status.hero[name]; - }; + return core.status.hero[name]; + }; - core.control.updateDamage = function (floorId, ctx) { - floorId = floorId || core.status.floorId; - if (!floorId || core.status.gameOver) return; - var onMap = ctx == null; - if (main.mode == "editor") { - ctx = core.canvas.damage; - core.updateCheckBlock(); - core.clearMap(ctx); - if (editor.uivalues.bigmap) return; - } + core.control.updateDamage = function (floorId, ctx) { + floorId = floorId || core.status.floorId; + if (!floorId || core.status.gameOver) return; + var onMap = ctx == null; + if (main.mode == "editor") { + ctx = core.canvas.damage; + core.updateCheckBlock(); + core.clearMap(ctx); + if (editor.uivalues.bigmap) return; + } - // 没有怪物手册 - if (!core.hasItem("book")) return; - core.status.damage.posX = core.bigmap.posX; - core.status.damage.posY = core.bigmap.posY; - if (!onMap) { - var width = core.floors[floorId].width, - height = core.floors[floorId].height; - // 地图过大的缩略图不绘制显伤 - if (width * height > core.bigmap.threshold) return; - } - this._updateDamage_damage(floorId, onMap); - this._updateDamage_extraDamage(floorId, onMap); - this.drawDamage(ctx); - }; + // 没有怪物手册 + if (!core.hasItem("book")) return; + core.status.damage.posX = core.bigmap.posX; + core.status.damage.posY = core.bigmap.posY; + if (!onMap) { + var width = core.floors[floorId].width, + height = core.floors[floorId].height; + // 地图过大的缩略图不绘制显伤 + if (width * height > core.bigmap.threshold) return; + } + this._updateDamage_damage(floorId, onMap); + this._updateDamage_extraDamage(floorId, onMap); + this.drawDamage(ctx); + }; - core.control.drawDamage = function (ctx) { - if ( - core.status.gameOver || - !core.status.damage /* || main.mode != 'play'*/ - ) - return; - var onMap = false; - if (ctx == null) { - ctx = core.canvas.damage; - core.clearMap("damage"); - onMap = true; - } + core.control.drawDamage = function (ctx) { + if ( + core.status.gameOver || + !core.status.damage /* || main.mode != 'play'*/ + ) + return; + var onMap = false; + if (ctx == null) { + ctx = core.canvas.damage; + core.clearMap("damage"); + onMap = true; + } - if (onMap && core.bigmap.v2) { - // 检查是否需要重算... - if ( - Math.abs(core.bigmap.posX - core.status.damage.posX) >= - core.bigmap.extend - 1 || - Math.abs(core.bigmap.posY - core.status.damage.posY) >= - core.bigmap.extend - 1 - ) { - return this.updateDamage(); - } - } - return this._drawDamage_draw(ctx, onMap); - }; + if (onMap && core.bigmap.v2) { + // 检查是否需要重算... + if ( + Math.abs(core.bigmap.posX - core.status.damage.posX) >= + core.bigmap.extend - 1 || + Math.abs(core.bigmap.posY - core.status.damage.posY) >= + core.bigmap.extend - 1 + ) { + return this.updateDamage(); + } + } + return this._drawDamage_draw(ctx, onMap); + }; - ////// 以x,y的形式返回每个点的事件 ////// - core.maps.getMapBlocksObj = function (floorId, noCache) { - floorId = floorId || core.status.floorId; - if ( - core.status.mapBlockObjs[floorId] && - !noCache && - main.mode != "editor" - ) - return core.status.mapBlockObjs[floorId]; + ////// 以x,y的形式返回每个点的事件 ////// + core.maps.getMapBlocksObj = function (floorId, noCache) { + floorId = floorId || core.status.floorId; + if ( + core.status.mapBlockObjs[floorId] && + !noCache && + main.mode != "editor" + ) + return core.status.mapBlockObjs[floorId]; - var obj = {}; - core.extractBlocks(floorId); - core.status.maps[floorId].blocks.forEach(function (block) { - obj[block.x + "," + block.y] = block; - }); - core.status.mapBlockObjs[floorId] = obj; - return obj; - }; + var obj = {}; + core.extractBlocks(floorId); + core.status.maps[floorId].blocks.forEach(function (block) { + obj[block.x + "," + block.y] = block; + }); + core.status.mapBlockObjs[floorId] = obj; + return obj; + }; - this.bignum = function (num, defaultValue) { - if (num == null || num == "") return defaultValue; - num = num + ""; - var list = { - w: 1e4, - e: 1e8, - z: 1e12, - j: 1e16, - g: 1e20, - }; - // 浮点数问题 - function checkFloat(num) { - if (!core.isset(num)) return 0; - num = num + ""; - var index = num.indexOf("."); - if (index < 0) return 0; - else return num.slice(index + 1).length; - } - var index = num.search(/w|e|z|j|g/); - if (index <= 0) { - num = parseInt(num); - if (core.isset(num)) return num; - else { - alert("不正确的输入"); - return defaultValue; - } - } - for (; index > 0; index = num.search(/w|e|z|j|g/)) { - var p = num[index], - q = list[p], - n = num.slice(0, index), - m = Math.pow(10, checkFloat(n)); - num = (n * m * q) / m + num.slice(index + 1); - } - return parseInt(num); - }; + this.bignum = function (num, defaultValue) { + if (num == null || num == "") return defaultValue; + num = num + ""; + var list = { + w: 1e4, + e: 1e8, + z: 1e12, + j: 1e16, + g: 1e20, + }; + // 浮点数问题 + function checkFloat(num) { + if (!core.isset(num)) return 0; + num = num + ""; + var index = num.indexOf("."); + if (index < 0) return 0; + else return num.slice(index + 1).length; + } + var index = num.search(/w|e|z|j|g/); + if (index <= 0) { + num = parseInt(num); + if (core.isset(num)) return num; + else { + alert("不正确的输入"); + return defaultValue; + } + } + for (; index > 0; index = num.search(/w|e|z|j|g/)) { + var p = num[index], + q = list[p], + n = num.slice(0, index), + m = Math.pow(10, checkFloat(n)); + num = (n * m * q) / m + num.slice(index + 1); + } + return parseInt(num); + }; - this.updateEditorDamage = function (noSave) { - core.updateDamage(); - heroStatus.forEach(function (status) { - editor.dom[status + "set"].value = core.status.hero[status]; - }); - if (!noSave && editor.saveHero) - core.setLocalStorage("editorHero", core.status.hero); - }; + this.updateEditorDamage = function (noSave) { + core.updateDamage(); + heroStatus.forEach(function (status) { + editor.dom[status + "set"].value = core.status.hero[status]; + }); + if (!noSave && editor.saveHero) + core.setLocalStorage("editorHero", core.status.hero); + }; - var _resizeMap = core.maps.resizeMap; - core.maps.resizeMap = function (floorId) { - _resizeMap.call(core.maps, floorId); - if (!core.plugin.initEditorDamage && main.mode == "editor") { - core.plugin.initEditorDamage = true; - var editorHero = core.getLocalStorage("editorHero"); - if (editorHero && saveHero) core.status.hero = editorHero; - else core.removeLocalStorage("editorHero"); - editor._heroStatus.forEach(function (e) { - editor.dom[e + "set"].onchange = function () { - var status = this.id.slice(0, -3); - core.status.hero[status] = core.bignum( - this.value, - core.status.hero[status] - ); - core.updateEditorDamage(); - }; - editor.dom[e + "add"].onclick = function () { - var status = this.id.slice(0, -3); - core.status.hero[status] += editor.statusRatio; - core.updateEditorDamage(); - }; - editor.dom[e + "rec"].onclick = function () { - var status = this.id.slice(0, -3); - core.status.hero[status] -= editor.statusRatio; - core.updateEditorDamage(); - }; - editor.dom[e + "help"].onclick = function () { - var status = this.id.slice(0, -4), - name = core.getStatusLabel(status); - var ratio = parseInt( - prompt( - "当前属性:" + - name + - "\n现在的点击按钮变化值:" + - editor.statusRatio + - ",请输入按下一次+/-按钮的属性变化量,可以写4w 10.2e这种字母缩写" - ) - ); - if (!core.isset(ratio)) { - printe("不合法的输入"); - return; - } - editor.statusRatio = ratio; - core.setLocalStorage("statusRatio", ratio); - }; - }); - var _updateMap = editor.updateMap; - editor.updateMap = function () { - _updateMap.call(editor); - core.updateEditorDamage(true); - }; - editor.mode.onmode = function (mode, callback) { - if (editor_mode.mode != mode) { - if (mode === "save") { - editor_mode.doActionList( - editor_mode.mode, - editor_mode.actionList, - function () { - if (callback) callback(); - core.updateEditorDamage(); - } - ); - } - if (editor_mode.mode === "nextChange" && mode) - editor_mode.showMode(mode); - if (mode !== "save") editor_mode.mode = mode; - editor_mode.actionList = []; - } - }; - } - }; -}, - "手册区分特殊属性": function () { + var _resizeMap = core.maps.resizeMap; + core.maps.resizeMap = function (floorId) { + _resizeMap.call(core.maps, floorId); + if (!core.plugin.initEditorDamage && main.mode == "editor") { + core.plugin.initEditorDamage = true; + var editorHero = core.getLocalStorage("editorHero"); + if (editorHero && saveHero) core.status.hero = editorHero; + else core.removeLocalStorage("editorHero"); + editor._heroStatus.forEach(function (e) { + editor.dom[e + "set"].onchange = function () { + var status = this.id.slice(0, -3); + core.status.hero[status] = core.bignum( + this.value, + core.status.hero[status] + ); + core.updateEditorDamage(); + }; + editor.dom[e + "add"].onclick = function () { + var status = this.id.slice(0, -3); + core.status.hero[status] += editor.statusRatio; + core.updateEditorDamage(); + }; + editor.dom[e + "rec"].onclick = function () { + var status = this.id.slice(0, -3); + core.status.hero[status] -= editor.statusRatio; + core.updateEditorDamage(); + }; + editor.dom[e + "help"].onclick = function () { + var status = this.id.slice(0, -4), + name = core.getStatusLabel(status); + var ratio = parseInt( + prompt( + "当前属性:" + + name + + "\n现在的点击按钮变化值:" + + editor.statusRatio + + ",请输入按下一次+/-按钮的属性变化量,可以写4w 10.2e这种字母缩写" + ) + ); + if (!core.isset(ratio)) { + printe("不合法的输入"); + return; + } + editor.statusRatio = ratio; + core.setLocalStorage("statusRatio", ratio); + }; + }); + var _updateMap = editor.updateMap; + editor.updateMap = function () { + _updateMap.call(editor); + core.updateEditorDamage(true); + }; + editor.mode.onmode = function (mode, callback) { + if (editor_mode.mode != mode) { + if (mode === "save") { + editor_mode.doActionList( + editor_mode.mode, + editor_mode.actionList, + function () { + if (callback) callback(); + core.updateEditorDamage(); + } + ); + } + if (editor_mode.mode === "nextChange" && mode) + editor_mode.showMode(mode); + if (mode !== "save") editor_mode.mode = mode; + editor_mode.actionList = []; + } + }; + } + }; + }, + 手册区分特殊属性: function () { // 在此增加新插件 this.arrsame = function (Arraya, Arrayb) { let a = Arraya || []; @@ -4806,7 +4820,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = return [enemy, texts]; }; }, - "一防减伤": function () { + 一防减伤: function () { // 在此增加新插件 ui.prototype._drawBook_drawRow3 = function ( index, @@ -4880,7 +4894,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = return this.getDefDamage(enemy, null, x, y, floorId); }; }, - "新道具栏/装备栏": function () { + "新道具栏/装备栏": function () { // 在此增加新插件 // 注:///// *** 裹起来的区域: 该区域内参数可以随意更改调整ui绘制 不会影响总体布局 // 请尽量修改该区域而不是其他区域 修改的时候最好可以对照现有ui修改 @@ -5264,6 +5278,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = itemText = core.replaceText(itemText); if (itemText[0] == "," || itemText[0] == ",") itemText = itemText.substring(1); + /* 一个根据道具id修改道具名字(右栏)的例子 * if (item.id == "xxx") itemNameColor = "red"; */ @@ -5291,6 +5306,9 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ); core.setTextAlign(ctx, "left"); core.setTextBaseline(ctx, "middle"); + if (itemCls === "equips" && item.id) { + itemName = "【" + item.equipCls + "】" + itemName; + } core.fillText( ctx, itemName, @@ -5300,45 +5318,83 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = itemNameFont, itemNameMaxWidth ); - core.fillText( - ctx, - "【" + itemClsName + "】", - itemCls_x, - itemCls_middle, - itemClsColor, - itemClsFont - ); - var statusText = "【装备类型】" + item.equipCls + "\n\n"; - /*if (core.status.event.id == "equipbox") { - var type = item.equip.type; - if (typeof type == "string") type = core.getEquipTypeByName(type); - var compare = core.compareEquipment(item.id, core.getEquip(type)); - if (info.select.action == "unload") compare = core.compareEquipment(null, item.id); - // --- 变化值... - for (var name in core.status.hero) { - if (typeof core.status.hero[name] != 'number') continue; - var nowValue = core.getRealStatus(name); - // 查询新值 - var newValue = Math.floor((core.getStatus(name) + (compare.value[name] || 0)) * - (core.getBuff(name) * 100 + (compare.percentage[name] || 0)) / 100); - if (nowValue == newValue) continue; - var color = newValue > nowValue ? '#00FF00' : '#FF0000'; - nowValue = core.formatBigNumber(nowValue); - newValue = core.formatBigNumber(newValue); - statusText += core.getStatusLabel(name) + " " + nowValue + "->\r[" + color + "]" + newValue + "\r\n"; - } - }*/ + if (!item.equip) + core.fillText( + ctx, + "【" + itemClsName + "】", + itemCls_x, + itemCls_middle, + itemClsColor, + itemClsFont + ); + + var statusText = ""; + if (core.status.event.id == "equipbox") { + var type = item.equip.type; + if (typeof type == "string") type = core.getEquipTypeByName(type); + var compare = core.compareEquipment(item.id, core.getEquip(type)); + var compare2; + if (item.equipCls === "双手剑") + compare2 = core.compareEquipment(null, core.getEquip(1)); + if (info.select.action == "unload") + compare = core.compareEquipment(null, item.id); + // --- 变化值... + for (var name in core.status.hero) { + if (typeof core.status.hero[name] != "number") continue; + var nowValue = core.getRealStatus(name); + // 查询新值 + var newValue = Math.floor( + ((core.getStatus(name) + + (compare.value[name] || 0) + + (compare2?.value[name] || 0)) * + (core.getBuff(name) * 100 + + (compare.percentage[name] || 0) + + (compare2?.percentage[name] || 0))) / + 100 + ); + if (nowValue == newValue) continue; + var color = newValue > nowValue ? "#00FF00" : "#FF0000"; + nowValue = core.formatBigNumber(nowValue); + newValue = core.formatBigNumber(newValue); + statusText += + core.getStatusLabel(name) + + " " + + nowValue + + "->\r[" + + color + + "]" + + newValue + + "\r\n"; + } + } itemText = statusText + itemText; - core.drawTextContent(ctx, itemText, { - left: itemText_x, - top: itemText_y, - bold: false, - color: "white", - align: "left", - fontSize: itemTextFontSize, - maxWidth: - rightbar_width - (itemText_x - rightbar_x) * 2 + itemTextFontSize / 2, - }); + if (item.equip) { + core.drawTextContent(ctx, itemText, { + left: itemText_x, + top: itemCls_middle, + bold: false, + color: "white", + align: "left", + fontSize: itemTextFontSize, + maxWidth: + rightbar_width - + (itemText_x - rightbar_x) * 2 + + itemTextFontSize / 2, + }); + } else { + core.drawTextContent(ctx, itemText, { + left: itemText_x, + top: itemText_y, + bold: false, + color: "white", + align: "left", + fontSize: itemTextFontSize, + maxWidth: + rightbar_width - + (itemText_x - rightbar_x) * 2 + + itemTextFontSize / 2, + }); + } ///// *** 退出按钮设置 var btnRadius = 10; @@ -5411,7 +5467,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = len = toDrawList.length; ///// *** 装备格设置 - var maxItem = 4; + var maxItem = 2; var box_width = 32, box_height = 32, box_borderStyle = "#fff", @@ -5437,8 +5493,8 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = var space_y = (equipList_height - maxLine * oneBoxHeight) / (1 + maxLine), space_x = (equipList_width - maxItem * oneBoxWidth) / (1 + maxItem); var box_x = equipList_x + space_x, - box_y = equipList_y + space_y; - for (var i = 0; i < len; i++) { + box_y = equipList_y + space_y + 12; + for (var i = 0; i < 2; i++) { var id = core.getEquip(i), name = toDrawList[i]; if (i === 0) name = "主手"; @@ -5482,28 +5538,90 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = core.drawLine( ctx, equipList_x + space_x + space_x + oneBoxWidth, - equipList_y + space_y, + equipList_y + space_y + 12, equipList_x + space_x + space_x + oneBoxWidth + box_width + box_borderWidth, - equipList_y + space_y + box_height + equipList_y + space_y + box_height + 12 ); core.drawLine( ctx, equipList_x + space_x + space_x + oneBoxWidth, - equipList_y + space_y + box_height, + equipList_y + space_y + box_height + 12, equipList_x + space_x + space_x + oneBoxWidth + box_width + box_borderWidth, - equipList_y + space_y + equipList_y + space_y + 12 ); } + ///// *** 装备格设置 + var maxItem = 3; + var box_width = 32, + box_height = 32, + box_borderStyle = "#fff", + box_selectBorderStyle = "gold", // 选中的装备格的颜色 + box_borderWidth = 2; + var boxName_fontSize = 14, + boxName_space = 2, + boxName_color = "#fff"; // 装备格名称与上面的装备格框的距离 + var maxLine = Math.ceil(len / maxItem); + ///// *** + var l = Math.sqrt(len); + if (Math.pow(l) == len && len != 4) { + if (l <= maxItem) maxItem = l; + } + maxItem = Math.min(toDrawList.length, maxItem); + info.equips = maxItem; + + var boxName_font = core.ui._buildFont(boxName_fontSize); + // 总宽高减去所有装备格宽高得到空隙大小 + var oneBoxWidth = box_width + box_borderWidth * 2; + var oneBoxHeight = + box_height + boxName_fontSize + boxName_space + 2 * box_borderWidth; + var space_y = (equipList_height - maxLine * oneBoxHeight) / (1 + maxLine), + space_x = (equipList_width - maxItem * oneBoxWidth) / (1 + maxItem); + var box_x = equipList_x + space_x, + box_y = equipList_y + space_y + space_y + oneBoxHeight; + for (var i = 2; i < len; i++) { + var id = core.getEquip(i), + name = toDrawList[i]; + var selectBorder = false; + if (core.status.thisUIEventInfo.select.type == i) selectBorder = true; + var borderStyle = selectBorder + ? box_selectBorderStyle + : box_borderStyle; + core.drawEquipbox_drawOne( + ctx, + name, + id, + box_x, + box_y, + box_width, + box_height, + boxName_space, + boxName_font, + boxName_color, + borderStyle, + box_borderWidth + ); + var todo = new Function( + "core.clickOneEquipbox('" + id + "'," + i + ")" + ); + core.addUIEventListener( + box_x - box_borderWidth / 2, + box_y - box_borderWidth / 2, + oneBoxWidth, + oneBoxHeight, + todo + ); + box_x += space_x + oneBoxWidth; + } }; this.drawToolbox = function (ctx) { @@ -5800,43 +5918,6 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = let equipClsid = core.material.items[id]?.equipCls; let equipCls0 = core.material.items[core.getEquip(0)]?.equipCls; let equipCls1 = core.material.items[core.getEquip(1)]?.equipCls; - if (equipCls0 === "双手剑") { - core.unloadEquip(0, function () { - core.status.route.push("unEquip:" + 0); - }); - } - if (equipClsid === "单手剑") { - if ( - equipCls1 !== "单手剑" && - equipCls1 !== "匕首" && - equipCls1 !== "盾牌" - ) { - core.unloadEquip(0, function () { - core.status.route.push("unEquip:" + 0); - }); - core.unloadEquip(1, function () { - core.status.route.push("unEquip:" + 1); - }); - } else if (equipCls0 !== "单手剑") { - core.unloadEquip(0, function () { - core.status.route.push("unEquip:" + 0); - }); - } - } - if (equipClsid === "法杖") { - if (equipCls1 !== "匕首" && equipCls1 !== "盾牌") { - core.unloadEquip(0, function () { - core.status.route.push("unEquip:" + 0); - }); - core.unloadEquip(1, function () { - core.status.route.push("unEquip:" + 1); - }); - } else { - core.unloadEquip(0, function () { - core.status.route.push("unEquip:" + 0); - }); - } - } if (equipClsid === "双手剑") { core.unloadEquip(0, function () { core.status.route.push("unEquip:" + 0); @@ -5845,34 +5926,6 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = core.status.route.push("unEquip:" + 1); }); } - if (equipClsid === "匕首") { - if (equipCls0 !== "匕首") { - core.unloadEquip(0, function () { - core.status.route.push("unEquip:" + 0); - }); - core.unloadEquip(1, function () { - core.status.route.push("unEquip:" + 1); - }); - } else { - core.unloadEquip(1, function () { - core.status.route.push("unEquip:" + 1); - }); - } - } - if (equipClsid === "盾牌") { - if (equipCls0 !== "单手剑" && equipCls0 !== "法杖") { - core.unloadEquip(0, function () { - core.status.route.push("unEquip:" + 0); - }); - core.unloadEquip(1, function () { - core.status.route.push("unEquip:" + 1); - }); - } else { - core.unloadEquip(1, function () { - core.status.route.push("unEquip:" + 1); - }); - } - } core.loadEquip(id, function () { core.status.route.push("equip:" + id); info.select.type = type; @@ -6278,7 +6331,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = core.registerReplayAction("equip", core.control._replayAction_equip); core.registerReplayAction("unEquip", core.control._replayAction_unEquip); }, - "技能树": function () { + 技能树: function () { // 在此增加新插件 // // 已学习的技能等级 flags._hasSkill_ @@ -7080,7 +7133,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = }; core.registerReplayAction("skill", control.prototype._replayAction_skill); }, - "animate": function () { + animate: function () { // -------------------- 插件说明 -------------------- // // github仓库:https://github.com/unanmed/animate @@ -7323,51 +7376,46 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = if (main.replayChecking) return (core.plugin.animate = {}); var M = Object.defineProperty; - var E = (n, s, t) => - s in n - ? M(n, s, { enumerable: !0, configurable: !0, writable: !0, value: t }) - : (n[s] = t); - var o = (n, s, t) => (E(n, typeof s != "symbol" ? s + "" : s, t), t); - let b = []; + var E = (n, i, t) => + i in n + ? M(n, i, { enumerable: !0, configurable: !0, writable: !0, value: t }) + : (n[i] = t); + var o = (n, i, t) => (E(n, typeof i != "symbol" ? i + "" : i, t), t); + let w = []; const k = (n) => { - for (const s of b) - if (s.status === "running") + for (const i of w) + if (i.status === "running") try { - for (const t of s.funcs) t(n - s.startTime); + for (const t of i.funcs) t(n - i.startTime); } catch (t) { - s.destroy(), console.error(t); + i.destroy(), console.error(t); } requestAnimationFrame(k); }; requestAnimationFrame(k); class I { constructor() { - o(this, "funcs", []); + o(this, "funcs", /* @__PURE__ */ new Set()); o(this, "status", "stop"); o(this, "startTime", 0); (this.status = "running"), - b.push(this), - requestAnimationFrame((s) => (this.startTime = s)); + w.push(this), + requestAnimationFrame((i) => (this.startTime = i)); } - add(s, t = !1) { - return t ? this.funcs.unshift(s) : this.funcs.push(s), this; + add(i) { + return this.funcs.add(i), this; } - remove(s) { - const t = this.funcs.findIndex((e) => e === s); - if (t === -1) - throw new ReferenceError( - "You are going to remove nonexistent ticker function." - ); - return this.funcs.splice(t, 1), this; + remove(i) { + return this.funcs.delete(i), this; } clear() { - this.funcs = []; + this.funcs.clear(); } destroy() { this.clear(), this.stop(); } stop() { - (this.status = "stop"), (b = b.filter((s) => s !== this)); + (this.status = "stop"), (w = w.filter((i) => i !== this)); } } class F { @@ -7380,70 +7428,70 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = o(this, "ticker", new I()); o(this, "value", {}); o(this, "listener", {}); - this.timing = (s) => s; + this.timing = (i) => i; } async all() { - if (Object.values(this.applying).every((s) => s === !0)) + if (Object.values(this.applying).every((i) => i === !0)) throw new ReferenceError("There is no animates to be waited."); - await new Promise((s) => { + await new Promise((i) => { const t = () => { Object.values(this.applying).every((e) => e === !1) && - (this.unlisten("end", t), s("all animated.")); + (this.unlisten("end", t), i("all animated.")); }; this.listen("end", t); }); } - async n(s) { - const t = Object.values(this.applying).filter((i) => i === !0).length; - if (t < s) + async n(i) { + const t = Object.values(this.applying).filter((s) => s === !0).length; + if (t < i) throw new ReferenceError( - `You are trying to wait ${s} animate, but there are only ${t} animate animating.` + `You are trying to wait ${i} animate, but there are only ${t} animate animating.` ); let e = 0; - await new Promise((i) => { + await new Promise((s) => { const r = () => { - e++, e === s && (this.unlisten("end", r), i(`${s} animated.`)); + e++, e === i && (this.unlisten("end", r), s(`${i} animated.`)); }; this.listen("end", r); }); } - async w(s) { - if (this.applying[s] === !1) - throw new ReferenceError(`The ${s} animate is not animating.`); + async w(i) { + if (this.applying[i] === !1) + throw new ReferenceError(`The ${i} animate is not animating.`); await new Promise((t) => { const e = () => { - this.applying[s] === !1 && - (this.unlisten("end", e), t(`${s} animated.`)); + this.applying[i] === !1 && + (this.unlisten("end", e), t(`${i} animated.`)); }; this.listen("end", e); }); } - listen(s, t) { - var e, i; - (i = (e = this.listener)[s]) != null || (e[s] = []), - this.listener[s].push(t); + listen(i, t) { + var e, s; + (s = (e = this.listener)[i]) != null || (e[i] = []), + this.listener[i].push(t); } - unlisten(s, t) { - const e = this.listener[s].findIndex((i) => i === t); + unlisten(i, t) { + const e = this.listener[i].findIndex((s) => s === t); if (e === -1) throw new ReferenceError( "You are trying to remove a nonexistent listener." ); - this.listener[s].splice(e, 1); + this.listener[i].splice(e, 1); } - hook(...s) { - const t = Object.entries(this.listener).filter((e) => s.includes(e[0])); - for (const [e, i] of t) for (const r of i) r(this, e); + hook(...i) { + const t = Object.entries(this.listener).filter((e) => i.includes(e[0])); + for (const [e, s] of t) for (const r of s) r(this, e); } } - function T(n) { + function y(n) { return n != null; } async function R(n) { - return new Promise((s) => setTimeout(s, n)); + return new Promise((i) => setTimeout(i, n)); } - class Y extends F { + class j extends F { constructor() { super(); o(this, "shakeTiming"); @@ -7491,7 +7539,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = }), this.ticker.add(() => { const { running: t } = this.listener; - if (T(t)) for (const e of t) e(this, "running"); + if (y(t)) for (const e of t) e(this, "running"); }); } get x() { @@ -7550,58 +7598,58 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = shake(t, e) { this.applying.shake === !0 && this.end(!0, "shake"), (this.applying.shake = !0); - const { easeTime: i, shakeTiming: r } = this, - h = this.getTime(); - if ((this.hook("start", "shakestart"), i <= 0)) + const { easeTime: s, shakeTiming: r } = this, + l = this.getTime(); + if ((this.hook("start", "shakestart"), s <= 0)) return this.end(!1, "shake"), this; - const l = () => { - const c = this.getTime() - h; - if (c > i) { - this.ticker.remove(l), + const a = () => { + const c = this.getTime() - l; + if (c > s) { + this.ticker.remove(a), (this.applying.shake = !1), (this.sx = 0), (this.sy = 0), this.hook("end", "shakeend"); return; } - const a = c / i, - m = r(a); + const h = c / s, + m = r(h); (this.sx = m * t), (this.sy = m * e); }; - return this.ticker.add(l), (this.animateFn.system.shake = l), this; + return this.ticker.add(a), (this.animateFn.system.shake = a), this; } moveAs(t) { this.applying.moveAs && this.end(!0, "moveAs"), (this.applying.moveAs = !0), (this.path = t); - const { easeTime: e, relation: i, timing: r } = this, - h = this.getTime(), - [l, u] = [this.x, this.y], - [c, a] = (() => { - if (i === "absolute") return t(1); + const { easeTime: e, relation: s, timing: r } = this, + l = this.getTime(), + [a, u] = [this.x, this.y], + [c, h] = (() => { + if (s === "absolute") return t(1); { const [d, f] = t(1); - return [l + d, u + f]; + return [a + d, u + f]; } })(); if ((this.hook("start", "movestart"), e <= 0)) return this.end(!1, "moveAs"), this; const m = () => { - const f = this.getTime() - h; + const f = this.getTime() - l; if (f > e) { this.end(!0, "moveAs"); return; } - const v = f / e, - [g, w] = t(r(v)); - i === "absolute" - ? ((this.ox = g), (this.oy = w)) - : ((this.ox = l + g), (this.oy = u + w)); + const g = f / e, + [v, x] = t(r(g)); + s === "absolute" + ? ((this.ox = v), (this.oy = x)) + : ((this.ox = a + v), (this.oy = u + x)); }; return ( - this.ticker.add(m, !0), + this.ticker.add(m), (this.animateFn.system.moveAs = m), - (this.targetValue.system.moveAs = [c, a]), + (this.targetValue.system.moveAs = [c, h]), this ); } @@ -7613,97 +7661,97 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ); (this.value[t] = e), (this.applying[t] = !1); } - apply(t, e, i = !1) { + apply(t, e) { this.applying[t] === !0 && this.end(!1, t), t in this.value || this.error(`You are trying to execute nonexistent property ${t}.`), (this.applying[t] = !0); - const r = this.value[t], - h = this.getTime(), - { timing: l, relation: u, easeTime: c } = this, - a = u === "absolute" ? e - r : e; - if ((this.hook("start"), c <= 0)) return this.end(!1, t), this; - const m = () => { - const f = this.getTime() - h; - if (f > c) { + const s = this.value[t], + r = this.getTime(), + { timing: l, relation: a, easeTime: u } = this, + c = a === "absolute" ? e - s : e; + if ((this.hook("start"), u <= 0)) return this.end(!1, t), this; + const h = () => { + const d = this.getTime() - r; + if (d > u) { this.end(!1, t); return; } - const v = f / c, - g = l(v); - this.value[t] = r + g * a; + const f = d / u, + g = l(f); + this.value[t] = s + g * c; }; return ( - this.ticker.add(m, i), - (this.animateFn.custom[t] = m), - (this.targetValue.custom[t] = a + r), + this.ticker.add(h), + (this.animateFn.custom[t] = h), + (this.targetValue.custom[t] = c + s), this ); } - applyMulti(t = !1) { + applyMulti() { this.applying["@@bind"] === !0 && this.end(!1, "@@bind"), (this.applying["@@bind"] = !0); - const e = this.bindInfo, - i = e.map((m) => this.value[m]), - r = this.getTime(), - { multiTiming: h, relation: l, easeTime: u } = this, - c = h(1); - if (c.length !== i.length) + const t = this.bindInfo, + e = t.map((h) => this.value[h]), + s = this.getTime(), + { multiTiming: r, relation: l, easeTime: a } = this, + u = r(1); + if (u.length !== e.length) throw new TypeError( - `The number of binded animate attributes and timing function returns's length does not match. binded: ${e.length}, timing: ${c.length}` + `The number of binded animate attributes and timing function returns's length does not match. binded: ${t.length}, timing: ${u.length}` ); - if ((this.hook("start"), u <= 0)) return this.end(!1, "@@bind"), this; - const a = () => { - const d = this.getTime() - r; - if (d > u) { + if ((this.hook("start"), a <= 0)) return this.end(!1, "@@bind"), this; + const c = () => { + const m = this.getTime() - s; + if (m > a) { this.end(!1, "@@bind"); return; } - const f = d / u, - v = h(f); - e.forEach((g, w) => { + const d = m / a, + f = r(d); + t.forEach((g, v) => { l === "absolute" - ? (this.value[g] = v[w]) - : (this.value[g] = i[w] + v[w]); + ? (this.value[g] = f[v]) + : (this.value[g] = e[v] + f[v]); }); }; return ( - this.ticker.add(a, t), - (this.animateFn.custom["@@bind"] = a), - (this.targetValue.system["@@bind"] = c), + this.ticker.add(c), + (this.animateFn.custom["@@bind"] = c), + (this.targetValue.system["@@bind"] = u), this ); } - applySys(t, e, i) { - i !== "move" && this.applying[i] === !0 && this.end(!0, i), - (this.applying[i] = !0); + applySys(t, e, s) { + s !== "move" && this.applying[s] === !0 && this.end(!0, s), + (this.applying[s] = !0); const r = this[t], - h = this.getTime(), - l = this.timing, + l = this.getTime(), + a = this.timing, u = this.relation, c = this.easeTime, - a = u === "absolute" ? e - r : e; - if ((this.hook("start", `${i}start`), c <= 0)) return this.end(!1, i); + h = u === "absolute" ? e - r : e; + if ((this.hook("start", `${s}start`), c <= 0)) return this.end(!0, s); const m = () => { - const f = this.getTime() - h; + const f = this.getTime() - l; if (f > c) { - this.end(!0, i); + this.end(!0, s); return; } - const v = f / c, - g = l(v); - (this[t] = r + a * g), t !== "oy" && this.hook(i); + const g = f / c, + v = a(g); + (this[t] = r + h * v), t !== "oy" && this.hook(s); }; - this.ticker.add(m, !0), + this.ticker.add(m), t === "ox" ? (this.animateFn.system.move[0] = m) : t === "oy" ? (this.animateFn.system.move[1] = m) - : (this.animateFn.system[i] = m), - i === "move" - ? (t === "ox" && (this.targetValue.system.move[0] = a + r), - t === "oy" && (this.targetValue.system.move[1] = a + r)) - : i !== "shake" && (this.targetValue.system[i] = a + r); + : (this.animateFn.system[s] = m), + s === "move" + ? (t === "ox" && (this.targetValue.system.move[0] = h + r), + t === "oy" && (this.targetValue.system.move[1] = h + r)) + : s !== "shake" && (this.targetValue.system[s] = h + r); } error(t, e) { throw e === "repeat" @@ -7726,11 +7774,11 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = : this.ticker.remove(this.animateFn.system[e]), e === "move") ) { - const [i, r] = this.targetValue.system.move; - (this.ox = i), (this.oy = r), this.hook("moveend", "end"); + const [s, r] = this.targetValue.system.move; + (this.ox = s), (this.oy = r), this.hook("moveend", "end"); } else if (e === "moveAs") { - const [i, r] = this.targetValue.system.moveAs; - (this.ox = i), (this.oy = r), this.hook("moveend", "end"); + const [s, r] = this.targetValue.system.moveAs; + (this.ox = s), (this.oy = r), this.hook("moveend", "end"); } else e === "rotate" ? ((this.angle = this.targetValue.system.rotate), @@ -7739,8 +7787,8 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ? ((this.size = this.targetValue.system.resize), this.hook("resizeend", "end")) : e === "@@bind" - ? this.bindInfo.forEach((r, h) => { - this.value[r] = this.targetValue.system["@@bind"][h]; + ? this.bindInfo.forEach((r, l) => { + this.value[r] = this.targetValue.system["@@bind"][l]; }) : ((this.sx = 0), (this.sy = 0), this.hook("shakeend", "end")); else @@ -7750,14 +7798,14 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = this.hook("end"); } } - class j extends F { + class O extends F { constructor() { super(); o(this, "now", {}); o(this, "target", {}); o(this, "transitionFn", {}); o(this, "value"); - o(this, "handleSet", (t, e, i) => (this.transition(e, i), !0)); + o(this, "handleSet", (t, e, s) => (this.transition(e, s), !0)); o(this, "handleGet", (t, e) => this.now[e]); (this.timing = (t) => t), (this.value = new Proxy(this.target, { @@ -7779,34 +7827,35 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = } transition(t, e) { if (e === this.target[t]) return this; - if (!T(this.now[t])) return (this.now[t] = e), this; + if (!y(this.now[t])) return (this.now[t] = e), this; this.applying[t] && this.end(t, !0), (this.applying[t] = !0), this.hook("start"); - const i = this.getTime(), + const s = this.getTime(), r = this.easeTime, - h = this.timing, - l = this.now[t], - u = e + (this.relation === "absolute" ? 0 : l), - c = u - l; + l = this.timing, + a = this.now[t], + u = e + (this.relation === "absolute" ? 0 : a), + c = u - a; this.target[t] = u; - const a = () => { - const d = this.getTime() - i; + const h = () => { + const d = this.getTime() - s; if (d >= r) { this.end(t); return; } const f = d / r; - (this.now[t] = h(f) * c + l), this.hook("running"); + (this.now[t] = l(f) * c + a), this.hook("running"); }; return ( - (this.transitionFn[t] = a), - r <= 0 ? (this.end(t), this) : (this.ticker.add(a), this) + (this.transitionFn[t] = h), + this.ticker.add(h), + r <= 0 ? (this.end(t), this) : this ); } end(t, e = !1) { - const i = this.transitionFn[t]; - if (!T(i)) + const s = this.transitionFn[t]; + if (!y(s)) throw new ReferenceError( `You are trying to end an ended transition: ${t}` ); @@ -7817,149 +7866,148 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = e || (this.now[t] = this.target[t]); } } - const x = (...n) => n.reduce((s, t) => s + t, 0), - y = (n) => { + const T = (...n) => n.reduce((i, t) => i + t, 0), + b = (n) => { if (n === 0) return 1; - let s = n; - for (; n > 1; ) n--, (s *= n); - return s; + let i = n; + for (; n > 1; ) n--, (i *= n); + return i; }, - A = (n, s) => Math.round(y(s) / (y(n) * y(s - n))), - p = (n, s, t = (e) => 1 - s(1 - e)) => + A = (n, i) => Math.round(b(i) / (b(n) * b(i - n))), + p = (n, i, t = (e) => 1 - i(1 - e)) => n === "in" - ? s + ? i : n === "out" ? t : n === "in-out" - ? (e) => (e < 0.5 ? s(e * 2) / 2 : 0.5 + t((e - 0.5) * 2) / 2) - : (e) => (e < 0.5 ? t(e * 2) / 2 : 0.5 + s((e - 0.5) * 2) / 2), + ? (e) => (e < 0.5 ? i(e * 2) / 2 : 0.5 + t((e - 0.5) * 2) / 2) + : (e) => (e < 0.5 ? t(e * 2) / 2 : 0.5 + i((e - 0.5) * 2) / 2), $ = Math.cosh(2), z = Math.acosh(2), V = Math.tanh(3), P = Math.atan(5); - function O() { + function Y() { return (n) => n; } function q(...n) { - const s = [0].concat(n); - s.push(1); - const t = s.length, + const i = [0].concat(n); + i.push(1); + const t = i.length, e = Array(t) .fill(0) - .map((i, r) => A(r, t - 1)); - return (i) => { - const r = e.map((h, l) => h * s[l] * (1 - i) ** (t - l - 1) * i ** l); - return x(...r); + .map((s, r) => A(r, t - 1)); + return (s) => { + const r = e.map((l, a) => l * i[a] * (1 - s) ** (t - a - 1) * s ** a); + return T(...r); }; } - function U(n, s) { + function U(n, i) { if (n === "sin") { - const t = (i) => Math.sin((i * Math.PI) / 2); - return p(s, (i) => 1 - t(1 - i), t); + const t = (s) => Math.sin((s * Math.PI) / 2); + return p(i, (s) => 1 - t(1 - s), t); } if (n === "sec") { - const t = (i) => 1 / Math.cos(i); - return p(s, (i) => t((i * Math.PI) / 3) - 1); + const t = (s) => 1 / Math.cos(s); + return p(i, (s) => t((s * Math.PI) / 3) - 1); } throw new TypeError( "Unexpected parameters are delivered in trigo timing function." ); } - function C(n, s) { + function C(n, i) { if (!Number.isInteger(n)) throw new TypeError( "The first parameter of power timing function only allow integer." ); - return p(s, (e) => e ** n); + return p(i, (e) => e ** n); } - function G(n, s) { - if (n === "sin") return p(s, (e) => (Math.cosh(e * 2) - 1) / ($ - 1)); + function G(n, i) { + if (n === "sin") return p(i, (e) => (Math.cosh(e * 2) - 1) / ($ - 1)); if (n === "tan") { - const t = (i) => (Math.tanh(i * 3) * 1) / V; - return p(s, (i) => 1 - t(1 - i), t); + const t = (s) => (Math.tanh(s * 3) * 1) / V; + return p(i, (s) => 1 - t(1 - s), t); } if (n === "sec") { - const t = (i) => 1 / Math.cosh(i); - return p(s, (i) => 1 - (t(i * z) - 0.5) * 2); + const t = (s) => 1 / Math.cosh(s); + return p(i, (s) => 1 - (t(s * z) - 0.5) * 2); } throw new TypeError( "Unexpected parameters are delivered in hyper timing function." ); } - function N(n, s) { + function N(n, i) { if (n === "sin") { - const t = (i) => (Math.asin(i) / Math.PI) * 2; - return p(s, (i) => 1 - t(1 - i), t); + const t = (s) => (Math.asin(s) / Math.PI) * 2; + return p(i, (s) => 1 - t(1 - s), t); } if (n === "tan") { - const t = (i) => Math.atan(i * 5) / P; - return p(s, (i) => 1 - t(1 - i), t); + const t = (s) => Math.atan(s * 5) / P; + return p(i, (s) => 1 - t(1 - s), t); } throw new TypeError( "Unexpected parameters are delivered in inverse trigo timing function." ); } - function B(n, s = () => 1) { + function B(n, i = () => 1) { let t = -1; return (e) => ( - (t *= -1), e < 0.5 ? n * s(e * 2) * t : n * s((1 - e) * 2) * t + (t *= -1), e < 0.5 ? n * i(e * 2) * t : n * i((1 - e) * 2) * t ); } - function D(n, s = 1, t = [0, 0], e = 0, i = (h) => 1, r = !1) { - return (h) => { - const l = s * h * Math.PI * 2 + (e * Math.PI) / 180, - u = Math.cos(l), - c = Math.sin(l), - a = n * i(i(r ? 1 - h : h)); - return [a * u + t[0], a * c + t[1]]; + function D(n, i = 1, t = [0, 0], e = 0, s = (l) => 1, r = !1) { + return (l) => { + const a = i * l * Math.PI * 2 + (e * Math.PI) / 180, + u = Math.cos(a), + c = Math.sin(a), + h = n * s(s(r ? 1 - l : l)); + return [h * u + t[0], h * c + t[1]]; }; } - function H(n, s, ...t) { + function H(n, i, ...t) { const e = [n].concat(t); - e.push(s); - const i = e.length, - r = Array(i) + e.push(i); + const s = e.length, + r = Array(s) .fill(0) - .map((h, l) => A(l, i - 1)); - return (h) => { - const l = r.map( - (c, a) => c * e[a][0] * (1 - h) ** (i - a - 1) * h ** a + .map((l, a) => A(a, s - 1)); + return (l) => { + const a = r.map( + (c, h) => c * e[h][0] * (1 - l) ** (s - h - 1) * l ** h ), - u = r.map((c, a) => c * e[a][1] * (1 - h) ** (i - a - 1) * h ** a); - return [x(...l), x(...u)]; + u = r.map((c, h) => c * e[h][1] * (1 - l) ** (s - h - 1) * l ** h); + return [T(...a), T(...u)]; }; } - if ("animate" in core.plugin) throw new ReferenceError(`插件中已存在名为animate的属性!`); core.plugin.animate = { - Animation: Y, + Animation: j, AnimationBase: F, Ticker: I, - Transition: j, - sleep: R, - circle: D, - bezierPath: H, - linear: O, + Transition: O, bezier: q, - trigo: U, - power: C, + bezierPath: H, + circle: D, hyper: G, - inverseTrigo: N, + linear: Y, + power: C, shake: B, + sleep: R, + trigo: U, + inverseTrigo: N, }; }, - "func": function () { + func: function () { // 功能函数集,具体有哪些函数看每个函数前的注释即可 // 安装方式:直接复制到插件里面,注意新建插件自带的 function () { } 不能删 // 使用方式:可以直接使用对象解构按需引入 @@ -8399,7 +8447,2109 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = } }; }, - "怪物碎裂特效": function () { + 音频系统: function () { + // 在此增加新插件 + /*首先,在造塔群下载所需的库文件,然后放置在塔目录下的 libs/thirdparty 或其他目录下,之后在 index.html 的最后加上下面这几行: + + + + + + + */ + // 将__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))); + } + // 开始流传输 + while (true) { + const { value, done } = await reader.read(); + await Promise.all(targets.map((v) => v.pump(value, done, response))); + if (done) break; + } + + 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; + } + on(event, fn, context) {} + 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.player.status !== AudioStatus.Playing) { + this.player.status = AudioStatus.Playing; + } + this.createSourceNode(this.buffer); + this.output.start(0, when); + this.playing = true; + + this.output.addEventListener("ended", () => { + this.playing = false; + if (this.player.status === AudioStatus.Playing) { + this.player.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.player.status !== AudioStatus.Playing) { + this.player.status = AudioStatus.Playing; + } + }); + audio.addEventListener("ended", () => { + this.playing = false; + if (this.player.status === AudioStatus.Playing) { + this.player.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.player.status === AudioStatus.Playing) { + this.player.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.player.status !== AudioStatus.Playing) { + this.player.status = AudioStatus.Playing; + } + this.createSourceNode(this.buffer); + this.output.start(0, when); + this.output.addEventListener("ended", () => { + this.playing = false; + if (this.player.status === AudioStatus.Playing) { + this.player.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) { + this.output = source.output; + + /** 效果器路由图 */ + this.effectRoute = []; + + /** 结束时长,当音频暂停或停止时,会经过这么长时间之后才真正终止播放,期间可以做音频淡入淡出等效果 */ + this.endTime = 0; + /** 暂停时播放了多长时间 */ + this.pauseCurrentTime = 0; + /** 当前播放状态 */ + this.player = player; + this.player.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.player.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 从音频的什么时候开始播放,单位秒 + */ + play(when = 0) { + if (this.player.status === AudioStatus.Playing) return; + this.link(); + 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.player.status = AudioStatus.Playing; + this.pauseTime = 0; + this.audioStartHook?.(this); + this.startAllEffect(); + if (this.source.player.status !== AudioStatus.Playing) { + this.source.player.status = AudioStatus.Playing; + } + } + + /** + * 暂停音频播放 + */ + async pause() { + if (this.player.status !== AudioStatus.Playing) return; + this.player.status = AudioStatus.Pausing; + this.stopIdentifier++; + const identifier = this.stopIdentifier; + if (this.audioEndHook) { + this.audioEndHook(this.endTime, this); + await sleep(this.endTime); + } + if ( + this.player.status !== AudioStatus.Pausing || + this.stopIdentifier !== identifier + ) { + return; + } + this.pauseCurrentTime = this.source.currentTime; + const time = this.source.stop(); + this.pauseTime = time; + if (this.shouldStop) { + this.player.status = AudioStatus.Stoped; + this.endAllEffect(); + + this.shouldStop = false; + } else { + this.player.status = AudioStatus.Paused; + this.endAllEffect(); + } + this.endAllEffect(); + } + + /** + * 继续音频播放 + */ + resume() { + if (this.player.status === AudioStatus.Playing) return; + if ( + this.player.status === AudioStatus.Pausing || + this.player.status === AudioStatus.Stoping + ) { + this.audioStartHook?.(this); + + return; + } + if (this.player.status === AudioStatus.Paused) { + this.play(this.pauseTime); + } else { + this.play(0); + } + this.player.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; + if (this.player.status !== AudioStatus.Playing) { + this.player.status = AudioStatus.Playing; + } + } + + /** + * 继续当前的 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) 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) => { + 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 () { + if (bgmController.playing) return; + if (core.musicStatus.bgmStatus) { + if (bgmController.playingBgm) { + bgmController.play(bgmController.playingBgm); + } else { + play(main.startBgm, 0); + } + } else { + pause(); + } + }; + 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).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 () { // 在此增加新插件 // -------------------- 安装说明 -------------------- // // 先安装两个在插件简介中说明的前置插件 @@ -8532,6 +10682,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = return { animation: ani, + onEnd: promise.then(() => { ani.ticker.destroy(); onEnd(); @@ -8643,22 +10794,22 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = applyFragWith, }; }, - "自定义常用事件": function () { - // editorBlocklyconfigPlus.js - // 自訂常見事件模板插件 - // 本插件引用了通用函數插件(Utility.js) - // 適用樣板:2.10.3 - // 請注意: - // 此插件對事件編輯器(editor_blocklyconfig)進行複寫,若還有其它針對事件編輯器做複寫的插件,請謹慎使用! - // 此插件對表格操作行為(editor_mode.doActionList)進行複寫,若還有其它對表格操作行為做複寫的插件,請謹慎使用! - // 使用方法: - // 現在在主頁下拉選單多了個常用事件模版,在那邊可以自由設定常用事件模板。 - // 設定完後按F5刷新,再到事件編輯器看就有你設定好的常用事件模板了。 + 自定义常用事件: function () { + // editorBlocklyconfigPlus.js + // 自訂常見事件模板插件 + // 本插件引用了通用函數插件(Utility.js) + // 適用樣板:2.10.3 + // 請注意: + // 此插件對事件編輯器(editor_blocklyconfig)進行複寫,若還有其它針對事件編輯器做複寫的插件,請謹慎使用! + // 此插件對表格操作行為(editor_mode.doActionList)進行複寫,若還有其它對表格操作行為做複寫的插件,請謹慎使用! + // 使用方法: + // 現在在主頁下拉選單多了個常用事件模版,在那邊可以自由設定常用事件模板。 + // 設定完後按F5刷新,再到事件編輯器看就有你設定好的常用事件模板了。 - if (main.mode == "editor") { - //#region 配置表格初始化 - let TableFileName = "project/table/CommonEventTemplate_comment.js"; - let TableRow = ` + if (main.mode == "editor") { + //#region 配置表格初始化 + let TableFileName = "project/table/CommonEventTemplate_comment.js"; + let TableRow = ` var CommonEventTemplate_comment = {"_type": "object", "_data": { "CommonEventTemplate": { @@ -8701,221 +10852,241 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = } }} `; - if (!events_c12a15a8_c380_4b28_8144_256cba95f760.CommonEventTemplate) { - /** - * @type {{[EvnetName:actionParserJson]}} - */ - events_c12a15a8_c380_4b28_8144_256cba95f760.CommonEventTemplate = { - 检测音乐如果没有开启则系统提示开启: [{ - type: "if", - condition: "!core.musicStatus.bgmStatus", - true: [ - "\t[系统提示]你当前音乐处于关闭状态,本塔开音乐游戏效果更佳", - ], - false: [], - }, ], - 仿新新魔塔一次性商人: [{ - type: "if", - condition: "switch:A", - true: [ - "\t[行商,trader]\b[this]这是购买我的道具后我给玩家的提示。", - { - type: "comment", - text: "下一条指令可视情况使用或不使用", - }, - { - type: "hide", - remove: true, - time: 250, - }, - ], - false: [{ - type: "confirm", - text: "我有3把黄钥匙,\n你出50金币就卖给你。", - yes: [{ - type: "if", - condition: "status:money>=50", - true: [{ - type: "setValue", - name: "status:money", - operator: "-=", - value: "50", - }, - { - type: "setValue", - name: "item:yellowKey", - operator: "+=", - value: "3", - }, - { - type: "playSound", - name: "确定", - stop: true, - }, - { - type: "setValue", - name: "switch:A", - value: "true", - }, - ], - false: [{ - type: "playSound", - name: "操作失败", - }, - "\t[行商,trader]\b[this]你的金币不足!", - ], - }, ], - no: [], - }, ], - }, ], - 全地图选中一个点: [{ - type: "comment", - text: "全地图选中一个点,需要用鼠标或触屏操作", - }, - { - type: "setValue", - name: "temp:X", - value: "status:x", - }, - { - type: "setValue", - name: "temp:Y", - value: "status:y", - }, - { - type: "tip", - text: "再次点击闪烁位置确认", - }, - { - type: "while", - condition: "true", - data: [{ - type: "drawSelector", - image: "winskin.webp", - code: 1, - x: "32*temp:X", - y: "32*temp:Y", - width: 32, - height: 32, - }, - { - type: "wait", - }, - { - type: "if", - condition: "(flag:type === 1)", - true: [{ - type: "if", - condition: "((temp:X===flag:x)&&(temp:Y===flag:y))", - true: [{ - type: "break", - n: 1, - }, ], - }, - { - type: "setValue", - name: "temp:X", - value: "flag:x", - }, - { - type: "setValue", - name: "temp:Y", - value: "flag:y", - }, - ], - }, - ], - }, - { - type: "drawSelector", - code: 1, - }, - { - type: "comment", - text: "流程进行到这里可以对[X,Y]点进行处理,比如", - }, - { - type: "closeDoor", - id: "yellowDoor", - loc: ["temp:X", "temp:Y"], - }, - ], - 多阶段Boss战斗: [{ - type: "comment", - text: "多阶段boss,请直接作为战后事件使用", - }, - { - type: "setValue", - name: "switch:A", - operator: "+=", - value: "1", - }, - { - type: "switch", - condition: "switch:A", - caseList: [{ - case: "1", - action: [{ - type: "setBlock", - number: "redSlime", - }, - "\t[2阶段boss,redSlime]\b[this]你以为你已经打败我了吗?没听说过史莱姆有九条命吗?", - ], - }, - { - case: "2", - action: [{ - type: "setBlock", - number: "blackSlime", - }, - "\t[3阶段boss,blackSlime]\b[this]不能消灭我的,只会让我更强大!", - ], - }, - { - case: "3", - action: [{ - type: "setBlock", - number: "slimelord", - }, - "\t[4阶段boss,slimelord]\b[this]我还能打!", - ], - }, - { - case: "4", - action: ["\t[4阶段boss,slimelord]我一定会回来的!"], - }, - ], - }, - ], - }; - } - //#endregion + if (!events_c12a15a8_c380_4b28_8144_256cba95f760.CommonEventTemplate) { + /** + * @type {{[EvnetName:actionParserJson]}} + */ + events_c12a15a8_c380_4b28_8144_256cba95f760.CommonEventTemplate = { + 检测音乐如果没有开启则系统提示开启: [ + { + type: "if", + condition: "!core.musicStatus.bgmStatus", + true: [ + "\t[系统提示]你当前音乐处于关闭状态,本塔开音乐游戏效果更佳", + ], + false: [], + }, + ], + 仿新新魔塔一次性商人: [ + { + type: "if", + condition: "switch:A", + true: [ + "\t[行商,trader]\b[this]这是购买我的道具后我给玩家的提示。", + { + type: "comment", + text: "下一条指令可视情况使用或不使用", + }, + { + type: "hide", + remove: true, + time: 250, + }, + ], + false: [ + { + type: "confirm", + text: "我有3把黄钥匙,\n你出50金币就卖给你。", + yes: [ + { + type: "if", + condition: "status:money>=50", + true: [ + { + type: "setValue", + name: "status:money", + operator: "-=", + value: "50", + }, + { + type: "setValue", + name: "item:yellowKey", + operator: "+=", + value: "3", + }, + { + type: "playSound", + name: "确定", + stop: true, + }, + { + type: "setValue", + name: "switch:A", + value: "true", + }, + ], + false: [ + { + type: "playSound", + name: "操作失败", + }, + "\t[行商,trader]\b[this]你的金币不足!", + ], + }, + ], + no: [], + }, + ], + }, + ], + 全地图选中一个点: [ + { + type: "comment", + text: "全地图选中一个点,需要用鼠标或触屏操作", + }, + { + type: "setValue", + name: "temp:X", + value: "status:x", + }, + { + type: "setValue", + name: "temp:Y", + value: "status:y", + }, + { + type: "tip", + text: "再次点击闪烁位置确认", + }, + { + type: "while", + condition: "true", + data: [ + { + type: "drawSelector", + image: "winskin.webp", + code: 1, + x: "32*temp:X", + y: "32*temp:Y", + width: 32, + height: 32, + }, + { + type: "wait", + }, + { + type: "if", + condition: "(flag:type === 1)", + true: [ + { + type: "if", + condition: "((temp:X===flag:x)&&(temp:Y===flag:y))", + true: [ + { + type: "break", + n: 1, + }, + ], + }, + { + type: "setValue", + name: "temp:X", + value: "flag:x", + }, + { + type: "setValue", + name: "temp:Y", + value: "flag:y", + }, + ], + }, + ], + }, + { + type: "drawSelector", + code: 1, + }, + { + type: "comment", + text: "流程进行到这里可以对[X,Y]点进行处理,比如", + }, + { + type: "closeDoor", + id: "yellowDoor", + loc: ["temp:X", "temp:Y"], + }, + ], + 多阶段Boss战斗: [ + { + type: "comment", + text: "多阶段boss,请直接作为战后事件使用", + }, + { + type: "setValue", + name: "switch:A", + operator: "+=", + value: "1", + }, + { + type: "switch", + condition: "switch:A", + caseList: [ + { + case: "1", + action: [ + { + type: "setBlock", + number: "redSlime", + }, + "\t[2阶段boss,redSlime]\b[this]你以为你已经打败我了吗?没听说过史莱姆有九条命吗?", + ], + }, + { + case: "2", + action: [ + { + type: "setBlock", + number: "blackSlime", + }, + "\t[3阶段boss,blackSlime]\b[this]不能消灭我的,只会让我更强大!", + ], + }, + { + case: "3", + action: [ + { + type: "setBlock", + number: "slimelord", + }, + "\t[4阶段boss,slimelord]\b[this]我还能打!", + ], + }, + { + case: "4", + action: ["\t[4阶段boss,slimelord]我一定会回来的!"], + }, + ], + }, + ], + }; + } + //#endregion - // 新增模板選項 - let editModeSelect = document.getElementById("editModeSelect"); - let newEditModeOption = document.createElement("option"); - newEditModeOption.value = "CommonEventTemplate"; - newEditModeOption.text = "常見事件模板"; - editModeSelect.add(newEditModeOption); + // 新增模板選項 + let editModeSelect = document.getElementById("editModeSelect"); + let newEditModeOption = document.createElement("option"); + newEditModeOption.value = "CommonEventTemplate"; + newEditModeOption.text = "常見事件模板"; + editModeSelect.add(newEditModeOption); - //檢查可用的編輯模板ID - let leftIDNumber = 11 - 1; - let ExistLeftElement = document.querySelector(".main"); - while (ExistLeftElement) { - leftIDNumber++; - ExistLeftElement = document.getElementById(`left${leftIDNumber}`); - } + //檢查可用的編輯模板ID + let leftIDNumber = 11 - 1; + let ExistLeftElement = document.querySelector(".main"); + while (ExistLeftElement) { + leftIDNumber++; + ExistLeftElement = document.getElementById(`left${leftIDNumber}`); + } - //新增編輯模板 - let MainDiv = document.querySelector(".main"); + //新增編輯模板 + let MainDiv = document.querySelector(".main"); - let CommonEventTemplateMainDiv = document.createElement("div"); - CommonEventTemplateMainDiv.id = `left${leftIDNumber}`; - CommonEventTemplateMainDiv.className = "leftTab"; - CommonEventTemplateMainDiv.style.zIndex = "-1"; - CommonEventTemplateMainDiv.style.opacity = "0"; + let CommonEventTemplateMainDiv = document.createElement("div"); + CommonEventTemplateMainDiv.id = `left${leftIDNumber}`; + CommonEventTemplateMainDiv.className = "leftTab"; + CommonEventTemplateMainDiv.style.zIndex = "-1"; + CommonEventTemplateMainDiv.style.opacity = "0"; - CommonEventTemplateMainDiv.innerHTML = ` + CommonEventTemplateMainDiv.innerHTML = `

常見事件模板   @@ -8938,959 +11109,981 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = `; - MainDiv.appendChild(CommonEventTemplateMainDiv); + MainDiv.appendChild(CommonEventTemplateMainDiv); - (async function () { - //等待編輯器初始化 - while (!editor_mode.ids) { - await Sleep(100); - } - //新增編輯模板ID - editor_mode.ids["CommonEventTemplate"] = `left${leftIDNumber}`; - editor_mode.init_dom_ids(); - //切換至常見事件模板 - editor_mode.CommonEventTemplate = function (callback) { - var objs = []; - editor.file.editCommonEventTemplate([], function (objs_) { - objs = objs_; - //console.log(objs_) - }); - //只查询不修改时,内部实现不是异步的,所以可以这么写 - var tableinfo = editor.table.objToTable(objs[0], objs[1]); - document.getElementById( - "table_298572d8-93dd-4c6e-a278-6a7d49831e3a" - ).innerHTML = tableinfo.HTML; - tableinfo.listen(tableinfo.guids); - if (Boolean(callback)) callback(); - }; + (async function () { + //等待編輯器初始化 + while (!editor_mode.ids) { + await Sleep(100); + } + //新增編輯模板ID + editor_mode.ids["CommonEventTemplate"] = `left${leftIDNumber}`; + editor_mode.init_dom_ids(); + //切換至常見事件模板 + editor_mode.CommonEventTemplate = function (callback) { + var objs = []; + editor.file.editCommonEventTemplate([], function (objs_) { + objs = objs_; + //console.log(objs_) + }); + //只查询不修改时,内部实现不是异步的,所以可以这么写 + var tableinfo = editor.table.objToTable(objs[0], objs[1]); + document.getElementById( + "table_298572d8-93dd-4c6e-a278-6a7d49831e3a" + ).innerHTML = tableinfo.HTML; + tableinfo.listen(tableinfo.guids); + if (Boolean(callback)) callback(); + }; - //檢查配置表格存在 - let TableRowExist = null; - fs.readFile(TableFileName, "base64", function (err, data) { - if (err) { - console.log(`察覺常見事件模板配置表格不存在,原因:${err}`); - console.log("新建一個常見事件模板配置表格。"); - TableRowExist = false; - } else { - TableRowExist = true; - } - }); - //等待配置表格載入完畢(最多0.3秒,超過則視為失敗) - for (let i = 0; i < 3; i++) { - if (TableRowExist == null) { - await Sleep(100); - } - } - //配置表格初始化 - if (TableRowExist != true) { - fs.mkdir("project/table", function (err, data) { - if (err) throw `常見事件模板配置表格目錄初始化失敗,原因:${err}`; - }); - fs.writeFile( - TableFileName, - editor.util.encode64(TableRow || ""), - "base64", - function (err, data) { - if (err) throw `常見事件模板配置表格文件初始化失敗,原因:${err}`; - } - ); - } - //載入配置表格 - //editor.file.loadCommentjs(callback); - (function () { - var key = "CommonEventTemplate_comment"; - var script = document.createElement("script"); - script.src = "project/table/" + key + ".js"; - document.body.appendChild(script); - script.onload = function () { - editor.file[key] = eval(key.replace(".", "_")); - var loaded = Boolean(editor.file[key]); - }; - })(); - //按下配置表格 - editor_multi.CommonEventTemplateEditCommentJs = function (mod) { - editor_multi.lintAutocomplete = true; - editor_multi.setLint(); - editor_multi.importFile(TableFileName); - }; + //檢查配置表格存在 + let TableRowExist = null; + fs.readFile(TableFileName, "base64", function (err, data) { + if (err) { + console.log(`察覺常見事件模板配置表格不存在,原因:${err}`); + console.log("新建一個常見事件模板配置表格。"); + TableRowExist = false; + } else { + TableRowExist = true; + } + }); + //等待配置表格載入完畢(最多0.3秒,超過則視為失敗) + for (let i = 0; i < 3; i++) { + if (TableRowExist == null) { + await Sleep(100); + } + } + //配置表格初始化 + if (TableRowExist != true) { + fs.mkdir("project/table", function (err, data) { + if (err) throw `常見事件模板配置表格目錄初始化失敗,原因:${err}`; + }); + fs.writeFile( + TableFileName, + editor.util.encode64(TableRow || ""), + "base64", + function (err, data) { + if (err) throw `常見事件模板配置表格文件初始化失敗,原因:${err}`; + } + ); + } + //載入配置表格 + //editor.file.loadCommentjs(callback); + (function () { + var key = "CommonEventTemplate_comment"; + var script = document.createElement("script"); + script.src = "project/table/" + key + ".js"; + document.body.appendChild(script); + script.onload = function () { + editor.file[key] = eval(key.replace(".", "_")); + var loaded = Boolean(editor.file[key]); + }; + })(); + //按下配置表格 + editor_multi.CommonEventTemplateEditCommentJs = function (mod) { + editor_multi.lintAutocomplete = true; + editor_multi.setLint(); + editor_multi.importFile(TableFileName); + }; - //定義表格操作行為 - editor_mode.OriginDoActionList = editor_mode.doActionList; - editor_mode.doActionList = function (mode, actionList, callback) { - if (editor_mode.mode == "CommonEventTemplate") { - if (actionList.length == 0) return; - printf("修改中..."); - var cb = function (objs_) { - if (objs_.slice(-1)[0] != null) { - printe(objs_.slice(-1)[0]); - throw objs_.slice(-1)[0]; - } - var str = "修改成功!"; - if ( - data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.firstData.name == - "template" - ) - str += "
请注意:全塔属性的name尚未修改,请及时予以设置。"; - printf(str); - if (callback) callback(); - }; - editor.file.editCommonEventTemplate(actionList, cb); - } else { - editor_mode.OriginDoActionList(mode, actionList, callback); - } - }; - //添加表格列 - editor.table.CommonEventTemplateAddFunc = function () { - let obj = events_c12a15a8_c380_4b28_8144_256cba95f760; + //定義表格操作行為 + editor_mode.OriginDoActionList = editor_mode.doActionList; + editor_mode.doActionList = function (mode, actionList, callback) { + if (editor_mode.mode == "CommonEventTemplate") { + if (actionList.length == 0) return; + printf("修改中..."); + var cb = function (objs_) { + if (objs_.slice(-1)[0] != null) { + printe(objs_.slice(-1)[0]); + throw objs_.slice(-1)[0]; + } + var str = "修改成功!"; + if ( + data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.firstData.name == + "template" + ) + str += "
请注意:全塔属性的name尚未修改,请及时予以设置。"; + printf(str); + if (callback) callback(); + }; + editor.file.editCommonEventTemplate(actionList, cb); + } else { + editor_mode.OriginDoActionList(mode, actionList, callback); + } + }; + //添加表格列 + editor.table.CommonEventTemplateAddFunc = function () { + let obj = events_c12a15a8_c380_4b28_8144_256cba95f760; - // 1.输入id - let newid = prompt("请输入新项的ID(支持中文)"); - if (newid == null || newid.length == 0) { - return; - } + // 1.输入id + let newid = prompt("请输入新项的ID(支持中文)"); + if (newid == null || newid.length == 0) { + return; + } - // 2.检查id是否符合规范或与已有id重复 - var conflict = true; - var basefield = "".replace(/\[[^\[]*\]$/, ""); + // 2.检查id是否符合规范或与已有id重复 + var conflict = true; + var basefield = "".replace(/\[[^\[]*\]$/, ""); - try { - var baseobj = eval("obj" + basefield); - conflict = newid in baseobj; - } catch (ee) { - // 理论上这里不会发生错误 - printe(ee); - throw ee; - } + try { + var baseobj = eval("obj" + basefield); + conflict = newid in baseobj; + } catch (ee) { + // 理论上这里不会发生错误 + printe(ee); + throw ee; + } - if (conflict) { - printe("id已存在, 请直接修改该项的值"); - return; - } + if (conflict) { + printe("id已存在, 请直接修改该项的值"); + return; + } - // 3.添加 - editor_mode.addAction(["add", basefield + "['" + newid + "']", null]); - editor_mode.onmode("save", function () { - printf("添加成功,刷新后生效;也可以继续新增其他项目。"); - }); //自动保存 删掉此行的话点保存按钮才会保存 - }; - //對表格的存讀 - editor.file.editCommonEventTemplate = function (actionList, callback) { - /*actionList:[ + // 3.添加 + editor_mode.addAction(["add", basefield + "['" + newid + "']", null]); + editor_mode.onmode("save", function () { + printf("添加成功,刷新后生效;也可以继续新增其他项目。"); + }); //自动保存 删掉此行的话点保存按钮才会保存 + }; + //對表格的存讀 + editor.file.editCommonEventTemplate = function (actionList, callback) { + /*actionList:[ ["change","['test']",['123']], ] 为[]时只查询不修改 */ - var data_obj = - events_c12a15a8_c380_4b28_8144_256cba95f760.CommonEventTemplate; - checkCallback(callback); - if (isset(actionList) && actionList.length > 0) { - actionList.forEach(function (value) { - value[1] = "['CommonEventTemplate']" + value[1]; - }); - editor.file.saveSetting("events", actionList, function (err) { - callback([err]); - }); - } else { - callback([ - Object.assign({}, data_obj), - editor.file.CommonEventTemplate_comment._data.CommonEventTemplate, - null, - ]); - } - }; - })(); + var data_obj = + events_c12a15a8_c380_4b28_8144_256cba95f760.CommonEventTemplate; + checkCallback(callback); + if (isset(actionList) && actionList.length > 0) { + actionList.forEach(function (value) { + value[1] = "['CommonEventTemplate']" + value[1]; + }); + editor.file.saveSetting("events", actionList, function (err) { + callback([err]); + }); + } else { + callback([ + Object.assign({}, data_obj), + editor.file.CommonEventTemplate_comment._data.CommonEventTemplate, + null, + ]); + } + }; + })(); - //複寫事件編輯器(editor_blocklyconfig) - editor_blocklyconfig = function () { - // start mark sfergsvae + //複寫事件編輯器(editor_blocklyconfig) + editor_blocklyconfig = function () { + // start mark sfergsvae - (function () { - var getCategory = function (name, custom) { - for (var node of document.getElementById("toolbox").children) { - if (node.getAttribute("name") == name) return node; - } - var node = document.createElement("category"); - node.setAttribute("name", name); - if (custom) node.setAttribute("custom", custom); - document.getElementById("toolbox").appendChild(node); - return node; - }; + (function () { + var getCategory = function (name, custom) { + for (var node of document.getElementById("toolbox").children) { + if (node.getAttribute("name") == name) return node; + } + var node = document.createElement("category"); + node.setAttribute("name", name); + if (custom) node.setAttribute("custom", custom); + document.getElementById("toolbox").appendChild(node); + return node; + }; - var toolboxObj = { - 入口方块: [ - '', - MotaActionFunctions.actionParser.parse( - [ - "欢迎使用事件编辑器", - "本事件触发一次后会消失", - { type: "hide", time: 500 }, - ], - "event" - ), - MotaActionFunctions.actionParser.parse({ - condition: "flag:__door__===2", - currentFloor: true, - priority: 0, - delayExecute: false, - multiExecute: false, - data: [{ type: "openDoor", loc: [10, 5] }], - }, - "autoEvent" - ), - MotaActionBlocks["changeFloor_m"].xmlText(), - MotaActionFunctions.actionParser.parse( - [{ - id: "shop1", - text: "\t[贪婪之神,moneyShop]勇敢的武士啊, 给我${20+2*flag:shop1}金币就可以:", - textInList: "1F金币商店", - choices: [{ - text: "生命+800", - need: "status:money>=20+2*flag:shop1", - action: [{ - type: "comment", - text: "新版商店中需要手动扣减金币和增加访问次数", - }, - { - type: "setValue", - name: "status:money", - operator: "-=", - value: "20+2*flag:shop1", - }, - { - type: "setValue", - name: "flag:shop1", - operator: "+=", - value: "1", - }, - { - type: "setValue", - name: "status:hp", - operator: "+=", - value: "800", - }, - ], - }, ], - }, - { - id: "itemShop", - item: true, - textInList: "道具商店", - choices: [{ id: "yellowKey", number: 10, money: 10 }], - }, - { - id: "keyShop1", - textInList: "回收钥匙商店", - commonEvent: "回收钥匙商店", - args: "", - }, - ], - "shop" - ), - MotaActionBlocks["common_m"].xmlText(), - MotaActionBlocks["beforeBattle_m"].xmlText(), - MotaActionBlocks["afterBattle_m"].xmlText(), - MotaActionBlocks["afterGetItem_m"].xmlText(), - MotaActionBlocks["afterOpenDoor_m"].xmlText(), - MotaActionBlocks["firstArrive_m"].xmlText(), - MotaActionBlocks["eachArrive_m"].xmlText(), - MotaActionBlocks["level_m"].xmlText(), - MotaActionFunctions.actionParser.parse( - [ - ["MTx", ""] - ], - "floorPartition" - ), - MotaActionBlocks["commonEvent_m"].xmlText(), - MotaActionBlocks["item_m"].xmlText(), - MotaActionFunctions.actionParser.parse( - [{ - title: "简单", - name: "Easy", - hard: 1, - action: [ - { type: "comment", text: "在这里写该难度需执行的事件" }, - ], - }, ], - "levelChoose" - ), - MotaActionFunctions.actionParser.parse({ - type: 0, - value: { atk: 10 }, - percentage: { speed: 10 }, - }, - "equip" - ), - MotaActionFunctions.actionParser.parse( - [{ - name: "bg.webp", - x: 0, - y: 0, - canvas: "bg", - }, ], - "floorImage" - ), - MotaActionFunctions.actionParser.parse({ - time: 160, - openSound: "door.mp3", - closeSound: "door.mp3", - keys: { yellowKey: 1, orangeKey: 1 }, - }, - "doorInfo" - ), - MotaActionBlocks["faceIds_m"].xmlText(), - MotaActionBlocks["mainStyle_m"].xmlText(), - MotaActionFunctions.actionParser.parse({ - 背景音乐: "bgm.mp3", - 确定: "confirm.mp3", - 攻击: "attack.mp3", - 背景图: "bg.webp", - 领域: "zone", - 文件名: "file.jpg", - }, - "nameMap" - ), - MotaActionFunctions.actionParser.parse( - [{ name: "hero.webp", width: 32, height: 32, prefix: "hero_" }], - "splitImages" - ), - ], - 显示文字: [ - MotaActionBlocks["text_0_s"].xmlText(), - MotaActionBlocks["text_1_s"].xmlText(), - MotaActionFunctions.actionParser.parseList( - "\t[小妖精,fairy]\f[fairy.webp,0,0]欢迎使用事件编辑器(双击方块可直接预览)" - ), - MotaActionBlocks["over_s"].xmlText(), - MotaActionFunctions.actionParser.parseList([{ - type: "overlist", - image: "bg_5043.webp", - memory: false, - hidetime: 30, - list: [{ - text: "", - sound: "", - time: 50, - textColor: "255,255,255,1", - boldColor: "0,0,0,1", - font: "bold 48px Verdana", - frame: 0, - }, ], - }, ]), - MotaActionFunctions.actionParser.parseList([{ - type: "cgtext", - bg: "bg_5043.webp", - memory: false, - WindowSkin: false, - head: { name: "face_050445.webp", px: -300 }, - name: "菲奥奈", - time: 0, - wait: 2000, - sound: "", - text: "这句话显示在对话框内", - bodyList: [ - { name: "tati_050145a.webp", px: 100, filter: false }, - ], - }, ]), - MotaActionBlocks["moveTextBox_s"].xmlText(), - MotaActionBlocks["clearTextBox_s"].xmlText(), - MotaActionBlocks["comment_s"].xmlText(), - MotaActionBlocks["autoText_s"].xmlText(), - MotaActionBlocks["scrollText_s"].xmlText(), - MotaActionBlocks["setText_s"].xmlText(), - MotaActionBlocks["tip_s"].xmlText(), - MotaActionBlocks["addPop_s"].xmlText(), - MotaActionBlocks["confirm_s"].xmlText(), - MotaActionBlocks["choices_s"].xmlText([ - "选择剑或者盾", - "流浪者", - "man", - 0, - "", - MotaActionBlocks["choicesContext"].xmlText([ - "剑", - "", - "", - null, - "", - "", - MotaActionFunctions.actionParser.parseList([ - { type: "openDoor", loc: [3, 3] }, - ]), - ]), - ]), - MotaActionBlocks["win_s"].xmlText(), - MotaActionBlocks["lose_s"].xmlText(), - MotaActionBlocks["restart_s"].xmlText(), - ], - 数据相关: [ - MotaActionBlocks["setValue_s"].xmlText([ - MotaActionBlocks["idIdList_e"].xmlText(["status", "生命"]), - "=", - "", - false, - ]), - MotaActionBlocks["setEnemy_s"].xmlText(), - MotaActionBlocks["setEnemyOnPoint_s"].xmlText(), - MotaActionBlocks["resetEnemyOnPoint_s"].xmlText(), - MotaActionBlocks["moveEnemyOnPoint_s"].xmlText(), - MotaActionBlocks["moveEnemyOnPoint_1_s"].xmlText(), - MotaActionBlocks["setEquip_s"].xmlText(), - MotaActionBlocks["setFloor_s"].xmlText(), - MotaActionBlocks["setGlobalAttribute_s"].xmlText(), - MotaActionBlocks["setGlobalValue_s"].xmlText(), - MotaActionBlocks["setGlobalFlag_s"].xmlText(), - MotaActionBlocks["setNameMap_s"].xmlText(), - MotaActionBlocks["input_s"].xmlText(), - MotaActionBlocks["input2_s"].xmlText(), - MotaActionBlocks["update_s"].xmlText(), - MotaActionBlocks["moveAction_s"].xmlText(), - MotaActionBlocks["changeFloor_s"].xmlText(), - MotaActionBlocks["changePos_s"].xmlText(), - MotaActionBlocks["battle_s"].xmlText(), - MotaActionBlocks["useItem_s"].xmlText(), - MotaActionBlocks["loadEquip_s"].xmlText(), - MotaActionBlocks["unloadEquip_s"].xmlText(), - MotaActionBlocks["openShop_s"].xmlText(), - MotaActionBlocks["disableShop_s"].xmlText(), - MotaActionBlocks["setHeroIcon_s"].xmlText(), - MotaActionBlocks["follow_s"].xmlText(), - MotaActionBlocks["unfollow_s"].xmlText(), - ], - 地图处理: [ - MotaActionBlocks["battle_1_s"].xmlText(), - MotaActionBlocks["openDoor_s"].xmlText(), - MotaActionBlocks["closeDoor_s"].xmlText(), - MotaActionBlocks["show_s"].xmlText(), - MotaActionBlocks["hide_s"].xmlText(), - MotaActionBlocks["setBlock_s"].xmlText(), - MotaActionBlocks["setBlockOpacity_s"].xmlText(), - MotaActionBlocks["setBlockFilter_s"].xmlText(), - MotaActionBlocks["turnBlock_s"].xmlText(), - MotaActionBlocks["moveHero_s"].xmlText(), - MotaActionBlocks["move_s"].xmlText(), - MotaActionBlocks["jumpHero_s"].xmlText(), - MotaActionBlocks["jumpHero_1_s"].xmlText(), - MotaActionBlocks["jump_s"].xmlText(), - MotaActionBlocks["jump_1_s"].xmlText(), - MotaActionBlocks["showBgFgMap_s"].xmlText(), - MotaActionBlocks["hideBgFgMap_s"].xmlText(), - MotaActionBlocks["setBgFgBlock_s"].xmlText(), - MotaActionBlocks["showFloorImg_s"].xmlText(), - MotaActionBlocks["hideFloorImg_s"].xmlText(), - ], - 事件控制: [ - MotaActionBlocks["if_1_s"].xmlText(), - MotaActionBlocks["if_s"].xmlText(), - MotaActionFunctions.actionParser.parseList({ - type: "switch", - condition: "判别值", - caseList: [{ - action: [ - { type: "comment", text: "当判别值是值的场合执行此事件" }, - ], - }, - { - case: "default", - action: [{ - type: "comment", - text: "当没有符合的值的场合执行default事件", - }, ], - }, - ], - }), - MotaActionFunctions.actionParser.parseList({ - type: "for", - name: "temp:A", - from: "0", - to: "12", - step: "1", - data: [], - }), - MotaActionFunctions.actionParser.parseList({ - type: "forEach", - name: "temp:A", - list: ["status:atk", "status:def"], - data: [], - }), - MotaActionBlocks["while_s"].xmlText(), - MotaActionBlocks["dowhile_s"].xmlText(), - MotaActionBlocks["break_s"].xmlText(), - MotaActionBlocks["continue_s"].xmlText(), - MotaActionBlocks["exit_s"].xmlText(), - MotaActionBlocks["trigger_s"].xmlText(), - MotaActionBlocks["insert_1_s"].xmlText(), - MotaActionBlocks["insert_2_s"].xmlText(), - ], - 特效表现: [ - MotaActionBlocks["sleep_s"].xmlText(), - MotaActionBlocks["changebg_s"].xmlText(), - MotaActionFunctions.actionParser.parseList({ - type: "wait", - timeout: 0, - data: [{ - case: "keyboard", - keycode: "13,32", - action: [{ - type: "comment", - text: "当按下回车(keycode=13)或空格(keycode=32)时执行此事件\n超时剩余时间会写入flag:timeout", - }, ], - }, - { - case: "mouse", - px: [0, 32], - py: [0, 32], - action: [{ - type: "comment", - text: "当点击地图左上角时执行此事件\n超时剩余时间会写入flag:timeout", - }, ], - }, - { - case: "condition", - condition: "flag:type==0\n&&flag:keycode==13", - action: [{ - type: "comment", - text: "当满足自定义条件时会执行此事件\n超时剩余时间会写入flag:timeout", - }, ], - }, - { - case: "timeout", - action: [ - { type: "comment", text: "当超时未操作时执行此事件" }, - ], - }, - ], - }), - MotaActionBlocks["waitAsync_s"].xmlText(), - MotaActionBlocks["stopAsync_s"].xmlText(), - MotaActionBlocks["op_s"].xmlText(), - MotaActionBlocks["drawWarning_s"].xmlText(), - MotaActionBlocks["changeMouse_s"].xmlText(), - MotaActionBlocks["removeMouse_s"].xmlText(), - MotaActionBlocks["vibrate_s"].xmlText(), - MotaActionBlocks["setanimate_s"].xmlText(), - MotaActionBlocks["deleteanimate_s"].xmlText(), - MotaActionBlocks["playanimate_s"].xmlText(), - MotaActionBlocks["clearanimate_s"].xmlText(), - MotaActionBlocks["animate_s"].xmlText(), - MotaActionBlocks["animate_1_s"].xmlText(), - MotaActionBlocks["stopAnimate_s"].xmlText(), - MotaActionBlocks["setViewport_s"].xmlText(), - MotaActionBlocks["setViewport_1_s"].xmlText(), - MotaActionBlocks["lockViewport_s"].xmlText(), - MotaActionBlocks["showStatusBar_s"].xmlText(), - MotaActionBlocks["hideStatusBar_s"].xmlText(), - MotaActionBlocks["setHeroOpacity_s"].xmlText(), - MotaActionBlocks["setCurtain_0_s"].xmlText(), - MotaActionBlocks["setCurtain_1_s"].xmlText(), - MotaActionBlocks["screenFlash_s"].xmlText(), - MotaActionBlocks["setWeather_s"].xmlText(), - MotaActionBlocks["callBook_s"].xmlText(), - MotaActionBlocks["callSave_s"].xmlText(), - MotaActionBlocks["autoSave_s"].xmlText(), - MotaActionBlocks["forbidSave_s"].xmlText(), - MotaActionBlocks["callLoad_s"].xmlText(), - ], - 音像处理: [ - MotaActionBlocks["animationDrawable_s"].xmlText(), - MotaActionBlocks["setanimate_s"].xmlText(), - MotaActionBlocks["deleteanimate_s"].xmlText(), - MotaActionBlocks["playanimate_s"].xmlText(), - MotaActionBlocks["clearanimate_s"].xmlText(), - MotaActionBlocks["showImage_s"].xmlText(), - MotaActionBlocks["showImage_1_s"].xmlText(), - MotaActionBlocks["hideImage_s"].xmlText(), - MotaActionBlocks["showTextImage_s"].xmlText(), - MotaActionBlocks["moveImage_s"].xmlText(), - MotaActionBlocks["rotateImage_s"].xmlText(), - MotaActionBlocks["scaleImage_s"].xmlText(), - MotaActionBlocks["showGif_s"].xmlText(), - MotaActionBlocks["playBgm_s"].xmlText(), - MotaActionBlocks["playStereo_s"].xmlText(), - MotaActionBlocks["moveStereo_s"].xmlText(), - MotaActionBlocks["pauseBgm_s"].xmlText(), - MotaActionBlocks["resumeBgm_s"].xmlText(), - MotaActionBlocks["loadBgm_s"].xmlText(), - MotaActionBlocks["freeBgm_s"].xmlText(), - MotaActionBlocks["playSound_s"].xmlText(), - MotaActionBlocks["playSound_1_s"].xmlText(), - MotaActionBlocks["stopSound_s"].xmlText(), - MotaActionBlocks["setVolume_s"].xmlText(), - MotaActionBlocks["setBgmSpeed_s"].xmlText(), - ], - UI绘制: [ - MotaActionBlocks["previewUI_s"].xmlText(), - MotaActionBlocks["clearMap_s"].xmlText(), - MotaActionBlocks["setAttribute_s"].xmlText(), - MotaActionBlocks["setFilter_s"].xmlText(), - MotaActionBlocks["fillText_s"].xmlText(), - MotaActionBlocks["fillBoldText_s"].xmlText(), - MotaActionBlocks["drawTextContent_s"].xmlText(), - MotaActionBlocks["fillRect_s"].xmlText(), - MotaActionBlocks["strokeRect_s"].xmlText(), - MotaActionBlocks["drawLine_s"].xmlText(), - MotaActionBlocks["drawArrow_s"].xmlText(), - MotaActionBlocks["fillPolygon_s"].xmlText(), - MotaActionBlocks["strokePolygon_s"].xmlText(), - MotaActionBlocks["fillEllipse_s"].xmlText(), - MotaActionBlocks["strokeEllipse_s"].xmlText(), - MotaActionBlocks["fillArc_s"].xmlText(), - MotaActionBlocks["strokeArc_s"].xmlText(), - MotaActionBlocks["drawImage_s"].xmlText(), - MotaActionBlocks["drawImage_1_s"].xmlText(), - MotaActionBlocks["drawIcon_s"].xmlText(), - MotaActionBlocks["drawBackground_s"].xmlText(), - MotaActionBlocks["drawSelector_s"].xmlText(), - MotaActionBlocks["drawSelector_1_s"].xmlText(), - ], - 原生脚本: [ - MotaActionBlocks["function_s"].xmlText(), - MotaActionBlocks["unknown_s"].xmlText(), - ], - 值块: [ - MotaActionBlocks["setValue_s"].xmlText([ - MotaActionBlocks["idIdList_e"].xmlText(["status", "生命"]), - "=", - "", - false, - ]), - MotaActionBlocks["expression_arithmetic_0"].xmlText(), - MotaActionBlocks["idFlag_e"].xmlText(), - MotaActionBlocks["idTemp_e"].xmlText(), - MotaActionBlocks["negate_e"].xmlText(), - MotaActionBlocks["unaryOperation_e"].xmlText(), - MotaActionBlocks["bool_e"].xmlText(), - MotaActionBlocks["idString_e"].xmlText(), - MotaActionBlocks["idIdList_e"].xmlText(), - MotaActionBlocks["idFixedList_e"].xmlText(), - MotaActionBlocks["enemyattr_e"].xmlText(), - MotaActionBlocks["blockId_e"].xmlText(), - MotaActionBlocks["blockNumber_e"].xmlText(), - MotaActionBlocks["blockCls_e"].xmlText(), - MotaActionBlocks["hasEquip_e"].xmlText(), - MotaActionBlocks["equip_e"].xmlText(), - MotaActionBlocks["nextXY_e"].xmlText(), - MotaActionBlocks["isReplaying_e"].xmlText(), - MotaActionBlocks["hasVisitedFloor_e"].xmlText(), - MotaActionBlocks["isShopVisited_e"].xmlText(), - MotaActionBlocks["canBattle_e"].xmlText(), - MotaActionBlocks["damage_e"].xmlText(), - MotaActionBlocks["damage_1_e"].xmlText(), - MotaActionBlocks["rand_e"].xmlText(), - MotaActionBlocks["evalString_e"].xmlText(), - ], - 常见事件模板: [ - '', - ], - 最近使用事件: [ - '', - ], - }; - var toolboxgap = ''; - //xml_text = MotaActionFunctions.actionParser.parse(obj,type||'event') - //MotaActionBlocks['idString_e'].xmlText() + var toolboxObj = { + 入口方块: [ + '', + MotaActionFunctions.actionParser.parse( + [ + "欢迎使用事件编辑器", + "本事件触发一次后会消失", + { type: "hide", time: 500 }, + ], + "event" + ), + MotaActionFunctions.actionParser.parse( + { + condition: "flag:__door__===2", + currentFloor: true, + priority: 0, + delayExecute: false, + multiExecute: false, + data: [{ type: "openDoor", loc: [10, 5] }], + }, + "autoEvent" + ), + MotaActionBlocks["changeFloor_m"].xmlText(), + MotaActionFunctions.actionParser.parse( + [ + { + id: "shop1", + text: "\t[贪婪之神,moneyShop]勇敢的武士啊, 给我${20+2*flag:shop1}金币就可以:", + textInList: "1F金币商店", + choices: [ + { + text: "生命+800", + need: "status:money>=20+2*flag:shop1", + action: [ + { + type: "comment", + text: "新版商店中需要手动扣减金币和增加访问次数", + }, + { + type: "setValue", + name: "status:money", + operator: "-=", + value: "20+2*flag:shop1", + }, + { + type: "setValue", + name: "flag:shop1", + operator: "+=", + value: "1", + }, + { + type: "setValue", + name: "status:hp", + operator: "+=", + value: "800", + }, + ], + }, + ], + }, + { + id: "itemShop", + item: true, + textInList: "道具商店", + choices: [{ id: "yellowKey", number: 10, money: 10 }], + }, + { + id: "keyShop1", + textInList: "回收钥匙商店", + commonEvent: "回收钥匙商店", + args: "", + }, + ], + "shop" + ), + MotaActionBlocks["common_m"].xmlText(), + MotaActionBlocks["beforeBattle_m"].xmlText(), + MotaActionBlocks["afterBattle_m"].xmlText(), + MotaActionBlocks["afterGetItem_m"].xmlText(), + MotaActionBlocks["afterOpenDoor_m"].xmlText(), + MotaActionBlocks["firstArrive_m"].xmlText(), + MotaActionBlocks["eachArrive_m"].xmlText(), + MotaActionBlocks["level_m"].xmlText(), + MotaActionFunctions.actionParser.parse( + [["MTx", ""]], + "floorPartition" + ), + MotaActionBlocks["commonEvent_m"].xmlText(), + MotaActionBlocks["item_m"].xmlText(), + MotaActionFunctions.actionParser.parse( + [ + { + title: "简单", + name: "Easy", + hard: 1, + action: [ + { type: "comment", text: "在这里写该难度需执行的事件" }, + ], + }, + ], + "levelChoose" + ), + MotaActionFunctions.actionParser.parse( + { + type: 0, + value: { atk: 10 }, + percentage: { speed: 10 }, + }, + "equip" + ), + MotaActionFunctions.actionParser.parse( + [ + { + name: "bg.webp", + x: 0, + y: 0, + canvas: "bg", + }, + ], + "floorImage" + ), + MotaActionFunctions.actionParser.parse( + { + time: 160, + openSound: "door.opus", + closeSound: "door.opus", + keys: { yellowKey: 1, orangeKey: 1 }, + }, + "doorInfo" + ), + MotaActionBlocks["faceIds_m"].xmlText(), + MotaActionBlocks["mainStyle_m"].xmlText(), + MotaActionFunctions.actionParser.parse( + { + 背景音乐: "bgm.opus", + 确定: "confirm.opus", + 攻击: "attack.opus", + 背景图: "bg.webp", + 领域: "zone", + 文件名: "file.jpg", + }, + "nameMap" + ), + MotaActionFunctions.actionParser.parse( + [{ name: "hero.webp", width: 32, height: 32, prefix: "hero_" }], + "splitImages" + ), + ], + 显示文字: [ + MotaActionBlocks["text_0_s"].xmlText(), + MotaActionBlocks["text_1_s"].xmlText(), + MotaActionFunctions.actionParser.parseList( + "\t[小妖精,fairy]\f[fairy.webp,0,0]欢迎使用事件编辑器(双击方块可直接预览)" + ), + MotaActionBlocks["over_s"].xmlText(), + MotaActionFunctions.actionParser.parseList([ + { + type: "overlist", + image: "bg_5043.webp", + memory: false, + hidetime: 30, + list: [ + { + text: "", + sound: "", + time: 50, + textColor: "255,255,255,1", + boldColor: "0,0,0,1", + font: "bold 48px Verdana", + frame: 0, + }, + ], + }, + ]), + MotaActionFunctions.actionParser.parseList([ + { + type: "cgtext", + bg: "bg_5043.webp", + memory: false, + WindowSkin: false, + head: { name: "face_050445.webp", px: -300 }, + name: "菲奥奈", + time: 0, + wait: 2000, + sound: "", + text: "这句话显示在对话框内", + bodyList: [ + { name: "tati_050145a.webp", px: 100, filter: false }, + ], + }, + ]), + MotaActionBlocks["moveTextBox_s"].xmlText(), + MotaActionBlocks["clearTextBox_s"].xmlText(), + MotaActionBlocks["comment_s"].xmlText(), + MotaActionBlocks["autoText_s"].xmlText(), + MotaActionBlocks["scrollText_s"].xmlText(), + MotaActionBlocks["setText_s"].xmlText(), + MotaActionBlocks["tip_s"].xmlText(), + MotaActionBlocks["addPop_s"].xmlText(), + MotaActionBlocks["confirm_s"].xmlText(), + MotaActionBlocks["choices_s"].xmlText([ + "选择剑或者盾", + "流浪者", + "man", + 0, + "", + MotaActionBlocks["choicesContext"].xmlText([ + "剑", + "", + "", + null, + "", + "", + MotaActionFunctions.actionParser.parseList([ + { type: "openDoor", loc: [3, 3] }, + ]), + ]), + ]), + MotaActionBlocks["win_s"].xmlText(), + MotaActionBlocks["lose_s"].xmlText(), + MotaActionBlocks["restart_s"].xmlText(), + ], + 数据相关: [ + MotaActionBlocks["setValue_s"].xmlText([ + MotaActionBlocks["idIdList_e"].xmlText(["status", "生命"]), + "=", + "", + false, + ]), + MotaActionBlocks["setEnemy_s"].xmlText(), + MotaActionBlocks["setEnemyOnPoint_s"].xmlText(), + MotaActionBlocks["resetEnemyOnPoint_s"].xmlText(), + MotaActionBlocks["moveEnemyOnPoint_s"].xmlText(), + MotaActionBlocks["moveEnemyOnPoint_1_s"].xmlText(), + MotaActionBlocks["setEquip_s"].xmlText(), + MotaActionBlocks["setFloor_s"].xmlText(), + MotaActionBlocks["setGlobalAttribute_s"].xmlText(), + MotaActionBlocks["setGlobalValue_s"].xmlText(), + MotaActionBlocks["setGlobalFlag_s"].xmlText(), + MotaActionBlocks["setNameMap_s"].xmlText(), + MotaActionBlocks["input_s"].xmlText(), + MotaActionBlocks["input2_s"].xmlText(), + MotaActionBlocks["update_s"].xmlText(), + MotaActionBlocks["moveAction_s"].xmlText(), + MotaActionBlocks["changeFloor_s"].xmlText(), + MotaActionBlocks["changePos_s"].xmlText(), + MotaActionBlocks["battle_s"].xmlText(), + MotaActionBlocks["useItem_s"].xmlText(), + MotaActionBlocks["loadEquip_s"].xmlText(), + MotaActionBlocks["unloadEquip_s"].xmlText(), + MotaActionBlocks["openShop_s"].xmlText(), + MotaActionBlocks["disableShop_s"].xmlText(), + MotaActionBlocks["setHeroIcon_s"].xmlText(), + MotaActionBlocks["follow_s"].xmlText(), + MotaActionBlocks["unfollow_s"].xmlText(), + ], + 地图处理: [ + MotaActionBlocks["battle_1_s"].xmlText(), + MotaActionBlocks["openDoor_s"].xmlText(), + MotaActionBlocks["closeDoor_s"].xmlText(), + MotaActionBlocks["show_s"].xmlText(), + MotaActionBlocks["hide_s"].xmlText(), + MotaActionBlocks["setBlock_s"].xmlText(), + MotaActionBlocks["setBlockOpacity_s"].xmlText(), + MotaActionBlocks["setBlockFilter_s"].xmlText(), + MotaActionBlocks["turnBlock_s"].xmlText(), + MotaActionBlocks["moveHero_s"].xmlText(), + MotaActionBlocks["move_s"].xmlText(), + MotaActionBlocks["jumpHero_s"].xmlText(), + MotaActionBlocks["jumpHero_1_s"].xmlText(), + MotaActionBlocks["jump_s"].xmlText(), + MotaActionBlocks["jump_1_s"].xmlText(), + MotaActionBlocks["showBgFgMap_s"].xmlText(), + MotaActionBlocks["hideBgFgMap_s"].xmlText(), + MotaActionBlocks["setBgFgBlock_s"].xmlText(), + MotaActionBlocks["showFloorImg_s"].xmlText(), + MotaActionBlocks["hideFloorImg_s"].xmlText(), + ], + 事件控制: [ + MotaActionBlocks["if_1_s"].xmlText(), + MotaActionBlocks["if_s"].xmlText(), + MotaActionFunctions.actionParser.parseList({ + type: "switch", + condition: "判别值", + caseList: [ + { + action: [ + { type: "comment", text: "当判别值是值的场合执行此事件" }, + ], + }, + { + case: "default", + action: [ + { + type: "comment", + text: "当没有符合的值的场合执行default事件", + }, + ], + }, + ], + }), + MotaActionFunctions.actionParser.parseList({ + type: "for", + name: "temp:A", + from: "0", + to: "12", + step: "1", + data: [], + }), + MotaActionFunctions.actionParser.parseList({ + type: "forEach", + name: "temp:A", + list: ["status:atk", "status:def"], + data: [], + }), + MotaActionBlocks["while_s"].xmlText(), + MotaActionBlocks["dowhile_s"].xmlText(), + MotaActionBlocks["break_s"].xmlText(), + MotaActionBlocks["continue_s"].xmlText(), + MotaActionBlocks["exit_s"].xmlText(), + MotaActionBlocks["trigger_s"].xmlText(), + MotaActionBlocks["insert_1_s"].xmlText(), + MotaActionBlocks["insert_2_s"].xmlText(), + ], + 特效表现: [ + MotaActionBlocks["sleep_s"].xmlText(), + MotaActionBlocks["changebg_s"].xmlText(), + MotaActionFunctions.actionParser.parseList({ + type: "wait", + timeout: 0, + data: [ + { + case: "keyboard", + keycode: "13,32", + action: [ + { + type: "comment", + text: "当按下回车(keycode=13)或空格(keycode=32)时执行此事件\n超时剩余时间会写入flag:timeout", + }, + ], + }, + { + case: "mouse", + px: [0, 32], + py: [0, 32], + action: [ + { + type: "comment", + text: "当点击地图左上角时执行此事件\n超时剩余时间会写入flag:timeout", + }, + ], + }, + { + case: "condition", + condition: "flag:type==0\n&&flag:keycode==13", + action: [ + { + type: "comment", + text: "当满足自定义条件时会执行此事件\n超时剩余时间会写入flag:timeout", + }, + ], + }, + { + case: "timeout", + action: [ + { type: "comment", text: "当超时未操作时执行此事件" }, + ], + }, + ], + }), + MotaActionBlocks["waitAsync_s"].xmlText(), + MotaActionBlocks["stopAsync_s"].xmlText(), + MotaActionBlocks["op_s"].xmlText(), + MotaActionBlocks["drawWarning_s"].xmlText(), + MotaActionBlocks["changeMouse_s"].xmlText(), + MotaActionBlocks["removeMouse_s"].xmlText(), + MotaActionBlocks["vibrate_s"].xmlText(), + MotaActionBlocks["setanimate_s"].xmlText(), + MotaActionBlocks["deleteanimate_s"].xmlText(), + MotaActionBlocks["playanimate_s"].xmlText(), + MotaActionBlocks["clearanimate_s"].xmlText(), + MotaActionBlocks["animate_s"].xmlText(), + MotaActionBlocks["animate_1_s"].xmlText(), + MotaActionBlocks["stopAnimate_s"].xmlText(), + MotaActionBlocks["setViewport_s"].xmlText(), + MotaActionBlocks["setViewport_1_s"].xmlText(), + MotaActionBlocks["lockViewport_s"].xmlText(), + MotaActionBlocks["showStatusBar_s"].xmlText(), + MotaActionBlocks["hideStatusBar_s"].xmlText(), + MotaActionBlocks["setHeroOpacity_s"].xmlText(), + MotaActionBlocks["setCurtain_0_s"].xmlText(), + MotaActionBlocks["setCurtain_1_s"].xmlText(), + MotaActionBlocks["screenFlash_s"].xmlText(), + MotaActionBlocks["setWeather_s"].xmlText(), + MotaActionBlocks["callBook_s"].xmlText(), + MotaActionBlocks["callSave_s"].xmlText(), + MotaActionBlocks["autoSave_s"].xmlText(), + MotaActionBlocks["forbidSave_s"].xmlText(), + MotaActionBlocks["callLoad_s"].xmlText(), + ], + 音像处理: [ + MotaActionBlocks["animationDrawable_s"].xmlText(), + MotaActionBlocks["setanimate_s"].xmlText(), + MotaActionBlocks["deleteanimate_s"].xmlText(), + MotaActionBlocks["playanimate_s"].xmlText(), + MotaActionBlocks["clearanimate_s"].xmlText(), + MotaActionBlocks["showImage_s"].xmlText(), + MotaActionBlocks["showImage_1_s"].xmlText(), + MotaActionBlocks["hideImage_s"].xmlText(), + MotaActionBlocks["showTextImage_s"].xmlText(), + MotaActionBlocks["moveImage_s"].xmlText(), + MotaActionBlocks["rotateImage_s"].xmlText(), + MotaActionBlocks["scaleImage_s"].xmlText(), + MotaActionBlocks["showGif_s"].xmlText(), + MotaActionBlocks["playBgm_s"].xmlText(), + MotaActionBlocks["playStereo_s"].xmlText(), + MotaActionBlocks["moveStereo_s"].xmlText(), + MotaActionBlocks["pauseBgm_s"].xmlText(), + MotaActionBlocks["resumeBgm_s"].xmlText(), + MotaActionBlocks["loadBgm_s"].xmlText(), + MotaActionBlocks["freeBgm_s"].xmlText(), + MotaActionBlocks["playSound_s"].xmlText(), + MotaActionBlocks["playSound_1_s"].xmlText(), + MotaActionBlocks["stopSound_s"].xmlText(), + MotaActionBlocks["setVolume_s"].xmlText(), + MotaActionBlocks["setBgmSpeed_s"].xmlText(), + ], + UI绘制: [ + MotaActionBlocks["previewUI_s"].xmlText(), + MotaActionBlocks["clearMap_s"].xmlText(), + MotaActionBlocks["setAttribute_s"].xmlText(), + MotaActionBlocks["setFilter_s"].xmlText(), + MotaActionBlocks["fillText_s"].xmlText(), + MotaActionBlocks["fillBoldText_s"].xmlText(), + MotaActionBlocks["drawTextContent_s"].xmlText(), + MotaActionBlocks["fillRect_s"].xmlText(), + MotaActionBlocks["strokeRect_s"].xmlText(), + MotaActionBlocks["drawLine_s"].xmlText(), + MotaActionBlocks["drawArrow_s"].xmlText(), + MotaActionBlocks["fillPolygon_s"].xmlText(), + MotaActionBlocks["strokePolygon_s"].xmlText(), + MotaActionBlocks["fillEllipse_s"].xmlText(), + MotaActionBlocks["strokeEllipse_s"].xmlText(), + MotaActionBlocks["fillArc_s"].xmlText(), + MotaActionBlocks["strokeArc_s"].xmlText(), + MotaActionBlocks["drawImage_s"].xmlText(), + MotaActionBlocks["drawImage_1_s"].xmlText(), + MotaActionBlocks["drawIcon_s"].xmlText(), + MotaActionBlocks["drawBackground_s"].xmlText(), + MotaActionBlocks["drawSelector_s"].xmlText(), + MotaActionBlocks["drawSelector_1_s"].xmlText(), + ], + 原生脚本: [ + MotaActionBlocks["function_s"].xmlText(), + MotaActionBlocks["unknown_s"].xmlText(), + ], + 值块: [ + MotaActionBlocks["setValue_s"].xmlText([ + MotaActionBlocks["idIdList_e"].xmlText(["status", "生命"]), + "=", + "", + false, + ]), + MotaActionBlocks["expression_arithmetic_0"].xmlText(), + MotaActionBlocks["idFlag_e"].xmlText(), + MotaActionBlocks["idTemp_e"].xmlText(), + MotaActionBlocks["negate_e"].xmlText(), + MotaActionBlocks["unaryOperation_e"].xmlText(), + MotaActionBlocks["bool_e"].xmlText(), + MotaActionBlocks["idString_e"].xmlText(), + MotaActionBlocks["idIdList_e"].xmlText(), + MotaActionBlocks["idFixedList_e"].xmlText(), + MotaActionBlocks["enemyattr_e"].xmlText(), + MotaActionBlocks["blockId_e"].xmlText(), + MotaActionBlocks["blockNumber_e"].xmlText(), + MotaActionBlocks["blockCls_e"].xmlText(), + MotaActionBlocks["hasEquip_e"].xmlText(), + MotaActionBlocks["equip_e"].xmlText(), + MotaActionBlocks["nextXY_e"].xmlText(), + MotaActionBlocks["isReplaying_e"].xmlText(), + MotaActionBlocks["hasVisitedFloor_e"].xmlText(), + MotaActionBlocks["isShopVisited_e"].xmlText(), + MotaActionBlocks["canBattle_e"].xmlText(), + MotaActionBlocks["damage_e"].xmlText(), + MotaActionBlocks["damage_1_e"].xmlText(), + MotaActionBlocks["rand_e"].xmlText(), + MotaActionBlocks["evalString_e"].xmlText(), + ], + 常见事件模板: [ + '', + ], + 最近使用事件: [ + '', + ], + }; + var toolboxgap = ''; + //xml_text = MotaActionFunctions.actionParser.parse(obj,type||'event') + //MotaActionBlocks['idString_e'].xmlText() - //#region 動態常見事件模板 - let CommonEventTemplateHTML = []; + //#region 動態常見事件模板 + let CommonEventTemplateHTML = []; - for (let commonEventName in events_c12a15a8_c380_4b28_8144_256cba95f760.CommonEventTemplate) { - if ( - events_c12a15a8_c380_4b28_8144_256cba95f760.CommonEventTemplate.hasOwnProperty( - commonEventName - ) - ) { - let actionParserJson = Array.from( - events_c12a15a8_c380_4b28_8144_256cba95f760.CommonEventTemplate[ - commonEventName - ] ?? [] - ); + for (let commonEventName in events_c12a15a8_c380_4b28_8144_256cba95f760.CommonEventTemplate) { + if ( + events_c12a15a8_c380_4b28_8144_256cba95f760.CommonEventTemplate.hasOwnProperty( + commonEventName + ) + ) { + let actionParserJson = Array.from( + events_c12a15a8_c380_4b28_8144_256cba95f760.CommonEventTemplate[ + commonEventName + ] ?? [] + ); - let labelHTML = ""; - let blockHTML = ""; + let labelHTML = ""; + let blockHTML = ""; - labelHTML = ``; + labelHTML = ``; - if (actionParserJson.length > 1) { - actionParserJson = { - type: "if", - condition: "true", - true: actionParserJson, - }; - } else if (actionParserJson.length < 1) { - actionParserJson = [ - "空的常用事件模板。\n請在主頁下拉菜單中,選擇常用事件模板,進行編輯。\n編輯後需按F5刷新事件編輯器。", - ]; - } - blockHTML = - MotaActionFunctions.actionParser.parseList(actionParserJson); + if (actionParserJson.length > 1) { + actionParserJson = { + type: "if", + condition: "true", + true: actionParserJson, + }; + } else if (actionParserJson.length < 1) { + actionParserJson = [ + "空的常用事件模板。\n請在主頁下拉菜單中,選擇常用事件模板,進行編輯。\n編輯後需按F5刷新事件編輯器。", + ]; + } + blockHTML = + MotaActionFunctions.actionParser.parseList(actionParserJson); - CommonEventTemplateHTML.push(labelHTML); - CommonEventTemplateHTML.push(blockHTML); - } - } + CommonEventTemplateHTML.push(labelHTML); + CommonEventTemplateHTML.push(blockHTML); + } + } - toolboxObj["常见事件模板"] = CommonEventTemplateHTML; - //#endregion + toolboxObj["常见事件模板"] = CommonEventTemplateHTML; + //#endregion - for (var name in toolboxObj) { - var custom = null; - if (name == "最近使用事件") custom = "searchBlockCategory"; - if (name == "入口方块") custom = "entranceCategory"; - getCategory(name, custom).innerHTML = - toolboxObj[name].join(toolboxgap); - } + for (var name in toolboxObj) { + var custom = null; + if (name == "最近使用事件") custom = "searchBlockCategory"; + if (name == "入口方块") custom = "entranceCategory"; + getCategory(name, custom).innerHTML = + toolboxObj[name].join(toolboxgap); + } - var blocklyArea = document.getElementById("blocklyArea"); - var blocklyDiv = document.getElementById("blocklyDiv"); - var workspace = Blockly.inject(blocklyDiv, { - media: "_server/blockly/media/", - toolbox: document.getElementById("toolbox"), - zoom: { - controls: true, - wheel: false, //滚轮改为上下(shift:左右)翻滚 - startScale: 1.0, - maxScale: 3, - minScale: 0.3, - scaleSpeed: 1.08, - }, - trashcan: false, - }); + var blocklyArea = document.getElementById("blocklyArea"); + var blocklyDiv = document.getElementById("blocklyDiv"); + var workspace = Blockly.inject(blocklyDiv, { + media: "_server/blockly/media/", + toolbox: document.getElementById("toolbox"), + zoom: { + controls: true, + wheel: false, //滚轮改为上下(shift:左右)翻滚 + startScale: 1.0, + maxScale: 3, + minScale: 0.3, + scaleSpeed: 1.08, + }, + trashcan: false, + }); - editor_blockly.isCommonEntry = function () { - var commonEntries = [ - "beforeBattle", - "afterBattle", - "afterOpenDoor", - "firstArrive", - "eachArrive", - "commonEvent", - "item", - ]; - return commonEntries.indexOf(editor_blockly.entryType) >= 0; - }; + editor_blockly.isCommonEntry = function () { + var commonEntries = [ + "beforeBattle", + "afterBattle", + "afterOpenDoor", + "firstArrive", + "eachArrive", + "commonEvent", + "item", + ]; + return commonEntries.indexOf(editor_blockly.entryType) >= 0; + }; - editor_blockly.entranceCategoryCallback = function (workspace) { - var list = toolboxObj["入口方块"]; - var xmlList = []; - var eventType = - (editor_blockly.isCommonEntry() ? - "common" : - editor_blockly.entryType) + "_m"; - for (var ii = 0, blockText; - (blockText = list[ii]); ii++) { - if ( - new RegExp('').exec(blockText) - ) { - var block = Blockly.Xml.textToDom( - "" + blockText + "" - ).firstChild; - block.setAttribute("gap", 5); - xmlList.push(block); - } - } - return xmlList; - }; + editor_blockly.entranceCategoryCallback = function (workspace) { + var list = toolboxObj["入口方块"]; + var xmlList = []; + var eventType = + (editor_blockly.isCommonEntry() + ? "common" + : editor_blockly.entryType) + "_m"; + for (var ii = 0, blockText; (blockText = list[ii]); ii++) { + if ( + new RegExp('').exec(blockText) + ) { + var block = Blockly.Xml.textToDom( + "" + blockText + "" + ).firstChild; + block.setAttribute("gap", 5); + xmlList.push(block); + } + } + return xmlList; + }; - workspace.registerToolboxCategoryCallback( - "entranceCategory", - editor_blockly.entranceCategoryCallback - ); + workspace.registerToolboxCategoryCallback( + "entranceCategory", + editor_blockly.entranceCategoryCallback + ); - editor_blockly.searchBlockCategoryCallback = function (workspace) { - var xmlList = []; - var labels = editor_blockly.searchBlock(); - for (var i = 0; i < labels.length; i++) { - var blockText = - "" + MotaActionBlocks[labels[i]].xmlText() + ""; - var block = Blockly.Xml.textToDom(blockText).firstChild; - block.setAttribute("gap", 5); - xmlList.push(block); - } - return xmlList; - }; + editor_blockly.searchBlockCategoryCallback = function (workspace) { + var xmlList = []; + var labels = editor_blockly.searchBlock(); + for (var i = 0; i < labels.length; i++) { + var blockText = + "" + MotaActionBlocks[labels[i]].xmlText() + ""; + var block = Blockly.Xml.textToDom(blockText).firstChild; + block.setAttribute("gap", 5); + xmlList.push(block); + } + return xmlList; + }; - workspace.registerToolboxCategoryCallback( - "searchBlockCategory", - editor_blockly.searchBlockCategoryCallback - ); + workspace.registerToolboxCategoryCallback( + "searchBlockCategory", + editor_blockly.searchBlockCategoryCallback + ); - var onresize = function (e) { - blocklyDiv.style.width = blocklyArea.offsetWidth + "px"; - blocklyDiv.style.height = blocklyArea.offsetHeight + "px"; - Blockly.svgResize(workspace); - }; - if (typeof editor !== "undefined" && !editor.isMobile) - window.addEventListener("resize", onresize, false); - onresize(); - //Blockly.svgResize(workspace); + var onresize = function (e) { + blocklyDiv.style.width = blocklyArea.offsetWidth + "px"; + blocklyDiv.style.height = blocklyArea.offsetHeight + "px"; + Blockly.svgResize(workspace); + }; + if (typeof editor !== "undefined" && !editor.isMobile) + window.addEventListener("resize", onresize, false); + onresize(); + //Blockly.svgResize(workspace); - //Blockly.bindEventWithChecks_(workspace.svgGroup_,"wheel",workspace,function(e){}); - document.getElementById("blocklyDiv").onmousewheel = function (e) { - //console.log(e); - e.preventDefault(); - var hvScroll = e.shiftKey ? "hScroll" : "vScroll"; - var mousewheelOffsetValue = - (20 / 380) * workspace.scrollbar[hvScroll].handleLength_ * 3; - workspace.scrollbar[hvScroll].handlePosition_ += - (e.deltaY || 0) + (e.detail || 0) > 0 ? - mousewheelOffsetValue : - -mousewheelOffsetValue; - workspace.scrollbar[hvScroll].onScroll_(); - // workspace.setScale(workspace.scale); - }; + //Blockly.bindEventWithChecks_(workspace.svgGroup_,"wheel",workspace,function(e){}); + document.getElementById("blocklyDiv").onmousewheel = function (e) { + //console.log(e); + e.preventDefault(); + var hvScroll = e.shiftKey ? "hScroll" : "vScroll"; + var mousewheelOffsetValue = + (20 / 380) * workspace.scrollbar[hvScroll].handleLength_ * 3; + workspace.scrollbar[hvScroll].handlePosition_ += + (e.deltaY || 0) + (e.detail || 0) > 0 + ? mousewheelOffsetValue + : -mousewheelOffsetValue; + workspace.scrollbar[hvScroll].onScroll_(); + // workspace.setScale(workspace.scale); + }; - var doubleClickCheck = [ - [0, "abc"] - ]; + var doubleClickCheck = [[0, "abc"]]; - function omitedcheckUpdateFunction(event) { - if (event.type === "create") { - editor_blockly.addIntoLastUsedType(event.blockId); - } - if (event.type === "ui" && event.element == "click") { - var newClick = [new Date().getTime(), event.blockId]; - var lastClick = doubleClickCheck.shift(); - doubleClickCheck.push(newClick); - if (newClick[0] - lastClick[0] < 500) { - if (newClick[1] === lastClick[1]) { - editor_blockly.doubleClickBlock(newClick[1]); - } - } - } - // Only handle these events - if (["create", "move", "change", "delete"].indexOf(event.type) < 0) - return; - if (editor_blockly.workspace.topBlocks_.length >= 2) { - editor_blockly.setValue("入口方块只能有一个"); - return; - } - var eventType = editor_blockly.entryType; - if (editor_blockly.workspace.topBlocks_.length == 1) { - var blockType = editor_blockly.workspace.topBlocks_[0].type; - if ( - blockType !== eventType + "_m" && - !(editor_blockly.isCommonEntry() && blockType == "common_m") - ) { - editor_blockly.setValue("入口方块类型错误"); - return; - } - } - try { - var code = Blockly.JavaScript.workspaceToCode(workspace).replace( - /\\(i|c|d|e|g|z)/g, - "\\\\$1" - ); - editor_blockly.setValue(code); - } catch (error) { - editor_blockly.setValue(String(error)); - if (error instanceof OmitedError) { - var blockName = error.blockName; - var varName = error.varName; - var block = error.block; - } - // console.log(error); - } - } + function omitedcheckUpdateFunction(event) { + if (event.type === "create") { + editor_blockly.addIntoLastUsedType(event.blockId); + } + if (event.type === "ui" && event.element == "click") { + var newClick = [new Date().getTime(), event.blockId]; + var lastClick = doubleClickCheck.shift(); + doubleClickCheck.push(newClick); + if (newClick[0] - lastClick[0] < 500) { + if (newClick[1] === lastClick[1]) { + editor_blockly.doubleClickBlock(newClick[1]); + } + } + } + // Only handle these events + if (["create", "move", "change", "delete"].indexOf(event.type) < 0) + return; + if (editor_blockly.workspace.topBlocks_.length >= 2) { + editor_blockly.setValue("入口方块只能有一个"); + return; + } + var eventType = editor_blockly.entryType; + if (editor_blockly.workspace.topBlocks_.length == 1) { + var blockType = editor_blockly.workspace.topBlocks_[0].type; + if ( + blockType !== eventType + "_m" && + !(editor_blockly.isCommonEntry() && blockType == "common_m") + ) { + editor_blockly.setValue("入口方块类型错误"); + return; + } + } + try { + var code = Blockly.JavaScript.workspaceToCode(workspace).replace( + /\\(i|c|d|e|g|z)/g, + "\\\\$1" + ); + editor_blockly.setValue(code); + } catch (error) { + editor_blockly.setValue(String(error)); + if (error instanceof OmitedError) { + var blockName = error.blockName; + var varName = error.varName; + var block = error.block; + } + // console.log(error); + } + } - workspace.addChangeListener(omitedcheckUpdateFunction); + workspace.addChangeListener(omitedcheckUpdateFunction); - workspace.addChangeListener(Blockly.Events.disableOrphans); + workspace.addChangeListener(Blockly.Events.disableOrphans); - editor_blockly.workspace = workspace; + editor_blockly.workspace = workspace; - MotaActionFunctions.workspace = function () { - return editor_blockly.workspace; - }; + MotaActionFunctions.workspace = function () { + return editor_blockly.workspace; + }; - // 因为在editor_blockly.parse里已经HTML转义过一次了,所以这里要覆盖掉以避免在注释中出现<等 - MotaActionFunctions.xmlText = function ( - ruleName, - inputs, - isShadow, - comment, - collapsed, - disabled - ) { - var rule = MotaActionBlocks[ruleName]; - var blocktext = isShadow ? "shadow" : "block"; - var xmlText = []; - xmlText.push( - "<" + - blocktext + - ' type="' + - ruleName + - '"' + - (collapsed ? ' collapsed="true"' : "") + - (disabled ? ' disabled="true"' : "") + - ">" - ); - if (!inputs) inputs = []; - for (var ii = 0, inputType; - (inputType = rule.argsType[ii]); ii++) { - var input = inputs[ii]; - var _input = ""; - var noinput = input === null || input === undefined; - if ( - noinput && - inputType === "field" && - MotaActionBlocks[rule.argsGrammarName[ii]].type !== - "field_dropdown" - ) - continue; - if (noinput && inputType === "field") { - noinput = false; - input = rule.fieldDefault(rule.args[ii]); - } - if (noinput) input = ""; - if ( - inputType === "field" && - MotaActionBlocks[rule.argsGrammarName[ii]].type === - "field_checkbox" - ) - input = input ? "TRUE" : "FALSE"; - if (inputType !== "field") { - var subList = false; - var subrulename = rule.argsGrammarName[ii]; - var subrule = MotaActionBlocks[subrulename]; - if (subrule instanceof Array) { - subrulename = subrule[subrule.length - 1]; - subrule = MotaActionBlocks[subrulename]; - subList = true; - } - _input = subrule.xmlText([], true); - if (noinput && !subList && !isShadow) { - //无输入的默认行为是: 如果语句块的备选方块只有一个,直接代入方块 - input = subrule.xmlText(); - } - } - xmlText.push("<" + inputType + ' name="' + rule.args[ii] + '">'); - xmlText.push(_input + input); - xmlText.push(""); - } - if (comment) { - xmlText.push(""); - xmlText.push(comment); - xmlText.push(""); - } - var next = inputs[rule.args.length]; - if (next) { - //next - xmlText.push(""); - xmlText.push(next); - xmlText.push(""); - } - xmlText.push(""); - return xmlText.join(""); - }; - })(); + // 因为在editor_blockly.parse里已经HTML转义过一次了,所以这里要覆盖掉以避免在注释中出现<等 + MotaActionFunctions.xmlText = function ( + ruleName, + inputs, + isShadow, + comment, + collapsed, + disabled + ) { + var rule = MotaActionBlocks[ruleName]; + var blocktext = isShadow ? "shadow" : "block"; + var xmlText = []; + xmlText.push( + "<" + + blocktext + + ' type="' + + ruleName + + '"' + + (collapsed ? ' collapsed="true"' : "") + + (disabled ? ' disabled="true"' : "") + + ">" + ); + if (!inputs) inputs = []; + for (var ii = 0, inputType; (inputType = rule.argsType[ii]); ii++) { + var input = inputs[ii]; + var _input = ""; + var noinput = input === null || input === undefined; + if ( + noinput && + inputType === "field" && + MotaActionBlocks[rule.argsGrammarName[ii]].type !== + "field_dropdown" + ) + continue; + if (noinput && inputType === "field") { + noinput = false; + input = rule.fieldDefault(rule.args[ii]); + } + if (noinput) input = ""; + if ( + inputType === "field" && + MotaActionBlocks[rule.argsGrammarName[ii]].type === + "field_checkbox" + ) + input = input ? "TRUE" : "FALSE"; + if (inputType !== "field") { + var subList = false; + var subrulename = rule.argsGrammarName[ii]; + var subrule = MotaActionBlocks[subrulename]; + if (subrule instanceof Array) { + subrulename = subrule[subrule.length - 1]; + subrule = MotaActionBlocks[subrulename]; + subList = true; + } + _input = subrule.xmlText([], true); + if (noinput && !subList && !isShadow) { + //无输入的默认行为是: 如果语句块的备选方块只有一个,直接代入方块 + input = subrule.xmlText(); + } + } + xmlText.push("<" + inputType + ' name="' + rule.args[ii] + '">'); + xmlText.push(_input + input); + xmlText.push(""); + } + if (comment) { + xmlText.push(""); + xmlText.push(comment); + xmlText.push(""); + } + var next = inputs[rule.args.length]; + if (next) { + //next + xmlText.push(""); + xmlText.push(next); + xmlText.push(""); + } + xmlText.push(""); + return xmlText.join(""); + }; + })(); - // end mark sfergsvae - } - .toString() - .split("// start mark sfergsvae")[1] - .split("// end mark sfergsvae")[0]; - } -}, - "夹击激光动画": function () { + // end mark sfergsvae + } + .toString() + .split("// start mark sfergsvae")[1] + .split("// end mark sfergsvae")[0]; + } + }, + 夹击激光动画: function () { function createCanvas(name, zIndex) { if (!name) return; var canvas = document.createElement("canvas"); @@ -10121,83 +12314,83 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = } }; }, - "瞬移轨迹": function () { - // 在此增加新插件 - function popMove() { - var ctx = core.getContextByName("popMove"); - if (!ctx) - ctx = core.createCanvas( - "popMove", - 0, - 0, - core.__PIXELS__, - core.__PIXELS__, - 71 - ); - ctx.canvas.classList.add('gameCanvas', 'anti-aliasing') - core.clearMap(ctx); - if (core.status.replay.speed <= 3 && !flags.stopPop) { - var list = core.status.popMove || []; - var count = 0; - list.forEach(function (one) { - // 由frame计算出dy + 瞬移轨迹: function () { + // 在此增加新插件 + function popMove() { + var ctx = core.getContextByName("popMove"); + if (!ctx) + ctx = core.createCanvas( + "popMove", + 0, + 0, + core.__PIXELS__, + core.__PIXELS__, + 71 + ); + ctx.canvas.classList.add("gameCanvas", "anti-aliasing"); + core.clearMap(ctx); + if (core.status.replay.speed <= 3 && !flags.stopPop) { + var list = core.status.popMove || []; + var count = 0; + list.forEach(function (one) { + // 由frame计算出dy - one.frame++; - // 绘制 + one.frame++; + // 绘制 - if (one.frame >= 0) core.setAlpha(ctx, 1 - one.frame / 30); - else core.setAlpha(ctx, 1); + if (one.frame >= 0) core.setAlpha(ctx, 1 - one.frame / 30); + else core.setAlpha(ctx, 1); - var length = Math.sqrt( - Math.pow(one.px2 - one.px, 2) + Math.pow(one.py2 - one.py, 2) - ); - //console.log(length) - var li = length / 16; - var lx = (one.px2 - one.px) / li; - var ly = (one.py2 - one.py) / li; - for (var i = 0; i < li; i += 1) { - core.setAlpha(ctx, (1 - one.frame / 30) * ((i / li) * 0.8 + 0.2)); - core.drawLine( - "popMove", - one.px + i * lx, - one.py + i * ly, - one.px + (i + 0.5) * lx, - one.py + (i + 0.5) * ly, - "#E1E1E1", - 6 - ); - if (i == 0) - core.strokeCircle("popMove", one.px, one.py, 6, "#E1E1E1", 3); - } - core.strokeCircle("popMove", one.px2, one.py2, 6, "#E1E1E1", 3); - core.strokeCircle( - "popMove", - one.px2, - one.py2, - 6 + (16 * one.frame) / 30, - "#E1E1E1", - 6 * (1 - one.frame / 30) - ); - //core.drawLine('popMove', one.px, one.py, one.px2, one.py2, '#E1E1E1', 6); + var length = Math.sqrt( + Math.pow(one.px2 - one.px, 2) + Math.pow(one.py2 - one.py, 2) + ); + //console.log(length) + var li = length / 16; + var lx = (one.px2 - one.px) / li; + var ly = (one.py2 - one.py) / li; + for (var i = 0; i < li; i += 1) { + core.setAlpha(ctx, (1 - one.frame / 30) * ((i / li) * 0.8 + 0.2)); + core.drawLine( + "popMove", + one.px + i * lx, + one.py + i * ly, + one.px + (i + 0.5) * lx, + one.py + (i + 0.5) * ly, + "#E1E1E1", + 6 + ); + if (i == 0) + core.strokeCircle("popMove", one.px, one.py, 6, "#E1E1E1", 3); + } + core.strokeCircle("popMove", one.px2, one.py2, 6, "#E1E1E1", 3); + core.strokeCircle( + "popMove", + one.px2, + one.py2, + 6 + (16 * one.frame) / 30, + "#E1E1E1", + 6 * (1 - one.frame / 30) + ); + //core.drawLine('popMove', one.px, one.py, one.px2, one.py2, '#E1E1E1', 6); - if (one.frame >= 30) count++; - }); - if (count > 0) list.splice(0, count); - } - } + if (one.frame >= 30) count++; + }); + if (count > 0) list.splice(0, count); + } + } - if (!main.replayChecking) { - core.registerAnimationFrame("popMove", true, popMove); - } - this.addPopMove = function (px, py, px2, py2, frame) { - var data = { px: px, py: py, px2: px2, py2: py2, frame: frame || 0 }; - if (core.status.replay.speed <= 3) { - if (!core.status.popMove) core.status.popMove = [data]; - else core.status.popMove.push(data); - } - }; -}, - "墓碑(编辑器)": function () { + if (!main.replayChecking) { + core.registerAnimationFrame("popMove", true, popMove); + } + this.addPopMove = function (px, py, px2, py2, frame) { + var data = { px: px, py: py, px2: px2, py2: py2, frame: frame || 0 }; + if (core.status.replay.speed <= 3) { + if (!core.status.popMove) core.status.popMove = [data]; + else core.status.popMove.push(data); + } + }; + }, + "墓碑(编辑器)": function () { // 在此增加新插件 if (main.mode != "editor") return; // 编辑器模式下使用 var mapData = null; @@ -10268,7 +12461,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = core.setAlpha("event2", alpha); }; }, - "小地图": function () { + 小地图: function () { // 在此增加新插件 // ----- 不可自定义 杂七杂八的变量 /** @type {{[x: string]: BFSResult}} */ @@ -10329,6 +12522,10 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = let allChangeEntries = Object.entries(defaultChange); + this.setq = function (floorId) { + core.setFlag("任务地点", floorId); + }; + const reset = core.events.resetGame; this.bfs = function () { areas = []; @@ -10683,7 +12880,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = } }; }, - "楼传": function () { + 楼传: function () { // 在此增加新插件 core.canMoveFloor = function () { @@ -11791,441 +13988,510 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = 0 ); }, - "CG回廊": function () { - // 在此增加新插件 - const CGUI = document.createElement("canvas"); //CGui画布设置 - CGUI.style.position = "absolute"; - CGUI.style.zIndex = 300; - CGUI.style.display = "none"; - CGUI.id = "CGUI"; - main.dom.gameGroup.insertAdjacentElement("afterend", CGUI); - CGUI.style.top = "50%"; - CGUI.style.left = "50%"; - CGUI.style.transform = "translate(-50%,-50%)"; - const ctx = CGUI.getContext("2d"); - main.dom.CGUI = CGUI; - let page = 0; //初始页面 - let show = false; //展示状态 - CGUI.onclick = function (e) { - try { - e.preventDefault(); - if (core.isPlaying()) return false; - const left = core.dom.gameGroup.offsetLeft; - const top = core.dom.gameGroup.offsetTop; - const px = Math.floor((e.clientX - left) / core.domStyle.scale), - py = Math.floor((e.clientY - top) / core.domStyle.scale); - core.ui.CG.onclick(px * 3, py * 3); - } catch (ee) { - main.log(ee); - } - }; + CG回廊: function () { + // 在此增加新插件 + const CGUI = document.createElement("canvas"); //CGui画布设置 + CGUI.style.position = "absolute"; + CGUI.style.zIndex = 300; + CGUI.style.display = "none"; + CGUI.id = "CGUI"; + main.dom.gameGroup.insertAdjacentElement("afterend", CGUI); + CGUI.style.top = "50%"; + CGUI.style.left = "50%"; + CGUI.style.transform = "translate(-50%,-50%)"; + const ctx = CGUI.getContext("2d"); + main.dom.CGUI = CGUI; + let page = 0; //初始页面 + let show = false; //展示状态 + CGUI.onclick = function (e) { + try { + e.preventDefault(); + if (core.isPlaying()) return false; + const left = core.dom.gameGroup.offsetLeft; + const top = core.dom.gameGroup.offsetTop; + const px = Math.floor((e.clientX - left) / core.domStyle.scale), + py = Math.floor((e.clientY - top) / core.domStyle.scale); + core.ui.CG.onclick(px * 3, py * 3); + } catch (ee) { + main.log(ee); + } + }; - class CG { - constructor() { - //cg列表 - this.UIMx = [ - //空位用‘none’填充,当前ui至多4列6行 - [ - ["eve_010102.webp", "eve_010203.webp", "eve_010304.webp"], - ["eve_010501.webp", "eve_010601.webp", "eve_010701.webp"], - ], - [ - ["eve_010801.webp", "eve_010902.webp", "eve_011001.webp"], - ["eve_011101.webp", "eve_011202.webp", "eve_011302.webp"], - ], - [ - ["eve_011402.webp", "eve_020102.webp", "eve_020201.webp"], - ["eve_020301.webp", "eve_020401.webp", "eve_020501.webp"], - ], - [ - ["eve_020605.webp", "eve_020701.webp", "eve_020801.webp"], - ["eve_030101.webp", "eve_030206.webp", "eve_030302.webp"], - ], - [ - ["eve_030508.webp", "eve_030601.webp", "eve_030801.webp"], - ["eve_030901.webp", "eve_031002.webp", "eve_031101.webp"], - ], - [ - ["eve_040201.webp", "eve_040401.webp", "eve_040501.webp"], - ["eve_040601.webp", "eve_040702.webp", "eve_040801.webp"], - ], - [ - ["eve_050101.webp", "eve_050201.webp", "eve_050401.webp"], - ["eve_050501.webp", "eve_050601.webp", "eve_050704.webp"], - ], - [ - ["eve_050801.webp", "eve_070101.webp", "bg_1511.webp"], - ["bg_1521.webp", "bg_2011.webp", "bg_2521.webp"], - ], - [ - ["bg_3042.webp", "bg_3551.webp", "bg_3571.webp"], - ["bg_3721.webp", "bg_5033.webp", "bg_5044.webp"], - ], - ]; - } + class CG { + constructor() { + this.cgs; + //cg列表 + this.UIMx = [ + //空位用‘none’填充,当前ui至多4列6行 + [ + ["eve_010102.webp", "eve_010203.webp", "eve_010304.webp"], + ["eve_010501.webp", "eve_010601.webp", "eve_010701.webp"], + ], + [ + ["eve_010801.webp", "eve_010902.webp", "eve_011001.webp"], + ["eve_011101.webp", "eve_011202.webp", "eve_011302.webp"], + ], + [ + ["eve_011402.webp", "eve_020102.webp", "eve_020201.webp"], + ["eve_020301.webp", "eve_020401.webp", "eve_020501.webp"], + ], + [ + ["eve_020605.webp", "eve_020701.webp", "eve_020801.webp"], + ["eve_030101.webp", "eve_030206.webp", "eve_030302.webp"], + ], + [ + ["eve_030508.webp", "eve_030601.webp", "eve_030801.webp"], + ["eve_030901.webp", "eve_031002.webp", "eve_031101.webp"], + ], + [ + ["eve_040201.webp", "eve_040401.webp", "eve_040501.webp"], + ["eve_040601.webp", "eve_040702.webp", "eve_040801.webp"], + ], + [ + ["eve_050101.webp", "eve_050201.webp", "eve_050401.webp"], + ["eve_050501.webp", "eve_050601.webp", "eve_050704.webp"], + ], + [ + ["eve_050801.webp", "eve_070101.webp", "bg_1511.webp"], + ["bg_1521.webp", "bg_2011.webp", "bg_2521.webp"], + ], + [ + ["bg_3042.webp", "bg_3551.webp", "bg_3571.webp"], + ["bg_3721.webp", "bg_5033.webp", "bg_5044.webp"], + ], + ]; + } - //更新 - update() { - this.background(); - this.drawUI(); - } - background() { - //画布大小设置 - if (core.domStyle.isVertical) { - CGUI.width = 1248; - CGUI.height = 2028; - } else { - CGUI.width = 2028; - CGUI.height = 1248; - } - core.setTextAlign(ctx, "center"); - } - onclick(px, py) { - //点击 - if (show) { - show = !show; - core.clearMap(ctx); - this.update(); - return; - } - const makeBox = ([x, y], [w, h]) => { - return [ - [x, y], - [x + w, y + h], - ]; - }; - const inRect = ([x, y], [ - [sx, sy], - [dx, dy] - ]) => { - return sx <= x && x <= dx && sy <= y && y <= dy; - }; - const pos = [px, py]; - const backbox = makeBox([15, 35], [210, 90]); - if (inRect(pos, backbox)) { - //离开按钮是一致的,其余的记区分横竖屏 - CGUI.style.display = "none"; - core.clearMap(ctx); - core.restart(); - return; - } - if (core.domStyle.isVertical) { - //竖屏 - const pageupbox = makeBox([30, 380], [144, 144]); - const pagedownbox = makeBox([30, 1080], [144, 144]); + //更新 + update() { + this.background(); + this.drawUI(); + } + background() { + //画布大小设置 + if (core.domStyle.isVertical) { + CGUI.width = 1248; + CGUI.height = 2028; + } else { + CGUI.width = 2028; + CGUI.height = 1248; + } + core.setTextAlign(ctx, "center"); + } + onclick(px, py) { + //点击 - const imagebox0 = makeBox([200, 300], [480, 320]); - const imagebox1 = makeBox([200, 750], [480, 320]); - const imagebox2 = makeBox([200, 1200], [480, 320]); + if (show) { + show = !show; + core.clearMap(ctx); + this.update(); + return; + } + const makeBox = ([x, y], [w, h]) => { + return [ + [x, y], + [x + w, y + h], + ]; + }; + const inRect = ([x, y], [[sx, sy], [dx, dy]]) => { + return sx <= x && x <= dx && sy <= y && y <= dy; + }; + const pos = [px, py]; + const backbox = makeBox([15, 35], [210, 90]); + if (inRect(pos, backbox)) { + //离开按钮是一致的,其余的记区分横竖屏 + CGUI.style.display = "none"; + core.clearMap(ctx); + core.restart(); + return; + } + if (core.domStyle.isVertical) { + //竖屏 + const pageupbox = makeBox([200, 1830], [200, 100]); + const pagedownbox = makeBox([900, 1830], [200, 100]); - const imagebox3 = makeBox([700, 300], [480, 320]); - const imagebox4 = makeBox([700, 750], [480, 320]); - const imagebox5 = makeBox([700, 1200], [480, 320]); - if (inRect(pos, pagedownbox)) { - //2代表当前最大页数-1 - if (page < this.UIMx.length - 1) { - page++; - core.clearMap(ctx); - this.update(); - } - } else if (inRect(pos, pageupbox)) { - if (page > 0) { - page--; - core.clearMap(ctx); - this.update(); - } - } else if (inRect(pos, imagebox0)) { - const img = core.material.images.images[this.UIMx[page][0][0]]; - if (img) { - ctx.save(); //保存设置 - ctx.translate(1248, 0); //重新定位右上角为基准 - ctx.rotate(Math.PI / 2); //旋转90度 - ctx.drawImage(img, 0, 0, 2028, 1248); - ctx.restore(); //重置画布设置 - show = !show; - } - } else if (inRect(pos, imagebox1)) { - const img = core.material.images.images[this.UIMx[page][0][1]]; - if (img) { - ctx.save(); //保存设置 - ctx.translate(1248, 0); //重新定位右上角为基准 - ctx.rotate(Math.PI / 2); //旋转90度 - ctx.drawImage(img, 0, 0, 2028, 1248); - ctx.restore(); //重置画布设置 - show = !show; - } - } else if (inRect(pos, imagebox2)) { - const img = core.material.images.images[this.UIMx[page][0][2]]; - if (img) { - ctx.save(); //保存设置 - ctx.translate(1248, 0); //重新定位右上角为基准 - ctx.rotate(Math.PI / 2); //旋转90度 - ctx.drawImage(img, 0, 0, 2028, 1248); - ctx.restore(); //重置画布设置 - show = !show; - } - } else if (inRect(pos, imagebox3)) { - const img = core.material.images.images[this.UIMx[page][1][0]]; - if (img) { - ctx.save(); //保存设置 - ctx.translate(1248, 0); //重新定位右上角为基准 - ctx.rotate(Math.PI / 2); //旋转90度 - ctx.drawImage(img, 0, 0, 2028, 1248); - ctx.restore(); //重置画布设置 - show = !show; - } - } else if (inRect(pos, imagebox4)) { - const img = core.material.images.images[this.UIMx[page][1][1]]; - if (img) { - ctx.save(); //保存设置 - ctx.translate(1248, 0); //重新定位右上角为基准 - ctx.rotate(Math.PI / 2); //旋转90度 - ctx.drawImage(img, 0, 0, 2028, 1248); - ctx.restore(); //重置画布设置 - show = !show; - } - } else if (inRect(pos, imagebox5)) { - const img = core.material.images.images[this.UIMx[page][1][2]]; - if (img) { - ctx.save(); //保存设置 - ctx.translate(1248, 0); //重新定位右上角为基准 - ctx.rotate(Math.PI / 2); //旋转90度 - ctx.drawImage(img, 0, 0, 2028, 1248); - ctx.restore(); //重置画布设置 - show = !show; - } - } - } else { - const pageupbox = makeBox([30, 340], [144, 144]); - const pagedownbox = makeBox([30, 840], [144, 144]); - const imagebox0 = makeBox([300, 300], [480, 320]); - const imagebox1 = makeBox([800, 300], [480, 320]); - const imagebox2 = makeBox([1300, 300], [480, 320]); - const imagebox3 = makeBox([300, 750], [480, 320]); - const imagebox4 = makeBox([800, 750], [480, 320]); - const imagebox5 = makeBox([1300, 750], [480, 320]); - if (inRect(pos, pagedownbox)) { - if (page < this.UIMx.length - 1) { - page++; - core.clearMap(ctx); - this.update(); - } - } else if (inRect(pos, pageupbox)) { - if (page > 0) { - page--; - core.clearMap(ctx); - this.update(); - } - } else if (inRect(pos, imagebox0)) { - const img = core.material.images.images[this.UIMx[page][0][0]]; - if (img) { - ctx.drawImage(img, 0, 0, 2028, 1248); - show = !show; - } - } else if (inRect(pos, imagebox1)) { - const img = core.material.images.images[this.UIMx[page][0][1]]; - if (img) { - ctx.drawImage(img, 0, 0, 2028, 1248); - show = !show; - } - } else if (inRect(pos, imagebox2)) { - const img = core.material.images.images[this.UIMx[page][0][2]]; - if (img) { - ctx.drawImage(img, 0, 0, 2028, 1248); - show = !show; - } - } else if (inRect(pos, imagebox3)) { - const img = core.material.images.images[this.UIMx[page][1][0]]; - if (img) { - ctx.drawImage(img, 0, 0, 2028, 1248); - show = !show; - } - } else if (inRect(pos, imagebox4)) { - const img = core.material.images.images[this.UIMx[page][1][1]]; - if (img) { - ctx.drawImage(img, 0, 0, 2028, 1248); - show = !show; - } - } else if (inRect(pos, imagebox5)) { - const img = core.material.images.images[this.UIMx[page][1][2]]; - if (img) { - ctx.drawImage(img, 0, 0, 2028, 1248); - show = !show; - } - } - } - } - drawUI() { - //绘制页面 - core.clearMap(CGUI); - const bgVertical = core.material.images.images["bg_2010.webp"]; //竖屏背景 - const bg = core.material.images.images["bg_5043.webp"]; //横屏背景 - if (core.domStyle.isVertical) { - //竖屏 + const imagebox0 = makeBox([50, 200], [560, 420]); + const imagebox1 = makeBox([50, 750], [560, 420]); + const imagebox2 = makeBox([50, 1300], [560, 420]); - core.fillRect(ctx, 0, 0, 1248, 2028, "#000000"); //黑色背景 - ctx.globalAlpha = 0.5; //透明度 - if (bgVertical) - ctx.drawImage(bgVertical, 0, 0, 1280, 1500, 0, 0, 1248, 2028); //绘制半透明背景图片 - ctx.globalAlpha = 1; //恢复为不透明 + const imagebox3 = makeBox([650, 200], [560, 420]); + const imagebox4 = makeBox([650, 750], [560, 420]); + const imagebox5 = makeBox([650, 1300], [560, 420]); + if (inRect(pos, pagedownbox)) { + //2代表当前最大页数-1 + if (page < this.UIMx.length - 1) { + page++; + core.clearMap(ctx); + this.update(); + } + } else if (inRect(pos, pageupbox)) { + if (page > 0) { + page--; + core.clearMap(ctx); + this.update(); + } + } else if (inRect(pos, imagebox0)) { + if (this.cgs.includes(this.UIMx[page][0][0])) { + const img = core.material.images.images[this.UIMx[page][0][0]]; + if (img) { + ctx.save(); //保存设置 + ctx.translate(1248, 0); //重新定位右上角为基准 + ctx.rotate(Math.PI / 2); //旋转90度 + ctx.drawImage(img, 0, 0, 2028, 1248); + ctx.restore(); //重置画布设置 + show = !show; + } + } + } else if (inRect(pos, imagebox1)) { + if (this.cgs.includes(this.UIMx[page][0][1])) { + const img = core.material.images.images[this.UIMx[page][0][1]]; + if (img) { + ctx.save(); //保存设置 + ctx.translate(1248, 0); //重新定位右上角为基准 + ctx.rotate(Math.PI / 2); //旋转90度 + ctx.drawImage(img, 0, 0, 2028, 1248); + ctx.restore(); //重置画布设置 + show = !show; + } + } + } else if (inRect(pos, imagebox2)) { + if (this.cgs.includes(this.UIMx[page][0][2])) { + const img = core.material.images.images[this.UIMx[page][0][2]]; + if (img) { + ctx.save(); //保存设置 + ctx.translate(1248, 0); //重新定位右上角为基准 + ctx.rotate(Math.PI / 2); //旋转90度 + ctx.drawImage(img, 0, 0, 2028, 1248); + ctx.restore(); //重置画布设置 + show = !show; + } + } + } else if (inRect(pos, imagebox3)) { + if (this.cgs.includes(this.UIMx[page][1][0])) { + const img = core.material.images.images[this.UIMx[page][1][0]]; + if (img) { + ctx.save(); //保存设置 + ctx.translate(1248, 0); //重新定位右上角为基准 + ctx.rotate(Math.PI / 2); //旋转90度 + ctx.drawImage(img, 0, 0, 2028, 1248); + ctx.restore(); //重置画布设置 + show = !show; + } + } + } else if (inRect(pos, imagebox4)) { + if (this.cgs.includes(this.UIMx[page][1][1])) { + const img = core.material.images.images[this.UIMx[page][1][1]]; + if (img) { + ctx.save(); //保存设置 + ctx.translate(1248, 0); //重新定位右上角为基准 + ctx.rotate(Math.PI / 2); //旋转90度 + ctx.drawImage(img, 0, 0, 2028, 1248); + ctx.restore(); //重置画布设置 + show = !show; + } + } + } else if (inRect(pos, imagebox5)) { + if (this.cgs.includes(this.UIMx[page][1][2])) { + const img = core.material.images.images[this.UIMx[page][1][2]]; + if (img) { + ctx.save(); //保存设置 + ctx.translate(1248, 0); //重新定位右上角为基准 + ctx.rotate(Math.PI / 2); //旋转90度 + ctx.drawImage(img, 0, 0, 2028, 1248); + ctx.restore(); //重置画布设置 + show = !show; + } + } + } + } else { + const pageupbox = makeBox([200, 1110], [200, 100]); + const pagedownbox = makeBox([1600, 1110], [200, 100]); + const imagebox0 = makeBox([75, 150], [600, 450]); + const imagebox1 = makeBox([725, 150], [600, 450]); + const imagebox2 = makeBox([1300, 150], [600, 450]); + const imagebox3 = makeBox([75, 650], [600, 450]); + const imagebox4 = makeBox([725, 650], [600, 450]); + const imagebox5 = makeBox([1375, 650], [600, 450]); + if (inRect(pos, pagedownbox)) { + if (page < this.UIMx.length - 1) { + page++; + core.clearMap(ctx); + this.update(); + } + } else if (inRect(pos, pageupbox)) { + if (page > 0) { + page--; + core.clearMap(ctx); + this.update(); + } + } else if (inRect(pos, imagebox0)) { + if (this.cgs.includes(this.UIMx[page][0][0])) { + const img = core.material.images.images[this.UIMx[page][0][0]]; + if (img) { + ctx.drawImage(img, 0, 0, 2028, 1248); + show = !show; + } + } + } else if (inRect(pos, imagebox1)) { + if (this.cgs.includes(this.UIMx[page][0][1])) { + const img = core.material.images.images[this.UIMx[page][0][1]]; + if (img) { + ctx.drawImage(img, 0, 0, 2028, 1248); + show = !show; + } + } + } else if (inRect(pos, imagebox2)) { + if (this.cgs.includes(this.UIMx[page][0][2])) { + const img = core.material.images.images[this.UIMx[page][0][2]]; + if (img) { + ctx.drawImage(img, 0, 0, 2028, 1248); + show = !show; + } + } + } else if (inRect(pos, imagebox3)) { + if (this.cgs.includes(this.UIMx[page][1][0])) { + const img = core.material.images.images[this.UIMx[page][1][0]]; + if (img) { + ctx.drawImage(img, 0, 0, 2028, 1248); + show = !show; + } + } + } else if (inRect(pos, imagebox4)) { + if (this.cgs.includes(this.UIMx[page][1][1])) { + const img = core.material.images.images[this.UIMx[page][1][1]]; + if (img) { + ctx.drawImage(img, 0, 0, 2028, 1248); + show = !show; + } + } + } else if (inRect(pos, imagebox5)) { + if (this.cgs.includes(this.UIMx[page][1][2])) { + const img = core.material.images.images[this.UIMx[page][1][2]]; + if (img) { + ctx.drawImage(img, 0, 0, 2028, 1248); + show = !show; + } + } + } + } + } + drawUI() { + //绘制页面 + core.clearMap(CGUI); + const bgVertical = core.material.images.images["bg_2010.webp"]; //竖屏背景 + const bg = core.material.images.images["bg_5043.webp"]; //横屏背景 - core.setTextAlign(ctx, "center"); - core.fillBoldText1( - ctx, - '◀离开', - 100, - 110, - "#FFFFFF", - "#000000", - 6, - core.ui._buildFont(66, true) - ); - core.fillBoldText1( - ctx, - '上一页', - 100, - 450, - page === 0 ? "#444444" : "#FFFFFF", - "#000000", - 6, - core.ui._buildFont(66, true) - ); + if (core.domStyle.isVertical) { + //竖屏 - core.fillBoldText1( - ctx, - (page + 1) + "/" + this.UIMx.length, - 100, - 800, - "#FFFFFF", - "#000000", - 6, - core.ui._buildFont(66, true) - ); - core.fillBoldText1( - ctx, - '下一页', - 100, - 1150, - page === this.UIMx.length - 1 ? "#444444" : "#FFFFFF", - "#000000", - 6, - core.ui._buildFont(66, true) - ); - // 添加向上翻页和向下翻页的按钮 + core.fillRect(ctx, 0, 0, 1248, 2028, "#000000"); //黑色背景 + ctx.globalAlpha = 0.5; //透明度 + if (bgVertical) + ctx.drawImage(bgVertical, 0, 0, 1280, 1500, 0, 0, 1248, 2028); //绘制半透明背景图片 + ctx.globalAlpha = 1; //恢复为不透明 + core.setTextAlign(ctx, "center"); + core.fillBoldText1( + ctx, + "◀离开", + 100, + 110, + "#FFFFFF", + "#000000", + 6, + core.ui._buildFont(66, true) + ); + core.fillBoldText1( + ctx, + "上一页", + 300, + 1900, + page === 0 ? "#444444" : "#FFFFFF", + "#000000", + 6, + core.ui._buildFont(66, true) + ); - // 添加3*2个4:3的画框,及图片 - for (let i = 0; i < 3; i++) { - for (let j = 0; j < 2; j++) { - const img = core.material.images.images[this.UIMx[page][j][i]]; - core.strokeRect( - ctx, - 200 + j * 500, - 300 + i * 450, - 480, - 320, - "#444444", - 5 - ); - if (img) - ctx.drawImage( - img, - 200 + j * 500 + 15, - 300 + i * 450 + 15, - 480 - 30, - 320 - 30 - ); - } - } - } else { - //横屏 - core.fillRect(ctx, 0, 0, 2028, 1248, "#000000"); //黑色背景 - ctx.globalAlpha = 0.5; //透明度 - if (bg) ctx.drawImage(bg, 0, 0, 1280, 720, 0, 0, 2028, 1248); //绘制半透明背景图片 - ctx.globalAlpha = 1; //恢复为不透明 - //core.drawWindowSkin('winskin1.png', ctx, 0, 0, 2028, 1248); - core.setTextAlign(ctx, "center"); - core.fillBoldText1( - ctx, - '◀离开', - 110, - 100, - "#FFFFFF", - "#000000", - 6, - core.ui._buildFont(66, true) - ); + core.fillBoldText1( + ctx, + page + 1 + "/" + this.UIMx.length, + 650, + 1900, + "#FFFFFF", + "#000000", + 6, + core.ui._buildFont(66, true) + ); + core.fillBoldText1( + ctx, + "下一页", + 1000, + 1900, + page === this.UIMx.length - 1 ? "#444444" : "#FFFFFF", + "#000000", + 6, + core.ui._buildFont(66, true) + ); + // 添加向上翻页和向下翻页的按钮 - // 添加向上翻页和向下翻页的按钮 - core.fillBoldText1( - ctx, - '上一页', - 100, - 400, - page === 0 ? "#444444" : "#FFFFFF", - "#000000", - 6, - core.ui._buildFont(66, true) - ); + // 添加3*2个4:3的画框,及图片 + for (let i = 0; i < 3; i++) { + for (let j = 0; j < 2; j++) { + const img = core.material.images.images[this.UIMx[page][j][i]]; + core.strokeRect( + ctx, + 50 + j * 600, + 200 + i * 550, + 560, + 420, + "#444444", + 5 + ); + if (this.cgs.includes(this.UIMx[page][j][i])) { + if (img) + ctx.drawImage( + img, + 50 + j * 600 + 15, + 200 + i * 550 + 15, + 560 - 30, + 420 - 30 + ); + } else { + ctx.fillStyle = "#000000"; + ctx.fillRect( + 50 + j * 600 + 15, + 200 + i * 550 + 15, + 560 - 30, + 420 - 30 + ); + const img = core.material.images.images["LOGO.webp"]; + if (img) + ctx.drawImage( + img, + 50 + j * 600 + 15, + 200 + i * 550 + 15, + 560 - 30, + 420 - 30 + ); + } + } + } + } else { + //横屏 + core.fillRect(ctx, 0, 0, 2028, 1248, "#000000"); //黑色背景 + ctx.globalAlpha = 0.5; //透明度 + if (bg) ctx.drawImage(bg, 0, 0, 1280, 720, 0, 0, 2028, 1248); //绘制半透明背景图片 + ctx.globalAlpha = 1; //恢复为不透明 + //core.drawWindowSkin('winskin1.png', ctx, 0, 0, 2028, 1248); + core.setTextAlign(ctx, "center"); + core.fillBoldText1( + ctx, + "◀离开", + 110, + 100, + "#FFFFFF", + "#000000", + 6, + core.ui._buildFont(66, true) + ); - core.fillBoldText1( - ctx, - (page + 1) + "/" + this.UIMx.length, - 100, - 650, - "#FFFFFF", - "#000000", - 6, - core.ui._buildFont(66, true) - ); - core.fillBoldText1( - ctx, - '下一页', - 100, - 900, - page === this.UIMx.length - 1 ? "#444444" : "#FFFFFF", - "#000000", - 6, - core.ui._buildFont(66, true) - ); + // 添加向上翻页和向下翻页的按钮 + core.fillBoldText1( + ctx, + "上一页", + 300, + 1180, + page === 0 ? "#444444" : "#FFFFFF", + "#000000", + 6, + core.ui._buildFont(66, true) + ); - // 添加3*2个4:3的画框 - for (let i = 0; i < 2; i++) { - for (let j = 0; j < 3; j++) { - core.strokeRect( - ctx, - 300 + j * 500, - 300 + i * 450, - 480, - 320, - "#444444", - 2 - ); - const img = core.material.images.images[this.UIMx[page][i][j]]; - if (img) - ctx.drawImage( - img, - 300 + j * 500 + 15, - 300 + i * 450 + 15, - 480 - 30, - 320 - 30 - ); - } - } - } - } - } - core.ui.CG = new CG(); - main.dom.CGMode.onclick = function () { - //点击开始页面的CG MODE进入cg回廊 - main.core.control.checkBgm(); - page = 0; - CGUI.style.display = "block"; - main.core.ui.CG.update(); - }; -}, - "光标设置": function () { + core.fillBoldText1( + ctx, + page + 1 + "/" + this.UIMx.length, + 1000, + 1180, + "#FFFFFF", + "#000000", + 6, + core.ui._buildFont(66, true) + ); + core.fillBoldText1( + ctx, + "下一页", + 1700, + 1180, + page === this.UIMx.length - 1 ? "#444444" : "#FFFFFF", + "#000000", + 6, + core.ui._buildFont(66, true) + ); + + // 添加3*2个4:3的画框 + for (let i = 0; i < 2; i++) { + for (let j = 0; j < 3; j++) { + core.strokeRect( + ctx, + 75 + j * 650, + 150 + i * 500, + 600, + 450, + "#444444", + 2 + ); + if (this.cgs.includes(this.UIMx[page][i][j])) { + const img = core.material.images.images[this.UIMx[page][i][j]]; + if (img) + ctx.drawImage( + img, + 75 + j * 650 + 15, + 150 + i * 500 + 15, + 600 - 30, + 450 - 30 + ); + } else { + ctx.fillStyle = "#000000"; + ctx.fillRect( + 75 + j * 650 + 15, + 150 + i * 500 + 15, + 600 - 30, + 450 - 30 + ); + const img = core.material.images.images["LOGO.webp"]; + if (img) + ctx.drawImage( + img, + 75 + j * 650 + 15, + 150 + i * 500 + 15, + 600 - 30, + 450 - 30 + ); + } + } + } + } + } + } + this.setcgs = function (img) { + const a = core.getLocalStorage("cgs", []); + if (img) { + if (!a.includes(img)) a.push(img); + core.setLocalStorage("cgs", a); + } else core.setLocalStorage("cgs"); + }; + core.ui.CG = new CG(); + main.dom.CGMode.onclick = function () { + //点击开始页面的CG MODE进入cg回廊 + main.core.control.checkBgm(); + page = 0; + main.core.ui.CG.cgs = core.getLocalStorage("cgs", []); + CGUI.style.display = "block"; + main.core.ui.CG.update(); + }; + }, + 光标设置: function () { // 在此增加新插件 this.changeMouse = function ( icon, @@ -12262,170 +14528,177 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = core.dom[div].style.cursor = "auto"; }; }, - "信息弹出": function () { - // 在此增加新插件 - /* 弹出显示某个内容 - * 使用方法:core.addPop(px, py, value, color, boldColor, left, jump, time, show, font, speed) - * 参数说明: - * px & py: number 弹出位置 - * value: string 显示内容 - * color: string 填充颜色 - * boldColor: string 描边颜色 - */ + 信息弹出: function () { + // 在此增加新插件 + /* 弹出显示某个内容 + * 使用方法:core.addPop(px, py, value, color, boldColor, left, jump, time, show, font, speed) + * 参数说明: + * px & py: number 弹出位置 + * value: string 显示内容 + * color: string 填充颜色 + * boldColor: string 描边颜色 + */ - // 默认字体 - var fontD = "16px Verdana"; - // 默认颜色 - var colorD = "red"; - // 默认描边颜色 - var boldColorD = "black"; + // 默认字体 + var fontD = "16px Verdana"; + // 默认颜色 + var colorD = "red"; + // 默认描边颜色 + var boldColorD = "black"; - /** 血量弹出 */ - function pop() { - var ctx = core.getContextByName("pop"); - if (!ctx) - ctx = core.createCanvas( - "pop", - 0, - 0, - core.__PIXELS__, - core.__PIXELS__, - 90 - ); - ctx.canvas.classList.add('gameCanvas', 'anti-aliasing') - core.clearMap(ctx); - core.setTextAlign("pop", "left"); - var list = core.status.pop || []; - var count = 0; - list.forEach(function (one) { - // 由frame计算出dy - var dy = 6 - one.frame * 0.2; - var dx = one.speed; - if (one.jump) { - one.py -= dy; - } - if (!one.left) { - one.px += dx; - } else { - one.px -= dx; - } - one.frame++; - // 绘制 - if (one.frame >= one.time) - core.setAlpha(ctx, 1 - (one.frame - one.time) / one.show); - else core.setAlpha(ctx, 1); - core.fillBoldText1( - ctx, - one.value, - one.px, - one.py, - one.color || "red", - one.boldColor || "black", - 2, - one.font - ); - if (one.frame >= one.time + one.show) count++; - }); - if (count > 0) list.splice(0, count); - } - if (!main.replayChecking) core.registerAnimationFrame("pop", true, pop); + /** 血量弹出 */ + function pop() { + var ctx = core.getContextByName("pop"); + if (!ctx) + ctx = core.createCanvas( + "pop", + 0, + 0, + core.__PIXELS__, + core.__PIXELS__, + 90 + ); + ctx.canvas.classList.add("gameCanvas", "anti-aliasing"); + core.clearMap(ctx); + core.setTextAlign("pop", "left"); + var list = core.status.pop || []; + var count = 0; + list.forEach(function (one) { + // 由frame计算出dy + var dy = 6 - one.frame * 0.2; + var dx = one.speed; + if (one.jump) { + one.py -= dy; + } + if (!one.left) { + one.px += dx; + } else { + one.px -= dx; + } + one.frame++; + // 绘制 + if (one.frame >= one.time) + core.setAlpha(ctx, 1 - (one.frame - one.time) / one.show); + else core.setAlpha(ctx, 1); + core.fillBoldText1( + ctx, + one.value, + one.px, + one.py, + one.color || "red", + one.boldColor || "black", + 2, + one.font + ); + if (one.frame >= one.time + one.show) count++; + }); + if (count > 0) list.splice(0, count); + } + let now = 0; + if (!main.replayChecking) + core.registerAnimationFrame("pop", true, (temptime) => { + if (temptime - now > 1000 / 60) { + now = temptime; + pop(); + } + }); - /** 添加弹出内容 */ - this.addPop = function ( - value, - px, - py, - color, - boldColor, - left, - jump, - time, - show, - font, - speed - ) { - var data = { - px: px, - py: py, - value: value, - color: color || colorD, - boldColor: boldColor || boldColorD, - frame: 0, - left: left || false, - jump: jump || false, - time: time || 60, - show: show || 30, - font: font || fontD, - speed: speed || 1, - }; - if (!core.status.pop) core.status.pop = [data]; - else core.status.pop.push(data); - }; -}, - "warning": function () { - // 在此增加新插件 - // 默认音效名 - var defaultSound = "jingbao.mp3"; - // 默认字体名 - var defaultFont = "Verdana"; + /** 添加弹出内容 */ + this.addPop = function ( + value, + px, + py, + color, + boldColor, + left, + jump, + time, + show, + font, + speed + ) { + var data = { + px: px, + py: py, + value: value, + color: color || colorD, + boldColor: boldColor || boldColorD, + frame: 0, + left: left || false, + jump: jump || false, + time: time || 60, + show: show || 30, + font: font || fontD, + speed: speed || 1, + }; + if (!core.status.pop) core.status.pop = [data]; + else core.status.pop.push(data); + }; + }, + warning: function () { + // 在此增加新插件 + // 默认音效名 + var defaultSound = "jingbao.opus"; + // 默认字体名 + var defaultFont = "Verdana"; - var timeout; - /** warning提示 - * @param {number} x 横坐标 - * @param {number} y 纵坐标 - * @param {string} text 显示的文字 - */ - this.drawWarning = function (x, y, size, text, text2, warning) { - if (timeout) return; - x = x ?? 6; - y = y ?? 6; - text = text || "boss"; - text += "
"; - for (var i = 0; i < 10; i++) text += " "; - text += text2; - // 生成文字 - var elements = document.querySelectorAll(".gameCanvas"); - var t = document.createElement("p"); - t.innerHTML = text; - t.style.position = "absolute"; - t.style.fontSize = size * core.domStyle.scale + "px"; - t.style.left = -(300 * core.domStyle.scale) + "px"; - t.style.top = parseInt(elements[0].style.height) / 2 - 100 + "px"; - t.style.zIndex = "300"; - t.style.color = "#f11"; - t.style.fontFamily = defaultFont; - t.style.overflow = "none"; - t.style.width = "100%"; - t.classList.add("warning"); - core.dom.gameDraw.appendChild(t); - setTimeout(function () { - t.style.left = 416 * core.domStyle.scale + "px"; - }, 50); - // 计算偏移量 - var px = ((6 - x) / 12) * 50; - var py = ((6 - y) / 12) * 50; - // 修改画布的scale和transform - elements.forEach(function (v) { - if (v instanceof HTMLCanvasElement) { - v.style.transform = "scale(2)translate(" + px + "%, " + py + "%)"; - } - }); - if (!warning) core.playSound(defaultSound); - // 拉回镜头 - timeout = setTimeout(function () { - timeout = setTimeout(function () { - timeout = void 0; - core.dom.gameDraw.removeChild(t); - }, 1500); - elements.forEach(function (v) { - if (v instanceof HTMLCanvasElement) { - v.style.transform = "none"; - } - }); - }, 1600); - }; -}, - "立体声音效": function () { + var timeout; + /** warning提示 + * @param {number} x 横坐标 + * @param {number} y 纵坐标 + * @param {string} text 显示的文字 + */ + this.drawWarning = function (x, y, size, text, text2, warning) { + if (timeout) return; + x = x ?? 6; + y = y ?? 6; + text = text || "boss"; + text += "
"; + for (var i = 0; i < 10; i++) text += " "; + text += text2; + // 生成文字 + var elements = document.querySelectorAll(".gameCanvas"); + var t = document.createElement("p"); + t.innerHTML = text; + t.style.position = "absolute"; + t.style.fontSize = size * core.domStyle.scale + "px"; + t.style.left = -(300 * core.domStyle.scale) + "px"; + t.style.top = parseInt(elements[0].style.height) / 2 - 100 + "px"; + t.style.zIndex = "300"; + t.style.color = "#f11"; + t.style.fontFamily = defaultFont; + t.style.overflow = "none"; + t.style.width = "100%"; + t.classList.add("warning"); + core.dom.gameDraw.appendChild(t); + setTimeout(function () { + t.style.left = 416 * core.domStyle.scale + "px"; + }, 50); + // 计算偏移量 + var px = ((6 - x) / 12) * 50; + var py = ((6 - y) / 12) * 50; + // 修改画布的scale和transform + elements.forEach(function (v) { + if (v instanceof HTMLCanvasElement) { + v.style.transform = "scale(2)translate(" + px + "%, " + py + "%)"; + } + }); + if (!warning) core.playSound(defaultSound); + // 拉回镜头 + timeout = setTimeout(function () { + timeout = setTimeout(function () { + timeout = void 0; + core.dom.gameDraw.removeChild(t); + }, 1500); + elements.forEach(function (v) { + if (v instanceof HTMLCanvasElement) { + v.style.transform = "none"; + } + }); + }, 1600); + }; + }, + 立体声音效: function () { // 在此增加新插件 // 音效双声道播放 var can = true; @@ -12529,7 +14802,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = }, 10); }; }, - "滑动转场": function () { + 滑动转场: function () { // 在此增加新插件 const defaultChange = { left: "leftPortal", // 左箭头 @@ -12719,538 +14992,536 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = }, 25); }; }, - "剧情cg": function () { - // 在此增加新插件 - const cg = document.createElement("canvas"); //cg画布设置 - cg.style.position = "absolute"; - cg.style.zIndex = 300; - cg.style.display = "none"; - cg.id = "cgText"; - main.dom.gameGroup.insertAdjacentElement("afterend", cg); - cg.style.top = "50%"; - cg.style.left = "50%"; - cg.style.transform = "translate(-50%,-50%)"; - const ctx = cg.getContext("2d"); - main.dom.cgText = cg; + 剧情cg: function () { + // 在此增加新插件 + const cg = document.createElement("canvas"); //cg画布设置 + cg.style.position = "absolute"; + cg.style.zIndex = 300; + cg.style.display = "none"; + cg.id = "cgText"; + main.dom.gameGroup.insertAdjacentElement("afterend", cg); + cg.style.top = "50%"; + cg.style.left = "50%"; + cg.style.transform = "translate(-50%,-50%)"; + const ctx = cg.getContext("2d"); + main.dom.cgText = cg; - cg.onmouseup = function (e) { - //鼠标抬起 + cg.onmouseup = function (e) { + //鼠标抬起 - try { - e.stopPropagation(); - if (!core.isPlaying()) return false; - core.unregisterAnimationFrame("skip"); - let a = core.getFlag("skip", false); - core.setFlag("skip", false); - if (a) { - const data = core.clone(core.status.event.data.current); + try { + e.stopPropagation(); + if (!core.isPlaying()) return false; + core.unregisterAnimationFrame("skip"); + let a = core.getFlag("skip", false); + core.setFlag("skip", false); + if (a) { + const data = core.clone(core.status.event.data.current); - core.insertAction(data); - core.doAction(); - } - } catch (ee) { - console.error(ee); - } - }; - cg.onmousedown = function (e) { - //鼠标按下 - try { - e.stopPropagation(); - 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.cgText.click(px * 3, py * 3); - } catch (ee) { - main.log(ee); - } - }; - cg.ontouchend = function (e) { - //触摸抬起 + core.insertAction(data); + core.doAction(); + } + } catch (ee) { + console.error(ee); + } + }; + cg.onmousedown = function (e) { + //鼠标按下 + try { + e.stopPropagation(); + 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.cgText.click(px * 3, py * 3); + } catch (ee) { + main.log(ee); + } + }; + cg.ontouchend = function (e) { + //触摸抬起 - try { - e.preventDefault(); - if (!core.isPlaying()) return false; - core.unregisterAnimationFrame("skip"); - core.setFlag("skip", false); - let a = core.getFlag("skip", false); - core.setFlag("skip", false); - if (a) { - const data = core.clone(core.status.event.data.current); + try { + e.preventDefault(); + if (!core.isPlaying()) return false; + core.unregisterAnimationFrame("skip"); + core.setFlag("skip", false); + let a = core.getFlag("skip", false); + core.setFlag("skip", false); + if (a) { + const data = core.clone(core.status.event.data.current); - core.insertAction(data); - core.doAction(); - } - } catch (ee) { - console.error(ee); - } - }; - cg.ontouchstart = 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.targetTouches[0].clientX - left) / core.domStyle.scale - ), - py = Math.floor( - (e.targetTouches[0].clientY - top) / core.domStyle.scale - ); - core.ui.cgText.click(px * 3, py * 3); - } catch (ee) { - main.log(ee); - } - }; - let auto = false; - class cgText { - constructor() { - //绘制需要的变量 - this.image = ""; - this.head = { name: "face_050445.webp", px: -300 }; - this.bodyList = [ - { name: "tati_050145a.webp", px: 100, filter: false }, - { name: "tati_120124.webp", px: 1100, filter: true }, - ]; - this.name = ""; - this.text = ""; - this.time = 0; - this.WindowSkin = false; - this.sound = ""; - this.beforeSound = 0; - this.wait = 200; - this.memory = false; - } - click(px, py) { - //点击效果 + core.insertAction(data); + core.doAction(); + } + } catch (ee) { + console.error(ee); + } + }; + cg.ontouchstart = 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.targetTouches[0].clientX - left) / core.domStyle.scale + ), + py = Math.floor( + (e.targetTouches[0].clientY - top) / core.domStyle.scale + ); + core.ui.cgText.click(px * 3, py * 3); + } catch (ee) { + main.log(ee); + } + }; + let auto = false; + class cgText { + constructor() { + //绘制需要的变量 + this.image = ""; + this.head = { name: "face_050445.webp", px: -300 }; + this.bodyList = [ + { name: "tati_050145a.webp", px: 100, filter: false }, + { name: "tati_120124.webp", px: 1100, filter: true }, + ]; + this.name = ""; + this.text = ""; + this.time = 0; + this.WindowSkin = false; + this.sound = ""; + this.beforeSound = 0; + this.wait = 200; + this.memory = false; + } + click(px, py) { + //点击效果 - const makeBox = ([x, y], [w, h]) => { - return [ - [x, y], - [x + w, y + h], - ]; - }; - const inRect = ([x, y], [ - [sx, sy], - [dx, dy] - ]) => { - return sx <= x && x <= dx && sy <= y && y <= dy; - }; - const pos = [px, py]; - const savebox = makeBox([1700, 1100], [192, 96]); - const saveboxVertical = makeBox([52, 1700], [96, 192]); - const skipbox = makeBox([1400, 1100], [192, 96]); - const skipboxVertical = makeBox([52, 1400], [96, 192]); - const autobox = makeBox([1700, 900], [192, 96]); - const autoboxVertical = makeBox([256, 1700], [96, 192]); - if ( - (core.domStyle.isVertical && - inRect(pos, skipboxVertical) && - !this.WindowSkin) || - (!core.domStyle.isVertical && - !this.WindowSkin && - inRect(pos, skipbox)) - ) { - auto = false; - let time = 0; - core.stopSound(this.beforeSound); - core.registerAnimationFrame("skip", true, (timestamp) => { - if (timestamp > time + 50) { - time = timestamp; - if ( - core.status.event.id == "action" && - core.status.event.data.type == "cgtext" - ) { - core.setFlag("skip", true); - main.dom.cgText.style.display = "none"; - core.doAction(); - } - } - }); - } else if ( - (core.domStyle.isVertical && - inRect(pos, autoboxVertical) && - !this.WindowSkin) || - (!core.domStyle.isVertical && - !this.WindowSkin && - inRect(pos, autobox)) - ) { - auto = !auto; + const makeBox = ([x, y], [w, h]) => { + return [ + [x, y], + [x + w, y + h], + ]; + }; + const inRect = ([x, y], [[sx, sy], [dx, dy]]) => { + return sx <= x && x <= dx && sy <= y && y <= dy; + }; + const pos = [px, py]; + const savebox = makeBox([1700, 1100], [192, 96]); + const saveboxVertical = makeBox([52, 1700], [96, 192]); + const skipbox = makeBox([1400, 1100], [192, 96]); + const skipboxVertical = makeBox([52, 1400], [96, 192]); + const autobox = makeBox([1700, 900], [192, 96]); + const autoboxVertical = makeBox([256, 1700], [96, 192]); + if ( + (core.domStyle.isVertical && + inRect(pos, skipboxVertical) && + !this.WindowSkin) || + (!core.domStyle.isVertical && + !this.WindowSkin && + inRect(pos, skipbox)) + ) { + auto = false; + let time = 0; + core.stopSound(this.beforeSound); + core.registerAnimationFrame("skip", true, (timestamp) => { + if (timestamp > time + 50) { + time = timestamp; + if ( + core.status.event.id == "action" && + core.status.event.data.type == "cgtext" + ) { + core.setFlag("skip", true); + main.dom.cgText.style.display = "none"; + core.doAction(); + } + } + }); + } else if ( + (core.domStyle.isVertical && + inRect(pos, autoboxVertical) && + !this.WindowSkin) || + (!core.domStyle.isVertical && + !this.WindowSkin && + inRect(pos, autobox)) + ) { + auto = !auto; - const data = core.clone(core.status.event.data.current); - data.showAll = true; - data.time = 0; - data.text = data.text.replace(/(\\(z))(\[.*?])?/g, ""); //去除打字机暂停效果 - data.sound = ""; - core.insertAction(data); - core.doAction(); - } else if ( - (core.domStyle.isVertical && - inRect(pos, saveboxVertical) && - !this.WindowSkin) || - (!core.domStyle.isVertical && - !this.WindowSkin && - inRect(pos, savebox)) - ) { - //存档 - auto = false; - if (core.status.event.animateUI) return; - if (core.status.event.interval != null) return; - const current = core.clone(core.status.event.data.current); - current.showAll = true; - current.time = 0; - current.sound = ""; - current.text = current.text.replace(/(\\(z))(\[.*?])?/g, ""); //去除当前事件所有打字机效果 - cg.style.display = "none"; - const data = [{ type: "callSave" }, current]; //插入存档事件 - core.insertAction(data); + const data = core.clone(core.status.event.data.current); + data.showAll = true; + data.time = 0; + data.text = data.text.replace(/(\\(z))(\[.*?])?/g, ""); //去除打字机暂停效果 + data.sound = ""; + core.insertAction(data); + core.doAction(); + } else if ( + (core.domStyle.isVertical && + inRect(pos, saveboxVertical) && + !this.WindowSkin) || + (!core.domStyle.isVertical && + !this.WindowSkin && + inRect(pos, savebox)) + ) { + //存档 + auto = false; + if (core.status.event.animateUI) return; + if (core.status.event.interval != null) return; + const current = core.clone(core.status.event.data.current); + current.showAll = true; + current.time = 0; + current.sound = ""; + current.text = current.text.replace(/(\\(z))(\[.*?])?/g, ""); //去除当前事件所有打字机效果 + cg.style.display = "none"; + const data = [{ type: "callSave" }, current]; //插入存档事件 + core.insertAction(data); - core.doAction(); - } else if (!core.status.event.data) { - cg.style.display = "none"; - core.ui._animateUI("hide", null, () => { - core.doAction(); - }); - } else { - // 正在淡入淡出的话不执行 - if (core.status.event.animateUI) return; - auto = false; + core.doAction(); + } else if (!core.status.event.data) { + cg.style.display = "none"; + core.ui._animateUI("hide", null, () => { + core.doAction(); + }); + } else { + // 正在淡入淡出的话不执行 + if (core.status.event.animateUI) return; + auto = false; - // 打字机效果显示全部文字 - if (core.status.event.interval != null) { - const data = core.clone(core.status.event.data?.current); - data.showAll = true; - data.time = 0; - data.text = data.text.replace(/(\\(z))(\[.*?])?/g, ""); //去除打字机暂停效果 - data.sound = ""; - core.insertAction(data); - core.doAction(); - return; - } else { - core.stopSound(this.beforeSound); - } + // 打字机效果显示全部文字 + if (core.status.event.interval != null) { + const data = core.clone(core.status.event.data?.current); + data.showAll = true; + data.time = 0; + data.text = data.text.replace(/(\\(z))(\[.*?])?/g, ""); //去除打字机暂停效果 + data.sound = ""; + core.insertAction(data); + core.doAction(); + return; + } else { + core.stopSound(this.beforeSound); + } - cg.style.display = "none"; - core.ui._animateUI("hide", null, () => { - core.doAction(); - }); - } - } + cg.style.display = "none"; + core.ui._animateUI("hide", null, () => { + core.doAction(); + }); + } + } - drawTextContent(ctx, content, config) { - //绘制多行文字并执行打字机效果 + drawTextContent(ctx, content, config) { + //绘制多行文字并执行打字机效果 - ctx = core.getContextByName(ctx); - // 设置默认配置项 - var textAttribute = - core.status.textAttribute || core.initStatus.textAttribute; - var globalAttribute = - core.status.globalAttribute || core.initStatus.globalAttribute; - config = core.clone(config || {}); - config.left = config.left || 0; - config.right = - config.left + (config.maxWidth == null ? core._PX_ : config.maxWidth); - config.top = config.top || 0; - config.color = core.arrayToRGBA(config.color || textAttribute.text); - if (config.bold == null) config.bold = textAttribute.bold; - config.italic = config.italic || false; - config.align = config.align || textAttribute.align || "left"; - config.fontSize = config.fontSize || textAttribute.textfont; - config.lineHeight = config.lineHeight || config.fontSize * 1.3; - config.defaultFont = config.font = config.font || globalAttribute.font; - config.time = config.time || 0; - config.letterSpacing = - config.letterSpacing == null ? - textAttribute.letterSpacing || 0 : - config.letterSpacing; + ctx = core.getContextByName(ctx); + // 设置默认配置项 + var textAttribute = + core.status.textAttribute || core.initStatus.textAttribute; + var globalAttribute = + core.status.globalAttribute || core.initStatus.globalAttribute; + config = core.clone(config || {}); + config.left = config.left || 0; + config.right = + config.left + (config.maxWidth == null ? core._PX_ : config.maxWidth); + config.top = config.top || 0; + config.color = core.arrayToRGBA(config.color || textAttribute.text); + if (config.bold == null) config.bold = textAttribute.bold; + config.italic = config.italic || false; + config.align = config.align || textAttribute.align || "left"; + config.fontSize = config.fontSize || textAttribute.textfont; + config.lineHeight = config.lineHeight || config.fontSize * 1.3; + config.defaultFont = config.font = config.font || globalAttribute.font; + config.time = config.time || 0; + config.letterSpacing = + config.letterSpacing == null + ? textAttribute.letterSpacing || 0 + : config.letterSpacing; - config.index = 0; - config.currcolor = config.color; - config.currfont = config.fontSize; - config.lineMargin = Math.max( - Math.round(config.fontSize / 4), - config.lineHeight - config.fontSize - ); - config.topMargin = parseInt(config.lineMargin / 2); - config.lineMaxHeight = config.lineMargin + config.fontSize; - config.offsetX = 0; - config.offsetY = 0; - config.line = 0; - config.blocks = []; - config.isHD = ctx == null || ctx.canvas.hasAttribute("isHD"); + config.index = 0; + config.currcolor = config.color; + config.currfont = config.fontSize; + config.lineMargin = Math.max( + Math.round(config.fontSize / 4), + config.lineHeight - config.fontSize + ); + config.topMargin = parseInt(config.lineMargin / 2); + config.lineMaxHeight = config.lineMargin + config.fontSize; + config.offsetX = 0; + config.offsetY = 0; + config.line = 0; + config.blocks = []; + config.isHD = ctx == null || ctx.canvas.hasAttribute("isHD"); - // 创建一个新的临时画布 - var tempCtx = document.createElement("canvas").getContext("2d"); - if (config.isHD && ctx) { - core.maps._setHDCanvasSize( - tempCtx, - ctx.canvas.width, - ctx.canvas.height - ); - } else { - tempCtx.canvas.width = ctx == null ? 1 : ctx.canvas.width; - tempCtx.canvas.height = ctx == null ? 1 : ctx.canvas.height; - } + // 创建一个新的临时画布 + var tempCtx = document.createElement("canvas").getContext("2d"); + if (config.isHD && ctx) { + core.maps._setHDCanvasSize( + tempCtx, + ctx.canvas.width, + ctx.canvas.height + ); + } else { + tempCtx.canvas.width = ctx == null ? 1 : ctx.canvas.width; + tempCtx.canvas.height = ctx == null ? 1 : ctx.canvas.height; + } - tempCtx.textBaseline = "top"; - tempCtx.font = core.ui._buildFont( - config.fontSize, - config.bold, - config.italic, - config.font - ); - tempCtx.fillStyle = config.color; - config = this._drawTextContent_draw(ctx, tempCtx, content, config); - return config; - } - _drawTextContent_draw(ctx, tempCtx, content, config) { - // Step 1: 绘制到tempCtx上,并记录下图块信息 - while (core.ui._drawTextContent_next(tempCtx, content, config)); + tempCtx.textBaseline = "top"; + tempCtx.font = core.ui._buildFont( + config.fontSize, + config.bold, + config.italic, + config.font + ); + tempCtx.fillStyle = config.color; + config = this._drawTextContent_draw(ctx, tempCtx, content, config); + return config; + } + _drawTextContent_draw(ctx, tempCtx, content, config) { + // Step 1: 绘制到tempCtx上,并记录下图块信息 + while (core.ui._drawTextContent_next(tempCtx, content, config)); - if (ctx == null) return config; + if (ctx == null) return config; - // Step 2: 从tempCtx绘制到画布上 - config.index = 0; - var _drawNext = function () { - if (config.index >= config.blocks.length) return false; - var block = config.blocks[config.index++]; - if (block != null) { - // It works, why? - const scale = config.isHD ? - devicePixelRatio * core.domStyle.scale : - 1; - ctx.restore(); - ctx.save(); //保存设置 - if (core.domStyle.isVertical) { - ctx.translate(1248, 0); //重新定位右上角为基准 - ctx.rotate(Math.PI / 2); //旋转90度 - } - ctx.drawImage( - tempCtx.canvas, - block.left * scale, - block.top * scale, - block.width * scale, - block.height * scale, - config.left + block.left + block.marginLeft, - config.top + block.top + block.marginTop, - block.width, - block.height - ); - ctx.restore(); - } - return true; - }; + // Step 2: 从tempCtx绘制到画布上 + config.index = 0; + var _drawNext = function () { + if (config.index >= config.blocks.length) return false; + var block = config.blocks[config.index++]; + if (block != null) { + // It works, why? + const scale = config.isHD + ? devicePixelRatio * core.domStyle.scale + : 1; + ctx.restore(); + ctx.save(); //保存设置 + if (core.domStyle.isVertical) { + ctx.translate(1248, 0); //重新定位右上角为基准 + ctx.rotate(Math.PI / 2); //旋转90度 + } + ctx.drawImage( + tempCtx.canvas, + block.left * scale, + block.top * scale, + block.width * scale, + block.height * scale, + config.left + block.left + block.marginLeft, + config.top + block.top + block.marginTop, + block.width, + block.height + ); + ctx.restore(); + } + return true; + }; - if (config.time == 0) { - while (_drawNext()); - if ( - (auto && !this.WindowSkin && !core.ui.cgText.sound) || - (core.ui.cgText.sound && !core.musicStatus.soundStatus) - ) { - setTimeout(() => { - if (auto) { - cg.style.display = "none"; - core.ui._animateUI("hide", null, () => { - core.doAction(); - }); - } - }, core.ui.cgText.wait); - } - } else { - clearInterval(core.status.event.interval); - core.status.event.interval = setInterval(function () { - if (!_drawNext()) { - clearInterval(core.status.event.interval); - core.status.event.interval = null; - if ( - (auto && !this.WindowSkin && !core.ui.cgText.sound) || - (core.ui.cgText.sound && !core.musicStatus.soundStatus) - ) - setTimeout(() => { - if (auto) { - cg.style.display = "none"; - core.ui._animateUI("hide", null, () => { - core.doAction(); - }); - } - }, core.ui.cgText.wait); - } - }, config.time); - } + if (config.time == 0) { + while (_drawNext()); + if ( + (auto && !this.WindowSkin && !core.ui.cgText.sound) || + (core.ui.cgText.sound && !core.musicStatus.soundStatus) + ) { + setTimeout(() => { + if (auto) { + cg.style.display = "none"; + core.ui._animateUI("hide", null, () => { + core.doAction(); + }); + } + }, core.ui.cgText.wait); + } + } else { + clearInterval(core.status.event.interval); + core.status.event.interval = setInterval(function () { + if (!_drawNext()) { + clearInterval(core.status.event.interval); + core.status.event.interval = null; + if ( + (auto && !this.WindowSkin && !core.ui.cgText.sound) || + (core.ui.cgText.sound && !core.musicStatus.soundStatus) + ) + setTimeout(() => { + if (auto) { + cg.style.display = "none"; + core.ui._animateUI("hide", null, () => { + core.doAction(); + }); + } + }, core.ui.cgText.wait); + } + }, config.time); + } - return config; - } + return config; + } - update() { - this.background(); - } - background() { - const img = core.material.images.images?.[this.image]; + update() { + this.background(); + } + background() { + const img = core.material.images.images?.[this.image]; - if (core.domStyle.isVertical) { - ctx.canvas.width = 1248; - ctx.canvas.height = 2028; - ctx.save(); //保存设置 - ctx.translate(1248, 0); //重新定位右上角为基准 - ctx.rotate(Math.PI / 2); //旋转90度 - } else { - ctx.canvas.width = 2028; - ctx.canvas.height = 1248; - } + if (core.domStyle.isVertical) { + ctx.canvas.width = 1248; + ctx.canvas.height = 2028; + ctx.save(); //保存设置 + ctx.translate(1248, 0); //重新定位右上角为基准 + ctx.rotate(Math.PI / 2); //旋转90度 + } else { + ctx.canvas.width = 2028; + ctx.canvas.height = 1248; + } - if (img) { - //绘制背景 - if (this.memory) ctx.filter = "sepia(50%)"; - ctx.drawImage(img, 0, 0, 2028, 1248); - ctx.filter = "none"; - } else { - core.fillRect(ctx, 0, 0, 2028, 1248); - } - this.bodyList.forEach((v) => { - //绘制立绘 - const body = core.material.images.images?.[v.name]; - if (v.filter) ctx.filter = "brightness(50%)"; - if (body) { - if (!v.w && !v.h && !v.scale) v.scale = 1.7 - if (!v.w && !v.h) { - ctx.drawImage( - body, - 0, - 0, - body.width, - body.height, - v.px, - 1248 - body.height * v.scale, - body.width * v.scale, - body.height * v.scale - ); - } else { - ctx.drawImage( - body, - 0, - 0, - body.width, - body.height, - v.px, - 1248 - (v.h ?? body.height), - v.w ?? body.width, - v.h ?? body.height) - } - } - ctx.filter = "none"; - }); - if (core.isPlaying() && !this.WindowSkin) - core.drawWindowSkin("winskin.webp", ctx, 30, 802, 1968, 416); //绘制对话框 - const head = core.material.images.images?.[this.head.name]; - if (head) { - //绘制头像 - ctx.drawImage( - head, - 0, - 0, - head.width, - head.height, - this.head.px, - 1248 - head.height * 2, - head.width * 2, - head.height * 2 - ); - } - if (core.isPlaying() && !this.WindowSkin) { - core.drawWindowSkin("winskin.webp", ctx, 1700, 1100, 192, 96); - core.fillBoldText1( - ctx, - "存 档", - 1736, - 1166, - "#FFFFFF", - "#000000", - 6, - "bold 48px Verdana" - ); - core.drawWindowSkin("winskin.webp", ctx, 1400, 1100, 192, 96); - core.fillBoldText1( - ctx, - "▶▶", - 1456, - 1166, - "#FFFFFF", - "#000000", - 6, - "bold 48px Verdana" - ); - core.drawWindowSkin("winskin.webp", ctx, 1700, 900, 192, 96); - let autoText = "AUTO"; - if (auto) autoText = "STOP"; - core.fillBoldText1( - ctx, - autoText, - 1722, - 966, - "#FFFFFF", - "#000000", - 6, - "bold 48px Verdana" - ); - } - if (this.name) - core.fillBoldText1( - ctx, - `【${this.name}】`, - 500, - 880, - "#FFFFFF", - "#000000", - 6, - "bold 48px Verdana" - ); //绘制名字 - if ( - this.sound && - core.material.sounds[this.sound] && - !core.getFlag("skip", false) && - core.musicStatus.soundStatus - ) { - this.beforeSound = core.playSound(this.sound, null, () => { - if ( - this.sound && - auto && - !this.WindowSkin && - core.musicStatus.soundStatus - ) { - setTimeout(() => { - if (auto) { - cg.style.display = "none"; - core.ui._animateUI("hide", null, () => { - core.doAction(); - }); - } - }, core.ui.cgText.wait); - } - }); - } - if (this.text && !core.getFlag("skip", false)) { - //绘制对话 - this.drawTextContent(ctx, this.text, { - left: 500, - top: 950, - bold: true, - color: "#FFFFFF", - align: "left", - fontSize: 48, - time: this.time || 0, - font: "Verdana", - maxWidth: 1000, - }); - } + if (img) { + //绘制背景 + if (this.memory) ctx.filter = "sepia(50%)"; + ctx.drawImage(img, 0, 0, 2028, 1248); + ctx.filter = "none"; + } else { + core.fillRect(ctx, 0, 0, 2028, 1248); + } + this.bodyList.forEach((v) => { + //绘制立绘 + const body = core.material.images.images?.[v.name]; + if (v.filter) ctx.filter = "brightness(50%)"; + if (body) { + if (!v.w && !v.h && !v.scale) v.scale = 1.7; + if (!v.w && !v.h) { + ctx.drawImage( + body, + 0, + 0, + body.width, + body.height, + v.px, + 1248 - body.height * v.scale, + body.width * v.scale, + body.height * v.scale + ); + } else { + ctx.drawImage( + body, + 0, + 0, + body.width, + body.height, + v.px, + 1248 - (v.h ?? body.height), + v.w ?? body.width, + v.h ?? body.height + ); + } + } + ctx.filter = "none"; + }); + if (core.isPlaying() && !this.WindowSkin) + core.drawWindowSkin("winskin.webp", ctx, 30, 802, 1968, 416); //绘制对话框 + const head = core.material.images.images?.[this.head.name]; + if (head) { + //绘制头像 + ctx.drawImage( + head, + 0, + 0, + head.width, + head.height, + this.head.px, + 1248 - head.height * 2, + head.width * 2, + head.height * 2 + ); + } + if (core.isPlaying() && !this.WindowSkin) { + core.drawWindowSkin("winskin.webp", ctx, 1700, 1100, 192, 96); + core.fillBoldText1( + ctx, + "存 档", + 1736, + 1166, + "#FFFFFF", + "#000000", + 6, + "bold 48px Verdana" + ); + core.drawWindowSkin("winskin.webp", ctx, 1400, 1100, 192, 96); + core.fillBoldText1( + ctx, + "▶▶", + 1456, + 1166, + "#FFFFFF", + "#000000", + 6, + "bold 48px Verdana" + ); + core.drawWindowSkin("winskin.webp", ctx, 1700, 900, 192, 96); + let autoText = "AUTO"; + if (auto) autoText = "STOP"; + core.fillBoldText1( + ctx, + autoText, + 1722, + 966, + "#FFFFFF", + "#000000", + 6, + "bold 48px Verdana" + ); + } + if (this.name) + core.fillBoldText1( + ctx, + `【${this.name}】`, + 500, + 880, + "#FFFFFF", + "#000000", + 6, + "bold 48px Verdana" + ); //绘制名字 + if ( + this.sound && + core.material.sounds[this.sound] && + !core.getFlag("skip", false) && + core.musicStatus.soundStatus + ) { + this.beforeSound = core.playSound(this.sound, null, () => { + if ( + this.sound && + auto && + !this.WindowSkin && + core.musicStatus.soundStatus + ) { + setTimeout(() => { + if (auto) { + cg.style.display = "none"; + core.ui._animateUI("hide", null, () => { + core.doAction(); + }); + } + }, core.ui.cgText.wait); + } + }); + } + if (this.text && !core.getFlag("skip", false)) { + //绘制对话 + this.drawTextContent(ctx, this.text, { + left: 500, + top: 950, + bold: true, + color: "#FFFFFF", + align: "left", + fontSize: 48, + time: this.time || 0, + font: "Verdana", + maxWidth: 1000, + }); + } - ctx.restore(); - } - } - core.ui.cgText = new cgText(); -}, - "旁白": function () { + ctx.restore(); + } + } + core.ui.cgText = new cgText(); + }, + 旁白: function () { // 在此增加新插件 const over = document.createElement("canvas"); //over画布设置 over.style.position = "absolute"; @@ -13740,73 +16011,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = } }; }, - "属性映射": function () { - // 在此增加新插件 - this.statusEquip = function () { - const hero = core.status.hero; - //装备具体效果在这里写,道具填写道具类型为equip并选择装备类型,道具的装备属性中装备类型遵循以下填写方式: - //固定装备孔的填写0/1/2/3,分别对应主手、副手、防具、饰品 - //主副手同时可使用的,填写 武器 - //具体的换装时装备切换操作写在新道具栏/物品栏插件 - //当前仅完善法杖、单手剑、双手剑、匕首、盾牌的多孔切换操作 - //主武器效果 - if (core.getEquip[0]) { - switch (core.getEquip[0]) { - case "sword1": - hero.atk = hero.str + hero.agi; - hero.magic = false; - break; - } - } - //副手效果 - if (core.getEquip[1]) { - switch (core.getEquip[1]) { - case "sword1": - hero.atk += hero.agi; - break; - } - } - //防具效果 - if (core.getEquip[2]) { - switch (core.getEquip[2]) { - case "sword1": - hero.def = hero.con + hero.agi; - hero.hpmax = 2.5 * hero.con; - break; - } - } - //饰品效果 - if (core.getEquip[3]) { - switch (core.getEquip[3]) { - case "sword1": - hero.speed += 0.4 * hero.int + 0.6 * hero.agi; - break; - } - } - }; - this.updateStatus = function () { - const hero = core.status.hero; - //默认映射关系 - hero.hpmax = hero.str * 50 + hero.con * 50; - hero.atk = hero.str * 0.5 + hero.int * 0.5; - hero.manamax = hero.agi * 0.5 + hero.int * 0.5; - hero.def = hero.con * 0.5 + hero.agi * 0.5; - hero.mdef = hero.con * 0.5 + hero.int * 0.5; - hero.speed = hero.str * 0.5 + hero.agi * 0.5; - hero.magic = false; - this.statusEquip(); //处理装备效果 - for (let v in hero) { - //归整 - if (typeof hero[v] === "number") { - hero[v] = Math.floor(hero[v]); - } - } - hero.hp = Math.min(hero.hp, hero.hpmax); - hero.mana = Math.min(hero.mana, hero.manamax); - core.status.hero = hero; - }; -}, - "回合制boss战": function () { + 回合制boss战: function () { // 在此增加新插件 const boss = document.createElement("canvas"); //boss战画布设置 boss.style.position = "absolute"; @@ -13854,1229 +16059,1246 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = } core.ui.boss = new boss1(); }, - "剧情视频引用": function () { - // 在此增加新插件 - let a; - let bgm; - - function gtouchstart() { - timeOutEvent = setTimeout(() => { - video.remove(); - video1.remove(); - core.doAction(); - clearTimeout(a); - core.playBgm(bgm); - core.resumeBgm(); - }, 2000); //这里设置定时器,定义长按500毫秒触发长按事件,时间可以自己改,个人感觉500毫秒非常合适 - return false; - } - - //手释放,如果在500毫秒内就释放,则取消长按事件,此时可以执行onclick应该执行的事件 - function gtouchend() { - if (timeOutEvent != 0) { - //这里写要执行的内容(尤如onclick事件) - console.log("你这是点击,不是长按"); - } - clearTimeout(timeOutEvent); //清除定时器 - return false; - } - - this.openvideo = function () { - if (!core.isPlaying()) return; - const video = document.createElement("iframe"); //iframe设置 - video.style.position = "absolute"; - video.style.zIndex = 320; - video.style.display = "block"; - video.id = "video"; - main.dom.gameGroup.insertAdjacentElement("afterend", video); - video.style.top = "50%"; - video.style.left = "50%"; - video.style.transform = "translate(-50%,-50%)"; - main.dom.video = video; - const video1 = document.createElement("canvas"); //video1画布设置 - video1.style.position = "absolute"; - video1.style.zIndex = 330; - video1.style.display = "block"; - video1.id = "video1"; - main.dom.gameGroup.insertAdjacentElement("afterend", video1); - video1.style.top = "50%"; - video1.style.left = "50%"; - video1.style.transform = "translate(-50%,-50%)"; - const ctx = video1.getContext("2d"); - main.dom.video1 = video1; - if (core.domStyle.isVertical) { - video.width = 416 * 3; - video.height = 676 * 3; - video.style.transform = "translate(-50%,-50%) rotate(90deg)"; //重新定位右上角为基准 - } else { - video.width = 676 * 3; - video.height = 416 * 3; - video.style.transform = "translate(-50%,-50%)"; - } - video1.ontouchstart = function (e) { - try { - e.preventDefault(); - if (!core.isPlaying()) return false; - gtouchstart(); - } catch (ee) { - main.log(ee); - } - }; - video1.ontouchend = function (e) { - try { - e.preventDefault(); - if (!core.isPlaying()) return false; - gtouchend(); - } catch (ee) { - main.log(ee); - } - }; - - video1.onmouseup = function (e) { - //鼠标抬起 - try { - e.stopPropagation(); - if (!core.isPlaying()) return false; - gtouchend(); - } catch (ee) { - console.error(ee); - } - }; - video1.onmousedown = function (e) { - //鼠标按下 - try { - e.stopPropagation(); - if (!core.isPlaying()) return false; - gtouchstart(); - } catch (ee) { - main.log(ee); - } - }; - let globalAlpha = 0; - let frame = 1; - let al = 0; - core.registerAnimationFrame("beforeop", true, function () { - al++; - core.clearMap(ctx) - ctx.globalAlpha = al / 30; - core.fillRect(ctx, 0, 0, video1.width, video1.height, "#000000"); - ctx.globalAlpha = 1; - core.fillBoldText1( - ctx, - "Loading...", - 1014, - 624, - "#FFFFFF", - "#000000", - 6, - "bold 72px Verdana" - ); - }); - core.control.resize(); - - //player.bilibili.com/player.html - //www.bilibili.com/blackboard/html5mobileplayer.html - // - video.src = - "///www.bilibili.com/blackboard/html5mobileplayer.html?isOutside=true&aid=6484104&bvid=BV1cs411b7cH&cid=10546155&p=1&poster=0&autoplay=1&high_quality=1&muted=0&danmaku=0"; - video.scrolling = "no"; - video.border = "0"; - video.crossorigin = true; - video.frameborder = "no"; - video.framespacing = "0"; - video.allowfullscreen = false; - - video.sandbox = - "allow-top-navigation allow-same-origin allow-forms allow-scripts"; - //gsl_play_mask - - video.addEventListener("load", function () { - core.unregisterAnimationFrame("beforeop"); - core.registerAnimationFrame("op", true, function () { - core.clearMap(ctx); - if (core.domStyle.isVertical) { - ctx.canvas.width = 416 * 3; - ctx.canvas.height = 676 * 3; - ctx.save(); //保存设置 - ctx.translate(416 * 3, 0); //重新定位右上角为基准 - ctx.rotate(Math.PI / 2); //旋转90度 - } else { - ctx.canvas.width = 676 * 3; - ctx.canvas.height = 416 * 3; - } - ctx.globalAlpha = 1; - core.fillRect(ctx, 0, 0, video1.width, video1.height, "#000000"); - - ctx.globalAlpha = globalAlpha / 30; - core.setTextAlign(ctx, "center"); - core.fillBoldText1( - ctx, - "长按2秒后跳过op", - 1014, - 624, - "#FFFFFF", - "#000000", - 6, - "bold 48px Verdana" - ); - globalAlpha += frame; - if (globalAlpha > 29) frame = -1; - ctx.restore(); - if (frame === -1 && globalAlpha < 0) { - core.clearMap(ctx); - core.unregisterAnimationFrame("op"); - } - }); - bgm = core.musicStatus.playingBgm; - core.playBgm("op.mp3"); - a = setTimeout(() => { - video.remove(); - video1.remove(); - core.playBgm(bgm); - core.doAction(); - }, 127500); - }); - }; -}, - "帧动画/图片叠拼": function () { - // 在此增加新插件 - this.animationDrawable = function ( - allFarme, - color, - globalAlpha, - imageList, - soundList - ) { - if (!core.isPlaying()) { - return core.doAction(); - } - const over = main.dom.over; - const ctx = over.getContext("2d"); - over.style.display = "block"; - - let farme = 0; - let now = 0; - core.registerAnimationFrame( - "animationDrawable", - true, - function (timestamp) { - if (timestamp - now > 1000 / 60) { - now = timestamp; - if (core.domStyle.isVertical) { - over.width = 1248; - over.height = 2028; - ctx.save(); //保存设置 - ctx.translate(1248, 0); //重新定位右上角为基准 - ctx.rotate(Math.PI / 2); //旋转90度 - } else { - over.width = 2028; - over.height = 1248; - } - - ctx.globalAlpha = (globalAlpha ?? 100) / 100; - core.fillRect(ctx, 0, 0, 2028, 1248, color); - - imageList.forEach(function (one) { - if ( - farme >= (one.beforefarme ?? 0) && - farme <= (one.afterfarme ?? allFarme) - ) { - const img = core.material.images.images?.[one.image]; - if (img) { - const gla = one.globalAlpha ?? 100; - const agla = one.aglobalAlpha ?? gla, - beforefarme = one.beforefarme ?? 0; - const afterfarme = one.afterfarme ?? allFarme; - - ctx.globalAlpha = - (gla + - ((agla - gla) * (farme - beforefarme)) / - (afterfarme - beforefarme || 1)) / - 100; - - const cx = - (one.cx ?? 0) + - (((one.acx ?? 0) - (one.cx ?? 0)) * - (farme - beforefarme)) / - (afterfarme - beforefarme || 1), - cy = - (one.cy ?? 0) + - (((one.acy ?? 0) - (one.cy ?? 0)) * - (farme - beforefarme)) / - (afterfarme - beforefarme || 1), - cw = - (one.cw ?? img.width) + - (((one.acw ?? img.width) - (one.cw ?? img.width)) * - (farme - beforefarme)) / - (afterfarme - beforefarme || 1), - ch = - (one.ch ?? img.height) + - (((one.acw ?? img.height) - (one.cw ?? img.height)) * - (farme - beforefarme)) / - (afterfarme - beforefarme || 1), - x = - (one.x ?? 0) + - (((one.ax ?? 0) - (one.x ?? 0)) * (farme - beforefarme)) / - (afterfarme - beforefarme || 1), - y = - (one.y ?? 0) + - (((one.ay ?? 0) - (one.y ?? 0)) * (farme - beforefarme)) / - (afterfarme - beforefarme || 1), - w = - (one.w ?? 2028) + - (((one.aw ?? 2028) - (one.w ?? 2028)) * - (farme - beforefarme)) / - (afterfarme - beforefarme || 1), - h = - (one.h ?? 1248) + - (((one.aw ?? 1248) - (one.w ?? 1248)) * - (farme - beforefarme)) / - (afterfarme - beforefarme || 1); - ctx.drawImage(img, cx, cy, cw, ch, x, y, w, h); - } - } - }); - soundList.forEach(function (one) { - const lisen = - one.sound && - core.material.sounds[one.sound] && - core.musicStatus.soundStatus; - if (farme == one.startfarme && lisen) { - if (one.stopbefore) core.stopSound(); - core.playSound(one.sound); - } - }); - farme++; - ctx.globalAlpha = 1; - ctx.restore(); - - if (farme > allFarme) { - core.unregisterAnimationFrame("animationDrawable"); - over.style.display = "none"; - core.doAction(); - } - } - } - ); - }; -}, - "musicMode": function () { - // 在此增加新插件 - const music = document.createElement("canvas"); - music.style.position = "absolute"; - music.style.zIndex = 300; - music.style.display = "none"; - music.id = "music"; - main.dom.gameGroup.insertAdjacentElement("afterend", music); - music.style.top = "50%"; - music.style.left = "50%"; - music.style.transform = "translate(-50%,-50%)"; - const ctx = music.getContext("2d"); - main.dom.music = music; - - const audio = document.createElement("audio") - audio.autoplay = true - audio.preload = 'auto' - - function getRandomInt(min, max) { - const minCeiled = Math.ceil(min); - const maxFloored = Math.floor(max); - return Math.floor(Math.random() * (maxFloored - minCeiled) + minCeiled); - } - let page = 0; //初始页面 - let ischange = false; - let isvolume = false; - let pcx = 0; - let pcy = 0; - music.addEventListener('mousedown', function (e) { - e.stopPropagation(); - 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.music.mousedown(px * 3, py * 3); - - }) - music.addEventListener('mousemove', function (e) { - - e.stopPropagation(); - 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.music.mousemove(px * 3, py * 3); - - }) - music.addEventListener('mouseup', function (e) { - - e.stopPropagation(); - ischange = false; - isvolume = false; - if (!main.core.ui.music.stop) audio.play() - - }) - music.addEventListener('mouseleave', function (e) { - - e.stopPropagation(); - ischange = false; - isvolume = false; - if (!main.core.ui.music.stop) audio.play() - - }) - music.addEventListener("touchstart", function (e) { - - e.preventDefault(); - const left = core.dom.gameGroup.offsetLeft; - const top = core.dom.gameGroup.offsetTop; - const px = Math.floor( - (e.touches[0].clientX - left) / core.domStyle.scale - ), - py = Math.floor( - (e.touches[0].clientY - top) / core.domStyle.scale - ); - core.ui.music.mousedown(px * 3, py * 3); - - }) - music.addEventListener('touchmove', function (e) { - - e.stopPropagation(); - const left = core.dom.gameGroup.offsetLeft; - const top = core.dom.gameGroup.offsetTop; - const px = Math.floor((e.touches[0].clientX - left) / core.domStyle.scale), - py = Math.floor((e.touches[0].clientY - top) / core.domStyle.scale); - core.ui.music.mousemove(px * 3, py * 3); - - }) - music.addEventListener('touchend', function (e) { - - e.stopPropagation(); - ischange = false; - isvolume = false; - if (!main.core.ui.music.stop) audio.play() - - }) - music.addEventListener('touchcancel', function (e) { - - e.stopPropagation(); - ischange = false; - isvolume = false; - - }) - - audio.addEventListener('ended', function () { - switch (main.core.ui.music.type) { - case 'danqu': - audio.currentTime = 0 - if (!main.core.ui.music.stop) audio.play() - main.core.ui.music.stop = false - page = main.core.ui.music.selection[0] - - break; - case 'xunhuan': - if (main.core.ui.music.selection[1] === main.core.ui.music.musicMx[main.core.ui.music.selection[0]].length - 1) { - if (main.core.ui.music.selection[0] === main.core.ui.music.musicMx.length - 1) { - main.core.ui.music.selection[0] = 0 - main.core.ui.music.selection[1] = 0 - } else { - main.core.ui.music.selection[0] += 1 - main.core.ui.music.selection[1] = 0 - } - } else { - main.core.ui.music.selection[1] += 1 - } - page = main.core.ui.music.selection[0] - audio.src = "project/bgms/" + main.core.ui.music.musicMx[main.core.ui.music.selection[0]][main.core.ui.music.selection[1]] - - if (!main.core.ui.music.stop) audio.play() - main.core.ui.music.stop = false - break; - case 'suiji': - main.core.ui.music.selection[0] = getRandomInt(0, main.core.ui.music.musicMx.length) - main.core.ui.music.selection[1] = getRandomInt(0, main.core.ui.music.musicMx[main.core.ui.music.selection[0]].length) - audio.src = "project/bgms/" + main.core.ui.music.musicMx[main.core.ui.music.selection[0]][main.core.ui.music.selection[1]] - page = main.core.ui.music.selection[0] - - if (!main.core.ui.music.stop) audio.play() - main.core.ui.music.stop = false - break; - } - }) - core.audio = audio - - class musicclass { - constructor() { - //music列表 - //需全塔属性注册并保存在bgms文件夹,每个数组为显示的一页内容 - this.musicMx = [ - ["Asphodelus_Ceui.mp3", "Blind_Alley.mp3"], - ["Crawler.mp3", "op.mp3", "theme.mp3"], - ]; - //音乐别名(将在播放器内显示的音乐名,music列表内的都要有对应歌名) - this.musicname = { - "Asphodelus_Ceui.mp3": "Asphodelus", - "Blind_Alley.mp3": "Blind", - "Crawler.mp3": "Crawler", - "op.mp3": "op", - "theme.mp3": "theme", - }; - this.selection = [0, 0] - this.stop = false - this.type = "xunhuan" - } - - //更新 - update() { - this.background(); - this.drawUI(); - } - background() { - //画布大小设置 - if (core.domStyle.isVertical) { - music.width = 1248; - music.height = 2028; - } else { - music.width = 2028; - music.height = 1248; - } - } - mousedown(px, py) { - //鼠标按下时 - //console.log(px, py) - const makeBox = ([x, y], [w, h]) => { - return [ - [x, y], - [x + w, y + h], - ]; - }; - const inRect = ([x, y], [ - [sx, sy], - [dx, dy] - ]) => { - return sx <= x && x <= dx && sy <= y && y <= dy; - }; - const pos = [px, py]; - const backbox = makeBox([15, 35], [210, 90]); - if (inRect(pos, backbox)) { - //离开按钮是一致的,其余的记区分横竖屏 - music.style.display = "none"; - core.clearMap(ctx); - core.unregisterAnimationFrame('music') - audio.src = "" - core.restart(); - - return; - } - if (core.domStyle.isVertical) { //竖屏 - - const pageupbox = makeBox([100, 900], [200, 100]); - const pagedownbox = makeBox([700, 900], [200, 100]); - const musicbox = makeBox([100, 200], [800, this.musicMx[page].length * 100]) - const beforebox = makeBox([310, 1720], [100, 100]) - const afterbox = makeBox([700, 1720], [100, 100]) - const playbox = makeBox([480, 1680], [160, 160]) - const typebox = makeBox([830, 1710], [150, 150]) - const changebox = makeBox([-100 + pcx, pcy + 590], [1000, 20]) - const volumebox = makeBox([890 + 250, 200], [20, 500]) - if (inRect(pos, pageupbox)) { - if (page !== 0) page -= 1 - return; - } - if (inRect(pos, pagedownbox)) { - if (page !== this.musicMx.length - 1) page += 1 - return; - } - if (inRect(pos, playbox)) { - if (this.stop) { - this.stop = !this.stop - audio.play() - } else { - this.stop = !this.stop - audio.pause() - } - return; - } - if (inRect(pos, beforebox)) { - switch (this.type) { - case 'danqu': - audio.currentTime = 0 - if (!this.stop) audio.play() - this.stop = false - page = this.selection[0] - - break; - case 'xunhuan': - if (this.selection[1] === 0) { - if (this.selection[0] === 0) { - this.selection[0] = this.musicMx.length - 1 - this.selection[1] = this.musicMx[this.selection[0]].length - 1 - } else { - this.selection[0] -= 1 - this.selection[1] = this.musicMx[this.selection[0]].length - 1 - } - } else { - this.selection[1] -= 1 - } - page = this.selection[0] - audio.src = "project/bgms/" + this.musicMx[this.selection[0]][this.selection[1]] - - if (!this.stop) audio.play() - this.stop = false - break; - case 'suiji': - this.selection[0] = getRandomInt(0, this.musicMx.length) - this.selection[1] = getRandomInt(0, this.musicMx[this.selection[0]].length) - audio.src = "project/bgms/" + this.musicMx[this.selection[0]][this.selection[1]] - page = this.selection[0] - - if (!this.stop) audio.play() - this.stop = false - break; - } - return; - } - if (inRect(pos, afterbox)) { - switch (this.type) { - case 'danqu': - audio.currentTime = 0 - if (!this.stop) audio.play() - this.stop = false - page = this.selection[0] - break; - case 'xunhuan': - if (this.selection[1] === this.musicMx[this.selection[0]].length - 1) { - if (this.selection[0] === this.musicMx.length - 1) { - this.selection[0] = 0 - this.selection[1] = 0 - } else { - this.selection[0] += 1 - this.selection[1] = 0 - } - } else { - this.selection[1] += 1 - } - page = this.selection[0] - audio.src = "project/bgms/" + this.musicMx[this.selection[0]][this.selection[1]] - - if (!this.stop) audio.play() - this.stop = false - break; - case 'suiji': - this.selection[0] = getRandomInt(0, this.musicMx.length) - this.selection[1] = getRandomInt(0, this.musicMx[this.selection[0]].length) - audio.src = "project/bgms/" + this.musicMx[this.selection[0]][this.selection[1]] - - page = this.selection[0] - if (!this.stop) audio.play() - this.stop = false - break; - } - return; - } - if (inRect(pos, typebox)) { - switch (this.type) { - case 'danqu': - this.type = 'xunhuan' - break; - case 'xunhuan': - this.type = 'suiji' - break; - case 'suiji': - this.type = 'danqu' - break; - } - return; - } - if (inRect(pos, musicbox)) { - pcy = -800 - const index = Math.floor((py - 1000 - pcy) / 100) - if (page !== this.selection[0] || index !== this.selection[1]) { - this.selection[0] = page - this.selection[1] = index - audio.src = "project/bgms/" + this.musicMx[page][index] - - if (!this.stop) audio.play() - this.stop = false - - } else { - if (this.stop) { - this.stop = !this.stop - audio.play() - } else { - this.stop = !this.stop - audio.pause() - } - } - return; - } - if (inRect(pos, changebox)) { - - const time = Math.floor((px - 100) / 1000 * audio.duration) - - audio.pause() - audio.currentTime = time; - - ischange = true - } - if (inRect(pos, volumebox)) { - const time = (700 - py) / 500 - audio.volume = time - isvolume = true - } - - } else { //横屏 - const pageupbox = makeBox([1050, 1100], [200, 100]); - const pagedownbox = makeBox([1550, 1100], [200, 100]); - const musicbox = makeBox([900, 100], [1000, this.musicMx[page].length * 100]) - const beforebox = makeBox([135, 740], [50, 50]) - const afterbox = makeBox([450, 740], [50, 50]) - const playbox = makeBox([250, 700], [200, 200]) - const typebox = makeBox([600, 700], [100, 100]) - const changebox = makeBox([100, 590], [600, 20]) - const volumebox = makeBox([100, 990], [600, 20]) - if (inRect(pos, pageupbox)) { - if (page !== 0) page -= 1 - return; - } - if (inRect(pos, pagedownbox)) { - if (page !== this.musicMx.length - 1) page += 1 - return; - } - if (inRect(pos, playbox)) { - if (this.stop) { - this.stop = !this.stop - audio.play() - } else { - this.stop = !this.stop - audio.pause() - } - return; - } - if (inRect(pos, beforebox)) { - switch (this.type) { - case 'danqu': - audio.currentTime = 0 - if (!this.stop) audio.play() - this.stop = false - page = this.selection[0] - - break; - case 'xunhuan': - if (this.selection[1] === 0) { - if (this.selection[0] === 0) { - this.selection[0] = this.musicMx.length - 1 - this.selection[1] = this.musicMx[this.selection[0]].length - 1 - } else { - this.selection[0] -= 1 - this.selection[1] = this.musicMx[this.selection[0]].length - 1 - } - } else { - this.selection[1] -= 1 - } - page = this.selection[0] - audio.src = "project/bgms/" + this.musicMx[this.selection[0]][this.selection[1]] - - if (!this.stop) audio.play() - this.stop = false - break; - case 'suiji': - this.selection[0] = getRandomInt(0, this.musicMx.length) - this.selection[1] = getRandomInt(0, this.musicMx[this.selection[0]].length) - audio.src = "project/bgms/" + this.musicMx[this.selection[0]][this.selection[1]] - page = this.selection[0] - - if (!this.stop) audio.play() - this.stop = false - break; - } - return; - } - if (inRect(pos, afterbox)) { - switch (this.type) { - case 'danqu': - audio.currentTime = 0 - if (!this.stop) audio.play() - this.stop = false - page = this.selection[0] - break; - case 'xunhuan': - if (this.selection[1] === this.musicMx[this.selection[0]].length - 1) { - if (this.selection[0] === this.musicMx.length - 1) { - this.selection[0] = 0 - this.selection[1] = 0 - } else { - this.selection[0] += 1 - this.selection[1] = 0 - } - } else { - this.selection[1] += 1 - } - page = this.selection[0] - audio.src = "project/bgms/" + this.musicMx[this.selection[0]][this.selection[1]] - - if (!this.stop) audio.play() - this.stop = false - break; - case 'suiji': - this.selection[0] = getRandomInt(0, this.musicMx.length) - this.selection[1] = getRandomInt(0, this.musicMx[this.selection[0]].length) - audio.src = "project/bgms/" + this.musicMx[this.selection[0]][this.selection[1]] - - page = this.selection[0] - if (!this.stop) audio.play() - this.stop = false - break; - } - return; - } - if (inRect(pos, typebox)) { - switch (this.type) { - case 'danqu': - this.type = 'xunhuan' - break; - case 'xunhuan': - this.type = 'suiji' - break; - case 'suiji': - this.type = 'danqu' - break; - } - return; - } - if (inRect(pos, musicbox)) { - const index = Math.floor((py - 100) / 100) - if (page !== this.selection[0] || index !== this.selection[1]) { - this.selection[0] = page - this.selection[1] = index - audio.src = "project/bgms/" + this.musicMx[page][index] - - if (!this.stop) audio.play() - this.stop = false - - } else { - if (this.stop) { - this.stop = !this.stop - audio.play() - } else { - this.stop = !this.stop - audio.pause() - } - } - return; - } - if (inRect(pos, changebox)) { - - const time = Math.floor((px - 100) / 600 * audio.duration) - - audio.pause() - audio.currentTime = time; - - ischange = true - } - if (inRect(pos, volumebox)) { - const time = (px - 100) / 600 - audio.volume = time - isvolume = true - } - } - } - mousemove(px, py) { - - if (ischange) { - if (core.domStyle.isVertical) { - const time = Math.min(Math.max(Math.floor((px - 100) / 1000 * audio.duration), 0), audio.duration) - - audio.currentTime = time - } else { - const time = Math.min(Math.max(Math.floor((px - 100) / 600 * audio.duration), 0), audio.duration) - - audio.currentTime = time - } - - } - if (isvolume) { - if (core.domStyle.isVertical) { - const time = Math.min(Math.max((700 - py) / 500, 0), 1) - audio.volume = time - } else { - const time = Math.min(Math.max((px - 100) / 600, 0), 1) - audio.volume = time - - } - } - } - - drawUI() { - //绘制页面 - core.clearMap(music); - const bgVertical = core.material.images.images["bg_2010.webp"]; //竖屏背景 - const bg = core.material.images.images["bg_5043.webp"]; //竖屏背景 - if (core.domStyle.isVertical) { - //竖屏 - - core.fillRect(ctx, 0, 0, 1248, 2028, "#000000"); //黑色背景 - ctx.globalAlpha = 0.5; //透明度 - if (bgVertical) - ctx.drawImage(bgVertical, 0, 0, 1280, 1500, 0, 0, 1248, 2028); //绘制半透明背景图片 - ctx.globalAlpha = 1; //恢复为不透明 - - core.setTextAlign(ctx, "center"); - core.fillBoldText1( - ctx, - '◀离开', - 110, - 100, - "#FFFFFF", - "#000000", - 6, - core.ui._buildFont(66, true) - ); - //core.fillRect(ctx, 440, 760, 50, 50) - pcx = 0 - pcy = -800 - ctx.strokeStyle = "#FFFFFF" - ctx.lineWidth = 3 - ctx.beginPath() - ctx.moveTo(50 + pcx, pcy + 1000) - ctx.lineTo(50 + pcx, pcy + 1900) - ctx.moveTo(1000 + pcx, pcy + 1000) - ctx.lineTo(1000 + pcx, pcy + 1900) - ctx.stroke() - let posy = 1100 - const indexList = this.musicMx[page] - core.setTextAlign(ctx, "left"); - for (let i = 0; i < indexList.length; i++) { - const text = this.musicname[indexList[i]] - core.fillBoldText1( - ctx, - text, - 100 + pcx, pcy + - posy - 30, - page === this.selection[0] && i === this.selection[1] ? "#FFFFFF" : "#444444", - "#000000", - 6, - core.ui._buildFont(66, true) - ); - ctx.strokeStyle = "#FFFFFF" - ctx.lineWidth = 3 - ctx.beginPath() - ctx.moveTo(100 + pcx, pcy + posy) - ctx.lineTo(900 + pcx, pcy + posy) - ctx.stroke() - posy += 100 - } - - - core.fillBoldText1( - ctx, - '上一页', - 100, - 1000, - page === 0 ? "#444444" : "#FFFFFF", - "#000000", - 6, - core.ui._buildFont(66, true) - ); - - core.fillBoldText1( - ctx, - (page + 1) + "/" + this.musicMx.length, - 450, - 1000, - "#FFFFFF", - "#000000", - 6, - core.ui._buildFont(66, true) - ); - core.fillBoldText1( - ctx, - '下一页', - 700, - 1000, - page === this.musicMx.length - 1 ? "#444444" : "#FFFFFF", - "#000000", - 6, - core.ui._buildFont(66, true) - ); - - pcx = 200 - pcy = 1000 - ctx.strokeStyle = "#ffffff" - ctx.lineWidth = 3 - ctx.beginPath() - ctx.moveTo(-100 + pcx, pcy + 600) - ctx.lineTo(900 + pcx, pcy + 600) - ctx.stroke() - ctx.fillStyle = "#ffffff" - ctx.font = "bold 96px Verdana" - ctx.fillText('|', 100 + pcx, pcy + 797) - ctx.fillText('◀', 115 + pcx, pcy + 800) - ctx.beginPath() - ctx.arc(355 + pcx, pcy + 770, 80, 0, 3 * Math.PI) - ctx.stroke() - ctx.fillText('|', 555 + pcx, pcy + 797) - ctx.fillText('▶', 505 + pcx, pcy + 800) - if (this.stop) { ctx.fillText('▶', 323 + pcx, pcy + 797) } else { ctx.fillText('||', 303 + pcx, pcy + 794) } - - const img = core.material.images.images[this.type + '.webp'] - if (img) ctx.drawImage(img, 600 + pcx, pcy + 655, 200, 200) - core.setTextAlign(ctx, "center"); - ctx.font = "bold 52px Verdana" - ctx.fillText('当前歌曲', 400 + pcx, pcy + 297) - ctx.fillText(this.musicname[this.musicMx[this.selection[0]][this.selection[1]]], 400 + pcx, pcy + 457) - - ctx.font = "bold 36px Verdana" - const thistime = audio.currentTime - - if (thistime) { - const timetext = (Math.floor(thistime / 60).toString()).padStart(2, '0') + ':' + Math.floor(thistime % 60).toString().padStart(2, '0') - ctx.fillText(timetext, 810 + pcx, pcy + 650) - } else { - const timetext = "00:00" - ctx.fillText(timetext, 810 + pcx, pcy + 650) - } - ctx.fillText("/", 880 + pcx, pcy + 650) - const fulltime = audio.duration - - if (fulltime) { - const timetext = Math.floor(fulltime / 60).toString().padStart(2, '0') + ':' + Math.floor(fulltime % 60).toString().padStart(2, '0') - ctx.fillText(timetext, 950 + pcx, pcy + 650) - } else { - const timetext = "00:00" - ctx.fillText(timetext, 950 + pcx, pcy + 650) - } - ctx.strokeStyle = "#ffffff" - ctx.lineWidth = 9 - ctx.fillStyle = 'rgba(255,255,255,0.5)' - const pointx = 1000 * thistime / fulltime - 100 - if (fulltime && thistime) { - ctx.beginPath() - ctx.moveTo(-100 + pcx, pcy + 600) - ctx.lineTo(pointx + pcx, pcy + 600) - ctx.stroke() - ctx.beginPath() - ctx.arc(pointx + pcx, pcy + 600, 10, 0, 2 * Math.PI) - ctx.fill() - } else { - ctx.beginPath() - ctx.arc(-100 + pcx, pcy + 600, 10, 0, 2 * Math.PI) - ctx.fill() - } - - pcx = 250 - pcy = 0 - ctx.fillText('音', 850 + pcx, pcy + 425) - ctx.fillText('量', 850 + pcx, pcy + 510) - ctx.beginPath() - ctx.moveTo(900 + pcx, pcy + 200) - ctx.lineTo(900 + pcx, pcy + 700) - ctx.stroke() - ctx.strokeStyle = "#ffffff" - ctx.lineWidth = 9 - ctx.fillStyle = 'rgba(255,255,255,0.5)' - - ctx.beginPath() - ctx.moveTo(900 + pcx, pcy + 700) - ctx.lineTo(900 + pcx, pcy - 500 * audio.volume + 700) - ctx.stroke() - ctx.beginPath() - ctx.arc(900 + pcx, pcy - 500 * audio.volume + 700, 10, 0, 2 * Math.PI) - ctx.fill() - core.fillBoldText1( - ctx, - Math.floor(100 * audio.volume), - 915 + pcx, - pcy + 200, - "#FFFFFF", - "#000000", - 6, - core.ui._buildFont(32, true) - ); - - } else { - //横屏 - core.fillRect(ctx, 0, 0, 2028, 1248, "#000000"); //黑色背景 - ctx.globalAlpha = 0.5; //透明度 - if (bg) ctx.drawImage(bg, 0, 0, 1280, 720, 0, 0, 2028, 1248); //绘制半透明背景图片 - ctx.globalAlpha = 1; //恢复为不透明 - core.setTextAlign(ctx, "center"); - - core.fillBoldText1( - ctx, - '◀离开', - 110, - 100, - "#FFFFFF", - "#000000", - 6, - core.ui._buildFont(66, true) - ); - //core.fillRect(ctx, 440, 760, 50, 50) - ctx.strokeStyle = "#FFFFFF" - ctx.lineWidth = 3 - ctx.beginPath() - ctx.moveTo(800, 100) - ctx.lineTo(800, 1148) - ctx.moveTo(900, 100) - ctx.lineTo(1900, 100) - ctx.stroke() - let posy = 200 - const indexList = this.musicMx[page] - core.setTextAlign(ctx, "left"); - for (let i = 0; i < indexList.length; i++) { - const text = this.musicname[indexList[i]] - core.fillBoldText1( - ctx, - text, - 950, - posy - 30, - page === this.selection[0] && i === this.selection[1] ? "#FFFFFF" : "#444444", - "#000000", - 6, - core.ui._buildFont(66, true) - ); - ctx.strokeStyle = "#FFFFFF" - ctx.lineWidth = 3 - ctx.beginPath() - ctx.moveTo(900, posy) - ctx.lineTo(1900, posy) - ctx.stroke() - posy += 100 - } - core.fillBoldText1( - ctx, - '上一页', - 1050, - 1200 - 30, - page === 0 ? "#444444" : "#FFFFFF", - "#000000", - 6, - core.ui._buildFont(66, true) - ); - - core.fillBoldText1( - ctx, - (page + 1) + "/" + this.musicMx.length, - 1350, - 1200 - 30, - "#FFFFFF", - "#000000", - 6, - core.ui._buildFont(66, true) - ); - core.fillBoldText1( - ctx, - '下一页', - 1550, - 1200 - 30, - page === this.musicMx.length - 1 ? "#444444" : "#FFFFFF", - "#000000", - 6, - core.ui._buildFont(66, true) - ); - ctx.strokeStyle = "#ffffff" - ctx.lineWidth = 3 - ctx.beginPath() - ctx.moveTo(100, 600) - ctx.lineTo(700, 600) - ctx.stroke() - ctx.fillStyle = "#ffffff" - ctx.font = "bold 48px Verdana" - ctx.fillText('|', 130, 797) - ctx.fillText('◀', 140, 800) - ctx.beginPath() - ctx.arc(310, 780, 50, 0, 2 * Math.PI) - ctx.stroke() - if (this.stop) { ctx.fillText('▶', 295, 797) } else { ctx.fillText('||', 285, 794) } - - ctx.fillText('|', 470, 797) - ctx.fillText('▶', 450, 800) - ctx.fillText('音量', 350, 900) - ctx.beginPath() - ctx.moveTo(100, 1000) - ctx.lineTo(700, 1000) - ctx.stroke() - ctx.strokeStyle = "#ffffff" - ctx.lineWidth = 9 - ctx.fillStyle = 'rgba(255,255,255,0.5)' - - ctx.beginPath() - ctx.moveTo(100, 1000) - ctx.lineTo(600 * audio.volume + 100, 1000) - ctx.stroke() - ctx.beginPath() - ctx.arc(600 * audio.volume + 100, 1000, 10, 0, 2 * Math.PI) - ctx.fill() - core.fillBoldText1( - ctx, - Math.floor(100 * audio.volume), - 720, - 1010, - "#FFFFFF", - "#000000", - 6, - core.ui._buildFont(32, true) - ); - const img = core.material.images.images[this.type + '.webp'] - if (img) ctx.drawImage(img, 580, 730, 100, 100) - core.setTextAlign(ctx, "center"); - ctx.font = "bold 48px Verdana" - ctx.fillText('当前歌曲', 400, 297) - ctx.fillText(this.musicname[this.musicMx[this.selection[0]][this.selection[1]]], 400, 397) - - ctx.font = "bold 36px Verdana" - const thistime = audio.currentTime - - if (thistime) { - const timetext = (Math.floor(thistime / 60).toString()).padStart(2, '0') + ':' + Math.floor(thistime % 60).toString().padStart(2, '0') - ctx.fillText(timetext, 510, 650) - } else { - const timetext = "00:00" - ctx.fillText(timetext, 510, 650) - } - ctx.fillText("/", 580, 650) - const fulltime = audio.duration - - if (fulltime) { - const timetext = Math.floor(fulltime / 60).toString().padStart(2, '0') + ':' + Math.floor(fulltime % 60).toString().padStart(2, '0') - ctx.fillText(timetext, 650, 650) - } else { - const timetext = "00:00" - ctx.fillText(timetext, 650, 650) - } - ctx.strokeStyle = "#ffffff" - ctx.lineWidth = 9 - ctx.fillStyle = 'rgba(255,255,255,0.5)' - const pointx = 600 * thistime / fulltime + 100 - if (fulltime && thistime) { - ctx.beginPath() - ctx.moveTo(100, 600) - ctx.lineTo(pointx, 600) - ctx.stroke() - ctx.beginPath() - ctx.arc(pointx, 600, 10, 0, 2 * Math.PI) - ctx.fill() - } else { - ctx.beginPath() - ctx.arc(100, 600, 10, 0, 2 * Math.PI) - ctx.fill() - } - - } - } - } - core.ui.music = new musicclass(); - main.dom.musicMode.onclick = function () { - //点击开始页面的CG MODE进入cg回廊 - main.core.control.checkBgm(); - main.core.control.pauseBgm(); - audio.src = "project/bgms/" + main.core.ui.music.musicMx[main.core.ui.music.selection[0]][main.core.ui.music.selection[1]] - - page = 0; - music.style.display = "block"; - core.registerAnimationFrame("music", null, () => { main.core.ui.music.update() }) - }; -}, - "横屏切换": function () { + 剧情视频引用: function () { + // 在此增加新插件 + let a; + let bgm; + + function gtouchstart() { + timeOutEvent = setTimeout(() => { + video.remove(); + video1.remove(); + core.doAction(); + clearTimeout(a); + core.playBgm(bgm); + core.resumeBgm(); + }, 2000); //这里设置定时器,定义长按500毫秒触发长按事件,时间可以自己改,个人感觉500毫秒非常合适 + return false; + } + + //手释放,如果在500毫秒内就释放,则取消长按事件,此时可以执行onclick应该执行的事件 + function gtouchend() { + if (timeOutEvent != 0) { + //这里写要执行的内容(尤如onclick事件) + console.log("你这是点击,不是长按"); + } + clearTimeout(timeOutEvent); //清除定时器 + return false; + } + + this.openvideo = function () { + if (!core.isPlaying()) return; + const video = document.createElement("iframe"); //iframe设置 + video.style.position = "absolute"; + video.style.zIndex = 320; + video.style.display = "block"; + video.id = "video"; + main.dom.gameGroup.insertAdjacentElement("afterend", video); + video.style.top = "50%"; + video.style.left = "50%"; + video.style.transform = "translate(-50%,-50%)"; + main.dom.video = video; + const video1 = document.createElement("canvas"); //video1画布设置 + video1.style.position = "absolute"; + video1.style.zIndex = 330; + video1.style.display = "block"; + video1.id = "video1"; + main.dom.gameGroup.insertAdjacentElement("afterend", video1); + video1.style.top = "50%"; + video1.style.left = "50%"; + video1.style.transform = "translate(-50%,-50%)"; + const ctx = video1.getContext("2d"); + main.dom.video1 = video1; + if (core.domStyle.isVertical) { + video.width = 416 * 3; + video.height = 676 * 3; + video.style.transform = "translate(-50%,-50%) rotate(90deg)"; //重新定位右上角为基准 + } else { + video.width = 676 * 3; + video.height = 416 * 3; + video.style.transform = "translate(-50%,-50%)"; + } + video1.ontouchstart = function (e) { + try { + e.preventDefault(); + if (!core.isPlaying()) return false; + gtouchstart(); + } catch (ee) { + main.log(ee); + } + }; + video1.ontouchend = function (e) { + try { + e.preventDefault(); + if (!core.isPlaying()) return false; + gtouchend(); + } catch (ee) { + main.log(ee); + } + }; + + video1.onmouseup = function (e) { + //鼠标抬起 + try { + e.stopPropagation(); + if (!core.isPlaying()) return false; + gtouchend(); + } catch (ee) { + console.error(ee); + } + }; + video1.onmousedown = function (e) { + //鼠标按下 + try { + e.stopPropagation(); + if (!core.isPlaying()) return false; + gtouchstart(); + } catch (ee) { + main.log(ee); + } + }; + let globalAlpha = 0; + let frame = 1; + let al = 0; + core.registerAnimationFrame("beforeop", true, function () { + al++; + core.clearMap(ctx); + ctx.globalAlpha = al / 30; + core.fillRect(ctx, 0, 0, video1.width, video1.height, "#000000"); + ctx.globalAlpha = 1; + core.fillBoldText1( + ctx, + "Loading...", + 1014, + 624, + "#FFFFFF", + "#000000", + 6, + "bold 72px Verdana" + ); + }); + core.control.resize(); + + //player.bilibili.com/player.html + //www.bilibili.com/blackboard/html5mobileplayer.html + // + video.src = + "///www.bilibili.com/blackboard/html5mobileplayer.html?isOutside=true&aid=6484104&bvid=BV1cs411b7cH&cid=10546155&p=1&poster=0&autoplay=1&high_quality=1&muted=0&danmaku=0"; + video.scrolling = "no"; + video.border = "0"; + video.crossorigin = true; + video.frameborder = "no"; + video.framespacing = "0"; + video.allowfullscreen = false; + + video.sandbox = + "allow-top-navigation allow-same-origin allow-forms allow-scripts"; + //gsl_play_mask + + video.addEventListener("load", function () { + core.unregisterAnimationFrame("beforeop"); + core.registerAnimationFrame("op", true, function () { + core.clearMap(ctx); + if (core.domStyle.isVertical) { + ctx.canvas.width = 416 * 3; + ctx.canvas.height = 676 * 3; + ctx.save(); //保存设置 + ctx.translate(416 * 3, 0); //重新定位右上角为基准 + ctx.rotate(Math.PI / 2); //旋转90度 + } else { + ctx.canvas.width = 676 * 3; + ctx.canvas.height = 416 * 3; + } + ctx.globalAlpha = 1; + core.fillRect(ctx, 0, 0, video1.width, video1.height, "#000000"); + + ctx.globalAlpha = globalAlpha / 30; + core.setTextAlign(ctx, "center"); + core.fillBoldText1( + ctx, + "长按2秒后跳过op", + 1014, + 624, + "#FFFFFF", + "#000000", + 6, + "bold 48px Verdana" + ); + globalAlpha += frame; + if (globalAlpha > 29) frame = -1; + ctx.restore(); + if (frame === -1 && globalAlpha < 0) { + core.clearMap(ctx); + core.unregisterAnimationFrame("op"); + } + }); + bgm = core.musicStatus.playingBgm; + core.playBgm("op.opus"); + a = setTimeout(() => { + video.remove(); + video1.remove(); + core.playBgm(bgm); + core.doAction(); + }, 127500); + }); + }; + }, + "帧动画/图片叠拼": function () { + // 在此增加新插件 + this.animationDrawable = function ( + allFarme, + color, + globalAlpha, + imageList, + soundList + ) { + if (!core.isPlaying()) { + return core.doAction(); + } + const over = main.dom.over; + const ctx = over.getContext("2d"); + over.style.display = "block"; + + let farme = 0; + let now = 0; + core.registerAnimationFrame( + "animationDrawable", + true, + function (timestamp) { + if (timestamp - now > 1000 / 60) { + now = timestamp; + if (core.domStyle.isVertical) { + over.width = 1248; + over.height = 2028; + ctx.save(); //保存设置 + ctx.translate(1248, 0); //重新定位右上角为基准 + ctx.rotate(Math.PI / 2); //旋转90度 + } else { + over.width = 2028; + over.height = 1248; + } + + ctx.globalAlpha = (globalAlpha ?? 100) / 100; + core.fillRect(ctx, 0, 0, 2028, 1248, color); + + imageList.forEach(function (one) { + if ( + farme >= (one.beforefarme ?? 0) && + farme <= (one.afterfarme ?? allFarme) + ) { + const img = core.material.images.images?.[one.image]; + if (img) { + const gla = one.globalAlpha ?? 100; + const agla = one.aglobalAlpha ?? gla, + beforefarme = one.beforefarme ?? 0; + const afterfarme = one.afterfarme ?? allFarme; + + ctx.globalAlpha = + (gla + + ((agla - gla) * (farme - beforefarme)) / + (afterfarme - beforefarme || 1)) / + 100; + + const cx = + (one.cx ?? 0) + + (((one.acx ?? 0) - (one.cx ?? 0)) * + (farme - beforefarme)) / + (afterfarme - beforefarme || 1), + cy = + (one.cy ?? 0) + + (((one.acy ?? 0) - (one.cy ?? 0)) * + (farme - beforefarme)) / + (afterfarme - beforefarme || 1), + cw = + (one.cw ?? img.width) + + (((one.acw ?? img.width) - (one.cw ?? img.width)) * + (farme - beforefarme)) / + (afterfarme - beforefarme || 1), + ch = + (one.ch ?? img.height) + + (((one.acw ?? img.height) - (one.cw ?? img.height)) * + (farme - beforefarme)) / + (afterfarme - beforefarme || 1), + x = + (one.x ?? 0) + + (((one.ax ?? 0) - (one.x ?? 0)) * (farme - beforefarme)) / + (afterfarme - beforefarme || 1), + y = + (one.y ?? 0) + + (((one.ay ?? 0) - (one.y ?? 0)) * (farme - beforefarme)) / + (afterfarme - beforefarme || 1), + w = + (one.w ?? 2028) + + (((one.aw ?? 2028) - (one.w ?? 2028)) * + (farme - beforefarme)) / + (afterfarme - beforefarme || 1), + h = + (one.h ?? 1248) + + (((one.aw ?? 1248) - (one.w ?? 1248)) * + (farme - beforefarme)) / + (afterfarme - beforefarme || 1); + ctx.drawImage(img, cx, cy, cw, ch, x, y, w, h); + } + } + }); + soundList.forEach(function (one) { + const lisen = + one.sound && + core.material.sounds[one.sound] && + core.musicStatus.soundStatus; + if (farme == one.startfarme && lisen) { + if (one.stopbefore) core.stopSound(); + core.playSound(one.sound); + } + }); + farme++; + ctx.globalAlpha = 1; + ctx.restore(); + + if (farme > allFarme) { + core.unregisterAnimationFrame("animationDrawable"); + over.style.display = "none"; + core.doAction(); + } + } + } + ); + }; + }, + musicMode: function () { + // 在此增加新插件 + const music = document.createElement("canvas"); + music.style.position = "absolute"; + music.style.zIndex = 300; + music.style.display = "none"; + music.id = "music"; + main.dom.gameGroup.insertAdjacentElement("afterend", music); + music.style.top = "50%"; + music.style.left = "50%"; + music.style.transform = "translate(-50%,-50%)"; + const ctx = music.getContext("2d"); + main.dom.music = music; + + const audio = core.plugin.audioSystem.bgmController; + + let page = 0; //初始页面 + + let isvolume = false; + + function shuffle(arr) { + let n = arr.length, + random; + while (n) { + random = (Math.random() * n--) >>> 0; + [arr[n], arr[random]] = [arr[random], arr[n]]; + } + return arr; + } + music.addEventListener("mousedown", function (e) { + e.stopPropagation(); + 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.music.mousedown(px * 3, py * 3); + }); + music.addEventListener("mousemove", function (e) { + e.stopPropagation(); + 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.music.mousemove(px * 3, py * 3); + }); + music.addEventListener("mouseup", function (e) { + e.stopPropagation(); + + isvolume = false; + }); + music.addEventListener("mouseleave", function (e) { + e.stopPropagation(); + + isvolume = false; + }); + music.addEventListener("touchstart", function (e) { + e.preventDefault(); + const left = core.dom.gameGroup.offsetLeft; + const top = core.dom.gameGroup.offsetTop; + const px = Math.floor( + (e.touches[0].clientX - left) / core.domStyle.scale + ), + py = Math.floor((e.touches[0].clientY - top) / core.domStyle.scale); + core.ui.music.mousedown(px * 3, py * 3); + }); + music.addEventListener("touchmove", function (e) { + e.stopPropagation(); + const left = core.dom.gameGroup.offsetLeft; + const top = core.dom.gameGroup.offsetTop; + const px = Math.floor( + (e.touches[0].clientX - left) / core.domStyle.scale + ), + py = Math.floor((e.touches[0].clientY - top) / core.domStyle.scale); + core.ui.music.mousemove(px * 3, py * 3); + }); + music.addEventListener("touchend", function (e) { + e.stopPropagation(); + + isvolume = false; + }); + music.addEventListener("touchcancel", function (e) { + e.stopPropagation(); + + isvolume = false; + }); + + class musicclass { + constructor() { + //music列表 + //需全塔属性注册并保存在bgms文件夹,每个数组为显示的一页内容 + this.musicMx = [ + ["Asphodelus_Ceui.opus", "Blind_Alley.opus"], + ["Crawler.opus", "op.opus", "theme.opus"], + ]; + //音乐别名(将在播放器内显示的音乐名,music列表内的都要有对应歌名) + this.musicname = { + "Asphodelus_Ceui.opus": "Asphodelus", + "Blind_Alley.opus": "Blind", + "Crawler.opus": "Crawler", + "op.opus": "op", + "theme.opus": "theme", + }; + this.selection = [0, 0]; + this.stop = false; + this.type = "xunhuan"; + this.randomList = []; + this.random = 0; + } + + //更新 + update() { + this.background(); + this.drawUI(); + } + background() { + //画布大小设置 + if (core.domStyle.isVertical) { + music.width = 1248; + music.height = 2028; + } else { + music.width = 2028; + music.height = 1248; + } + } + mousedown(px, py) { + //鼠标按下时 + + const makeBox = ([x, y], [w, h]) => { + return [ + [x, y], + [x + w, y + h], + ]; + }; + const inRect = ([x, y], [[sx, sy], [dx, dy]]) => { + return sx <= x && x <= dx && sy <= y && y <= dy; + }; + const pos = [px, py]; + const backbox = makeBox([15, 35], [210, 90]); + if (inRect(pos, backbox)) { + //离开按钮是一致的,其余的记区分横竖屏 + music.style.display = "none"; + core.clearMap(ctx); + + core.unregisterAnimationFrame("music"); + core.restart(); + + return; + } + if (core.domStyle.isVertical) { + //竖屏 + + const pageupbox = makeBox([100, 1230], [200, 100]); + const pagedownbox = makeBox([950, 1230], [200, 100]); + const musicbox = makeBox( + [100, 200], + [1048, this.musicMx[page].length * 100] + ); + const beforebox = makeBox([120, 1620], [100, 100]); + const afterbox = makeBox([780, 1620], [100, 100]); + const playbox = makeBox([420, 1580], [200, 200]); + const typebox = makeBox([1040, 1600], [120, 120]); + + const volumebox = makeBox([250, 1940], [1050, 20]); + if (inRect(pos, pageupbox)) { + if (page !== 0) page -= 1; + return; + } + if (inRect(pos, pagedownbox)) { + if (page !== this.musicMx.length - 1) page += 1; + return; + } + if (inRect(pos, playbox)) { + if (this.stop) { + this.stop = !this.stop; + + core.resumeBgm(); + } else { + this.stop = !this.stop; + core.pauseBgm(); + } + return; + } + if (inRect(pos, beforebox)) { + this.stop = false; + switch (this.type) { + case "danqu": + core.playBgm( + main.core.ui.music.musicMx[main.core.ui.music.selection[0]][ + main.core.ui.music.selection[1] + ] + ); + + page = this.selection[0]; + + break; + case "xunhuan": + if (this.selection[1] === 0) { + if (this.selection[0] === 0) { + this.selection[0] = this.musicMx.length - 1; + this.selection[1] = + this.musicMx[this.selection[0]].length - 1; + } else { + this.selection[0] -= 1; + this.selection[1] = + this.musicMx[this.selection[0]].length - 1; + } + } else { + this.selection[1] -= 1; + } + this.randomList.indexOf( + this.musicMx[this.selection[0]][this.selection[1]] + ); + page = this.selection[0]; + + core.playBgm( + main.core.ui.music.musicMx[main.core.ui.music.selection[0]][ + main.core.ui.music.selection[1] + ] + ); + + break; + case "suiji": + if (this.random > 0) { + this.random -= 1; + } else { + this.random = this.randomList.length - 1; + } + this.selection[0] = this.musicMx.findIndex((v) => + v.includes(this.randomList[this.random]) + ); + this.selection[1] = this.musicMx[this.selection[0]].indexOf( + this.randomList[this.random] + ); + + page = this.selection[0]; + + core.playBgm( + main.core.ui.music.musicMx[main.core.ui.music.selection[0]][ + main.core.ui.music.selection[1] + ] + ); + + break; + } + return; + } + if (inRect(pos, afterbox)) { + this.stop = false; + switch (this.type) { + case "danqu": + core.playBgm( + main.core.ui.music.musicMx[main.core.ui.music.selection[0]][ + main.core.ui.music.selection[1] + ] + ); + + page = this.selection[0]; + break; + case "xunhuan": + if ( + this.selection[1] === + this.musicMx[this.selection[0]].length - 1 + ) { + if (this.selection[0] === this.musicMx.length - 1) { + this.selection[0] = 0; + this.selection[1] = 0; + } else { + this.selection[0] += 1; + this.selection[1] = 0; + } + } else { + this.selection[1] += 1; + } + this.random = this.randomList.indexOf( + this.musicMx[this.selection[0]][this.selection[1]] + ); + page = this.selection[0]; + + core.playBgm( + main.core.ui.music.musicMx[main.core.ui.music.selection[0]][ + main.core.ui.music.selection[1] + ] + ); + + break; + case "suiji": + if (this.random < this.randomList.length - 1) { + this.random += 1; + } else { + this.random = 0; + } + this.selection[0] = this.musicMx.findIndex((v) => + v.includes(this.randomList[this.random]) + ); + this.selection[1] = this.musicMx[this.selection[0]].indexOf( + this.randomList[this.random] + ); + + page = this.selection[0]; + core.playBgm( + main.core.ui.music.musicMx[main.core.ui.music.selection[0]][ + main.core.ui.music.selection[1] + ] + ); + + break; + } + return; + } + if (inRect(pos, typebox)) { + switch (this.type) { + case "danqu": + this.type = "xunhuan"; + break; + case "xunhuan": + this.type = "suiji"; + break; + case "suiji": + this.type = "danqu"; + break; + } + return; + } + if (inRect(pos, musicbox)) { + const index = Math.floor((py - 200) / 100); + if (page !== this.selection[0] || index !== this.selection[1]) { + this.selection[0] = page; + this.selection[1] = index; + this.randomList.indexOf( + this.musicMx[this.selection[0]][this.selection[1]] + ); + + core.playBgm( + main.core.ui.music.musicMx[main.core.ui.music.selection[0]][ + main.core.ui.music.selection[1] + ] + ); + + this.stop = false; + } else { + if (this.stop) { + this.stop = !this.stop; + core.resumeBgm(); + } else { + this.stop = !this.stop; + core.pauseBgm(); + } + } + return; + } + + if (inRect(pos, volumebox)) { + const time = Math.min(Math.max((px - 250) / 800, 0), 1); + audio.setVolume(time); + core.plugin.audioSystem.soundPlayer.setVolume(time); + isvolume = true; + } + } else { + //横屏 + const pageupbox = makeBox([1050, 1100], [200, 100]); + const pagedownbox = makeBox([1550, 1100], [200, 100]); + const musicbox = makeBox( + [900, 100], + [1000, this.musicMx[page].length * 100] + ); + const beforebox = makeBox([60, 620], [100, 100]); + const afterbox = makeBox([450, 620], [100, 100]); + const playbox = makeBox([200, 570], [200, 200]); + const typebox = makeBox([620, 600], [120, 120]); + + const volumebox = makeBox([100, 990], [600, 20]); + if (inRect(pos, pageupbox)) { + if (page !== 0) page -= 1; + return; + } + if (inRect(pos, pagedownbox)) { + if (page !== this.musicMx.length - 1) page += 1; + return; + } + if (inRect(pos, playbox)) { + if (this.stop) { + this.stop = !this.stop; + core.resumeBgm(); + } else { + this.stop = !this.stop; + core.pauseBgm(); + } + return; + } + if (inRect(pos, beforebox)) { + this.stop = false; + switch (this.type) { + case "danqu": + if (!this.stop) + core.playBgm( + main.core.ui.music.musicMx[main.core.ui.music.selection[0]][ + main.core.ui.music.selection[1] + ] + ); + + page = this.selection[0]; + + break; + case "xunhuan": + if (this.selection[1] === 0) { + if (this.selection[0] === 0) { + this.selection[0] = this.musicMx.length - 1; + this.selection[1] = + this.musicMx[this.selection[0]].length - 1; + } else { + this.selection[0] -= 1; + this.selection[1] = + this.musicMx[this.selection[0]].length - 1; + } + } else { + this.selection[1] -= 1; + } + this.random = this.randomList.indexOf( + this.musicMx[this.selection[0]][this.selection[1]] + ); + page = this.selection[0]; + + if (!this.stop) + core.playBgm( + main.core.ui.music.musicMx[main.core.ui.music.selection[0]][ + main.core.ui.music.selection[1] + ] + ); + + break; + case "suiji": + if (this.random > 0) { + this.random -= 1; + } else { + this.random = this.randomList.length - 1; + } + this.selection[0] = this.musicMx.findIndex((v) => + v.includes(this.randomList[this.random]) + ); + this.selection[1] = this.musicMx[this.selection[0]].indexOf( + this.randomList[this.random] + ); + + page = this.selection[0]; + + if (!this.stop) + core.playBgm( + main.core.ui.music.musicMx[main.core.ui.music.selection[0]][ + main.core.ui.music.selection[1] + ] + ); + + break; + } + return; + } + if (inRect(pos, afterbox)) { + this.stop = false; + switch (this.type) { + case "danqu": + if (!this.stop) + core.playBgm( + main.core.ui.music.musicMx[main.core.ui.music.selection[0]][ + main.core.ui.music.selection[1] + ] + ); + + page = this.selection[0]; + break; + case "xunhuan": + if ( + this.selection[1] === + this.musicMx[this.selection[0]].length - 1 + ) { + if (this.selection[0] === this.musicMx.length - 1) { + this.selection[0] = 0; + this.selection[1] = 0; + } else { + this.selection[0] += 1; + this.selection[1] = 0; + } + } else { + this.selection[1] += 1; + } + this.randomList.findIndex( + (v) => + v === this.musicMx[this.selection[0]][this.selection[1]] + ); + page = this.selection[0]; + + if (!this.stop) + core.playBgm( + main.core.ui.music.musicMx[main.core.ui.music.selection[0]][ + main.core.ui.music.selection[1] + ] + ); + + break; + case "suiji": + if (this.random < this.randomList.length - 1) { + this.random += 1; + } else { + this.random = 0; + } + this.selection[0] = this.musicMx.findIndex((v) => + v.includes(this.randomList[this.random]) + ); + this.selection[1] = this.musicMx[this.selection[0]].indexOf( + main.core.ui.music.randomList[main.core.ui.music.random] + ); + + page = this.selection[0]; + if (!this.stop) + core.playBgm( + main.core.ui.music.musicMx[main.core.ui.music.selection[0]][ + main.core.ui.music.selection[1] + ] + ); + + break; + } + return; + } + if (inRect(pos, typebox)) { + switch (this.type) { + case "danqu": + this.type = "xunhuan"; + break; + case "xunhuan": + this.type = "suiji"; + break; + case "suiji": + this.type = "danqu"; + break; + } + return; + } + if (inRect(pos, musicbox)) { + const index = Math.floor((py - 100) / 100); + if (page !== this.selection[0] || index !== this.selection[1]) { + this.selection[0] = page; + this.selection[1] = index; + this.randomList.indexOf( + (v) => v === this.musicMx[this.selection[0]][this.selection[1]] + ); + + core.playBgm( + main.core.ui.music.musicMx[main.core.ui.music.selection[0]][ + main.core.ui.music.selection[1] + ] + ); + this.stop = false; + } else { + if (this.stop) { + this.stop = !this.stop; + core.resumeBgm(); + } else { + this.stop = !this.stop; + core.pauseBgm(); + } + } + return; + } + + if (inRect(pos, volumebox)) { + const time = Math.min(Math.max((px - 100) / 600, 0), 1); + audio.setVolume(time); + core.plugin.audioSystem.soundPlayer.setVolume(time); + isvolume = true; + } + } + } + mousemove(px, py) { + if (isvolume) { + if (core.domStyle.isVertical) { + const time = Math.min(Math.max((px - 250) / 800, 0), 1); + audio.setVolume(time); + core.plugin.audioSystem.soundPlayer.setVolume(time); + } else { + const time = Math.min(Math.max((px - 100) / 600, 0), 1); + audio.setVolume(time); + core.plugin.audioSystem.soundPlayer.setVolume(time); + } + } + } + + drawUI() { + //绘制页面 + core.clearMap(music); + const bgVertical = core.material.images.images["bg_2010.webp"]; //竖屏背景 + const bg = core.material.images.images["bg_5043.webp"]; //竖屏背景 + if (core.domStyle.isVertical) { + //竖屏 + + core.fillRect(ctx, 0, 0, 1248, 2028, "#000000"); //黑色背景 + ctx.globalAlpha = 0.3; //透明度 + if (bgVertical) + ctx.drawImage(bgVertical, 0, 0, 1280, 1500, 0, 0, 1248, 2028); //绘制半透明背景图片 + ctx.globalAlpha = 1; //恢复为不透明 + + core.setTextAlign(ctx, "center"); + core.fillBoldText1( + ctx, + "◀离开", + 110, + 100, + "#FFFFFF", + "#000000", + 6, + core.ui._buildFont(66, true) + ); + + ctx.strokeStyle = "#FFFFFF"; + ctx.lineWidth = 3; + ctx.beginPath(); + ctx.moveTo(100, 200); + ctx.lineTo(1148, 200); + + ctx.stroke(); + let posy = 300; + const indexList = this.musicMx[page]; + core.setTextAlign(ctx, "left"); + for (let i = 0; i < indexList.length; i++) { + const text = this.musicname[indexList[i]]; + core.fillBoldText1( + ctx, + text, + 150, + posy - 30, + page === this.selection[0] && i === this.selection[1] + ? "#FFFFFF" + : "#444444", + "#000000", + 6, + core.ui._buildFont(66, true) + ); + ctx.strokeStyle = "#FFFFFF"; + ctx.lineWidth = 3; + ctx.beginPath(); + ctx.moveTo(100, posy); + ctx.lineTo(1148, posy); + ctx.stroke(); + posy += 100; + } + ctx.beginPath(); + ctx.moveTo(100, 1210); + ctx.lineTo(1148, 1210); + ctx.moveTo(100, 1200); + ctx.lineTo(1148, 1200); + ctx.stroke(); + + core.fillBoldText1( + ctx, + "上一页", + 100, + 1300, + page === 0 ? "#444444" : "#FFFFFF", + "#000000", + 6, + core.ui._buildFont(66, true) + ); + + core.fillBoldText1( + ctx, + page + 1 + "/" + this.musicMx.length, + 580, + 1300, + "#FFFFFF", + "#000000", + 6, + core.ui._buildFont(66, true) + ); + core.fillBoldText1( + ctx, + "下一页", + 950, + 1300, + page === this.musicMx.length - 1 ? "#444444" : "#FFFFFF", + "#000000", + 6, + core.ui._buildFont(66, true) + ); + + ctx.strokeStyle = "#ffffff"; + ctx.lineWidth = 3; + + ctx.fillStyle = "#ffffff"; + ctx.font = "bold 96px Verdana"; + ctx.fillText("|", 100, 1697); + ctx.fillText("◀", 115, 1700); + ctx.beginPath(); + ctx.arc(505, 1670, 80, 0, 3 * Math.PI); + ctx.stroke(); + ctx.fillText("|", 835, 1697); + ctx.fillText("▶", 785, 1700); + if (this.stop) { + ctx.fillText("▶", 473, 1697); + } else { + ctx.fillText("||", 453, 1694); + } + + const img = core.material.images.images[this.type + ".webp"]; + if (img) ctx.drawImage(img, 1000, 1555, 200, 200); + core.setTextAlign(ctx, "center"); + ctx.font = "bold 52px Verdana"; + ctx.fillText("当前歌曲", 625, 1397); + ctx.fillText( + this.musicname[this.musicMx[this.selection[0]][this.selection[1]]], + 625, + 1507 + ); + + ctx.fillStyle = "#ffffff"; + ctx.font = "bold 48px Verdana"; + ctx.fillText("音量", 150, 1970); + ctx.lineWidth = 3; + ctx.beginPath(); + ctx.moveTo(250, 1950); + ctx.lineTo(1050, 1950); + ctx.stroke(); + ctx.strokeStyle = "#ffffff"; + ctx.lineWidth = 9; + ctx.fillStyle = "rgba(255,255,255,0.5)"; + + ctx.beginPath(); + ctx.moveTo(250, 1950); + ctx.lineTo(800 * audio.getVolume() + 250, 1950); + ctx.stroke(); + ctx.beginPath(); + ctx.arc(800 * audio.getVolume() + 250, 1950, 10, 0, 2 * Math.PI); + ctx.fill(); + core.fillBoldText1( + ctx, + Math.floor(100 * audio.getVolume()), + 1120, + 1970, + "#FFFFFF", + "#000000", + 6, + core.ui._buildFont(56, true) + ); + } else { + //横屏 + + core.fillRect(ctx, 0, 0, 2028, 1248, "#000000"); //黑色背景 + ctx.globalAlpha = 0.5; //透明度 + if (bg) ctx.drawImage(bg, 0, 0, 1280, 720, 0, 0, 2028, 1248); //绘制半透明背景图片 + ctx.globalAlpha = 1; //恢复为不透明 + core.setTextAlign(ctx, "center"); + + core.fillBoldText1( + ctx, + "◀离开", + 110, + 100, + "#FFFFFF", + "#000000", + 6, + core.ui._buildFont(66, true) + ); + + ctx.strokeStyle = "#FFFFFF"; + ctx.lineWidth = 3; + ctx.beginPath(); + ctx.moveTo(800, 100); + ctx.lineTo(800, 1148); + ctx.moveTo(900, 100); + ctx.lineTo(1900, 100); + ctx.stroke(); + let posy = 200; + const indexList = this.musicMx[page]; + core.setTextAlign(ctx, "left"); + for (let i = 0; i < indexList.length; i++) { + const text = this.musicname[indexList[i]]; + core.fillBoldText1( + ctx, + text, + 950, + posy - 30, + page === this.selection[0] && i === this.selection[1] + ? "#FFFFFF" + : "#444444", + "#000000", + 6, + core.ui._buildFont(66, true) + ); + ctx.strokeStyle = "#FFFFFF"; + ctx.lineWidth = 3; + ctx.beginPath(); + ctx.moveTo(900, posy); + ctx.lineTo(1900, posy); + ctx.stroke(); + posy += 100; + } + core.fillBoldText1( + ctx, + "上一页", + 1050, + 1200 - 30, + page === 0 ? "#444444" : "#FFFFFF", + "#000000", + 6, + core.ui._buildFont(66, true) + ); + + core.fillBoldText1( + ctx, + page + 1 + "/" + this.musicMx.length, + 1350, + 1200 - 30, + "#FFFFFF", + "#000000", + 6, + core.ui._buildFont(66, true) + ); + core.fillBoldText1( + ctx, + "下一页", + 1550, + 1200 - 30, + page === this.musicMx.length - 1 ? "#444444" : "#FFFFFF", + "#000000", + 6, + core.ui._buildFont(66, true) + ); + ctx.strokeStyle = "#ffffff"; + ctx.lineWidth = 3; + + ctx.fillStyle = "#ffffff"; + ctx.font = "bold 96px Verdana"; + ctx.fillText("|", 60, 697); + ctx.fillText("◀", 70, 700); + ctx.beginPath(); + ctx.arc(295, 670, 80, 0, 2 * Math.PI); + ctx.stroke(); + if (this.stop) { + ctx.fillText("▶", 245, 697); + } else { + ctx.fillText("||", 245, 694); + } + + ctx.fillText("|", 490, 697); + ctx.fillText("▶", 450, 700); + ctx.font = "bold 48px Verdana"; + ctx.fillText("音量", 350, 900); + ctx.beginPath(); + ctx.moveTo(100, 1000); + ctx.lineTo(700, 1000); + ctx.stroke(); + ctx.strokeStyle = "#ffffff"; + ctx.lineWidth = 9; + ctx.fillStyle = "rgba(255,255,255,0.5)"; + + ctx.beginPath(); + ctx.moveTo(100, 1000); + ctx.lineTo(600 * audio.getVolume() + 100, 1000); + ctx.stroke(); + ctx.beginPath(); + ctx.arc(600 * audio.getVolume() + 100, 1000, 10, 0, 2 * Math.PI); + ctx.fill(); + core.fillBoldText1( + ctx, + Math.floor(100 * audio.getVolume()), + 720, + 1010, + "#FFFFFF", + "#000000", + 6, + core.ui._buildFont(56, true) + ); + const img = core.material.images.images[this.type + ".webp"]; + if (img) ctx.drawImage(img, 580, 560, 200, 200); + core.setTextAlign(ctx, "center"); + ctx.font = "bold 48px Verdana"; + ctx.fillText("当前歌曲", 400, 297); + ctx.fillText( + this.musicname[this.musicMx[this.selection[0]][this.selection[1]]], + 400, + 397 + ); + } + } + } + core.ui.music = new musicclass(); + main.dom.musicMode.onclick = function () { + //点击开始页面的CG MODE进入cg回廊 + + core.playBgm( + main.core.ui.music.musicMx[main.core.ui.music.selection[0]][ + main.core.ui.music.selection[1] + ] + ); + + const arr = main.core.ui.music.musicMx.flat(Infinity); + main.core.ui.music.randomList = shuffle(arr); + main.core.ui.music.random = main.core.ui.music.randomList.indexOf( + main.core.ui.music.musicMx[main.core.ui.music.selection[0]][ + main.core.ui.music.selection[1] + ] + ); + page = 0; + music.style.display = "block"; + let time = 0; + core.registerAnimationFrame("music", null, (temptime) => { + if (temptime > time + 1000 / 60) { + time = temptime; + main.core.ui.music.update(); + const duration = + core.plugin.audioSystem.bgmController.player.getRoute( + "bgms." + + main.core.ui.music.musicMx[main.core.ui.music.selection[0]][ + main.core.ui.music.selection[1] + ] + ).duration; + + const currentTime = + core.plugin.audioSystem.bgmController.player.getRoute( + "bgms." + + main.core.ui.music.musicMx[main.core.ui.music.selection[0]][ + main.core.ui.music.selection[1] + ] + ).currentTime; + if (currentTime && duration && duration - currentTime < 0.05) { + if (core.domStyle.isVertical) { + core.ui.music.mousedown(830, 1770); + } else { + core.ui.music.mousedown(475, 765); + } + } + } + }); + }; + }, + 横屏切换: function () { // 在此增加新插件 this.triggerFullscreen = async function (full) { if (!!document.fullscreenElement && !full) { @@ -15114,181 +17336,231 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = } }; }, - "图片压缩webp导出": function () { - // 在此增加新插件 - //使用方法:进入游戏后开始游戏,F12打开控制台,输入core.towebp(image),image为已在全塔属性中注册过的图片名字,需要""括起来 - this.towebp = function (image) { - const canvas = document.createElement("canvas"); //背景画布设置 - const ctx = canvas.getContext("2d"); - const img = core.material.images.images[image]; - canvas.width = img.width; - canvas.height = img.height; - ctx.drawImage(img, 0, 0); - const webpDataURL = canvas.toDataURL("image/webp", 0.85); //第二个参数为画面质量,范围为0-1,1为无损 - console.log(webpDataURL); - const link = document.createElement("a"); - link.href = webpDataURL; - const name = image.substring(0, image.indexOf(".")); - link.download = name + ".webp"; - link.click(); - }; - this.towebpall = function () { - const canvas = document.createElement("canvas"); //背景画布设置 - const ctx = canvas.getContext("2d"); - for (const image in core.material.images.images) { - this.towebp(image); - } - }; - this.towebpsome = function (images) { - images.forEach((image) => { - core.towebp(image); - }); - }; -}, - "帧动画特效(游戏界面)": function () { - // 在此增加新插件 - const animate2 = document.createElement("canvas"); - animate2.style.zIndex = 71; - animate2.id = "animate2"; - animate2.classList.add('gameCanvas', 'anti-aliasing') - animate2.style.display = "block" - animate2.width = 416 - animate2.height = 416 - animate2.style.width = core.__PIXELS__ * core.domStyle.scale + 'px' - animate2.style.height = core.__PIXELS__ * core.domStyle.scale + 'px' - main.dom.animate2 = animate2; - const anctx = animate2.getContext('2d') + 图片压缩webp导出: function () { + // 在此增加新插件 + //使用方法:进入游戏后开始游戏,F12打开控制台,输入core.towebp(image),image为已在全塔属性中注册过的图片名字,需要""括起来 + this.towebp = function (image) { + const canvas = document.createElement("canvas"); //背景画布设置 + const ctx = canvas.getContext("2d"); + const img = core.material.images.images[image]; + canvas.width = img.width; + canvas.height = img.height; + ctx.drawImage(img, 0, 0); + const webpDataURL = canvas.toDataURL("image/webp", 0.85); //第二个参数为画面质量,范围为0-1,1为无损 + console.log(webpDataURL); + const link = document.createElement("a"); + link.href = webpDataURL; + const name = image.substring(0, image.indexOf(".")); + link.download = name + ".webp"; + link.click(); + }; + this.towebpall = function () { + const canvas = document.createElement("canvas"); //背景画布设置 + const ctx = canvas.getContext("2d"); + for (const image in core.material.images.images) { + this.towebp(image); + } + }; + this.towebpsome = function (images) { + images.forEach((image) => { + core.towebp(image); + }); + }; + }, + "帧动画特效(游戏界面)": function () { + // 在此增加新插件 + const animate2 = document.createElement("canvas"); //画布设置 + animate2.style.zIndex = 71; + animate2.id = "animate2"; + animate2.classList.add("gameCanvas", "anti-aliasing"); + animate2.style.display = "block"; + animate2.width = 416; + animate2.height = 416; + animate2.style.width = core.__PIXELS__ * core.domStyle.scale + "px"; + animate2.style.height = core.__PIXELS__ * core.domStyle.scale + "px"; + main.dom.animate2 = animate2; + const anctx = animate2.getContext("2d"); - main.dom.gameDraw.appendChild(animate2); + main.dom.gameDraw.appendChild(animate2); - core.plugin.playing = new Set() + core.plugin.playing = new Set(); - this.setanimate = function (name, - px, - py, - width, - height, - allFarme, - imageList, - soundList) { - const data = { - px: px, - py: py, - width: width, - height: height, - allFarme: allFarme, - imageList: imageList, - soundList: soundList - } - core.setFlag("animate_" + name, data) + this.setanimate = function ( + name, + px, + py, + width, + height, + allFarme, + imageList, + soundList + ) { + const data = { + px: px, + py: py, + width: width, + height: height, + allFarme: allFarme, + imageList: imageList, + soundList: soundList, + }; + core.setFlag("animate_" + name, data); + }; + this.deleteanimate = function (name) { + core.setFlag("animate_" + name); + }; + let thistime = 0; + this.playanimate = function (name, x, y, hero, scalex, scaley) { + const data = { + name: name, + x: x, + y: y, + hero: hero, + scalex: scalex, + scaley: scaley, + farme: 0, + }; - } - this.deleteanimate = function (name) { - core.setFlag("animate_" + name) + core.plugin.playing.add(data); + }; + core.registerAnimationFrame("animateonmap", true, function (timestamp) { + if (timestamp - thistime > 1000 / 60) { + thistime = timestamp; + core.clearMap(anctx); + core.plugin.playing.forEach((one) => { + const data = flags["animate_" + one.name]; + if (!data) { + core.plugin.playing.delete(one); + } else { + data.imageList.forEach(function (image) { + if ( + one.farme >= (image.beforefarme ?? 0) && + one.farme <= (image.afterfarme ?? data.allFarme) + ) { + const img = core.material.images.images?.[image.image]; + if (img) { + const gla = image.globalAlpha ?? 100; + const agla = image.aglobalAlpha ?? gla, + beforefarme = image.beforefarme ?? 0; + const afterfarme = image.afterfarme ?? data.allFarme; - } - let thistime = 0 - this.playanimate = function (name, x, y, hero, scalex, scaley) { - const data = { name: name, x: x, y: y, hero: hero, scalex: scalex, scaley: scaley, farme: 0 } + anctx.globalAlpha = + (gla + + ((agla - gla) * (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1)) / + 100; - core.plugin.playing.add(data) + const cx = + (image.cx ?? 0) + + (((image.acx ?? 0) - (image.cx ?? 0)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + cy = + (image.cy ?? 0) + + (((image.acy ?? 0) - (image.cy ?? 0)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + cw = + (image.cw ?? img.width) + + (((image.acw ?? img.width) - (image.cw ?? img.width)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + ch = + (image.ch ?? img.height) + + (((image.acw ?? img.height) - (image.cw ?? img.height)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + x = + (image.x ?? 0) + + (((image.ax ?? 0) - (image.x ?? 0)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + y = + (image.y ?? 0) + + (((image.ay ?? 0) - (image.y ?? 0)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + w = + (image.w ?? one.width) + + (((image.aw ?? one.width) - (image.w ?? one.width)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + h = + (image.h ?? one.height) + + (((image.aw ?? one.height) - (image.w ?? one.height)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1), + angle = + (Math.PI * + ((image.image.angle ?? 0) + + (((image.aangle ?? 0) - (image.image.angle ?? 0)) * + (one.farme - beforefarme)) / + (afterfarme - beforefarme || 1))) / + 180; - } - core.registerAnimationFrame("animateonmap", true, function (timestamp) { - if (timestamp - thistime > 1000 / 60) { - thistime = timestamp; - core.clearMap(anctx) - core.plugin.playing.forEach(one => { - const data = flags["animate_" + one.name] - if (!data) { - core.plugin.playing.delete(one) - } else { - data.imageList.forEach(function (image) { - if (one.farme >= (image.beforefarme ?? 0) && - one.farme <= (image.afterfarme ?? data.allFarme) - ) { - const img = core.material.images.images?.[image.image]; - if (img) { - const gla = image.globalAlpha ?? 100; - const agla = image.aglobalAlpha ?? gla, - beforefarme = image.beforefarme ?? 0; - const afterfarme = image.afterfarme ?? data.allFarme; - - anctx.globalAlpha = - (gla + - ((agla - gla) * (one.farme - beforefarme)) / - (afterfarme - beforefarme || 1)) / - 100; - - const cx = - (image.cx ?? 0) + - (((image.acx ?? 0) - (image.cx ?? 0)) * - (one.farme - beforefarme)) / - (afterfarme - beforefarme || 1), - cy = - (image.cy ?? 0) + - (((image.acy ?? 0) - (image.cy ?? 0)) * - (one.farme - beforefarme)) / - (afterfarme - beforefarme || 1), - cw = - (image.cw ?? img.width) + - (((image.acw ?? img.width) - (image.cw ?? img.width)) * - (one.farme - beforefarme)) / - (afterfarme - beforefarme || 1), - ch = - (image.ch ?? img.height) + - (((image.acw ?? img.height) - (image.cw ?? img.height)) * - (one.farme - beforefarme)) / - (afterfarme - beforefarme || 1), - x = - (image.x ?? 0) + - (((image.ax ?? 0) - (image.x ?? 0)) * (one.farme - beforefarme)) / - (afterfarme - beforefarme || 1), - y = - (image.y ?? 0) + - (((image.ay ?? 0) - (image.y ?? 0)) * (one.farme - beforefarme)) / - (afterfarme - beforefarme || 1), - w = - (image.w ?? one.width) + - (((image.aw ?? one.width) - (image.w ?? one.width)) * - (one.farme - beforefarme)) / - (afterfarme - beforefarme || 1), - h = - (image.h ?? one.height) + - (((image.aw ?? one.height) - (image.w ?? one.height)) * - (one.farme - beforefarme)) / - (afterfarme - beforefarme || 1), - angle = (Math.PI * (image.angel ?? 0) / 180) + ((Math.PI * (image.aangel ?? 0) / 180) - ((Math.PI * (image.angel ?? 0) / 180)) * (one.farme - beforefarme)) / (afterfarme - beforefarme || 1); - if (one.hero) { - let sx, sy; - if (core.status.heroMoving < 0) { - sx = 0; - sy = 0 - } else { - sx = core.utils.scan[core.status.hero.loc.direction].x * 4 * core.status.heroMoving - sy = core.utils.scan[core.status.hero.loc.direction].y * 4 * core.status.heroMoving - } - const herox = core.status.hero.loc.x * 32 + 16 + sx - const heroy = core.status.hero.loc.y * 32 + 16 + sy - core.drawImage(anctx, img, cx, cy, cw, ch, herox + (x - data.px) * one.scalex, heroy + (y - data.py) * one.scaley, w * one.scalex, h * one.scaley, angle) - } else { core.drawImage(anctx, img, cx, cy, cw, ch, one.x + (x - data.px) * one.scalex, one.y + (y - data.py) * one.scaley, w * one.scalex, h * one.scaley, angle); } - } - } - }) - data.soundList.forEach(function (sound) { - const lisen = sound.sound && core.material.sounds[sound.sound] && core.musicStatus.soundStatus; - if (one.farme == sound.startfarme && lisen) { - if (sound.stopbefore) core.stopSound(); - core.playSound(sound.sound); - } - }) - one.farme++; - if (one.farme > data.allFarme) core.plugin.playing.delete(one) - } - }) - } - - }) - -} -} \ No newline at end of file + if (one.hero) { + let sx, sy; + if (core.status.heroMoving < 0) { + sx = 0; + sy = 0; + } else { + sx = + core.utils.scan[core.status.hero.loc.direction].x * + 4 * + core.status.heroMoving; + sy = + core.utils.scan[core.status.hero.loc.direction].y * + 4 * + core.status.heroMoving; + } + const herox = core.status.hero.loc.x * 32 + 16 + sx; + const heroy = core.status.hero.loc.y * 32 + 16 + sy; + core.drawImage( + anctx, + img, + cx, + cy, + cw, + ch, + herox + (x - data.px) * one.scalex, + heroy + (y - data.py) * one.scaley, + w * one.scalex, + h * one.scaley, + angle + ); + } else { + core.drawImage( + anctx, + img, + cx, + cy, + cw, + ch, + one.x + (x - data.px) * one.scalex, + one.y + (y - data.py) * one.scaley, + w * one.scalex, + h * one.scaley, + angle + ); + } + } + } + }); + data.soundList.forEach(function (sound) { + const lisen = + sound.sound && + core.material.sounds[sound.sound] && + core.musicStatus.soundStatus; + if (one.farme == sound.startfarme && lisen) { + if (sound.stopbefore) core.stopSound(); + core.playSound(sound.sound); + } + }); + one.farme++; + if (one.farme > data.allFarme) core.plugin.playing.delete(one); + } + }); + } + }); + }, +}; diff --git a/project/sounds/aiy010000010.mp3 b/project/sounds/aiy010000010.mp3 deleted file mode 100644 index 4389b53..0000000 Binary files a/project/sounds/aiy010000010.mp3 and /dev/null differ diff --git a/project/sounds/aiy010000010.opus b/project/sounds/aiy010000010.opus new file mode 100644 index 0000000..0574c82 Binary files /dev/null and b/project/sounds/aiy010000010.opus differ diff --git a/project/sounds/aiy010000020.mp3 b/project/sounds/aiy010000020.mp3 deleted file mode 100644 index 77111c6..0000000 Binary files a/project/sounds/aiy010000020.mp3 and /dev/null differ diff --git a/project/sounds/aiy010000020.opus b/project/sounds/aiy010000020.opus new file mode 100644 index 0000000..a5768d9 Binary files /dev/null and b/project/sounds/aiy010000020.opus differ diff --git a/project/sounds/aiy010000030.mp3 b/project/sounds/aiy010000030.mp3 deleted file mode 100644 index c2b47e7..0000000 Binary files a/project/sounds/aiy010000030.mp3 and /dev/null differ diff --git a/project/sounds/aiy010000030.opus b/project/sounds/aiy010000030.opus new file mode 100644 index 0000000..450cf99 Binary files /dev/null and b/project/sounds/aiy010000030.opus differ diff --git a/project/sounds/aiy020000005.opus b/project/sounds/aiy020000005.opus new file mode 100644 index 0000000..5e05539 Binary files /dev/null and b/project/sounds/aiy020000005.opus differ diff --git a/project/sounds/aiy020000010.opus b/project/sounds/aiy020000010.opus new file mode 100644 index 0000000..257f445 Binary files /dev/null and b/project/sounds/aiy020000010.opus differ diff --git a/project/sounds/aiy020000020.opus b/project/sounds/aiy020000020.opus new file mode 100644 index 0000000..4ef0df5 Binary files /dev/null and b/project/sounds/aiy020000020.opus differ diff --git a/project/sounds/aiy020000030.opus b/project/sounds/aiy020000030.opus new file mode 100644 index 0000000..680d345 Binary files /dev/null and b/project/sounds/aiy020000030.opus differ diff --git a/project/sounds/aiy020000040.opus b/project/sounds/aiy020000040.opus new file mode 100644 index 0000000..7d8b8dd Binary files /dev/null and b/project/sounds/aiy020000040.opus differ diff --git a/project/sounds/aiy020000050.opus b/project/sounds/aiy020000050.opus new file mode 100644 index 0000000..54e571a Binary files /dev/null and b/project/sounds/aiy020000050.opus differ diff --git a/project/sounds/aiy020000060.opus b/project/sounds/aiy020000060.opus new file mode 100644 index 0000000..a574a48 Binary files /dev/null and b/project/sounds/aiy020000060.opus differ diff --git a/project/sounds/aiy020000070.opus b/project/sounds/aiy020000070.opus new file mode 100644 index 0000000..c4250aa Binary files /dev/null and b/project/sounds/aiy020000070.opus differ diff --git a/project/sounds/aiy020000080.opus b/project/sounds/aiy020000080.opus new file mode 100644 index 0000000..5002cc3 Binary files /dev/null and b/project/sounds/aiy020000080.opus differ diff --git a/project/sounds/aiy020000090.opus b/project/sounds/aiy020000090.opus new file mode 100644 index 0000000..cedb5f0 Binary files /dev/null and b/project/sounds/aiy020000090.opus differ diff --git a/project/sounds/aiy020000100.opus b/project/sounds/aiy020000100.opus new file mode 100644 index 0000000..deded59 Binary files /dev/null and b/project/sounds/aiy020000100.opus differ diff --git a/project/sounds/aiy020000110.opus b/project/sounds/aiy020000110.opus new file mode 100644 index 0000000..574f59c Binary files /dev/null and b/project/sounds/aiy020000110.opus differ diff --git a/project/sounds/aiy020000120.opus b/project/sounds/aiy020000120.opus new file mode 100644 index 0000000..0e982bc Binary files /dev/null and b/project/sounds/aiy020000120.opus differ diff --git a/project/sounds/aiy020000130.opus b/project/sounds/aiy020000130.opus new file mode 100644 index 0000000..837d498 Binary files /dev/null and b/project/sounds/aiy020000130.opus differ diff --git a/project/sounds/aiy020000140.opus b/project/sounds/aiy020000140.opus new file mode 100644 index 0000000..b57af22 Binary files /dev/null and b/project/sounds/aiy020000140.opus differ diff --git a/project/sounds/aiy020000150.opus b/project/sounds/aiy020000150.opus new file mode 100644 index 0000000..4ab93aa Binary files /dev/null and b/project/sounds/aiy020000150.opus differ diff --git a/project/sounds/aiy020000160.opus b/project/sounds/aiy020000160.opus new file mode 100644 index 0000000..14cf9f9 Binary files /dev/null and b/project/sounds/aiy020000160.opus differ diff --git a/project/sounds/aiy020000170.opus b/project/sounds/aiy020000170.opus new file mode 100644 index 0000000..fbf0b94 Binary files /dev/null and b/project/sounds/aiy020000170.opus differ diff --git a/project/sounds/aiy020000180.opus b/project/sounds/aiy020000180.opus new file mode 100644 index 0000000..2dfcfc2 Binary files /dev/null and b/project/sounds/aiy020000180.opus differ diff --git a/project/sounds/aiy310000010.mp3 b/project/sounds/aiy310000010.mp3 deleted file mode 100644 index d6bf306..0000000 Binary files a/project/sounds/aiy310000010.mp3 and /dev/null differ diff --git a/project/sounds/aiy310000010.opus b/project/sounds/aiy310000010.opus new file mode 100644 index 0000000..9955fab Binary files /dev/null and b/project/sounds/aiy310000010.opus differ diff --git a/project/sounds/aiy310000020.mp3 b/project/sounds/aiy310000020.mp3 deleted file mode 100644 index 84ad00e..0000000 Binary files a/project/sounds/aiy310000020.mp3 and /dev/null differ diff --git a/project/sounds/aiy310000020.opus b/project/sounds/aiy310000020.opus new file mode 100644 index 0000000..99fe711 Binary files /dev/null and b/project/sounds/aiy310000020.opus differ diff --git a/project/sounds/aiy310000030.mp3 b/project/sounds/aiy310000030.mp3 deleted file mode 100644 index ca51c6c..0000000 Binary files a/project/sounds/aiy310000030.mp3 and /dev/null differ diff --git a/project/sounds/aiy310000030.opus b/project/sounds/aiy310000030.opus new file mode 100644 index 0000000..e62ade9 Binary files /dev/null and b/project/sounds/aiy310000030.opus differ diff --git a/project/sounds/aiy310000040.mp3 b/project/sounds/aiy310000040.mp3 deleted file mode 100644 index 139b9c4..0000000 Binary files a/project/sounds/aiy310000040.mp3 and /dev/null differ diff --git a/project/sounds/aiy310000040.opus b/project/sounds/aiy310000040.opus new file mode 100644 index 0000000..ecd0f9b Binary files /dev/null and b/project/sounds/aiy310000040.opus differ diff --git a/project/sounds/aiy310000050.mp3 b/project/sounds/aiy310000050.mp3 deleted file mode 100644 index b0b68b9..0000000 Binary files a/project/sounds/aiy310000050.mp3 and /dev/null differ diff --git a/project/sounds/aiy310000050.opus b/project/sounds/aiy310000050.opus new file mode 100644 index 0000000..12f5233 Binary files /dev/null and b/project/sounds/aiy310000050.opus differ diff --git a/project/sounds/aiy310000060.mp3 b/project/sounds/aiy310000060.mp3 deleted file mode 100644 index 9773718..0000000 Binary files a/project/sounds/aiy310000060.mp3 and /dev/null differ diff --git a/project/sounds/aiy310000060.opus b/project/sounds/aiy310000060.opus new file mode 100644 index 0000000..4e36bcd Binary files /dev/null and b/project/sounds/aiy310000060.opus differ diff --git a/project/sounds/aiy310000070.mp3 b/project/sounds/aiy310000070.mp3 deleted file mode 100644 index 3b2667c..0000000 Binary files a/project/sounds/aiy310000070.mp3 and /dev/null differ diff --git a/project/sounds/aiy310000070.opus b/project/sounds/aiy310000070.opus new file mode 100644 index 0000000..db9d0e7 Binary files /dev/null and b/project/sounds/aiy310000070.opus differ diff --git a/project/sounds/aiy310000080.mp3 b/project/sounds/aiy310000080.mp3 deleted file mode 100644 index 392969d..0000000 Binary files a/project/sounds/aiy310000080.mp3 and /dev/null differ diff --git a/project/sounds/aiy310000080.opus b/project/sounds/aiy310000080.opus new file mode 100644 index 0000000..c303fb3 Binary files /dev/null and b/project/sounds/aiy310000080.opus differ diff --git a/project/sounds/aiy310000090.mp3 b/project/sounds/aiy310000090.mp3 deleted file mode 100644 index 7ace161..0000000 Binary files a/project/sounds/aiy310000090.mp3 and /dev/null differ diff --git a/project/sounds/aiy310000090.opus b/project/sounds/aiy310000090.opus new file mode 100644 index 0000000..63289e6 Binary files /dev/null and b/project/sounds/aiy310000090.opus differ diff --git a/project/sounds/aiy310000100.mp3 b/project/sounds/aiy310000100.mp3 deleted file mode 100644 index 57907d8..0000000 Binary files a/project/sounds/aiy310000100.mp3 and /dev/null differ diff --git a/project/sounds/aiy310000100.opus b/project/sounds/aiy310000100.opus new file mode 100644 index 0000000..e62de21 Binary files /dev/null and b/project/sounds/aiy310000100.opus differ diff --git a/project/sounds/aiy310000110.mp3 b/project/sounds/aiy310000110.mp3 deleted file mode 100644 index 955cda3..0000000 Binary files a/project/sounds/aiy310000110.mp3 and /dev/null differ diff --git a/project/sounds/aiy310000110.opus b/project/sounds/aiy310000110.opus new file mode 100644 index 0000000..3c6a541 Binary files /dev/null and b/project/sounds/aiy310000110.opus differ diff --git a/project/sounds/aiy310000120.mp3 b/project/sounds/aiy310000120.mp3 deleted file mode 100644 index d387bdd..0000000 Binary files a/project/sounds/aiy310000120.mp3 and /dev/null differ diff --git a/project/sounds/aiy310000120.opus b/project/sounds/aiy310000120.opus new file mode 100644 index 0000000..3961d24 Binary files /dev/null and b/project/sounds/aiy310000120.opus differ diff --git a/project/sounds/aiy310000130.opus b/project/sounds/aiy310000130.opus new file mode 100644 index 0000000..e5dab39 Binary files /dev/null and b/project/sounds/aiy310000130.opus differ diff --git a/project/sounds/aiy310000140.opus b/project/sounds/aiy310000140.opus new file mode 100644 index 0000000..e7bf71f Binary files /dev/null and b/project/sounds/aiy310000140.opus differ diff --git a/project/sounds/aiy310000150.opus b/project/sounds/aiy310000150.opus new file mode 100644 index 0000000..b6fe0bd Binary files /dev/null and b/project/sounds/aiy310000150.opus differ diff --git a/project/sounds/aiy310000160.opus b/project/sounds/aiy310000160.opus new file mode 100644 index 0000000..1de7696 Binary files /dev/null and b/project/sounds/aiy310000160.opus differ diff --git a/project/sounds/aiy310000170.opus b/project/sounds/aiy310000170.opus new file mode 100644 index 0000000..55df5b4 Binary files /dev/null and b/project/sounds/aiy310000170.opus differ diff --git a/project/sounds/aiy310000180.opus b/project/sounds/aiy310000180.opus new file mode 100644 index 0000000..dc9a85c Binary files /dev/null and b/project/sounds/aiy310000180.opus differ diff --git a/project/sounds/aiy310000190.opus b/project/sounds/aiy310000190.opus new file mode 100644 index 0000000..821e276 Binary files /dev/null and b/project/sounds/aiy310000190.opus differ diff --git a/project/sounds/aiy310000200.opus b/project/sounds/aiy310000200.opus new file mode 100644 index 0000000..51ba4fc Binary files /dev/null and b/project/sounds/aiy310000200.opus differ diff --git a/project/sounds/aiy310000210.opus b/project/sounds/aiy310000210.opus new file mode 100644 index 0000000..4fe0fa9 Binary files /dev/null and b/project/sounds/aiy310000210.opus differ diff --git a/project/sounds/aiy310000220.opus b/project/sounds/aiy310000220.opus new file mode 100644 index 0000000..169de30 Binary files /dev/null and b/project/sounds/aiy310000220.opus differ diff --git a/project/sounds/aiy310000230.opus b/project/sounds/aiy310000230.opus new file mode 100644 index 0000000..db0f37d Binary files /dev/null and b/project/sounds/aiy310000230.opus differ diff --git a/project/sounds/aiy310000240.opus b/project/sounds/aiy310000240.opus new file mode 100644 index 0000000..597e491 Binary files /dev/null and b/project/sounds/aiy310000240.opus differ diff --git a/project/sounds/aiy310000250.opus b/project/sounds/aiy310000250.opus new file mode 100644 index 0000000..e8ada96 Binary files /dev/null and b/project/sounds/aiy310000250.opus differ diff --git a/project/sounds/aiy310000260.opus b/project/sounds/aiy310000260.opus new file mode 100644 index 0000000..1d7bae9 Binary files /dev/null and b/project/sounds/aiy310000260.opus differ diff --git a/project/sounds/aiy310000280.opus b/project/sounds/aiy310000280.opus new file mode 100644 index 0000000..649f1fd Binary files /dev/null and b/project/sounds/aiy310000280.opus differ diff --git a/project/sounds/aiy310000290.opus b/project/sounds/aiy310000290.opus new file mode 100644 index 0000000..f4222de Binary files /dev/null and b/project/sounds/aiy310000290.opus differ diff --git a/project/sounds/aiy310000300.opus b/project/sounds/aiy310000300.opus new file mode 100644 index 0000000..32c2f49 Binary files /dev/null and b/project/sounds/aiy310000300.opus differ diff --git a/project/sounds/aiy350000010.mp3 b/project/sounds/aiy350000010.mp3 deleted file mode 100644 index 57c17f9..0000000 Binary files a/project/sounds/aiy350000010.mp3 and /dev/null differ diff --git a/project/sounds/aiy350000010.opus b/project/sounds/aiy350000010.opus new file mode 100644 index 0000000..0f41912 Binary files /dev/null and b/project/sounds/aiy350000010.opus differ diff --git a/project/sounds/aiy350000020.mp3 b/project/sounds/aiy350000020.mp3 deleted file mode 100644 index 6ebb9bc..0000000 Binary files a/project/sounds/aiy350000020.mp3 and /dev/null differ diff --git a/project/sounds/aiy350000020.opus b/project/sounds/aiy350000020.opus new file mode 100644 index 0000000..b99c603 Binary files /dev/null and b/project/sounds/aiy350000020.opus differ diff --git a/project/sounds/aiy350000030.mp3 b/project/sounds/aiy350000030.mp3 deleted file mode 100644 index 2f57a03..0000000 Binary files a/project/sounds/aiy350000030.mp3 and /dev/null differ diff --git a/project/sounds/aiy350000030.opus b/project/sounds/aiy350000030.opus new file mode 100644 index 0000000..773d947 Binary files /dev/null and b/project/sounds/aiy350000030.opus differ diff --git a/project/sounds/aiy350000040.mp3 b/project/sounds/aiy350000040.mp3 deleted file mode 100644 index 13d4523..0000000 Binary files a/project/sounds/aiy350000040.mp3 and /dev/null differ diff --git a/project/sounds/aiy350000040.opus b/project/sounds/aiy350000040.opus new file mode 100644 index 0000000..df657bf Binary files /dev/null and b/project/sounds/aiy350000040.opus differ diff --git a/project/sounds/aiy350000050.mp3 b/project/sounds/aiy350000050.mp3 deleted file mode 100644 index 5c763e4..0000000 Binary files a/project/sounds/aiy350000050.mp3 and /dev/null differ diff --git a/project/sounds/aiy350000050.opus b/project/sounds/aiy350000050.opus new file mode 100644 index 0000000..d520d2e Binary files /dev/null and b/project/sounds/aiy350000050.opus differ diff --git a/project/sounds/aiy350000060.mp3 b/project/sounds/aiy350000060.mp3 deleted file mode 100644 index 790d096..0000000 Binary files a/project/sounds/aiy350000060.mp3 and /dev/null differ diff --git a/project/sounds/aiy350000060.opus b/project/sounds/aiy350000060.opus new file mode 100644 index 0000000..47f1642 Binary files /dev/null and b/project/sounds/aiy350000060.opus differ diff --git a/project/sounds/aiy350000070.mp3 b/project/sounds/aiy350000070.mp3 deleted file mode 100644 index 236c48a..0000000 Binary files a/project/sounds/aiy350000070.mp3 and /dev/null differ diff --git a/project/sounds/aiy350000070.opus b/project/sounds/aiy350000070.opus new file mode 100644 index 0000000..b02685c Binary files /dev/null and b/project/sounds/aiy350000070.opus differ diff --git a/project/sounds/aiy350000080.mp3 b/project/sounds/aiy350000080.mp3 deleted file mode 100644 index f6753db..0000000 Binary files a/project/sounds/aiy350000080.mp3 and /dev/null differ diff --git a/project/sounds/aiy350000080.opus b/project/sounds/aiy350000080.opus new file mode 100644 index 0000000..868a458 Binary files /dev/null and b/project/sounds/aiy350000080.opus differ diff --git a/project/sounds/aiy350000090.mp3 b/project/sounds/aiy350000090.mp3 deleted file mode 100644 index 869aea1..0000000 Binary files a/project/sounds/aiy350000090.mp3 and /dev/null differ diff --git a/project/sounds/aiy350000090.opus b/project/sounds/aiy350000090.opus new file mode 100644 index 0000000..26a24b1 Binary files /dev/null and b/project/sounds/aiy350000090.opus differ diff --git a/project/sounds/aiy350000100.mp3 b/project/sounds/aiy350000100.mp3 deleted file mode 100644 index f87b58f..0000000 Binary files a/project/sounds/aiy350000100.mp3 and /dev/null differ diff --git a/project/sounds/aiy350000100.opus b/project/sounds/aiy350000100.opus new file mode 100644 index 0000000..45199fe Binary files /dev/null and b/project/sounds/aiy350000100.opus differ diff --git a/project/sounds/aiy350000110.mp3 b/project/sounds/aiy350000110.mp3 deleted file mode 100644 index 553ac12..0000000 Binary files a/project/sounds/aiy350000110.mp3 and /dev/null differ diff --git a/project/sounds/aiy350000110.opus b/project/sounds/aiy350000110.opus new file mode 100644 index 0000000..ef10116 Binary files /dev/null and b/project/sounds/aiy350000110.opus differ diff --git a/project/sounds/aiy350000120.mp3 b/project/sounds/aiy350000120.mp3 deleted file mode 100644 index 57f9899..0000000 Binary files a/project/sounds/aiy350000120.mp3 and /dev/null differ diff --git a/project/sounds/aiy350000120.opus b/project/sounds/aiy350000120.opus new file mode 100644 index 0000000..5c9fd50 Binary files /dev/null and b/project/sounds/aiy350000120.opus differ diff --git a/project/sounds/aiy350000130.mp3 b/project/sounds/aiy350000130.mp3 deleted file mode 100644 index 62e68dc..0000000 Binary files a/project/sounds/aiy350000130.mp3 and /dev/null differ diff --git a/project/sounds/aiy350000130.opus b/project/sounds/aiy350000130.opus new file mode 100644 index 0000000..c07b760 Binary files /dev/null and b/project/sounds/aiy350000130.opus differ diff --git a/project/sounds/aiy350000140.mp3 b/project/sounds/aiy350000140.mp3 deleted file mode 100644 index b4ff73c..0000000 Binary files a/project/sounds/aiy350000140.mp3 and /dev/null differ diff --git a/project/sounds/aiy350000140.opus b/project/sounds/aiy350000140.opus new file mode 100644 index 0000000..50ddd6d Binary files /dev/null and b/project/sounds/aiy350000140.opus differ diff --git a/project/sounds/aiy350000150.mp3 b/project/sounds/aiy350000150.mp3 deleted file mode 100644 index b8d9ce2..0000000 Binary files a/project/sounds/aiy350000150.mp3 and /dev/null differ diff --git a/project/sounds/aiy350000150.opus b/project/sounds/aiy350000150.opus new file mode 100644 index 0000000..7626306 Binary files /dev/null and b/project/sounds/aiy350000150.opus differ diff --git a/project/sounds/aiy350000160.mp3 b/project/sounds/aiy350000160.mp3 deleted file mode 100644 index 563717f..0000000 Binary files a/project/sounds/aiy350000160.mp3 and /dev/null differ diff --git a/project/sounds/aiy350000160.opus b/project/sounds/aiy350000160.opus new file mode 100644 index 0000000..6a0e778 Binary files /dev/null and b/project/sounds/aiy350000160.opus differ diff --git a/project/sounds/aiy350000170.mp3 b/project/sounds/aiy350000170.mp3 deleted file mode 100644 index 23266c1..0000000 Binary files a/project/sounds/aiy350000170.mp3 and /dev/null differ diff --git a/project/sounds/aiy350000170.opus b/project/sounds/aiy350000170.opus new file mode 100644 index 0000000..264c29b Binary files /dev/null and b/project/sounds/aiy350000170.opus differ diff --git a/project/sounds/aiy350000180.mp3 b/project/sounds/aiy350000180.mp3 deleted file mode 100644 index 0a52d64..0000000 Binary files a/project/sounds/aiy350000180.mp3 and /dev/null differ diff --git a/project/sounds/aiy350000180.opus b/project/sounds/aiy350000180.opus new file mode 100644 index 0000000..f30c59e Binary files /dev/null and b/project/sounds/aiy350000180.opus differ diff --git a/project/sounds/aiy350000190.mp3 b/project/sounds/aiy350000190.mp3 deleted file mode 100644 index 5379fbb..0000000 Binary files a/project/sounds/aiy350000190.mp3 and /dev/null differ diff --git a/project/sounds/aiy350000190.opus b/project/sounds/aiy350000190.opus new file mode 100644 index 0000000..c2a045a Binary files /dev/null and b/project/sounds/aiy350000190.opus differ diff --git a/project/sounds/aiy350000200.mp3 b/project/sounds/aiy350000200.mp3 deleted file mode 100644 index 7bf86fd..0000000 Binary files a/project/sounds/aiy350000200.mp3 and /dev/null differ diff --git a/project/sounds/aiy350000200.opus b/project/sounds/aiy350000200.opus new file mode 100644 index 0000000..d964326 Binary files /dev/null and b/project/sounds/aiy350000200.opus differ diff --git a/project/sounds/aiy350000210.mp3 b/project/sounds/aiy350000210.mp3 deleted file mode 100644 index 01426ec..0000000 Binary files a/project/sounds/aiy350000210.mp3 and /dev/null differ diff --git a/project/sounds/aiy350000210.opus b/project/sounds/aiy350000210.opus new file mode 100644 index 0000000..dcf95ec Binary files /dev/null and b/project/sounds/aiy350000210.opus differ diff --git a/project/sounds/aiy350000220.mp3 b/project/sounds/aiy350000220.mp3 deleted file mode 100644 index 7687c76..0000000 Binary files a/project/sounds/aiy350000220.mp3 and /dev/null differ diff --git a/project/sounds/aiy350000220.opus b/project/sounds/aiy350000220.opus new file mode 100644 index 0000000..ba965cf Binary files /dev/null and b/project/sounds/aiy350000220.opus differ diff --git a/project/sounds/aiy350000230.mp3 b/project/sounds/aiy350000230.mp3 deleted file mode 100644 index ef72218..0000000 Binary files a/project/sounds/aiy350000230.mp3 and /dev/null differ diff --git a/project/sounds/aiy350000230.opus b/project/sounds/aiy350000230.opus new file mode 100644 index 0000000..88cd8a9 Binary files /dev/null and b/project/sounds/aiy350000230.opus differ diff --git a/project/sounds/aiy710000010.mp3 b/project/sounds/aiy710000010.mp3 deleted file mode 100644 index 6e08794..0000000 Binary files a/project/sounds/aiy710000010.mp3 and /dev/null differ diff --git a/project/sounds/aiy710000010.opus b/project/sounds/aiy710000010.opus new file mode 100644 index 0000000..bcf6341 Binary files /dev/null and b/project/sounds/aiy710000010.opus differ diff --git a/project/sounds/aiy710000020.mp3 b/project/sounds/aiy710000020.mp3 deleted file mode 100644 index d025b23..0000000 Binary files a/project/sounds/aiy710000020.mp3 and /dev/null differ diff --git a/project/sounds/aiy710000020.opus b/project/sounds/aiy710000020.opus new file mode 100644 index 0000000..f4de94a Binary files /dev/null and b/project/sounds/aiy710000020.opus differ diff --git a/project/sounds/aiy710000030.mp3 b/project/sounds/aiy710000030.mp3 deleted file mode 100644 index ad200f2..0000000 Binary files a/project/sounds/aiy710000030.mp3 and /dev/null differ diff --git a/project/sounds/aiy710000030.opus b/project/sounds/aiy710000030.opus new file mode 100644 index 0000000..c6f5d74 Binary files /dev/null and b/project/sounds/aiy710000030.opus differ diff --git a/project/sounds/aiy710000040.mp3 b/project/sounds/aiy710000040.mp3 deleted file mode 100644 index dbdbbd2..0000000 Binary files a/project/sounds/aiy710000040.mp3 and /dev/null differ diff --git a/project/sounds/aiy710000040.opus b/project/sounds/aiy710000040.opus new file mode 100644 index 0000000..02e9b14 Binary files /dev/null and b/project/sounds/aiy710000040.opus differ diff --git a/project/sounds/aiy710000050.mp3 b/project/sounds/aiy710000050.mp3 deleted file mode 100644 index f304d67..0000000 Binary files a/project/sounds/aiy710000050.mp3 and /dev/null differ diff --git a/project/sounds/aiy710000050.opus b/project/sounds/aiy710000050.opus new file mode 100644 index 0000000..a37c230 Binary files /dev/null and b/project/sounds/aiy710000050.opus differ diff --git a/project/sounds/aiy710000060.mp3 b/project/sounds/aiy710000060.mp3 deleted file mode 100644 index 1366af4..0000000 Binary files a/project/sounds/aiy710000060.mp3 and /dev/null differ diff --git a/project/sounds/aiy710000060.opus b/project/sounds/aiy710000060.opus new file mode 100644 index 0000000..2fae4fc Binary files /dev/null and b/project/sounds/aiy710000060.opus differ diff --git a/project/sounds/aiy710000070.mp3 b/project/sounds/aiy710000070.mp3 deleted file mode 100644 index 1528e54..0000000 Binary files a/project/sounds/aiy710000070.mp3 and /dev/null differ diff --git a/project/sounds/aiy710000070.opus b/project/sounds/aiy710000070.opus new file mode 100644 index 0000000..ce2b71c Binary files /dev/null and b/project/sounds/aiy710000070.opus differ diff --git a/project/sounds/aiy710000080.mp3 b/project/sounds/aiy710000080.mp3 deleted file mode 100644 index 600011d..0000000 Binary files a/project/sounds/aiy710000080.mp3 and /dev/null differ diff --git a/project/sounds/aiy710000080.opus b/project/sounds/aiy710000080.opus new file mode 100644 index 0000000..0673c92 Binary files /dev/null and b/project/sounds/aiy710000080.opus differ diff --git a/project/sounds/aiy710000090.mp3 b/project/sounds/aiy710000090.mp3 deleted file mode 100644 index b091686..0000000 Binary files a/project/sounds/aiy710000090.mp3 and /dev/null differ diff --git a/project/sounds/aiy710000090.opus b/project/sounds/aiy710000090.opus new file mode 100644 index 0000000..9990f15 Binary files /dev/null and b/project/sounds/aiy710000090.opus differ diff --git a/project/sounds/aiy710000100.mp3 b/project/sounds/aiy710000100.mp3 deleted file mode 100644 index 3f84955..0000000 Binary files a/project/sounds/aiy710000100.mp3 and /dev/null differ diff --git a/project/sounds/aiy710000100.opus b/project/sounds/aiy710000100.opus new file mode 100644 index 0000000..28b109b Binary files /dev/null and b/project/sounds/aiy710000100.opus differ diff --git a/project/sounds/aiy710000110.mp3 b/project/sounds/aiy710000110.mp3 deleted file mode 100644 index 1095ffa..0000000 Binary files a/project/sounds/aiy710000110.mp3 and /dev/null differ diff --git a/project/sounds/aiy710000110.opus b/project/sounds/aiy710000110.opus new file mode 100644 index 0000000..ad02c45 Binary files /dev/null and b/project/sounds/aiy710000110.opus differ diff --git a/project/sounds/aiy710000120.mp3 b/project/sounds/aiy710000120.mp3 deleted file mode 100644 index 81be490..0000000 Binary files a/project/sounds/aiy710000120.mp3 and /dev/null differ diff --git a/project/sounds/aiy710000120.opus b/project/sounds/aiy710000120.opus new file mode 100644 index 0000000..0985ea1 Binary files /dev/null and b/project/sounds/aiy710000120.opus differ diff --git a/project/sounds/aiy710000130.mp3 b/project/sounds/aiy710000130.mp3 deleted file mode 100644 index bde952f..0000000 Binary files a/project/sounds/aiy710000130.mp3 and /dev/null differ diff --git a/project/sounds/aiy710000130.opus b/project/sounds/aiy710000130.opus new file mode 100644 index 0000000..07881d1 Binary files /dev/null and b/project/sounds/aiy710000130.opus differ diff --git a/project/sounds/aiy820000010.mp3 b/project/sounds/aiy820000010.mp3 deleted file mode 100644 index 04b2978..0000000 Binary files a/project/sounds/aiy820000010.mp3 and /dev/null differ diff --git a/project/sounds/aiy820000010.opus b/project/sounds/aiy820000010.opus new file mode 100644 index 0000000..4503491 Binary files /dev/null and b/project/sounds/aiy820000010.opus differ diff --git a/project/sounds/aiy820000020.mp3 b/project/sounds/aiy820000020.mp3 deleted file mode 100644 index ef06278..0000000 Binary files a/project/sounds/aiy820000020.mp3 and /dev/null differ diff --git a/project/sounds/aiy820000020.opus b/project/sounds/aiy820000020.opus new file mode 100644 index 0000000..e405674 Binary files /dev/null and b/project/sounds/aiy820000020.opus differ diff --git a/project/sounds/attack.mp3 b/project/sounds/attack.mp3 deleted file mode 100644 index 16098f7..0000000 Binary files a/project/sounds/attack.mp3 and /dev/null differ diff --git a/project/sounds/attack.opus b/project/sounds/attack.opus new file mode 100644 index 0000000..acd40a4 Binary files /dev/null and b/project/sounds/attack.opus differ diff --git a/project/sounds/bomb.mp3 b/project/sounds/bomb.mp3 deleted file mode 100644 index 8a98067..0000000 Binary files a/project/sounds/bomb.mp3 and /dev/null differ diff --git a/project/sounds/bomb.opus b/project/sounds/bomb.opus new file mode 100644 index 0000000..443e6af Binary files /dev/null and b/project/sounds/bomb.opus differ diff --git a/project/sounds/cancel.mp3 b/project/sounds/cancel.mp3 deleted file mode 100644 index 3842eee..0000000 Binary files a/project/sounds/cancel.mp3 and /dev/null differ diff --git a/project/sounds/cancel.opus b/project/sounds/cancel.opus new file mode 100644 index 0000000..da26056 Binary files /dev/null and b/project/sounds/cancel.opus differ diff --git a/project/sounds/centerFly.mp3 b/project/sounds/centerFly.mp3 deleted file mode 100644 index 8246763..0000000 Binary files a/project/sounds/centerFly.mp3 and /dev/null differ diff --git a/project/sounds/centerFly.opus b/project/sounds/centerFly.opus new file mode 100644 index 0000000..fd94f13 Binary files /dev/null and b/project/sounds/centerFly.opus differ diff --git a/project/sounds/confirm.mp3 b/project/sounds/confirm.mp3 deleted file mode 100644 index 138beeb..0000000 Binary files a/project/sounds/confirm.mp3 and /dev/null differ diff --git a/project/sounds/confirm.opus b/project/sounds/confirm.opus new file mode 100644 index 0000000..821a7dc Binary files /dev/null and b/project/sounds/confirm.opus differ diff --git a/project/sounds/cursor.mp3 b/project/sounds/cursor.mp3 deleted file mode 100644 index 652bf07..0000000 Binary files a/project/sounds/cursor.mp3 and /dev/null differ diff --git a/project/sounds/cursor.opus b/project/sounds/cursor.opus new file mode 100644 index 0000000..7eec58d Binary files /dev/null and b/project/sounds/cursor.opus differ diff --git a/project/sounds/door.mp3 b/project/sounds/door.mp3 deleted file mode 100644 index ea6706d..0000000 Binary files a/project/sounds/door.mp3 and /dev/null differ diff --git a/project/sounds/door.opus b/project/sounds/door.opus new file mode 100644 index 0000000..dce3824 Binary files /dev/null and b/project/sounds/door.opus differ diff --git a/project/sounds/equip.mp3 b/project/sounds/equip.mp3 deleted file mode 100644 index 36bbd02..0000000 Binary files a/project/sounds/equip.mp3 and /dev/null differ diff --git a/project/sounds/equip.opus b/project/sounds/equip.opus new file mode 100644 index 0000000..2bd2c63 Binary files /dev/null and b/project/sounds/equip.opus differ diff --git a/project/sounds/error.mp3 b/project/sounds/error.mp3 deleted file mode 100644 index 329cca4..0000000 Binary files a/project/sounds/error.mp3 and /dev/null differ diff --git a/project/sounds/error.opus b/project/sounds/error.opus new file mode 100644 index 0000000..973ee32 Binary files /dev/null and b/project/sounds/error.opus differ diff --git a/project/sounds/floor.mp3 b/project/sounds/floor.mp3 deleted file mode 100644 index 96dc4fa..0000000 Binary files a/project/sounds/floor.mp3 and /dev/null differ diff --git a/project/sounds/floor.opus b/project/sounds/floor.opus new file mode 100644 index 0000000..0f603d3 Binary files /dev/null and b/project/sounds/floor.opus differ diff --git a/project/sounds/gem.mp3 b/project/sounds/gem.mp3 deleted file mode 100644 index c29b9df..0000000 Binary files a/project/sounds/gem.mp3 and /dev/null differ diff --git a/project/sounds/gem.opus b/project/sounds/gem.opus new file mode 100644 index 0000000..f7bbf6c Binary files /dev/null and b/project/sounds/gem.opus differ diff --git a/project/sounds/icePickaxe.mp3 b/project/sounds/icePickaxe.mp3 deleted file mode 100644 index 29ed9b0..0000000 Binary files a/project/sounds/icePickaxe.mp3 and /dev/null differ diff --git a/project/sounds/icePickaxe.opus b/project/sounds/icePickaxe.opus new file mode 100644 index 0000000..479b8e5 Binary files /dev/null and b/project/sounds/icePickaxe.opus differ diff --git a/project/sounds/item.mp3 b/project/sounds/item.mp3 deleted file mode 100644 index 5d82178..0000000 Binary files a/project/sounds/item.mp3 and /dev/null differ diff --git a/project/sounds/item.opus b/project/sounds/item.opus new file mode 100644 index 0000000..9a488f0 Binary files /dev/null and b/project/sounds/item.opus differ diff --git a/project/sounds/jingbao.mp3 b/project/sounds/jingbao.mp3 deleted file mode 100644 index c2c4aaa..0000000 Binary files a/project/sounds/jingbao.mp3 and /dev/null differ diff --git a/project/sounds/jingbao.opus b/project/sounds/jingbao.opus new file mode 100644 index 0000000..b2a57e1 Binary files /dev/null and b/project/sounds/jingbao.opus differ diff --git a/project/sounds/jump.mp3 b/project/sounds/jump.mp3 deleted file mode 100644 index b8ce8f7..0000000 Binary files a/project/sounds/jump.mp3 and /dev/null differ diff --git a/project/sounds/jump.opus b/project/sounds/jump.opus new file mode 100644 index 0000000..b1c8c01 Binary files /dev/null and b/project/sounds/jump.opus differ diff --git a/project/sounds/load.mp3 b/project/sounds/load.mp3 deleted file mode 100644 index e680f4d..0000000 Binary files a/project/sounds/load.mp3 and /dev/null differ diff --git a/project/sounds/load.opus b/project/sounds/load.opus new file mode 100644 index 0000000..215881f Binary files /dev/null and b/project/sounds/load.opus differ diff --git a/project/sounds/open_ui.mp3 b/project/sounds/open_ui.mp3 deleted file mode 100644 index 0282a08..0000000 Binary files a/project/sounds/open_ui.mp3 and /dev/null differ diff --git a/project/sounds/open_ui.opus b/project/sounds/open_ui.opus new file mode 100644 index 0000000..dbad758 Binary files /dev/null and b/project/sounds/open_ui.opus differ diff --git a/project/sounds/pickaxe.mp3 b/project/sounds/pickaxe.mp3 deleted file mode 100644 index f6dc258..0000000 Binary files a/project/sounds/pickaxe.mp3 and /dev/null differ diff --git a/project/sounds/pickaxe.opus b/project/sounds/pickaxe.opus new file mode 100644 index 0000000..2a9924d Binary files /dev/null and b/project/sounds/pickaxe.opus differ diff --git a/project/sounds/recovery.mp3 b/project/sounds/recovery.mp3 deleted file mode 100644 index 76b67f3..0000000 Binary files a/project/sounds/recovery.mp3 and /dev/null differ diff --git a/project/sounds/recovery.opus b/project/sounds/recovery.opus new file mode 100644 index 0000000..07091c8 Binary files /dev/null and b/project/sounds/recovery.opus differ diff --git a/project/sounds/save.mp3 b/project/sounds/save.mp3 deleted file mode 100644 index 295dbf2..0000000 Binary files a/project/sounds/save.mp3 and /dev/null differ diff --git a/project/sounds/save.opus b/project/sounds/save.opus new file mode 100644 index 0000000..58f2c9a Binary files /dev/null and b/project/sounds/save.opus differ diff --git a/project/sounds/shop.mp3 b/project/sounds/shop.mp3 deleted file mode 100644 index b654aa2..0000000 Binary files a/project/sounds/shop.mp3 and /dev/null differ diff --git a/project/sounds/shop.opus b/project/sounds/shop.opus new file mode 100644 index 0000000..1accbf1 Binary files /dev/null and b/project/sounds/shop.opus differ diff --git a/project/sounds/zone.mp3 b/project/sounds/zone.mp3 deleted file mode 100644 index 414b287..0000000 Binary files a/project/sounds/zone.mp3 and /dev/null differ diff --git a/project/sounds/zone.opus b/project/sounds/zone.opus new file mode 100644 index 0000000..ccdade8 Binary files /dev/null and b/project/sounds/zone.opus differ diff --git a/project/types/action.d.ts b/project/types/action.d.ts new file mode 100644 index 0000000..17464a1 --- /dev/null +++ b/project/types/action.d.ts @@ -0,0 +1,137 @@ +/** + * 鼠标与触屏操作的函数 + */ +type MotaMouseFunc = (x: number, y: number, px: number, py: number) => boolean; + +/** + * 按键操作的函数 + */ +type MotaKeyboardFunc = (e: KeyboardEvent) => boolean; + +/** + * 没有最乱,只有更乱 + */ +interface RegisteredActionMap { + keyDown: (keyCode: number) => boolean; + keyDownCtrl: () => boolean; + keyUp: (keyCode: number, altKey: boolean, fromReplay: boolean) => boolean; + longClick: MotaMouseFunc; + onStatusBarClick: (px: number, py: number, vertical: boolean) => boolean; + ondown: MotaMouseFunc; + onkeyDown: MotaKeyboardFunc; + onkeyUp: MotaKeyboardFunc; + onmousewheel: (direct: 1 | -1) => boolean; + onmove: MotaMouseFunc; + onup: MotaMouseFunc; + pressKey: (keyCode: number) => boolean; +} + +type ActionKey = keyof RegisteredActionMap; + +/** + * 将注册的函数的返回值变成void就变成了actions上的函数... + */ +type VoidedActionFuncs = { + [P in ActionKey]: (...params: Parameters) => void; +}; + +/** + * 点击位置 + */ +interface ClickLoc extends Loc { + /** + * 格子的大小(这不是32还能是其它的吗?? + */ + size: 32; +} + +interface RegisteredActionOf { + /** + * 交互的类型 + */ + action: K; + + /** + * 交互的唯一标识符 + */ + name: string; + + /** + * 优先级,越高越优先执行 + */ + priority: number; + + /** + * 交互函数 + */ + func: RegisteredActionMap[K]; +} + +/** + * 交互模块 + */ +interface Actions extends VoidedActionFuncs { + /** + * 横向的最后一个格子的横坐标 + */ + readonly LAST: number; + + /** + * 格子长度的一半 + */ + readonly _HX_: number; + + /** + * 格子高度的一半 + */ + readonly _HY_: number; + + /** + * 脚本编辑中的交互函数 + */ + readonly actionsdata: ActionData; + + /** + * 所有已注册的交互操作 + */ + readonly actions: { + [P in ActionKey]: RegisteredActionOf

[]; + }; + + /** + * 此函数将注册一个用户交互行为。 + * @param action 要注册的交互类型 + * @param name 自定义名称,可被注销使用 + * @param func 执行函数,如果func返回true,则不会再继续执行其他的交互函数 + * @param priority 优先级,优先级高的将会被执行。此项可不填,默认为0 + */ + registerAction( + action: K, + name: string, + func: RegisteredActionMap[K], + priority?: number + ): void; + + /** + * 注销一个用户交互行为 + * @param action 要注销的交互类型 + * @param name 要注销的自定义名称 + */ + unregisterAction(action: ActionKey, name: string): void; + + /** + * 执行一个用户交互行为 + */ + doRegisteredAction( + action: K, + ...params: Parameters + ): void; + + /** + * 判断一个横坐标是否在(_HX_ - 2, _HX_ + 2)范围外 + * @param x 要判断的横坐标 + */ + _out(x: number): boolean; +} + +declare const actions: new () => Actions; diff --git a/project/types/control.d.ts b/project/types/control.d.ts new file mode 100644 index 0000000..321b45a --- /dev/null +++ b/project/types/control.d.ts @@ -0,0 +1,1104 @@ +/** + * 帧动画函数 + */ +type FrameFunc = (time: number) => void; + +/** + * 录像操作函数,返回true表示执行成功 + */ +type ReplayFunc = (action: string) => boolean; + +/** + * 游戏画面大小变化时执行的函数 + */ +type ResizeFunc = (obj: DeepReadonly) => void; + +/** + * 勇士属性中的数字属性 + */ +type NumbericHeroStatus = SelectType; + +/** + * 存读档类型 + */ +type SLType = + | 'save' + | 'load' + | 'reload' + | 'replayLoad' + | 'replayRemain' + | 'replaySince'; + +/** + * 天气等级 + */ +type WeatherLevel = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10; + +/** + * resize函数的参数 + */ +interface ResizeObj { + /** + * body元素的宽度 + */ + clientWidth: number; + + /** + * body元素的高度 + */ + clientHeight: number; + + /** + * 边框的宽度 + */ + BORDER: 3; + + /** + * 状态栏的宽度 + */ + BAR_WIDTH: number; + + /** + * 工具栏的高度 + */ + TOOLBAR_HEIGHT: 38; + + /** + * 计算边框之后的游戏画面的宽度 + */ + outerWidth: number; + + /** + * 计算边框之后的游戏画面的高度 + */ + outerHeight: number; + + /** + * 全局属性 + */ + globalAttribute: GlobalAttribute; + + /** + * 边框样式,css字符串 + */ + border: string; + + /** + * 状态栏显示的状态项 + */ + statusDisplayArr: string[]; + + /** + * 状态栏显示的状态项数 + */ + count: number; + + /** + * 状态栏显示的行数 + */ + col: number; + + /** + * 竖屏下状态栏的高度 + */ + statusBarHeightInVertical: number; + + /** + * 竖屏下工具栏的高度 + */ + toolbarHeightInVertical: number; + + /** + * 是否开启底部工具栏 + */ + extendToolbar: number; + + /** + * @deprecated + * 是否是15x15 + */ + is15x15: false; +} + +interface RenderFrame { + /** + * 帧动画的名称 + */ + name: string; + + /** + * 是否需要进入游戏后才执行 + */ + needPlaying: boolean; + + /** + * 每帧执行的函数 + */ + func: FrameFunc; +} + +interface ReplayAction { + /** + * 录像操作的名称 + */ + name: string; + + /** + * 录像操作执行的函数 + */ + func: ReplayFunc; +} + +interface ResizeAction { + /** + * resize操作的名称 + */ + name: string; + + /** + * 游戏画面变化时执行的函数 + */ + func: ResizeFunc; +} + +interface WeatherAction { + /** + * 天气每帧执行的函数 + */ + frameFunc?: (time: number, level: WeatherLevel) => void; + + /** + * 天气的初始化函数 + */ + initFunc: (level: WeatherLevel) => void; +} + +interface FrameObj { + angle: number; + index: number; + mirror: number; + opacity: number; + x: number; + y: number; + zoom: number; +} + +/** + * 主要用来进行游戏控制,比如行走控制、自动寻路、存读档等等游戏核心内容 + */ +interface Control { + /** + * 刷新状态栏时是否不执行自动事件 + */ + readonly noAutoEvent: boolean; + + /** + * 注册的帧动画 + */ + readonly renderFrameFunc: RenderFrame[]; + + /** + * 注册的录像操作 + */ + readonly replayActions: ReplayAction[]; + + /** + * 注册的resize操作 + */ + readonly resizes: ResizeAction[]; + + /** + * 注册的天气 + */ + readonly weathers: Record; + + /** + * 脚本编辑的control函数列表 + */ + readonly controlData: ControlData; + + /** + * 注册一个animationFrame + * @param name 名称,可用来作为注销使用 + * @param needPlaying 是否只在游戏运行时才执行(在标题界面不执行) + * @param func 要执行的函数,传入time(从页面加载完毕到当前所经过的时间)作为参数 + */ + registerAnimationFrame( + name: string, + needPlaying: boolean, + func: FrameFunc + ): void; + + /** + * 注销一个animationFrame + * @param name 要注销的函数名称 + */ + unregisterAnimationFrame(name: string): void; + + /** + * 进入标题画面 + * @example core.showStartAnimate(); // 重启游戏但不重置bgm + * @param noAnimate 是否不由黑屏淡入而是立即亮屏 + * @param callback 完全亮屏后的回调函数 + */ + showStartAnimate(noAnimate?: boolean, callback?: () => void): void; + + /** + * 淡出标题画面 + * @example core.hideStartAnimate(core.startGame); // 淡出标题画面并开始新游戏,跳过难度选择 + * @param callback 标题画面完全淡出后的回调函数 + */ + hideStartAnimate(callback?: () => void): void; + + /** + * 判断游戏是否已经开始 + */ + isPlaying(): boolean; + + /** + * 清除游戏状态和数据 + */ + clearStatus(): void; + + /** + * 清除地图上绘制的自动寻路路线 + */ + clearAutomaticRouteNode(x: number, y: number): void; + + /** + * 停止自动寻路操作 + */ + stopAutomaticRoute(): void; + + /** + * 保存剩下的寻路,并停止 + */ + saveAndStopAutomaticRoute(): void; + + /** + * 继续剩下的自动寻路操作 + */ + continueAutomaticRoute(): void; + + /** + * 清空剩下的自动寻路列表 + */ + clearContinueAutomaticRoute(callback?: () => any): void; + + /** + * 半自动寻路,用于鼠标或手指拖动 + * @param destX 鼠标或手指的起拖点横坐标 + * @param destY 鼠标或手指的起拖点纵坐标 + * @param stepPostfix 拖动轨迹的数组表示,每项为一步的方向和目标点。 + */ + setAutomaticRoute(destX: number, destY: number, stepPostfix: Loc[]): void; + + /** + * 连续行走 + * @param steps 压缩的步伐数组,每项表示朝某方向走多少步 + */ + setAutoHeroMove(steps: CompressedStep[]): void; + + /** + * 设置行走的效果动画 + */ + setHeroMoveInterval(callback?: () => any): void; + + /** + * 每移动一格后执行的函数 + */ + moveOneStep(callback?: () => any): void; + + /** + * 尝试前进一步,如果面前不可被踏入就会直接触发该点事件 + * @example core.moveAction(core.doAction); // 尝试前进一步,然后继续事件处理 + * @param callback 走一步后的回调函数 + */ + moveAction(callback?: () => void): void; + + /** + * 连续前进,不撞南墙不回头 + * @example core.moveHero(); // 连续前进 + * @param direction 移动的方向,不设置就是勇士当前的方向 + * @param callback 回调函数,设置了就只走一步 + */ + moveHero(direction?: Dir, callback?: () => void): void; + + /** + * 当前是否正在移动 + */ + isMoving(): boolean; + + /** + * 停止勇士的一切行动并等待勇士停下 + * @example core.waitHeroToStop(core.vibrate); // 等待勇士停下,然后视野左右抖动1秒 + * @param callback 勇士停止后的回调函数 + */ + waitHeroToStop(callback?: () => void): void; + + /** + * 主角转向并计入录像,不会导致跟随者聚集,会导致视野重置到以主角为中心 + * @example core.turnHero(); // 主角顺时针旋转,即单击主角或按下Z键的效果 + * @param direction 主角的新朝向,可为up, down, left, right, :left, :right, :back七种之一,不填视为:right + */ + turnHero(direction?: TurnDir): void; + + /** + * 瞬移到某一点 + * @param x 瞬移至的横坐标 + * @param y 瞬移至的纵坐标 + * @param ignoreSteps 忽略的步数,不填则会自动计算 + */ + moveDirectly(x: number, y: number, ignoreSteps?: number): boolean; + + /** + * 尝试瞬移,如果该点有图块/事件/阻激夹域捕则会瞬移到它旁边再走一步(不可踏入的话当然还是触发该点事件),这一步的方向优先和瞬移前主角的朝向一致 + * @example core.tryMoveDirectly(6, 0); // 尝试瞬移到地图顶部的正中央,以样板0层为例,实际效果是瞬移到了上楼梯下面一格然后向上走一步并触发上楼事件 + * @param destX 目标点的横坐标 + * @param destY 目标点的纵坐标 + */ + tryMoveDirectly(destX: number, destY: number): boolean; + + /** + * 绘制主角和跟随者并重置视野到以主角为中心 + * @example core.drawHero(); // 原地绘制主角的静止帧 + * @param status 绘制状态 + * @param offset 相对主角逻辑位置的偏移量,不填视为无偏移 + * @param frame 绘制第几帧 + */ + drawHero( + status?: Exclude, + offset?: number, + frame?: number + ): void; + + /** + * 改变勇士的不透明度 + * @param opacity 要设置成的不透明度 + * @param moveMode 动画的缓动模式 + * @param time 动画时间,不填视为无动画 + * @param callback 动画执行完毕的回调函数 + */ + setHeroOpacity( + opacity: number, + moveMode?: EaseMode, + time?: any, + callback?: () => any + ): void; + + /** + * 设置游戏系统画布的偏移量 + * @param canvasId 字符串或数字,根据ts的说法应该只能填数字,但是浏览器会提高字符串的方式。 + * 但是还是建议填数字,排列顺序一般是纵深从低到高排列 + * @param x 偏移横坐标 + * @param y 偏移纵坐标 + */ + setGameCanvasTranslate( + canvasId: string | number, + x: number, + y: number + ): void; + + /** + * 加减所有游戏系统画布的偏移 + * @param x 增加的横坐标 + * @param y 增加的纵坐标 + */ + addGameCanvasTranslate(x: number, y: number): void; + + /** + * 更新大地图的可见区域 + */ + updateViewport(): void; + + /** + * 设置视野范围 + * @param px 相对大地图左上角的偏移横坐标,单位像素 + * @param py 相对大地图左上角的偏移纵坐标,单位像素 + */ + setViewport(px?: number, py?: number): void; + + /** + * 移动视野范围,这东西真的有人用吗...高级动画 + setViewport就完事了( + * @param x 移动的横坐标,单位格子 + * @param y 移动的纵坐标,单位格子 + * @param moveMode 缓动方式 + * @param time 动画时间 + * @param callback 动画完毕后的回调函数 + */ + moveViewport( + x: number, + y: number, + moveMode?: EaseMode, + time?: number, + callback?: () => void + ): void; + + /** + * 获取主角面前第n格的横坐标 + * @example core.closeDoor(core.nextX(), core.nextY(), 'yellowDoor', core.turnHero); // 在主角面前关上一扇黄门,然后主角顺时针旋转90° + * @param n 目标格与主角的距离,面前为正数,背后为负数,脚下为0,不填视为1 + */ + nextX(n?: number): number; + + /** + * 获取主角面前第n格的纵坐标 + * @example core.jumpHero(core.nextX(2), core.nextY(2)); // 主角向前跃过一格,即跳跃靴道具的使用效果 + * @param n 目标格与主角的距离,面前为正数,背后为负数,脚下为0,不填视为1 + */ + nextY(n?: number): number; + + /** + * 判定主角是否身处某个点的锯齿领域(取曼哈顿距离) + * @example core.nearHero(6, 6, 6); // 判定主角是否身处点(6,6)的半径为6的锯齿领域 + * @param x 领域的中心横坐标 + * @param y 领域的中心纵坐标 + * @param n 领域的半径,不填视为1 + */ + nearHero(x: number, y: number, n?: number): boolean; + + /** + * 立刻聚集所有的跟随者 + */ + gatherFollowers(): void; + + /** + * 更新跟随者坐标 + */ + updateFollowers(): void; + + /** + * 更新领域、夹击、阻击的伤害地图 + * @param floorId 更新的地图id + */ + updateCheckBlock(floorId?: FloorIds): void; + + /** + * 检查并执行领域、夹击、阻击事件 + */ + checkBlock(): void; + + /** + * @deprecated 使用core.updateStatusBar代替。重算并绘制地图显伤 + * @example core.updateDamage(); // 更新当前地图的显伤,绘制在显伤层(废话) + * @param floorId 地图id,不填视为当前地图。预览地图时填写 + * @param ctx 绘制到的画布,如果填写了就会画在该画布而不是显伤层 + */ + updateDamage(floorId?: FloorIds, ctx?: CtxRefer): void; + + /** + * 重绘地图显伤 + * @param ctx 绘制到的画布 + */ + drawDamage(ctx?: CtxRefer): void; + + /** + * 选择录像文件 + */ + chooseReplayFile(): void; + + /** + * 开始播放一个录像 + */ + startReplay(list: string[]): void; + + /** + * 更改播放状态,暂停还是播放 + */ + triggerReplay(): void; + + /** + * 暂停播放 + */ + pauseReplay(): void; + + /** + * 恢复播放 + */ + resumeReplay(): void; + + /** + * 单步播放 + */ + stepReplay(): void; + + /** + * 加速播放 + */ + speedUpReplay(): void; + + /** + * 减速播放 + */ + speedDownReplay(): void; + + /** + * 设置播放速度 + */ + setReplaySpeed(speed: number): void; + + /** + * 停止录像播放 + * @param force 是否是强制停止播放(例如点击停止播放按钮) + */ + stopReplay(force?: boolean): void; + + /** + * 回退录像播放 + */ + rewindReplay(): void; + + /** + * 是否正在播放录像 + */ + isReplaying(): boolean; + + /** + * 回放下一个操作 + */ + replay(): void; + + /** + * 注册一个录像行为 + * @param name 自定义名称,可用于注销使用 + * @param func 具体执行录像的函数,可为一个函数或插件中的函数名; + * 需要接受一个action参数,代表录像回放时的下一个操作 + * func返回true代表成功处理了此录像行为,false代表没有处理此录像行为。 + */ + registerReplayAction(name: string, func: ReplayFunc): void; + + /** + * 注销一个录像行为 + * @param 要注销的录像行为 + */ + unregisterReplayAction(name: string): void; + + /** + * 自动存档 + * @param removeLast 是否移除位于自动存档栈底部的存档 + */ + autosave(removeLast?: any): void; + + /** + * 实际进行自动存档 + */ + checkAutosave(): void; + + /** + * 实际进行存读档事件 + */ + doSL(id: string, type: SLType): void; + + /** + * 同步存档到服务器 + * @param type 同步的类型,填all表示所有都同步,否则只同步当前存档 + */ + syncSave(type?: 'all'): void; + + /** + * 从服务器加载存档 + */ + syncLoad(): void; + + /** + * 存档到本地 + */ + saveData(): Save; + + /** + * 从本地读档 + */ + loadData(data: Save, callback?: () => void): void; + + /** + * 获得某个存档内容 + */ + getSave(index: number, callback?: (data?: Save) => void): void; + + /** + * 获得某些存档内容 + */ + getSaves(ids: number, callback?: (data?: Save) => void): void; + getSaves( + ids: number[], + callback?: (data?: Record) => void + ): void; + + /** + * 获得所有存档内容 + */ + getAllSaves(callback?: (data?: Save[]) => void): void; + + /** + * 获得所有存在存档的存档位 + */ + getSaveIndexes(callback?: (data: Record) => void): void; + + /** + * 判断某个存档位是否存在存档 + */ + hasSave(index: number): boolean; + + /** + * 删除某个存档 + */ + removeSave(index: number, callback?: () => void): void; + + /** + * 设置主角的某个属性 + * @example core.setStatus('loc', {x : 0, y : 0, direction : 'up'}); // 设置主角位置为地图左上角,脸朝上 + * @param name 属性名 + * @param value 属性的新值 + */ + setStatus(name: K, value: HeroStatus[K]): void; + + /** + * 增减主角的某个属性,等价于core.setStatus(name, core.getStatus(name) + value) + * @example core.addStatus('name', '酱'); // 在主角的名字后加一个“酱”字 + * @param name 属性名 + * @param value 属性的增量,请注意旧量和增量中只要有一个是字符串就会把两者连起来成为一个更长的字符串 + */ + addStatus>( + name: K, + value: HeroStatus[K] + ): void; + + /** + * 读取主角的某个属性,不包括百分比修正 + * @example core.getStatus('loc'); // 读取主角的坐标和朝向 + * @param name 属性名 + * @returns 属性值 + */ + getStatus(name: K): HeroStatus[K]; + + /** + * 从status中获得属性,如果不存在则从勇士属性中获取 + * @param status 要从中获取的属性对象 + * @param name 属性名 + */ + getStatusOrDefault( + status?: DeepPartial, + name?: K + ): HeroStatus[K]; + + /** + * 计算主角的某个属性,包括百分比修正 + * @example core.getRealStatus('atk'); // 计算主角的攻击力,包括百分比修正。战斗使用的就是这个值 + * @param name 属性名,注意只能用于数值类属性 + */ + getRealStatus(name: K): number; + + /** + * 从status中获得增幅后的属性,如果不存在则从勇士属性中获取 + * @param status 要从中获取的属性对象 + * @param name 属性名 + */ + getRealStatusOrDefault( + status?: DeepPartial, + name?: K + ): number; + + /** + * 获得勇士原始属性(无装备和衰弱影响) + * @param name 获取的属性名 + */ + getNakedStatus(name?: keyof NumbericHeroStatus): number; + + /** + * 获得某个状态的中文名 + * @param name 要获取的属性名 + */ + getStatusLabel(name: string): string; + + /** + * 设置主角某个属性的百分比修正倍率,初始值为1, + * 倍率存放在flag: `__${name}_${buff}__` 中 + * @example core.setBuff('atk', 0.5); // 主角能发挥出的攻击力减半 + * @param name 属性名,注意只能用于数值类属性 + * @param value 新的百分比修正倍率,不填(效果上)视为1 + */ + setBuff(name: K, value?: number): void; + + /** + * 增减主角某个属性的百分比修正倍率,加减法叠加和抵消。等价于 core.setBuff(name, core.getBuff(name) + value) + * @example core.addBuff('atk', -0.1); // 主角获得一层“攻击力减一成”的负面效果 + * @param name 属性名,注意只能用于数值类属性 + * @param value 倍率的增量 + */ + addBuff(name: K, value: number): void; + + /** + * 读取主角某个属性的百分比修正倍率,初始值为1 + * @example core.getBuff('atk'); // 主角当前能发挥出多大比例的攻击力 + * @param name 属性的英文名 + */ + getBuff(name: keyof NumbericHeroStatus): number; + + /** + * 变更勇士的debuff + * @param action 触发的类型,get表示获得debuff,remove表示移除debuff + * @param type 获取的debuff列表 + */ + triggerDebuff(action: string, type: string | string[]): void; + + /** + * 设置勇士位置 + * 值得注意的是,这句话虽然会使勇士改变位置,但并不会使界面重新绘制; + * 如需立刻重新绘制地图还需调用:core.clearMap('hero'); core.drawHero(); 来对界面进行更新。 + * @example core.setHeroLoc('x', 5) // 将勇士当前位置的横坐标设置为5。 + * @param name 要设置的坐标属性 + * @param value 新值 + * @param noGather 是否聚集跟随者 + */ + setHeroLoc(name: 'x' | 'y', value: number, noGather?: boolean): void; + setHeroLoc(name: 'direction', value: Dir, noGather?: boolean): void; + + /** + * 获取主角的位置,朝向 + * @example core.getHeroLoc(); // 获取主角的位置和朝向 + * @param name 要读取横坐标还是纵坐标还是朝向还是都读取 + */ + getHeroLoc(): Loc; + getHeroLoc(name: K): Loc[K]; + + /** + * 根据级别的数字获取对应的名称,后者定义在全塔属性 + * @example core.getLvName(); // 获取主角当前级别的名称,如“下级佣兵” + * @param lv 级别的数字,不填则视为主角当前的级别 + * @returns 级别的名称,如果不存在就还是返回字符串类型的数字 + */ + getLvName(lv?: number): string; + + /** + * 获得下次升级需要的经验值。 + * 升级扣除模式下会返回经验差值;非扣除模式下会返回总共需要的经验值。 + * 如果无法进行下次升级,返回null。 + */ + getNextLvUpNeed(): number | null; + + /** + * 设置一个flag变量 + * @example core.setFlag('poison', true); // 令主角中毒 + * @param name 变量名,支持中文,这东西用中文就是不规范( + * @param value 变量的新值,不填或填null视为删除 + */ + setFlag(name: string, value?: any): void; + + /** + * 增减一个flag变量,等价于 core.setFlag(name, core.getFlag(name, 0) + value) + * @example core.addFlag('hatred', 1); // 增加1点仇恨值 + * @param name 变量名,支持中文 + * @param value 变量的增量 + */ + addFlag(name: string, value: number | string): void; + + /** + * 获取一个flag变量 + * @param name 变量名,支持中文,这东西用中文就是不规范( + * @param defaultValue 当变量不存在时的返回值,可选(事件流中默认填0)。 + * @returns flags[name] ?? defaultValue + */ + getFlag(name: string, defaultValue?: T): T; + + /** + * 判定一个flag变量是否不为falsy + * @example core.hasFlag('poison'); // 判断主角当前是否中毒 + * @param name 变量名,支持中文,这东西用中文就是不规范( + */ + hasFlag(name: string): boolean; + + /** + * 删除某个flag + * @param name 要删除的变量名 + */ + removeFlag(name: string): void; + + /** + * 设置某个独立开关 + * @param x 横坐标 + * @param y 纵坐标 + * @param floorId 楼层id + * @param name 独立开关的名称 + * @param value 要设置成的值 + */ + setSwitch( + x?: number, + y?: number, + floorId?: FloorIds, + name?: string, + value?: any + ): void; + + /** + * 获得某个独立开关 + * @param x 横坐标 + * @param y 纵坐标 + * @param floorId 楼层id + * @param name 独立开关的名称 + * @param value 默认值 + */ + getSwitch( + x?: number, + y?: number, + floorId?: FloorIds, + name?: string, + defaultValue?: T + ): T; + + /** + * 增加某个独立开关 + * @param x 横坐标 + * @param y 纵坐标 + * @param floorId 楼层id + * @param name 独立开关的名称 + * @param value 增加的值 + */ + addSwitch( + x?: number, + y?: number, + floorId?: FloorIds, + name?: string, + value?: number | string + ): void; + + /** + * 是否存在某个独立开关 + * @param x 横坐标 + * @param y 纵坐标 + * @param floorId 楼层id + * @param name 独立开关的名称 + */ + hasSwitch( + x?: number, + y?: number, + floorId?: FloorIds, + name?: string + ): boolean; + + /** + * 删除某个独立开关 + * @param x 横坐标 + * @param y 纵坐标 + * @param floorId 楼层id + * @param name 独立开关的名称 + */ + removeSwitch( + x?: number, + y?: number, + floorId?: FloorIds, + name?: string + ): void; + + /** + * 锁定用户控制,常常用于事件处理 + */ + lockControl(): void; + + /** + * 解锁用户控制 + */ + unlockControl(): void; + + /** + * 开启调试模式, 此模式下可以按Ctrl键进行穿墙, 并忽略一切事件。 + * 此模式下不可回放录像和上传成绩。 + */ + debug(): void; + + /** + * 清空录像折叠信息 + */ + clearRouteFolding(): void; + + /** + * 检查录像折叠信息 + */ + checkRouteFolding(): void; + + /** + * 获得映射文件名 + */ + getMappedName(name: K): NameMap[K]; + + /** + * 设置天气,不计入存档。如需长期生效请使用core.events._action_setWeather()函数 + * @example core.setWeather('fog', 10); // 设置十级大雾天 + * @param type 新天气的类型,不填视为无天气 + * @param level 新天气(晴天除外)的级别,必须为不大于10的正整数,不填视为5 + */ + setWeather(type?: string, level?: WeatherLevel): void; + + /** + * 注册一个天气 + * @param name 天气的名称 + * @param initFunc 初始化函数 + * @param frameFunc 每帧执行的函数 + */ + registerWeather( + name: string, + initFunc: WeatherAction['initFunc'], + frameFunc?: WeatherAction['frameFunc'] + ): void; + + /** + * 注销一个天气 + * @param name 要注销的天气名称 + */ + unregisterWeather(name: string): void; + + /** + * 更改画面色调,不计入存档。如需长期生效请使用core.events._action_setCurtain()函数 + * @example core.setCurtain(); // 恢复画面色调,用时四分之三秒 + * @param color 颜色数组,不填视为[0, 0, 0, 0] + * @param time 渐变时间,单位为毫秒。不填视为750ms + * @param moveMode 缓动模式 + * @param callback 更改完毕后的回调函数 + */ + setCurtain( + color?: RGBArray, + time?: number, + moveMode?: EaseMode, + callback?: () => void + ): void; + + /** + * 画面闪烁 + * @example core.screenFlash([255, 0, 0, 1], 3); // 红屏一闪而过 + * @param color 颜色数组 + * @param time 单次闪烁时长,实际闪烁效果为先花其三分之一的时间渐变到目标色调,再花剩余三分之二的时间渐变回去 + * @param times 闪烁的总次数,不填或填0都视为1 + * @param moveMode 缓动模式 + * @param callback 闪烁全部完毕后的回调函数 + */ + screenFlash( + color: RGBArray, + time: number, + times?: number, + moveMode?: string, + callback?: () => void + ): void; + + /** + * 播放背景音乐,中途开播但不计入存档且只会持续到下次场景切换。如需长期生效请将背景音乐的文件名赋值给flags.__bgm__ + * @example core.playBgm('bgm.mp3', 30); // 播放bgm.mp3,并跳过前半分钟 + * @param bgm 背景音乐的文件名,支持全塔属性中映射前的中文名 + * @param startTime 跳过前多少秒 + */ + playBgm(bgm: BgmIds | NameMapIn, startTime?: number): void; + + /** + * 设置背景音乐的播放速度和音调 + * @param speed 要设置到的速度,100是原速 + * @param usePitch 是否允许声调改变 + */ + setBgmSpeed(speed: number, usePitch?: boolean): void; + + /** + * 暂停背景音乐的播放 + */ + pauseBgm(): void; + + /** + * 恢复背景音乐的播放 + */ + resumeBgm(resumeTime?: number): void; + + /** + * 设置音乐图标的开启关闭状态 + */ + setMusicBtn(): void; + + /** + * 开启或关闭背景音乐的播放 + */ + triggerBgm(): void; + + /** + * 播放一个音效 + * @param sound 音效名 + * @param pitch 音调,同时会修改播放速度,100为原速 + * @param callback 回调函数 + * @returns 音效的唯一标识符,用于停止音效等操作 + */ + playSound( + sound: SoundIds | NameMapIn, + pitch?: number, + callback?: () => void + ): number; + + /** + * 停止音频 + * @param id 停止的音频标识符,不填则停止所有 + */ + stopSound(id?: number): void; + + /** + * 获得正在播放的所有音效的id列表 + * @param name 要获得的音效名 + */ + getPlayingSounds(name?: SoundIds | NameMapIn): number[]; + + /** + * 检查bgm状态,没有播放的话就播放 + */ + checkBgm(): void; + + /** + * 设置屏幕放缩 + * @param delta 在所有可用放缩数组中增加的下标数 + */ + setDisplayScale(delta: number): void; + + /** + * 清空状态栏 + */ + clearStatusBar(): void; + + /** + * 更新状态栏和地图显伤,会在下一个动画帧更新 + * @param doNotCheckAutoEvents 是否不检查自动事件 + * @param immediate 是否立刻刷新,而非延迟到下一动画帧刷新 + */ + updateStatusBar(doNotCheckAutoEvents?: boolean, immediate?: boolean): void; + + /** + * 显示状态栏 + */ + showStatusBar(): void; + + /** + * 隐藏状态栏 + * @param showToolbox 是否显示工具栏 + */ + hideStatusBar(showToolbox?: boolean): void; + + /** + * 更新状态栏的勇士图标 + */ + updateHeroIcon(name: ImageIds): void; + + /** + * 改变工具栏为按钮1-8 + * @param useButton 是否显示为按钮1-8 + */ + setToolbarButton(useButton?: boolean): void; + + /** + * 注册一个resize函数 + * @param name 名称,可供注销使用 + * @param func 游戏画面发生变化时执行的函数 + */ + registerResize(name: string, func: ResizeFunc): void; + + /** + * 注销一个resize函数 + */ + unregisterResize(name: string): void; + + /** + * 屏幕分辨率改变后执行的函数 + */ + resize(): void; +} + +declare const control: new () => Control; diff --git a/project/types/core.d.ts b/project/types/core.d.ts new file mode 100644 index 0000000..84c0492 --- /dev/null +++ b/project/types/core.d.ts @@ -0,0 +1,1450 @@ +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// + +type MaterialIcon = { + [C in Exclude]: { + [P in AllIdsOf]: number; + }; +} & { + /** + * 勇士的图标信息 + */ + hero: { + /** + * 各个方向的图标信息 + */ + [D in Dir2]: { + /** + * 行数 + */ + loc: number; + + /** + * 第一列 + */ + stop: number; + + /** + * 第二列 + */ + leftFoot: number; + + /** + * 第三列 + */ + midFoot: number; + + /** + * 第四列 + */ + rightFoot: number; + }; + } & { + /** + * 勇士的宽度 + */ + width: number; + + /** + * 勇士的高度 + */ + height: number; + }; +}; + +type MaterialImages = { + /** + * 各个类型的图块的图片 + */ + [C in Exclude]: HTMLImageElement; +} & { + /** + * 空气墙 + */ + airwall: HTMLImageElement; + + /** + * 自动元件 + */ + autotile: Record, HTMLImageElement>; + + /** + * 全塔属性注册的图片 + */ + images: Record; + + /** + * 额外素材 + */ + tilesets: Record; +}; + +interface Material { + /** + * 动画信息 + */ + readonly animates: Record; + + /** + * 素材的图片信息 + */ + readonly images: MaterialImages; + + /** + * 音乐信息 + */ + readonly bgms: Record; + + /** + * 音效信息 + */ + readonly sounds: Record; + + /** + * 怪物信息 + * @example core.material.enemys.greenSlime // 获得绿色史莱姆的属性数据 + */ + readonly enemys: { + [P in EnemyIds]: Enemy

; + }; + + /** + * 道具信息 + */ + readonly items: { + [P in AllIdsOf<'items'>]: Item

; + }; + + /** + * 图标信息 + */ + readonly icons: DeepReadonly; + + /** + * @deprecated + * core定义了,但在代码中完全没有找到这个东西?用处未知 + */ + readonly ground: CanvasRenderingContext2D; + + /** + * 楼层背景的画布context + */ + readonly groundCanvas: CanvasRenderingContext2D; + + /** + * 楼层背景的canvas样式 + */ + readonly groundPattern: CanvasPattern; + + /** + * 自动元件的父子关系 + */ + readonly autotileEdges: Record< + AllNumbersOf<'autotile'>, + AllNumbersOf<'autotile'>[] + >; +} + +interface Timeout { + /** + * 单击勇士时的计时器,用于判断双击 + */ + turnHeroTimeout?: number; + + /** + * 按住500ms后进行长按判定的计时器 + */ + onDownTimeout?: number; + + /** + * 长按跳过等待事件的计时器 + */ + sleepTimeout?: number; +} + +interface Interval { + /** + * 勇士移动的定时器 + */ + heroMoveInterval?: number; + + /** + * 长按计时器 + */ + onDownInterval?: number; +} + +interface AnimateFrame { + /** + * 游戏总时间 + */ + readonly totalTime: number; + + /** + * 本次游戏开始的时间 + */ + readonly totalTimeStart: number; + + /** + * @deprecated + * 样板没有出现过 + */ + globalAnimate: boolean; + + /** + * 当前raf的时间戳,即从游戏加载完毕到现在经过的时间 + */ + readonly globalTime: number; + + /** + * @deprecated + * 样板没有出现过 + */ + selectorTime: number; + + /** + * @deprecated + * 样板没有出现过 + */ + selectorUp: boolean; + + /** + * 上一次全局动画的时间(怪物、npc等抖动一下的时间) + */ + readonly animateTime: number; + + /** + * 勇士移动的时候上一次的换腿时间 + */ + readonly moveTime: number; + + /** + * @deprecated + * 样板没有出现过 + */ + lastLegTime: number; + + /** + * 当前是否在左腿上,使用了四帧插件时无效 + */ + readonly leftLeg: boolean; + + /** + * 当前天气信息 + */ + readonly weather: Weather; + + /** + * 左上角提示 + */ + readonly tip?: Readonly; + + /** + * 异步信息,想不到吧,这玩意是一个以number为索引的回调函数列表 + */ + readonly asyncId: Record void>; + + /** + * 上一个异步事件的id + */ + readonly lastAsyncId: number; +} + +interface Weather { + /** + * 当前的raf时间戳,同globalTime,但只有部分天气有用 + */ + time: number; + + /** + * 当前天气类型 + */ + type: string; + + /** + * 谁会去用这个玩意??? + */ + nodes: any[]; + + /** + * 谁会去用这个玩意??? + */ + data: any; + + /** + * 当前的天气等级 + */ + readonly level: number; + + /** + * 雾的图片信息 + */ + readonly fog: HTMLImageElement; + + /** + * 多云的图片信息 + */ + readonly cloud: HTMLImageElement; + + /** + * 晴天的图片信息 + */ + readonly sun: HTMLImageElement; +} + +interface Tip { + /** + * 显示的文字 + */ + text: string; + + /** + * 文字的左边像素位置 + */ + textX: 21 | 45; + + /** + * 提示的宽度 + */ + width: number; + + /** + * 当前的不透明度,会在显示提示时不断变化 + */ + opacity: number; + + /** + * 在显示阶段还是常亮阶段还是消失阶段 + */ + stage: number; + + /** + * 图标的帧数,即显示图标的第几帧 + */ + frame: number; + + /** + * 当前的raf时间戳 + */ + time: number; + + /** + * 在提示进入常亮阶段后经过了多长时间 + */ + displayTime: number; +} + +interface MusicStatus { + /** + * AudioContext信息,注意如果浏览器不支持的话会是null + */ + audioContext: AudioContext; + + /** + * 是否允许播放BGM + */ + bgmStatus: boolean; + + /** + * 是否允许播放SE + */ + soundStatus: boolean; + + /** + * 正在播放的BGM + */ + playingBgm: string; + + /** + * 上次播放的bgm + */ + lastBgm: string; + + /** + * 音量控制节点,只对音效有效,但为什么样板只有一个呢 + */ + gainNode: GainNode; + + /** + * 正在播放的SE,这个__name是音效名 + */ + playingSounds: Record; + + /** + * 用户音量 + */ + userVolume: number; + + /** + * 设计音量,好吧其实不能设计,只有淡入淡出的时候有用 + */ + designVolume: number; + + /** + * 音乐播放速度 + */ + bgmSpeed: number; + + /** + * 修改音乐播放速度时是否修改音调 + */ + bgmUsePitch: boolean; + + /** + * 缓存过BGM内容 + */ + cachedBgms: string[]; + + /** + * 缓存的bgm数量 + */ + cachedBgmCount: 8; +} + +interface CorePlatform { + /** + * 是否http + */ + isOnline: boolean; + + /** + * 是否是PC + */ + isPC: boolean; + + /** + * 是否是Android + */ + isAndroid: boolean; + + /** + * 是否是iOS + */ + isIOS: boolean; + + /** + * 平台信息 + */ + string: 'PC' | 'Android' | 'IOS' | ''; + + /** + * 是否是微信 + */ + isWeChat: boolean; + + /** + * 是否是QQ + */ + isQQ: boolean; + + /** + * 是否是Chrome + */ + isChrome: boolean; + + /** + * 是否是safari浏览器 + */ + isSafari: boolean; + + /** + * 是否支持复制到剪切板 + */ + supportCopy: boolean; + + /** + * 读取文件时的input元素(我也不知道干啥的 + */ + fileInput: HTMLInputElement; + + /** + * FileReader示例 + */ + fileReader: FileReader; + + /** + * 读取成功 + */ + successCallback?: (obj: any) => void; + + /** + * 读取失败 + */ + errorCallback?: () => void; +} + +/** + * dom信息,没有全部标注,只标注了一部分特例 + */ +type MainDom = { + /** + * 所有的状态信息 + */ + status: HTMLCollectionOf; + + /** + * 所有的工具栏图片 + */ + tools: HTMLCollectionOf; + + /** + * 所有的游戏画布 + */ + gameCanvas: HTMLCollectionOf; + + /** + * 所有的状态显示信息,有的是

有的是就挺离谱 + */ + statusLabels: HTMLCollectionOf; + + /** + *

标签的状态显示文字 + */ + statusText: HTMLCollectionOf; + + /** + * 自绘状态栏画布的context + */ + statusCanvasCtx: CanvasRenderingContext2D; + + [key: string]: HTMLElement; +}; + +interface DomStyle { + /** + * 当前缩放大小 + */ + scale: number; + + /** + * 就是window.devicePixelRatio + */ + ratio: number; + + /** + * 高清画布列表 + */ + hdCanvas: string[]; + + /** + * 可以缩放到的缩放比例,是 [1, 1.25, 1.5, 1.75, 2, 2.25, 2.5] 的子数组 + */ + availableScale: number[]; + + /** + * 是否是竖屏 + */ + isVertical: boolean; + + /** + * 是否显示状态栏 + */ + showStatusBar: boolean; + + /** + * 当前道具栏是否是数字键 + */ + toolbarBtn: boolean; +} + +interface CoreBigmap { + /** + * 大地图中会跟随勇士移动的画布 + */ + canvas: string[]; + + /** + * 大地图的横向偏移量,单位像素 + */ + offsetX: number; + + /** + * 大地图的纵向偏移量,单位像素 + */ + offsetY: number; + + /** + * v2优化下的横向偏移格子数 + */ + posX: number; + + /** + * v2优化下的纵向偏移格子数 + */ + posY: number; + + /** + * 地图宽度,单位格子 + */ + width: number; + + /** + * 地图高度,单位格子 + */ + height: number; + + /** + * 是否使用v2优化 + */ + v2: boolean; + + /** + * 判定为超大的图的地图面积临界,使用了显示宝石血瓶详细信息插件的话是256 + */ + threshold: 1024; + + /** + * v2优化下,显示超出的格子数,例如样板是10,那么13*13的样板就是33*33,还用于判断是否进行更新等 + */ + extend: 10; + + /** + * @deprecated + * 又出现了!样板中没有的东西 + */ + scale: 1; + + /** + * 绘制缩略图时的临时画布 + */ + tempCanvas: CanvasRenderingContext2D; + + /** + * 绘制地图时的双缓冲层 + */ + cacheCanvas: CanvasRenderingContext2D; +} + +interface CoreSave { + /** + * 当前存档页面显示的页码数 + */ + saveIndex: number; + + /** + * 当前存在存档的存档位 + */ + ids: Record; + + /** + * 自动存档信息 + */ + autosave: Readonly; + + /** + * 收藏的存档 + */ + favorite: number[]; + + /** + * 保存的存档名称 + */ + favoriteName: Record; +} + +interface Autosave { + /** + * 当前自动存档位 + */ + now: number; + + /** + * 当前存档信息 + */ + data?: Save[]; + + /** + * 自动存档位的最大值 + */ + max: 20; + + /** + * 是否将自动存档写入本地文件 + */ + storage: true; + + /** + * @deprecated + * 每5秒钟会被设置一次的raf时间戳,不知道干什么的。。。 + */ + time: number; + + /** + * @deprecated + * 样板在不停设置这个东西,但不知道什么用处,因为没有调用它的地方 + */ + updated: boolean; + + /** + * 不太清楚干什么的,看起来好像与存档无关,是与本地存储有关的 + */ + cache: Record; +} + +interface CoreValues { + /** + * 血网伤害 + */ + lavaDamage: number; + + /** + * 中毒伤害 + */ + poisonDamage: number; + + /** + * 衰弱状态下攻防减少的数值。如果此项不小于1,则作为实际下降的数值(比如10就是攻防各下降10 + * 如果在0到1之间则为下降的比例(比如0.3就是下降30%的攻防) + */ + weakValue: number; + + /** + * 红宝石加攻数值 + */ + redGem: number; + + /** + * 蓝宝石加防数值 + */ + blueGem: number; + + /** + * 绿宝石加魔防数值 + */ + greenGem: number; + + /** + * 红血瓶加血数值 + */ + redPotion: number; + + /** + * 蓝血瓶加血数值 + */ + bluePotion: number; + + /** + * 黄血瓶加血数值 + */ + yellowPotion: number; + + /** + * 绿血瓶加血数值 + */ + greenPotion: number; + + /** + * 默认的破甲比例 + */ + breakArmor: number; + + /** + * 默认的反击比例 + */ + counterAttack: number; + + /** + * 默认的净化比例 + */ + purify: number; + + /** + * 仇恨属性中,每杀一个怪增加的仇恨值 + */ + hatred: number; + + /** + * 全局动画速度 + */ + animateSpeed: number; + + /** + * 勇士移动速度 + */ + moveSpeed: number; + + /** + * 竖屏下状态栏显示行数 + */ + statusCanvasRowsOnMobile: 1 | 2 | 3 | 4 | 5; + + /** + * 楼层切换时间 + */ + floorChangeTime: number; +} + +type CoreStatusBarElements = { + /** + * 状态栏图标信息 + */ + readonly icons: Record; + + /** + * 状态栏的图标元素 + */ + readonly image: Record; + + readonly [key: string]: HTMLElement; +}; + +type Materails = [ + 'animates', + 'enemys', + 'items', + 'npcs', + 'terrains', + 'enemy48', + 'npc48', + 'icons' +]; + +type CoreFlagProperties = + | 'autoScale' + | 'betweenAttackMax' + | 'blurFg' + | 'canGoDeadZone' + | 'disableShopOnDamage' + | 'displayCritical' + | 'displayEnemyDamage' + | 'displayExtraDamage' + | 'enableAddPoint' + | 'enableEnemyPoint' + | 'enableGentleClick' + | 'enableHDCanvas' + | 'enableMoveDirectly' + | 'enableNegativeDamage' + | 'enableRouteFolding' + | 'equipboxButton' + | 'extendToolbar' + | 'flyNearStair' + | 'flyRecordPosition' + | 'ignoreChangeFloor' + | 'itemFirstText' + | 'leftHandPrefer' + | 'startUsingCanvas' + | 'statusCanvas'; + +type CoreFlags = { + [P in CoreFlagProperties]: boolean; +} & { + /** + * 地图伤害的显示模式 + */ + extraDamageType: number; + + /** + * 当前的状态栏显示项 + */ + statusBarItems: string[]; +}; + +type CoreDataFromMain = + | 'dom' + | 'statusBar' + | 'canvas' + | 'images' + | 'tilesets' + | 'materials' + | 'animates' + | 'bgms' + | 'sounds' + | 'floorIds' + | 'floors' + | 'floorPartitions'; + +/** + * 样板的core的类型,不得不感叹样板的结构真的很神奇(简称粪),两个看似毫无关联的东西都会有着千丝万缕的联系 + */ +interface Core extends Pick { + /** + * 地图的格子宽度 + */ + readonly _WIDTH_: number; + + /** + * 地图的格子高度 + */ + readonly _HEIGHT_: number; + + /** + * 地图的像素宽度 + */ + readonly _PX_: number; + + /** + * 地图的像素高度 + */ + readonly _PY_: number; + + /** + * 地图宽度的一半 + */ + readonly _HALF_WIDTH_: number; + + /** + * 地图高度的一半 + */ + readonly _HALF_HEIGHT_: number; + + /** + * @deprecated + * 地图可视部分大小 + */ + readonly __SIZE__: number; + + /** + * @deprecated + * 地图像素 + */ + readonly __PIXELS__: number; + + /** + * @deprecated + * 地图像素的一半 + */ + readonly __HALF_SIZE__: number; + + /** + * 游戏素材 + */ + readonly material: Material; + + /** + * 计时器(样板的神秘操作 + */ + readonly timeout: Timeout; + + /** + * 定时器 + */ + readonly interval: Interval; + + /** + * 全局动画信息 + */ + readonly animateFrame: AnimateFrame; + + /** + * 音乐状态 + */ + readonly musicStatus: Readonly; + + /** + * 当前游戏平台 + */ + readonly platform: Readonly; + + /** + * dom样式 + */ + readonly domStyle: Readonly; + + /** + * 大地图信息 + */ + readonly bigmap: Readonly; + + /** + * 存档信息 + */ + readonly saves: Readonly; + + /** + * 全局数值信息 + */ + readonly values: CoreValues; + + /** + * 游戏的初始状态 + */ + readonly initStatus: DeepReadonly; + + /** + * 所有的自定义画布 + */ + readonly dymCanvas: Record; + + /** + * 游戏状态 + */ + readonly status: GameStatus; + + /** + * 设置信息 + */ + readonly flags: CoreFlags; + + /** + * 获得所有楼层的信息 + * @example core.floors[core.status.floorId].events // 获得本楼层的所有自定义事件 + */ + readonly floors: DeepReadonly<{ + [P in FloorIds]: ResolvedFloor

; + }>; + + /** + * 游戏主要逻辑模块 + */ + readonly control: Control; + + /** + * 游戏的全塔属性信息 + */ + readonly data: Omit; + + /** + * 游戏加载模块 + */ + readonly loader: Loader; + + /** + * 游戏的事件模块 + */ + readonly events: Events; + + /** + * 游戏的怪物模块 + */ + readonly enemys: Enemys; + + /** + * 游戏的物品模块 + */ + readonly items: Items; + + /** + * 游戏的地图模块 + */ + readonly maps: Maps; + + /** + * 游戏的ui模块 + */ + readonly ui: Ui; + + /** + * 游戏的工具模块 + */ + readonly utils: Utils; + + /** + * 游戏的图标模块 + */ + readonly icons: Icons; + + /** + * 游戏的交互模块 + */ + readonly actions: Actions; + + /** + * 游戏的插件模块 + */ + readonly plugin: PluginDeclaration; + + /** + * 进行游戏初始化 + * @param coreData 初始化信息 + * @param callback 初始化完成后的回调函数 + */ + init(coreData: MainData, callback?: () => void): void; + + /** + * @deprecated + * 在一个上下文下执行函数(真的有人会用这个东西吗? + * @param func 要执行的函数 + * @param _this 执行函数的上下文 + * @param params 函数的参数 + */ + doFunc( + func: F, + _this: any, + ...params: Parameters + ): ReturnType; +} + +type CoreMixin = Core & + Forward & + Forward & + Forward & + Forward & + Forward & + Forward & + Forward & + Forward & + Forward & + Forward & + Forward; + +interface MainStyle extends Readonly { + /** + * 初始界面的背景图 + */ + readonly startBackground: string; + + /** + * 竖屏下初始界面的背景图 + */ + readonly startVerticalBackground: string; + + /** + * 初始界面的文字样式 + */ + readonly startLogoStyle: string; + + /** + * 初始界面的选项样式 + */ + readonly startButtonsStyle: string; +} + +interface SplitImageData { + /** + * 要切分的图片id + */ + readonly name: ImageIds; + + /** + * 每个小图的宽度 + */ + readonly width: number; + + /** + * 每个小图的高度 + */ + readonly height: number; + + /** + * 切分成的小图的前缀名 + */ + readonly prefix: string; +} + +interface Main extends MainData { + /** + * 是否在录像验证中 + */ + readonly replayChecking: boolean; + + /** + * @deprecated + * 就是core,应该没人会用main.core吧( + */ + readonly core: CoreMixin; + + /** + * 游戏的dom信息 + */ + readonly dom: Readonly; + + /** + * 游戏版本,发布后会被随机为数字,请勿使用该属性 + */ + readonly version: string; + + /** + * 是否使用压缩文件 + */ + readonly useCompress: boolean; + + /** + * 存档页数 + */ + readonly savePages: number; + + /** + * 循环临界的分界 + */ + readonly criticalUseLoop: number; + + /** + * 当前游戏模式,是编辑器还是游玩界面 + */ + readonly mode: 'play' | 'editor'; + + /** + * 是否使用远程bgm + */ + readonly bgmRemote: boolean; + + /** + * 远程bgm目录 + */ + readonly bgmRemoteRoot: string; + + /** + * 所有的系统画布 + */ + readonly canvas: Record; + + /** + * 获得所有楼层的信息,等同于core.floors,但两者不是引用关系 + */ + readonly floors: DeepReadonly<{ + [P in FloorIds]: ResolvedFloor

; + }>; + + /** + * 所有的素材图片名称 + */ + readonly materials: Materials; + + /** + * 要加载的project目录下的文件 + */ + readonly pureData: string[]; + + /** + * 要加载的libs目录下的文件 + */ + readonly loadList: string[]; + + /** + * 开始界面中当前选中的按钮 + */ + readonly selectedButton: number; + + /** + * 当前启动服务是否支持高层塔优化 + */ + readonly supportBunch: boolean; + + /** + * 状态栏的图标信息 + */ + readonly statusBar: CoreStatusBarElements; + + /** + * 游戏版本 + */ + readonly __VERSION__: string; + + /** + * 游戏版本代码 + */ + readonly __VERSION_CODE__: number; + + /** + * 初始化游戏 + * @param mode 初始化游戏的模式,游玩还是编辑器 + * @param callback 初始化完成后的回调函数 + */ + init(mode: 'play' | 'editor', callback: () => void): void; + + /** + * 动态加载js文件 + * @param dir 加载的js文件的目录 + * @param loadList 加载的js文件的文件名数组,不带后缀 + * @param callback 加载完毕后的回调函数 + */ + loadJs(dir: string, loadList: string[], callback: () => void): void; + + /** + * 动态加载一个js文件 + * @param dir 加载的js文件的目录 + * @param modName 加载的js文件的名称,不带后缀名,如果是使用压缩文件会自动加上.min + * @param callback 加载完毕后的回调函数,传入的参数是modName + */ + loadMod( + dir: string, + modName: string, + callback: (name: string) => void + ): void; + + /** + * 动态加载所有楼层 + * @param callback 加载完成后的回调函数 + */ + loadFloors(callback: () => void): void; + + /** + * 动态加载一个楼层 + * @param floorId 加载的楼层id + * @param callback 加载完成后的回调函数,传入的参数是加载的楼层id + */ + loadFloor( + floorId: F, + callback: (floorId: F) => void + ): void; + + /** + * 设置加载界面的加载提示文字 + */ + setMainTipsText(text: string): void; + + /** + * @deprecated + * 输出内容(极不好用,建议换成console,我甚至不知道样板为什么会有这个东西) + * @param e 输出内容 + * @param error 输出内容是否是报错 + */ + log(e: string | Error, error?: boolean): void; + + /** + * 生成选择光标的keyframes + */ + createOnChoiceAnimation(): void; + + /** + * 选中开始界面的一个按钮 + * @param index 要选中的按钮 + */ + selectButton(index: number): void; + + /** + * 加载一系列字体 + * @param fonts 要加载的字体列表 + */ + importFonts(fonts: FontIds[]): void; + + /** + * 执行样板的所有监听 + */ + listen(): void; +} + +interface Flags { + /** + * 当前的难度代码 + */ + readonly hard: number; + + /** + * 本次游戏的种子 + */ + readonly __seed__: number; + + /** + * 当前的随机数 + */ + readonly __rand__: number; + + /** + * 难度的颜色,css字符串 + */ + readonly __hardColor__: Color; + + /** + * 平面楼传下,每个楼层的离开位置 + */ + readonly __leaveLoc__: Record; + + /** + * 剧情文本属性 + */ + readonly textAttribute: TextAttribute; + + /** + * 楼层是否到达过 + */ + readonly __visited__: Record; + + [key: string]: any; +} + +interface MapDataOf { + /** + * 图块的id + */ + id: NumberToId[T]; + + /** + * 图块的类型 + */ + cls: ClsOf; +} + +/** + * 样板的主对象 + */ +declare const main: Main; + +/** + * 样板的核心对象 + */ +declare const core: CoreMixin; + +/** + * 所有的变量 + */ +declare let flags: Flags; + +/** + * 勇士信息 + */ +declare let hero: HeroStatus; + +// 让你总是拼错!(不过现在有ts了应该拼不错了 +declare const ture: true; +declare const flase: false; +declare const on: true; +declare const off: false; + +/** + * 全塔属性 + */ +declare const data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d: DataCore; + +/** + * 所有的怪物信息 + */ +declare const enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80: { + [P in EnemyIds]: Enemy

; +}; + +/** + * 所有的公共事件 + */ +declare const events_c12a15a8_c380_4b28_8144_256cba95f760: { + commonEvent: Record; +}; + +/** + * 脚本编辑 + */ +declare const functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a: FunctionsData; + +/** + * 所有的图标信息 + */ +declare const icons_4665ee12_3a1f_44a4_bea3_0fccba634dc1: MaterialIcon; + +/** + * 所有的道具信息 + */ +declare const items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a: { + [P in AllIdsOf<'items'>]: Item

; +}; + +/** + * 所有的图块信息 + */ +declare const maps_90f36752_8815_4be8_b32b_d7fad1d0542e: { + [P in keyof NumberToId]: MapDataOf

; +}; + +/** + * 插件信息 + */ +declare const plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1: PluginDeclaration; diff --git a/project/types/data.d.ts b/project/types/data.d.ts new file mode 100644 index 0000000..157fead --- /dev/null +++ b/project/types/data.d.ts @@ -0,0 +1,140 @@ +interface MainData { + /** + * 所有的楼层id + */ + readonly floorIds: FloorIds[]; + + /** + * 分区指定 + */ + readonly floorPatitions: [FloorIds, FloorIds?][]; + + /** + * 所有的额外素材 + */ + readonly tilesets: string[]; + + /** + * 所有的动画 + */ + readonly animates: AnimationIds[]; + + /** + * 所有的bgm + */ + readonly bgms: BgmIds[]; + + /** + * 所有的音效 + */ + readonly sounds: SoundIds[]; + + /** + * 所有的字体 + */ + readonly fonts: FontIds[]; + + /** + * 文件别名 + */ + readonly nameMap: NameMap; + + /** + * 难度选择 + */ + readonly levelChoose: LevelChooseEvent[]; + + /** + * 装备孔的名称 + */ + readonly equipName: string[]; + + /** + * 初始界面的bgm + */ + readonly startBgm: BgmIds; + + /** + * 主样式 + */ + readonly styles: MainStyle; + + /** + * 图片切分信息 + */ + readonly splitImages: SplitImageData; +} + +interface FirstData { + /** + * 游戏标题 + */ + title: string; + + /** + * 游戏英文名,应当与mota.config.ts中的一致 + */ + name: string; + + /** + * 游戏版本 + */ + version: string; + + /** + * 初始地图 + */ + floorId: FloorIds; + + /** + * 勇士的初始信息 + */ + hero: HeroStatus; + + /** + * 标题界面事件化 + */ + startCanvas: MotaEvent; + + /** + * 初始剧情 + */ + startText: MotaEvent; + + /** + * 全局商店信息 + */ + shops: ShopEventOf[]; + + /** + * 升级事件 + */ + levelUp: LevelUpEvent; +} + +/** + * 全塔属性信息 + */ +interface DataCore { + /** + * 全塔属性的main信息 + */ + readonly main: MainData; + + /** + * 初始化信息 + */ + readonly firstData: FirstData; + + /** + * 全局数值 + */ + readonly values: CoreValues; + + /** + * 全局变量 + */ + readonly flags: CoreFlags; +} + +declare const data: new () => Omit; diff --git a/project/types/enemy.d.ts b/project/types/enemy.d.ts new file mode 100644 index 0000000..543a099 --- /dev/null +++ b/project/types/enemy.d.ts @@ -0,0 +1,382 @@ +type PartialNumbericEnemyProperty = + | 'value' + | 'zone' + | 'repulse' + | 'laser' + | 'breakArmor' + | 'counterAttack' + | 'vampire' + | 'hpBuff' + | 'atkBuff' + | 'defBuff' + | 'range' + | 'haloRange' + | 'n' + | 'purify' + | 'atkValue' + | 'defValue' + | 'damage'; + +type BooleanEnemyProperty = + | 'zoneSquare' + | 'haloSquare' + | 'notBomb' + | 'add' + | 'haloAdd'; + +type Enemy = { + /** + * 怪物id + */ + id: I; + + /** + * 怪物名称 + */ + name: string; + + /** + * 在怪物手册中映射到的怪物ID。如果此项不为null,则在怪物手册中,将用目标ID来替换该怪物原本的ID。 + * 常被运用在同一个怪物的多朝向上 + */ + displayIdInBook: EnemyIds; + + /** + * 战前事件 + */ + beforeBattle: MotaEvent; + + /** + * 战后事件 + */ + afterBattle: MotaEvent; +} & { + [P in PartialNumbericEnemyProperty]?: number; +} & { + [P in BooleanEnemyProperty]: boolean; +} & EnemyInfoBase; + +/** + * 怪物的特殊属性定义 + */ +type EnemySpecialDeclaration = [ + id: number, + name: string | ((enemy: Enemy) => string), + desc: string | ((enemy: Enemy) => string), + color: Color, + extra?: number +]; + +interface DamageString { + /** + * 伤害字符串 + */ + damage: string; + + /** + * 伤害颜色 + */ + color: Color; +} + +interface EnemyInfoBase { + /** + * 生命值 + */ + hp: number; + + /** + * 攻击力 + */ + atk: number; + + /** + * 防御力 + */ + def: number; + + /** + * 金币 + */ + money: number; + + /** + * 经验 + */ + exp: number; + + /** + * 加点量 + */ + point: number; + + /** + * 特殊属性列表 + */ + special: number[]; +} + +interface EnemyInfo extends EnemyInfoBase { + /** + * 支援信息 + */ + guards: [x: number, y: number, id: EnemyIds]; +} + +interface DamageInfo { + /** + * 怪物生命值 + */ + mon_hp: number; + + /** + * 怪物攻击力 + */ + mon_atk: number; + + /** + * 怪物防御力 + */ + mon_def: number; + + /** + * 先攻伤害 + */ + init_damage: number; + + /** + * 怪物的每回合伤害 + */ + per_damage: number; + + /** + * 勇士的每回合伤害 + */ + hero_per_damage: number; + + /** + * 战斗的回合数 + */ + turn: number; + + /** + * 勇士损失的生命值 + */ + damage: number; +} + +interface BookEnemyInfo extends Enemy, EnemyInfo { + /** + * 怪物的坐标列表 + */ + locs?: [x: number, y: number][]; + + /** + * 怪物的中文名 + */ + name: string; + + /** + * 特殊属性名称列表 + */ + specialText: string[]; + + /** + * 特殊属性的颜色列表 + */ + specialColor: Color[]; + + /** + * 怪物的伤害 + */ + damage: number; + + /** + * 第一个临界的加攻的值 + */ + critical: number; + + /** + * 临界的减伤值 + */ + criticalDamage: number; + + /** + * ratio防减伤 + */ + defDamage: number; +} + +/** + * 怪物模块 + */ +interface Enemys extends EnemyData { + /** + * 所有的怪物信息 + */ + readonly enemys: { + [P in EnemyIds]: Enemy

; + }; + + /** + * 脚本编辑的怪物相关 + */ + readonly enemydata: EnemyData; + + /** + * 获得所有怪物原始数据的一个副本 + */ + getEnemys(): { + [P in EnemyIds]: Enemy

; + }; + + /** + * 获得某种敌人的全部特殊属性名称 + * @example core.getSpecialText('greenSlime') // ['先攻', '3连击', '破甲', '反击'] + * @param enemy 敌人id或敌人对象,如core.material.enemys.greenSlime + * @returns 字符串数组 + */ + getSpecialText(enemy: EnemyIds | Enemy): string[]; + + /** + * 获得所有特殊属性的颜色 + * @param enemy 敌人id或敌人对象,如core.material.enemys.greenSlime + */ + getSpecialColor(enemy: EnemyIds | Enemy): Color[]; + + /** + * 获得所有特殊属性的额外标记 + * @param enemy 敌人id或敌人对象,如core.material.enemys.greenSlime + */ + getSpecialFlag(enemy: EnemyIds | Enemy): number[]; + + /** + * 获得某种敌人的某种特殊属性的介绍 + * @example core.getSpecialHint('bat', 1) // '先攻:怪物首先攻击' + * @param enemy 敌人id或敌人对象,用于确定属性的具体数值 + * @param special 属性编号,可以是该敌人没有的属性 + * @returns 属性的介绍,以属性名加中文冒号开头 + */ + getSpecialHint(enemy: EnemyIds | Enemy, special: number): string; + + /** + * 获得某个敌人的某项属性值 + * @param enemy 敌人id或敌人对象 + * @param name 获取的敌人属性 + * @param x 敌人的横坐标 + * @param y 敌人的纵坐标 + * @param floorId 敌人所在楼层 + */ + getEnemyValue( + enemy: EnemyIds | Enemy, + name: K, + x?: number, + y?: number, + floorId?: FloorIds + ): Enemy[K]; + + /** + * 判定主角当前能否打败某只敌人 + * @example core.canBattle('greenSlime',0,0,'MT0') // 能否打败主塔0层左上角的绿头怪(假设有) + * @param enemy 敌人id或敌人对象 + * @param x 敌人的横坐标 + * @param y 敌人的纵坐标 + * @param floorId 敌人所在的地图 + * @returns true表示可以打败,false表示无法打败 + */ + canBattle( + enemy: EnemyIds | Enemy, + x?: number, + y?: number, + floorId?: FloorIds + ): boolean; + + /** + * 获得某只敌人的地图显伤,包括颜色 + * @example core.getDamageString('greenSlime', 0, 0, 'MT0') // 绿头怪的地图显伤 + * @param enemy 敌人id或敌人对象 + * @param x 敌人的横坐标 + * @param y 敌人的纵坐标 + * @param floorId 敌人所在的地图 + */ + getDamageString( + enemy: EnemyIds | Enemy, + x?: number, + y?: number, + floorId?: FloorIds + ): DamageString; + + /** + * 获得某只敌人接下来的若干个临界及其减伤,算法基于useLoop开关选择回合法或二分法 + * @example core.nextCriticals('greenSlime', 9, 0, 0, 'MT0') // 绿头怪接下来的9个临界 + * @param enemy 敌人id或敌人对象 + * @param number 要计算的临界数量,默认为1 + * @param x 敌人的横坐标 + * @param y 敌人的纵坐标 + * @param floorId 敌人所在的地图 + * @returns 两列的二维数组,每行表示一个临界及其减伤 + */ + nextCriticals( + enemy: EnemyIds | Enemy, + number?: number, + x?: number, + y?: number, + floorId?: FloorIds + ): [critical: number, damage: number][]; + + /** + * 计算再加若干点防御能使某只敌人对主角的总伤害降低多少 + * @example core.nextCriticals('greenSlime', 10, 0, 0, 'MT0') // 再加10点防御能使绿头怪的伤害降低多少 + * @param enemy 敌人id或敌人对象 + * @param k 假设主角增加的防御力,默认为1 + * @param x 敌人的横坐标 + * @param y 敌人的纵坐标 + * @param floorId 敌人所在的地图 + * @returns 总伤害的减少量 + */ + getDefDamage( + enemy: EnemyIds | Enemy, + k?: number, + x?: number, + y?: number, + floorId?: FloorIds + ): number; + + /** + * 获得某只敌人对主角的总伤害 + * @example core.getDamage('greenSlime',0,0,'MT0') // 绿头怪的总伤害 + * @param enemy 敌人id或敌人对象 + * @param x 敌人的横坐标 + * @param y 敌人的纵坐标 + * @param floorId 敌人所在的地图 + * @returns 总伤害,如果因为没有破防或无敌怪等其他原因无法战斗,则返回null + */ + getDamage( + enemy: EnemyIds | Enemy, + x?: number, + y?: number, + floorId?: FloorIds + ): number; + + /** + * 获得某张地图的敌人集合,用于手册绘制 + * @example core.getCurrentEnemys('MT0') // 主塔0层的敌人集合 + * @param floorId 地图id + * @returns 敌人集合,按伤害升序排列,支持多朝向怪合并 + */ + getCurrentEnemys(floorId?: FloorIds): Enemy[]; + + /** + * 检查某些楼层是否还有漏打的(某种)敌人 + * @example core.hasEnemyLeft('greenSlime', ['sample0', 'sample1']) // 样板0层和1层是否有漏打的绿头怪 + * @param enemyId 敌人id,可选,默认为任意敌人 + * @param floorId 地图id或其数组,可选,默认为当前地图 + * @returns true表示有敌人被漏打,false表示敌人已死光 + */ + hasEnemyLeft( + enemyId?: EnemyIds | EnemyIds[], + floorId?: FloorIds | FloorIds[] + ): boolean; +} + +declare const enemys: new () => Enemys; diff --git a/project/types/event.d.ts b/project/types/event.d.ts new file mode 100644 index 0000000..9b6b21d --- /dev/null +++ b/project/types/event.d.ts @@ -0,0 +1,763 @@ +/** + * 注册的系统事件函数 + */ +type SystemEventFunc = (data: any, callback: (...params: any[]) => any) => void; + +/** + * 注册的事件函数 + */ +type EventFunc = (data: any, x?: number, y?: number, prefix?: string) => void; + +/** + * 处理所有和事件相关的操作 + */ +interface Events extends EventData { + /** + * 脚本编辑中的事件相关内容 + */ + eventdata: EventData; + + /** + * 公共事件信息 + */ + commonEvent: Record; + + /** + * 所有的系统事件 + */ + systemEvent: Record; + + /** + * 注册的自定义事件 + */ + actions: Record; + + /** + * 开始新游戏 + * @example core.startGame('咸鱼乱撞', 0, ''); // 开始一局咸鱼乱撞难度的新游戏,随机种子为0 + * @param hard 难度名,会显示在左下角(横屏)或右下角(竖屏) + * @param seed 随机种子,相同的种子保证了录像的可重复性 + * @param route 经由base64压缩后的录像,用于从头开始的录像回放 + * @param callback 回调函数 + */ + startGame( + hard: string, + seed: number, + route?: string, + callback?: () => void + ): void; + + /** + * 游戏结束 + * @example core.gameOver(); // 游戏失败 + * @param ending 结局名,省略表示失败 + * @param fromReplay true表示在播放录像 + * @param norank true表示不计入榜单 + */ + gameOver(ending?: string, fromReplay?: boolean, norank?: boolean): void; + + /** + * 重新开始游戏;此函数将回到标题页面 + */ + restart(): void; + + /** + * 询问是否需要重新开始 + */ + confirmRestart(): void; + + /** + * 注册一个系统事件 + * @param type 事件名 + * @param func 为事件的处理函数,可接受(data,callback)参数 + */ + registerSystemEvent(type: string, func: SystemEventFunc): void; + + /** + * 注销一个系统事件 + * @param type 事件名 + */ + unregisterSystemEvent(type: string): void; + + /** + * 执行一个系统事件 + * @param type 执行的事件名 + * @param data 数据信息 + * @param callback 传入事件处理函数的回调函数 + */ + doSystemEvent( + type: string, + data: any, + callback?: (...params: any[]) => any + ): void; + + /** + * 触发(x,y)点的系统事件;会执行该点图块的script属性,同时支持战斗(会触发战后)、道具(会触发道具后)、楼层切换等等 + * @param x 横坐标 + * @param y 纵坐标 + * @param callback 回调函数 + */ + trigger(x: number, y: number, callback?: () => void): void; + + /** + * 战斗,如果填写了坐标就会删除该点的敌人并触发战后事件 + * @example core.battle('greenSlime'); // 和从天而降的绿头怪战斗(如果打得过) + * @param id 敌人id,必填 + * @param x 敌人的横坐标 + * @param y 敌人的纵坐标 + * @param force true表示强制战斗 + * @param callback 回调函数 + */ + battle( + id: AllIdsOf<'enemys' | 'enemy48'>, + x?: number, + y?: number, + force?: boolean, + callback?: () => void + ): void; + + /** + * 开门(包括三种基础墙) + * @example core.openDoor(0, 0, true, core.jumpHero); // 打开左上角的门,需要钥匙,然后主角原地跳跃半秒 + * @param x 门的横坐标 + * @param y 门的纵坐标 + * @param needKey true表示需要钥匙,会导致机关门打不开 + * @param callback 门完全打开后或打不开时的回调函数 + */ + openDoor( + x: number, + y: number, + needKey?: boolean, + callback?: () => void + ): void; + + /** + * 获得道具并提示,如果填写了坐标就会删除该点的该道具 + * @example core.getItem('book'); // 获得敌人手册并提示 + * @param id 道具id,必填 + * @param num 获得的数量,不填视为1,填了就别填坐标了 + * @param x 道具的横坐标 + * @param y 道具的纵坐标 + * @param callback 回调函数 + */ + getItem( + id: AllIdsOf<'items'>, + num?: number, + x?: number, + y?: number, + callback?: () => void + ): void; + + /** + * 轻按获得面前的物品或周围唯一物品 + * @param noRoute 若为true则不计入录像 + */ + getNextItem(noRoute?: boolean): void; + + /** + * 场景切换 + * @example core.changeFloor('MT0'); // 传送到主塔0层,主角坐标和朝向不变,黑屏时间取用户设置值 + * @param floorId 传送的目标地图id,可以填':before'和':after'分别表示楼下或楼上 + * @param stair 传送的位置,可以填':now'(保持不变,可省略),':symmetry'(中心对称),':symmetry_x'(左右对称),':symmetry_y'(上下对称)或图块id(该图块最好在目标层唯一,一般为'downFloor'或'upFloor') + * @param heroLoc 传送的坐标(如果填写了,就会覆盖上述的粗略目标位置)和传送后主角的朝向(不填表示保持不变) + * @param time 传送的黑屏时间,单位为毫秒。不填为用户设置值 + * @param callback 黑屏结束后的回调函数 + */ + changeFloor( + floorId: FloorIds, + stair?: FloorChangeStair | AllIds, + heroLoc?: Partial, + time?: number, + callback?: () => void + ): void; + + /** + * 是否到达过某个楼层 + * @param floorId 楼层id + */ + hasVisitedFloor(floorId?: FloorIds): boolean; + + /** + * 到达某楼层 + * @param floorId 楼层id + */ + visitFloor(floorId?: FloorIds): void; + + /** + * 推箱子 + * @param data 图块信息 + */ + pushBox(data?: Block): void; + + /** + * 当前是否在冰上 + */ + onSki(number?: number): boolean; + + /** + * 注册一个自定义事件 + * @param type 事件类型 + * @param func 事件的处理函数,可接受(data, x, y, prefix)参数 + * data为事件内容,x和y为当前点坐标(可为null),prefix为当前点前缀 + */ + registerEvent(type: string, func: EventFunc): void; + + /** + * 注销一个自定义事件 + * @param type 事件类型 + */ + unregisterEvent(type: string): void; + + /** + * 执行一个自定义事件 + * @param data 事件信息 + * @param x 事件横坐标 + * @param y 事件纵坐标 + * @param prefix 当前点前缀 + */ + doEvent(data: any, x?: number, y?: number, prefix?: string): void; + + /** + * 直接设置事件列表 + * @param list 事件信息 + * @param x 横坐标 + * @param y 纵坐标 + * @param callback 事件执行完毕后的回调函数 + */ + setEvents( + list: MotaEvent, + x?: number, + y?: number, + callback?: () => void + ): void; + + /** + * 开始执行一系列自定义事件 + * @param list 事件信息 + * @param x 横坐标 + * @param y 纵坐标 + * @param callback 事件执行完毕后的回调函数 + */ + startEvents( + list?: MotaEvent, + x?: number, + y?: number, + callback?: () => void + ): void; + + /** + * 执行下一个事件指令,常作为回调 + * @example + * // 事件中的原生脚本,配合勾选“不自动执行下一个事件”来达到此改变色调只持续到下次场景切换的效果 + * core.setCurtain([0,0,0,1], undefined, null, core.doAction); + */ + doAction(): void; + + /** + * 插入一段事件;此项不可插入公共事件,请用 core.insertCommonEvent + * @example core.insertAction('一段文字'); // 插入一个显示文章 + * @param action 单个事件指令,或事件指令数组 + * @param x 新的当前点横坐标 + * @param y 新的当前点纵坐标 + * @param callback 新的回调函数 + * @param addToLast 插入的位置,true表示插入到末尾,否则插入到开头 + */ + insertAction( + action: MotaEvent | MotaAction, + x?: number, + y?: number, + callback?: () => void, + addToLast?: boolean + ): void; + + /** + * 插入一个公共事件 + * @example core.insertCommonEvent('加点事件', [3]); + * @param name 公共事件名;如果公共事件不存在则直接忽略 + * @param args 参数列表,为一个数组,将依次赋值给 flag:arg1, flag:arg2, ... + * @param x 新的当前点横坐标 + * @param y 新的当前点纵坐标 + * @param callback 新的回调函数 + * @param addToLast 插入的位置,true表示插入到末尾,否则插入到开头 + */ + insertCommonEvent( + name: EventDeclaration, + args?: any[], + x?: number, + y?: number, + callback?: () => void, + addToLast?: boolean + ): void; + + /** + * 获得一个公共事件 + * @param name 公共事件名称 + */ + getCommonEvent(name: EventDeclaration): any; + + /** + * 恢复一个事件 + * @param data 事件信息 + */ + recoverEvents(data?: any): void; + + /** + * 检测自动事件 + */ + checkAutoEvents(): void; + + /** + * 当前是否在执行某个自动事件 + * @param symbol 自动事件的标识符 + * @param value 不太清楚有什么用 + */ + autoEventExecuting(symbol?: string, value?: any): boolean; + + /** + * 当前是否执行过某个自动事件 + * @param symbol 自动事件的标识符 + * @param value 不太清楚有什么用 + */ + autoEventExecuted(symbol?: string, value?: any): boolean; + + /** + * 将当前点坐标入栈 + */ + pushEventLoc(x: number, y: number, floorId?: FloorIds): void; + + /** + * 弹出事件坐标点 + */ + popEventLoc(): void; + + /** + * 预编辑事件 + * @param data 事件信息 + */ + precompile(data?: any): any; + + /** + * 点击怪物手册时的打开操作 + * @param fromUserAction 是否是用户开启的 + */ + openBook(fromUserAction?: boolean): void; + + /** + * 点击楼层传送器时的打开操作 + * @param fromUserAction 是否是用户开启的 + */ + useFly(fromUserAction?: boolean): void; + + /** 点击装备栏时的打开操作 */ + openEquipbox(fromUserAction?: boolean): void; + + /** + * 点击工具栏时的打开操作 + * @param fromUserAction 是否是用户开启的 + */ + openToolbox(fromUserAction?: boolean): void; + + /** + * 点击快捷商店按钮时的打开操作 + * @param fromUserAction 是否是用户开启的 + */ + openQuickShop(fromUserAction?: boolean): void; + + /** + * 点击虚拟键盘时的打开操作 + * @param fromUserAction 是否是用户开启的 + */ + openKeyBoard(fromUserAction?: boolean): void; + + /** + * 点击存档按钮时的打开操作 + * @param fromUserAction 是否是用户开启的 + */ + save(fromUserAction?: boolean): void; + + /** + * 点击读档按钮时的打开操作 + * @param fromUserAction 是否是用户开启的 + */ + load(fromUserAction?: boolean): void; + + /** + * 点击设置按钮时的操作 + * @param fromUserAction 是否是用户开启的 + */ + openSettings(fromUserAction?: boolean): void; + + /** + * 当前是否有未处理完毕的异步事件(不包含动画和音效) + */ + hasAsync(): boolean; + + /** + * 立刻停止所有异步事件 + */ + stopAsync(): void; + + /** + * 是否有异步动画 + */ + hasAsyncAnimate(): boolean; + + /** + * 跟随 + * @param name 要跟随的一个合法的4x4的行走图名称,需要在全塔属性注册 + */ + follow(name: ImageIds | NameMapIn): void; + + /** + * 取消跟随 + * @param name 取消跟随的行走图,不填则取消全部跟随者 + */ + unfollow(name?: ImageIds | NameMapIn): void; + + /** + * 数值操作 + * @param name 操作的数值的名称 + * @param operator 操作运算符 + * @param value 值 + * @param prefix 独立开关前缀 + */ + setValue( + name: `${EventValuePreffix}:${string}`, + operator: MotaOperator, + value: number, + prefix?: string + ): void; + + /** + * 设置一项敌人属性并计入存档 + * @example core.setEnemy('greenSlime', 'def', 0); // 把绿头怪的防御设为0 + * @param id 敌人id + * @param name 属性的英文缩写 + * @param value 属性的新值 + * @param operator 操作符 + * @param prefix 独立开关前缀,一般不需要 + * @param norefresh 是否不刷新状态栏 + */ + setEnemy( + id: AllIdsOf<'enemys' | 'enemy48'>, + name: K, + value: Enemy[K], + operator?: MotaOperator, + prefix?: string, + norefresh?: boolean + ): void; + + /** + * 设置某个点的敌人属性 + * @param x 横坐标 + * @param y 纵坐标 + * @param floorId 楼层id + * @param name 属性的英文缩写 + * @param value 属性的新值 + * @param operator 操作符 + * @param prefix 独立开关前缀,一般不需要 + * @param norefresh 是否不刷新状态栏 + */ + setEnemyOnPoint( + x: number, + y: number, + floorId: FloorIds, + name: K, + value: Enemy[K], + operator?: MotaOperator, + prefix?: string, + norefresh?: boolean + ): void; + + /** + * 重置某个点的敌人属性 + * @param x 横坐标 + * @param y 纵坐标 + * @param floorId 楼层id + * @param norefresh 是否不刷新状态栏 + */ + resetEnemyOnPoint( + x: number, + y: number, + floorId?: FloorIds, + norefresh?: boolean + ): void; + + /** + * 将某个点已经设置的敌人属性移动到其他点 + * @param fromX 起始横坐标 + * @param fromY 起始纵坐标 + * @param toX 目标横坐标 + * @param toY 目标纵坐标 + * @param floorId 楼层id + * @param norefresh 是否不刷新状态栏 + */ + moveEnemyOnPoint( + fromX: number, + fromY: number, + toX: number, + toY: number, + floorId?: FloorIds, + norefresh?: boolean + ): void; + + /** + * 设置一项楼层属性并刷新状态栏 + * @example core.setFloorInfo('ratio', 2, 'MT0'); // 把主塔0层的血瓶和宝石变为双倍效果 + * @param name 要求改的属性名 + * @param values 属性的新值 + * @param floorId 楼层id,不填视为当前层 + * @param prefix 独立开关前缀,一般不需要,下同 + */ + setFloorInfo( + name: K, + values?: Floor[K], + floorId?: FloorIds, + prefix?: string + ): void; + + /** + * 设置全塔属性 + * @param name 属性名 + * @param value 属性值 + */ + setGlobalAttribute( + name: K, + value: GlobalAttribute[K] + ): void; + + /** + * 设置一个系统开关 + * @example core.setGlobalFlag('steelDoorWithoutKey', true); // 使全塔的所有铁门都不再需要钥匙就能打开 + * @param name 系统开关的英文名 + * @param value 开关的新值,您可以用!core.flags[name]简单地表示将此开关反转 + */ + setGlobalFlag( + name: K, + value: CoreFlags[K] + ): void; + + /** + * 设置文件别名 + * @param name 别名 + * @param value 别名对应的文件名 + */ + setNameMap(name: string, value?: SourceIds): void; + + /** + * 设置剧情文本的属性 + */ + setTextAttribute(data: Partial): void; + + /** + * 移动对话框 + * @param code 对话框的代码 + * @param loc 目标位置 + * @param relative 是否是相对模式 + * @param moveMode 缓动模式 + * @param time 动画时间 + * @param callback 移动完毕的回调函数 + */ + moveTextBox( + code: number, + loc: LocArr, + relative?: boolean, + moveMode?: EaseMode, + time?: number, + callback?: () => void + ): void; + + /** + * 清除对话框 + * @param code 对话框的代码 + * @param callback 回调函数 + */ + clearTextBox(code: number, callback: () => void): void; + + /** + * 关门,目标点必须为空地 + * @example core.closeDoor(0, 0, 'yellowWall', core.jumpHero); // 在左上角关掉一堵黄墙,然后主角原地跳跃半秒 + * @param x 横坐标 + * @param y 纵坐标 + * @param id 门的id,也可以用三种基础墙 + * @param callback 门完全关上后的回调函数 + */ + closeDoor( + x: number, + y: number, + id: AllIdsOf>, + callback?: () => void + ): void; + + /** + * 显示一张图片 + * @example + * // 裁剪winskin.png的最左边128×128px,放大到铺满整个视野,1秒内淡入到50%透明,编号为1 + * core.showImage(1, core.material.images.images['winskin.png'], [0,0,128,128], [0,0,416,416], 0.5, 1000); + * @param code 图片编号,为不大于50的正整数,加上100后就是对应画布层的z值,较大的会遮罩较小的,注意色调层的z值为125,UI层为140 + * @param image 图片文件名(可以是全塔属性中映射前的中文名)或图片对象(见上面的例子) + * @param sloc 一行且至多四列的数组,表示从原图裁剪的左上角坐标和宽高 + * @param loc 一行且至多四列的数组,表示图片在视野中的左上角坐标和宽高 + * @param opacityVal 不透明度,为小于1的正数。不填视为1 + * @param time 淡入时间,单位为毫秒。不填视为0 + * @param callback 图片完全显示出来后的回调函数 + */ + showImage( + code: number, + image: ImageIds | NameMapIn | ImageSource, + sloc?: [number, number, number, number], + loc?: [number, number, number?, number?], + opacityVal?: number, + time?: number, + callback?: () => void + ): void; + + /** + * 隐藏一张图片 + * @example core.hideImage(1, 1000, core.jumpHero); // 1秒内淡出1号图片,然后主角原地跳跃半秒 + * @param code 图片编号 + * @param time 淡出时间,单位为毫秒 + * @param callback 图片完全消失后的回调函数 + */ + hideImage(code: number, time?: number, callback?: () => void): void; + + /** + * 移动一张图片并/或改变其透明度 + * @example core.moveImage(1, null, 0.5); // 1秒内把1号图片变为50%透明 + * @param code 图片编号 + * @param to 新的左上角坐标,省略表示原地改变透明度 + * @param opacityVal 新的透明度,省略表示不变 + * @param moveMode 移动模式 + * @param time 移动用时,单位为毫秒。不填视为1秒 + * @param callback 图片移动完毕后的回调函数 + */ + moveImage( + code: number, + to?: LocArr, + opacityVal?: number, + moveMode?: string, + time?: number, + callback?: () => void + ): void; + + /** + * 旋转一张图片 + * @param code 图片编号 + * @param center 旋转中心像素(以屏幕为基准);不填视为图片本身中心 + * @param angle 旋转角度;正数为顺时针,负数为逆时针 + * @param moveMode 旋转模式 + * @param time 移动用时,单位为毫秒。不填视为1秒 + * @param callback 图片移动完毕后的回调函数 + */ + rotateImage( + code: number, + center?: LocArr, + angle?: number, + moveMode?: EaseMode, + time?: number, + callback?: () => void + ): void; + + /** + * 放缩一张图片 + * @param code 图片编号 + * @param center 旋转中心像素(以屏幕为基准);不填视为图片本身中心 + * @param scale 放缩至的比例 + * @param moveMode 旋转模式 + * @param time 移动用时,单位为毫秒。不填视为1秒 + * @param callback 图片移动完毕后的回调函数 + */ + scaleImage( + code: number, + center?: LocArr, + scale?: number, + moveMode?: string, + time?: number, + callback?: () => void + ): void; + + /** + * 绘制一张动图或擦除所有动图 + * @example core.showGif(); // 擦除所有动图 + * @param name 动图文件名,可以是全塔属性中映射前的中文名 + * @param x 动图在视野中的左上角横坐标 + * @param y 动图在视野中的左上角纵坐标 + */ + showGif( + name?: + | Extract> + | NameMapIn>>, + x?: number, + y?: number + ): void; + + /** + * 调节bgm的音量 + * @example core.setVolume(0, 100, core.jumpHero); // 0.1秒内淡出bgm,然后主角原地跳跃半秒 + * @param value 新的音量,为0或不大于1的正数。注意系统设置中是这个值的平方根的十倍 + * @param time 渐变用时,单位为毫秒。不填或小于100毫秒都视为0 + * @param callback 渐变完成后的回调函数 + */ + setVolume(value: number, time?: number, callback?: () => void): void; + + /** + * 视野抖动 + * @example core.vibrate(); // 视野左右抖动1秒 + * @param direction 抖动方向 + * @param time 抖动时长,单位为毫秒 + * @param speed 抖动速度 + * @param power 抖动幅度 + * @param callback 抖动平息后的回调函数 + */ + vibrate( + direction?: string, + time?: number, + speed?: number, + power?: number, + callback?: () => void + ): void; + + /** + * 强制移动主角(包括后退),这个函数的作者已经看不懂这个函数了 + * @example core.eventMoveHero(['forward'], 125, core.jumpHero); // 主角强制前进一步,用时1/8秒,然后主角原地跳跃半秒 + * @param steps 步伐数组,注意后退时跟随者的行为会很难看 + * @param time 每步的用时,单位为毫秒。0或不填则取主角的移速,如果后者也不存在就取0.1秒 + * @param callback 移动完毕后的回调函数 + */ + eventMoveHero(steps: Step[], time?: number, callback?: () => void): void; + + /** + * 主角跳跃,跳跃勇士。ex和ey为目标点的坐标,可以为null表示原地跳跃。time为总跳跃时间。 + * @example core.jumpHero(); // 主角原地跳跃半秒 + * @param ex 跳跃后的横坐标 + * @param ey 跳跃后的纵坐标 + * @param time 跳跃时长,单位为毫秒。不填视为半秒 + * @param callback 跳跃完毕后的回调函数 + */ + jumpHero( + ex?: number, + ey?: number, + time?: number, + callback?: () => void + ): void; + + /** + * 更改主角行走图 + * @example core.setHeroIcon('npc48.png', true); // 把主角从阳光变成样板0层左下角的小姐姐,但不立即刷新 + * @param name 新的行走图文件名,可以是全塔属性中映射前的中文名。映射后会被存入core.status.hero.image + * @param noDraw true表示不立即刷新(刷新会导致大地图下视野重置到以主角为中心) + */ + setHeroIcon(name: string, noDraw?: boolean): void; + + /** 检查升级事件 */ + checkLvUp(): void; + + /** + * 尝试使用一个道具 + * @example core.tryUseItem('pickaxe'); // 尝试使用破墙镐 + * @param itemId 道具id,其中敌人手册、传送器和飞行器会被特殊处理 + */ + tryUseItem(itemId: ItemIdOf<'tools' | 'constants'>): void; +} + +declare const events: new () => Events; diff --git a/project/types/eventDec.d.ts b/project/types/eventDec.d.ts new file mode 100644 index 0000000..296ce3b --- /dev/null +++ b/project/types/eventDec.d.ts @@ -0,0 +1,313 @@ +type MotaAction = any; +type MotaEvent = any[]; + +/** + * 某种类型的商店 + */ +type ShopEventOf = ShopEventMap[T]; + +interface ShopEventMap { + /** + * 普通商店 + */ + common: CommonShopEvent; + + /** + * 道具商店 + */ + item: ItemShopEvent; + + /** + * 公共事件商店 + */ + event: CommonEventShopEvent; +} + +interface ShopEventBase { + /** + * 商店的id + */ + id: string; + + /** + * 商店快捷名称 + */ + textInList: string; + + /** + * 是否在未开启状态下快捷商店不显示该商店 + */ + mustEnable: boolean; + + /** + * 是否不可预览 + */ + disablePreview: boolean; +} + +/** + * 普通商店的一个商店选项 + */ +interface CommonShopChoice { + /** + * 选项文字 + */ + text: string; + + /** + * 选项需求,需要是一个表达式 + */ + need: string; + + /** + * 图标 + */ + icon: AllIds; + + /** + * 文字的颜色 + */ + color: Color; + + /** + * 该选项被选中时执行的事件 + */ + action: MotaEvent; +} + +/** + * 普通商店 + */ +interface CommonShopEvent extends ShopEventBase { + /** + * 商店中显示的文字 + */ + text: string; + + /** + * 普通商店的选项 + */ + choices: CommonShopChoice[]; +} + +/** + * 道具商店的一个选项 + */ +interface ItemShopChoice { + /** + * 该选项的道具id + */ + id: AllIdsOf<'items'>; + + /** + * 道具存量 + */ + number: number; + + /** + * 购买时消耗的资源数量,是字符串大概是因为这玩意可以用${} + */ + money: string; + + /** + * 卖出时获得的资源数量 + */ + sell: string; + + /** + * 出现条件 + */ + condition: string; +} + +/** + * 道具商店 + */ +interface ItemShopEvent extends ShopEventBase { + /** + * 道具商店标识 + */ + item: true; + + /** + * 购买消耗什么东西,金币还是经验 + */ + use: 'money' | 'exp'; + + /** + * 每个选项 + */ + choices: ItemShopChoice[]; +} + +interface CommonEventShopEvent { + /** + * 使用的公共事件 + */ + commonEvent: EventDeclaration; +} + +interface AutoEventBase { + /** + * 自动事件的触发条件 + */ + condition: string; + + /** + * 是否只在当前层检测 + */ + currentFloor: boolean; + + /** + * 优先级,优先级越高越优先执行 + */ + priority: number; + + /** + * 是否在事件流中延迟执行 + */ + delayExecute: boolean; + + /** + * 是否允许多次执行 + */ + multiExecute: boolean; + + /** + * 当条件满足时执行的事件 + */ + data: MotaEvent; +} + +interface AutoEvent extends AutoEventBase { + /** + * 当前的楼层id + */ + floorId: FloorIds; + + /** + * 自动事件的索引 + */ + index: string; + + /** + * 事件所在的横坐标 + */ + x: number; + + /** + * 事件所在的纵坐标 + */ + y: number; + + /** + * 事件的唯一标识符 + */ + symbol: string; +} + +interface LevelChooseEvent { + /** + * 难度名称 + */ + title: string; + + /** + * 难度简称 + */ + name: string; + + /** + * 难度的hard值 + */ + hard: number; + + /** + * 难度的颜色 + */ + color: RGBArray; + + /** + * 选择该难度时执行的事件 + */ + action: MotaEvent; +} + +interface LevelUpEvent { + /** + * 升级所需经验 + */ + need: number; + + /** + * 这个等级的等级名 + */ + title: string; + + /** + * 升级时执行的事件 + */ + action: MotaEvent; +} + +/** + * 门信息 + */ +interface DoorInfo { + /** + * 开门时间 + */ + time: number; + + /** + * 开门音效 + */ + openSound: SoundIds; + + /** + * 关门音效 + */ + closeSound: SoundIds; + + /** + * 需要的钥匙 + */ + keys: Partial | `${ItemIdOf<'tools'>}:o`, number>>; + + /** + * 开门后事件 + */ + afterOpenDoor?: MotaEvent; +} + +interface ChangeFloorEvent { + /** + * 到达的楼层 + */ + floorId: ':before' | ':after' | ':now' | FloorIds; + + /** + * 到达的坐标,填了的话stair就无效了 + */ + loc?: LocArr; + + /** + * 到达的坐标 + */ + stair?: FloorChangeStair; + + /** + * 勇士朝向 + */ + direction?: HeroTurnDir; + + /** + * 楼层转换时间 + */ + time?: number; + + /** + * 是否不可穿透 + */ + ignoreChangeFloor?: boolean; +} diff --git a/project/types/eventStatus.d.ts b/project/types/eventStatus.d.ts new file mode 100644 index 0000000..5a13d10 --- /dev/null +++ b/project/types/eventStatus.d.ts @@ -0,0 +1,456 @@ +interface EventStatusDataMap { + /** + * 执行事件中 + */ + action: ActionStatusData; + + /** + * 怪物手册的信息,是当前选择了哪个怪物 + */ + book: number; + + /** + * 楼层传送器中当前楼层索引 + */ + fly: number; + + /** + * 浏览地图时的信息 + */ + viewMaps: ViewMapStatusData; + + /** + * 装备栏的信息 + */ + equipbox: EquipboxStatusData; + + /** + * 道具栏的信息 + */ + toolbox: ToolboxStatusData; + + /** + * 存档界面的信息 + */ + save: SaveStatusData; + load: SaveStatusData; + replayLoad: SaveStatusData; + replayRemain: SaveStatusData; + replaySince: SaveStatusData; + + /** + * 文本框界面的信息 + */ + text: TextStatusData; + + /** + * 确认框界面的信息 + */ + confirmBox: ConfirmStatusData; + + /** + * 关于界面,帮助界面,怪物手册详细信息界面,虚拟键盘界面,系统设置界面,系统选项栏界面, + * 快捷商店界面,存档笔记界面,同步存档界面,光标界面,录像回放界面,游戏信息界面,没有东西 + */ + about: null; + help: null; + 'book-detail': null; + keyBoard: null; + switchs: null; + 'switchs-sounds': null; + 'switchs-display': null; + 'switchs-action': null; + settings: null; + selectShop: null; + notes: null; + syncSave: null; + syncSelect: null; + localSaveSelect: null; + storageRemove: null; + cursor: null; + replay: null; + gameInfo: null; +} + +interface _EventStatusSelectionMap { + /** + * 执行事件中,一般是选择框的当前选中项 + */ + action: number; + + /** + * 装备栏中当前选中了哪个装备 + */ + equipbox: number; + + /** + * 道具栏中当前选中了哪个道具 + */ + toolbox: number; + + /** + * 当前是否是删除模式 + */ + save: boolean; + load: boolean; + + /** + * 当前选择了确认(0)还是取消(1) + */ + confirmBox: 0 | 1; + + /** + * 系统设置界面,存档笔记界面,同步存档界面,录像回放界面,游戏信息界面,当前的选择项 + */ + switchs: number; + 'switchs-sounds': number; + 'switchs-display': number; + 'switchs-action': number; + settings: number; + notes: number; + syncSave: number; + syncSelect: number; + localSaveSelect: number; + storageRemove: number; + replay: number; + gameInfo: number; +} + +interface _EventStatusUiMap { + /** + * 执行事件中,一般是与选择框有关的 + */ + action: ActionStatusUi; + + /** + * 如果是从浏览地图界面呼出的怪物手册,该项是当前正在浏览的地图的索引(注意不是id) + */ + book: number; + + /** + * 确认框中显示的文字 + */ + confirmBox: string; + + /** + * 显示设置的选择信息 + */ + 'switchs-display': SwitchsStatusData; + + /** + * 系统选项栏的选择信息 + */ + settings: SwitchsStatusData; + + /** + * 快捷商店界面,存档笔记界面,同步存档界面,录像回放界面,游戏信息界面的绘制信息 + */ + selectShop: SelectShopStatusUi; + notes: SelectShopStatusUi; + syncSave: SelectShopStatusUi; + syncSelect: SelectShopStatusUi; + localSaveSelect: SelectShopStatusUi; + storageRemove: SelectShopStatusUi; + gameInfo: SelectShopStatusUi; +} + +interface _EventStatusIntervalMap { + /** + * 执行事件中,一般用于呼出某个界面时暂存当前事件信息(? + */ + action: ActionStatusData; + + /** + * 如果是从事件中呼出的,用于存储当前事件信息,当退出怪物手册时恢复事件 + */ + book: ActionStatusData; + + /** + * 如果是从事件中呼出的,用于存储当前事件信息,当退出存档节目时恢复事件 + */ + save: ActionStatusData; + load: ActionStatusData; +} + +interface _EventStatusTimeoutMap { + /** + * 执行事件中,一般是等待用户操作事件等事件中的超时时间的判定 + */ + action: number; +} + +interface _EventStatusAnimateUiMap { + /** + * 执行事件中,一般是对话框事件的动画定时器 + */ + action: number; +} + +type EventStatus = keyof EventStatusDataMap; + +type _FillEventStatus = { + [P in EventStatus]: P extends keyof T ? T[P] : null; +}; + +type EventStatusSelectionMap = _FillEventStatus<_EventStatusSelectionMap>; +type EventStatusUiMap = _FillEventStatus<_EventStatusUiMap>; +type EventStatusIntervalMap = _FillEventStatus<_EventStatusIntervalMap>; +type EventStatusTimeoutMap = _FillEventStatus<_EventStatusTimeoutMap>; +type EventStatusAnimateUiMap = _FillEventStatus<_EventStatusAnimateUiMap>; + +/** + * 某个事件状态下的信息 + */ +interface EventStatusOf { + /** + * 当前事件状态的类型 + */ + id: T; + + /** + * 当前事件状态的信息 + */ + data: EventStatusDataMap[T]; + + /** + * 当前事件状态的选择信息 + */ + selection: EventStatusSelectionMap[T]; + + /** + * 当前事件状态的ui信息 + */ + ui: EventStatusUiMap[T]; + + /** + * 当前事件状态的定时器信息 + */ + interval: EventStatusIntervalMap[T]; + + /** + * 当前事件状态的计时器信息 + */ + timeout: EventStatusTimeoutMap[T]; + + /** + * 当前事件状态的动画信息 + */ + animateUi: EventStatusAnimateUiMap[T]; +} + +interface ActionStatusEventList { + /** + * 要执行的事件列表 + */ + todo: MotaEvent; + + /** + * 全部的事件列表 + */ + total: MotaEvent; + + /** + * 执行条件 + */ + contidion: string; +} + +interface ActionLocStackInfo { + /** + * 横坐标 + */ + x: number; + + /** + * 纵坐标 + */ + y: number; + + /** + * 楼层id + */ + floorId: FloorIds; +} + +/** + * 执行事件中 + */ +interface ActionStatusData { + /** + * 当前的事件列表 + */ + list: DeepReadonly; + + /** + * 事件执行的横坐标,或者对话框的横坐标 + */ + x?: number; + + /** + * 事件执行的纵坐标,或者对话框的纵坐标 + */ + y?: number; + + /** + * 事件执行完毕的回调函数 + */ + callback?: () => void; + + /** + * 不太清楚用处,可能是与自动事件有关的 + */ + appendingEvents: MotaEvent[]; + + /** + * 事件的坐标栈 + */ + locStack: any[]; + + /** + * 当前的事件类型 + */ + type: EventType; + + /** + * 当前事件 + */ + current: MotaAction; +} + +interface ActionStatusUi { + /** + * 显示文字事件的文字,包括确认框等 + */ + text: string; + + /** + * 确认框中确定时执行的事件 + */ + yes?: MotaEvent; + + /** + * 确认框中取消时执行的事件 + */ + no?: MotaEvent; + + /** + * 当前是选择事件时所有的选项 + */ + choices?: string[]; + + /** + * 当前是选择事件时选项框的宽度 + */ + width?: number; +} + +interface ViewMapStatusData { + /** + * 当前浏览的楼层索引 + */ + index: number; + + /** + * 是否显示伤害 + */ + damage: boolean; + + /** + * 大地图是否显示全部地图 + */ + all: boolean; + + /** + * 大地图不显示全部地图时当前的横坐标,单位格子 + */ + x: number; + + /** + * 大地图不显示全部地图时当前的纵坐标,单位格子 + */ + y: number; +} + +interface EquipboxStatusData { + /** + * 拥有装备的当前页数 + */ + page: number; + + /** + * 当前选中的装备 + */ + selectId: ItemIdOf<'equips'>; +} + +interface ToolboxStatusData { + /** + * 消耗道具的当前页码数 + */ + toolsPage: number; + + /** + * 永久道具的当前页码数 + */ + constantsPage: number; + + /** + * 当前选中的道具id + */ + selectId: ItemIdOf<'constants' | 'tools'>; +} + +interface SaveStatusData { + /** + * 当前存读档界面的页码数 + */ + page: number; + + /** + * 选择的框的偏移量,在不同状态下意义不同 + */ + offset: number; + + /** + * 当前存读档界面的模式,fav表示收藏,all表示所有存档 + */ + mode: 'fav' | 'all'; +} + +interface TextStatusData { + /** + * 文本框要显示的文字列表 + */ + list: string[]; + + /** + * 文字显示完毕后的回调函数 + */ + callback: () => void; +} + +interface ConfirmStatusData { + /** + * 点击确认时 + */ + yes: () => void; + + /** + * 点击取消时 + */ + no: () => void; +} + +interface SwitchsStatusData { + /** + * 选择项 + */ + choices: string[]; +} + +interface SelectShopStatusUi { + /** + * 选择框的偏移量 + */ + offset: number; +} diff --git a/project/types/function.d.ts b/project/types/function.d.ts new file mode 100644 index 0000000..86c1e1c --- /dev/null +++ b/project/types/function.d.ts @@ -0,0 +1,282 @@ +interface ActionData { + /** + * 当按键弹起时 + * @param keyCode 按键的keyCode + * @param altKey 当前是否按下了alt键 + */ + onKeyUp(keyCode: number, altKey: boolean): boolean; + + /** + * 当点击状态栏时 + * @param px 点击的横坐标 + * @param py 点击的纵坐标 + * @param vertical 当前是否是竖屏 + */ + onClickStatusBar(px: number, py: number, vertical: boolean): boolean; +} + +interface ControlData { + /** + * 获取保存信息 + */ + saveData(): Save; + + /** + * 读取一个存档 + * @param data 存档信息 + * @param callback 读取完毕后的回调函数 + */ + loadData(data: Save, callback?: () => void): void; + + /** + * 获取一个属性对应的中文名 + * @param name 要获取的状态名称 + */ + getStatusLabel(name: string): string; + + /** + * 变更勇士的debuff + * @param action 触发的类型,get表示获得debuff,remove表示移除debuff + * @param type 获取的debuff列表 + */ + triggerDebuff(action: 'get' | 'remove', type: string | string[]): void; + + /** + * 立即仅更新状态栏 + */ + updateStatusBar(): void; + + /** + * 更新一个地图的地图伤害 + * @param floorId 要更新的楼层id + */ + updateCheckBlock(floorId: FloorIds): void; + + /** + * 每步移动后执行的函数 + * @param callback 回调函数(好像没什么必要吧 + */ + moveOneStep(callback?: () => void): void; + + /** + * 瞬移到某一点 + * @param x 瞬移至的横坐标 + * @param y 瞬移至的纵坐标 + * @param ignoreSteps 忽略的步数,不填则会自动计算 + */ + moveDirectly(x: number, y: number, ignoreSteps?: number): boolean; + + /** + * 并行脚本 + * @param time 距离游戏加载完毕经过的时间 + */ + parallelDo(time: number): void; +} + +interface EnemyData { + /** + * 获得所有特殊属性定义 + */ + getSpecials(): EnemySpecialDeclaration[]; + + /** + * 获得怪物真实属性 + * @param enemy 敌人id或敌人对象 + * @param hero 勇士信息,不填则从core.status.hero获取 + * @param x 敌人的横坐标 + * @param y 敌人的纵坐标 + * @param floorId 敌人所在的地图 + */ + getEnemyInfo( + enemy: EnemyIds | Enemy, + hero?: HeroStatus, + x?: number, + y?: number, + floorId?: FloorIds + ): EnemyInfo; + + /** + * 获得战斗伤害信息(实际伤害计算函数) + * @param enemy 敌人id或敌人对象 + * @param hero 勇士信息,不填则从core.status.hero获取 + * @param x 敌人的横坐标 + * @param y 敌人的纵坐标 + * @param floorId 敌人所在的地图 + */ + getDamageInfo( + enemy: EnemyIds | Enemy, + hero?: HeroStatus, + x?: number, + y?: number, + floorId?: FloorIds + ): DamageInfo; + + /** + * 判定某种特殊属性的有无 + * @example core.hasSpecial('greenSlime', 1) // 判定绿头怪有无先攻属性 + * @param special 敌人id或敌人对象或正整数数组或自然数 + * @param test 待检查的属性编号 + * @returns 若special为数组或数且含有test或相等、或special为敌人id或对象且具有此属性,则返回true + */ + hasSpecial( + special: number | number[] | EnemyIds | Enemy, + test: number + ): boolean; +} + +interface UiData { + /** + * 获取道具栏要显示的道具 + * @param cls 要获取的类型 + */ + getToolboxItems>(cls: T): ItemIdOf[]; + + /** + * 绘制状态栏 + */ + drawStatusBar(): void; + + /** + * 数据统计界面统计的道具数量 + */ + drawStatistics(): AllIdsOf<'items'>[]; + + /** + * 绘制关于界面 + */ + drawAbout(): void; +} + +interface EventData { + /** + * 重置游戏 + * @param hero 勇士信息 + * @param hard 难度信息 + * @param floorId 勇士所在楼层 + * @param maps 所有的地图信息 + * @param values 全局数值信息 + */ + resetGame( + hero: HeroStatus, + hard: string, + floorId: FloorIds, + maps: GameStatus['maps'], + values: Partial + ): void; + + /** + * 游戏获胜 + * @param reason 胜利原因 + * @param norank 是否不计榜 + * @param noexit 是否不退出 + */ + win(reason: string, norank?: boolean, noexit?: boolean): void; + + /** + * 游戏失败 + * @param reason 失败原因 + */ + lose(reason: string): void; + + /** + * 切换楼层中,即屏幕完全变黑的那一刻 + * @param floorId 目标楼层 + * @param heroLoc 勇士到达的位置 + */ + changingFloor(floorId: FloorIds, heroLoc: Loc): void; + + /** + * 切换楼层后 + * @param floorId 目标楼层 + */ + afterChangeFloor(floorId: FloorIds): void; + + /** + * 飞往某个楼层 + * @param toId 目标楼层 + * @param callback 飞到后的回调函数 + */ + flyTo(toId: FloorIds, callback: () => void): void; + + /** + * 与怪物战斗前 + * @param enemyId 打败的怪物 + * @param x 怪物横坐标 + * @param y 怪物纵坐标 + */ + beforeBattle( + enemyId: AllIdsOf<'enemys' | 'enemy48'>, + x?: number, + y?: number + ): void; + + /** + * 与怪物战斗后 + * @param enemyId 打败的怪物 + * @param x 怪物横坐标 + * @param y 怪物纵坐标 + */ + afterBattle( + enemyId: AllIdsOf<'enemys' | 'enemy48'>, + x?: number, + y?: number + ): void; + + /** + * 开门后 + * @param doorId 门的id + * @param x 门的横坐标 + * @param y 门的纵坐标 + */ + afterOpenDoor( + doorId: AllIdsOf>, + x: number, + y: number + ): void; + + /** + * 获得道具后 + * @param itemId 道具id + * @param x 道具横坐标 + * @param y 道具纵坐标 + * @param isGentleClick 是否是轻按 + */ + afterGetItem( + itemId: AllIdsOf<'items'>, + x: number, + y: number, + isGentleClick?: boolean + ): void; + + /** + * 推箱子后 + */ + afterPushBox(): void; +} + +interface FunctionsData { + /** + * 交互信息 + */ + actions: ActionData; + + /** + * 游戏的逻辑信息 + */ + control: ControlData; + + /** + * 怪物信息 + */ + enemys: EnemyData; + + /** + * ui信息 + */ + ui: UiData; + + /** + * 事件信息 + */ + events: EventData; +} diff --git a/project/types/icon.d.ts b/project/types/icon.d.ts new file mode 100644 index 0000000..47bfaef --- /dev/null +++ b/project/types/icon.d.ts @@ -0,0 +1,71 @@ +type IconIds = + | keyof MaterialIcon['animates'] + | keyof MaterialIcon['autotile'] + | keyof MaterialIcon['enemy48'] + | keyof MaterialIcon['enemys'] + | keyof MaterialIcon['hero'] + | keyof MaterialIcon['items'] + | keyof MaterialIcon['items'] + | keyof MaterialIcon['npc48'] + | keyof MaterialIcon['npcs'] + | keyof MaterialIcon['terrains']; + +interface IconOffsetInfo { + /** + * 图块所在额外素材的id + */ + image: string; + + /** + * 图块所在图片位于额外素材的横坐标 + */ + x: number; + + /** + * 图块所在图片位于额外素材的纵坐标 + */ + y: number; +} + +/** + * 和图标相关的内容 + */ +interface Icons { + /** + * 图标信息 + */ + readonly icons: MaterialIcon; + + /** + * 额外素材偏移起点 + */ + readonly tilesetStartOffset: 10000; + + /** + * 图标的id + */ + readonly allIconIds: IconIds; + + /** + * 获得所有图标类型 + */ + getIcons(): MaterialIcon; + + /** + * 根据ID获得图块类型 + */ + getClsFromId(id: T): ClsOf; + + /** + * 获得所有图标的ID + */ + getAllIconIds(): IconIds; + + /** + * 根据图块数字或ID获得所在的tileset和坐标信息 + * @param id 图块数字或id + */ + getTilesetOffset(id: string | number): IconOffsetInfo | null; +} + +declare const icons: new () => Icons; diff --git a/project/types/item.d.ts b/project/types/item.d.ts new file mode 100644 index 0000000..aca1067 --- /dev/null +++ b/project/types/item.d.ts @@ -0,0 +1,281 @@ +interface Item> { + /** + * 道具id + */ + id: I; + + /** + * 道具的类型 + */ + cls: ItemClsOf; + + /** + * 道具的名称 + */ + name: string; + + /** + * 道具的描述 + */ + text?: string; + + /** + * 是否在道具栏隐藏 + */ + hideInToolBox: boolean; + + /** + * 装备信息 + */ + equip: ItemClsOf extends 'equips' ? Equip : never; + + /** + * 回放使用时是否不先打开道具栏再使用 + */ + hideInReplay: boolean; + + /** + * 即捡即用效果 + */ + itemEffect?: string; + + /** + * 即捡即用道具捡过之后的提示 + */ + itemEffectTip?: string; + + /** + * 使用道具时执行的事件 + */ + useItemEvent?: MotaEvent; + + /** + * 使用道具时执行的代码 + */ + useItemEffect?: string; + + /** + * 能否使用道具 + */ + canUseItemEffect?: string | boolean; +} + +interface EquipBase { + /** + * 装备增加的数值 + */ + value: Record, number>; + + /** + * 装备增加的百分比 + */ + percentage: Record, number>; +} + +interface Equip extends EquipBase { + /** + * 可以装备到的装备孔 + */ + type: number | string; + + /** + * 穿上装备时执行的事件 + */ + equipEvent: MotaEvent; + + /** + * 脱下装备时执行的事件 + */ + unequipEvent: MotaEvent; +} + +/** + * 道具相关的内容 + */ +interface Items { + /** + * 获得所有道具 + */ + getItems(): { + [P in AllIdsOf<'items'>]: Item

; + }; + + /** + * 执行即捡即用类的道具获得时的效果 + * @example core.getItemEffect('redPotion', 10) // 执行获得10瓶红血的效果 + * @param itemId 道具id + * @param itemNum 道具数量,默认为1 + */ + getItemEffect(itemId: AllIdsOf<'items'>, itemNum?: number): void; + + /** + * 即捡即用类的道具获得时的额外提示 + * @example core.getItemEffectTip(redPotion) // (获得 红血瓶)',生命+100' + * @param itemId 道具id + * @returns 图块属性itemEffectTip的内容 + */ + getItemEffectTip(itemId: AllIdsOf<'items'>): string; + + /** + * 使用一个道具 + * @example core.useItem('pickaxe', true) // 使用破墙镐,不计入录像,无回调 + * @param itemId 道具id + * @param noRoute 是否不计入录像,快捷键使用的请填true,否则可省略 + * @param callback 道具使用完毕或使用失败后的回调函数,好像没什么意义吧( + */ + useItem( + itemId: ItemIdOf<'tools' | 'constants'>, + noRoute?: boolean, + callback?: () => void + ): void; + + /** + * 检查能否使用某种道具 + * @example core.canUseItem('pickaxe') // 能否使用破墙镐 + * @param itemId 道具id + * @returns true表示可以使用 + */ + canUseItem(itemId: AllIdsOf<'items'>): boolean; + + /** + * 统计某种道具的持有量 + * @example core.itemCount('yellowKey') // 持有多少把黄钥匙 + * @param itemId 道具id + * @returns 该种道具的持有量,不包括已穿戴的装备 + */ + itemCount(itemId: AllIdsOf<'items'>): number; + + /** + * 检查主角是否持有某种道具(不包括已穿戴的装备) + * @example core.hasItem('yellowKey') // 主角是否持有黄钥匙 + * @param itemId 道具id + * @returns true表示持有 + */ + hasItem(itemId: AllIdsOf<'items'>): boolean; + + /** + * 检查主角是否穿戴着某件装备 + * @example core.hasEquip('sword5') // 主角是否装备了神圣剑 + * @param itemId 装备id + * @returns true表示已装备 + */ + hasEquip(itemId: ItemIdOf<'equips'>): boolean; + + /** + * 检查主角某种类型的装备目前是什么 + * @example core.getEquip(1) // 主角目前装备了什么盾牌 + * @param equipType 装备类型,自然数 + * @returns 装备id,null表示未穿戴 + */ + getEquip(equipType: number): ItemIdOf<'equips'> | null; + + /** + * 设置某种道具的持有量 + * @example core.setItem('yellowKey', 3) // 设置黄钥匙为3把 + * @param itemId 道具id + * @param itemNum 新的持有量,可选,自然数,默认为0 + */ + setItem(itemId: AllIdsOf<'items'>, itemNum?: number): void; + + /** + * 静默增减某种道具的持有量 不会更新游戏画面或是显示提示 + * @example core.addItem('yellowKey', -2) // 没收两把黄钥匙 + * @param itemId 道具id + * @param itemNum 增加量,负数表示减少 + */ + addItem(itemId: AllIdsOf<'items'>, itemNum?: number): void; + + /** + * @deprecated 使用addItem代替。 + * 删除某个物品一定的数量,相当于addItem(itemId, -n); + * @param itemId 道具id + * @param itemNum 减少量,负数表示增加 + */ + removeItem(itemId?: AllIdsOf<'items'>, itemNum?: number): void; + + /** + * 根据类型获得一个可用的装备孔 + * @param equipId 道具名称 + */ + getEquipTypeByName(name?: ItemIdOf<'equips'>): number; + + /** + * 判定某件装备的类型 + * @example core.getEquipTypeById('shield5') // 1(盾牌) + * @param equipId 装备id + * @returns 类型编号,自然数 + */ + getEquipTypeById(equipId: ItemIdOf<'equips'>): number; + + /** + * 检查能否穿上某件装备 + * @example core.canEquip('sword5', true) // 主角可以装备神圣剑吗,如果不能会有提示 + * @param equipId 装备id + * @param hint 无法穿上时是否提示(比如是因为未持有还是别的什么原因) + * @returns true表示可以穿上,false表示无法穿上 + */ + canEquip(equipId: ItemIdOf<'equips'>, hint?: boolean): boolean; + + /** + * 尝试穿上某件背包里的装备并提示 + * @example core.loadEquip('sword5') // 尝试装备上背包里的神圣剑,无回调 + * @param equipId 装备id + * @param callback 穿戴成功或失败后的回调函数 + */ + loadEquip(equipId: ItemIdOf<'equips'>, callback?: () => void): void; + + /** + * 脱下某个类型的装备 + * @example core.unloadEquip(1) // 卸下盾牌,无回调 + * @param equipType 装备类型编号,自然数 + * @param callback 卸下装备后的回调函数 + */ + unloadEquip(equipType: number, callback?: () => void): void; + + /** + * 比较两件(类型可不同)装备的优劣 + * @example core.compareEquipment('sword5', 'shield5') // 比较神圣剑和神圣盾的优劣 + * @param compareEquipId 装备甲的id + * @param beComparedEquipId 装备乙的id + * @returns 两装备的各属性差,甲减乙,0省略 + */ + compareEquipment>( + compareEquipId: F, + beComparedEquipId: Exclude, F> + ): EquipBase; + + /** + * 保存当前套装 + * @example core.quickSaveEquip(1) // 将当前套装保存为1号套装 + * @param index 套装编号,自然数 + */ + quickSaveEquip(index: number): void; + + /** + * 快速换装 + * @example core.quickLoadEquip(1) // 快速换上1号套装 + * @param index 套装编号,自然数 + */ + quickLoadEquip(index: number): void; + + /** + * 设置某个装备的属性并计入存档 + * @example core.setEquip('sword1', 'value', 'atk', 300, '+='); // 设置铁剑的攻击力数值再加300 + * @param equipId 装备id + * @param valueType 增幅类型,只能是value(数值)或percentage(百分比) + * @param name 要修改的属性名称,如atk + * @param value 要修改到的属性数值 + * @param operator 操作符,如+=表示在原始值上增加 + * @param prefix 独立开关前缀,一般不需要 + */ + setEquip( + equipId: ItemIdOf<'equips'>, + valueType: 'value' | 'percentage', + name: keyof SelectType, + value: number, + operator?: MotaOperator, + prefix?: string + ): void; +} + +declare const items: new () => Items; diff --git a/project/types/loader.d.ts b/project/types/loader.d.ts new file mode 100644 index 0000000..ae8f95a --- /dev/null +++ b/project/types/loader.d.ts @@ -0,0 +1,65 @@ +/** + * 负责资源的加载 + */ +interface Loader { + /** + * 加载一系列图片 + * @param dir 图片所在目录 + * @param names 图片名称列表 + * @param toSave 要保存到的对象 + * @param callback 加载完毕后的回调函数 + */ + loadImages( + dir: string, + names: string[], + toSave: Record, + callback?: () => void + ): void; + + /** + * 加载某一张图片 + * @param dir 图片所在目录 + * @param imgName 图片名称 + * @param callback 加载完毕的回调函数 + */ + loadImage(dir: string, imgName: string, callback?: () => void): void; + + /** + * 从zip中加载一系列图片 + * @param url 图片所在目录 + * @param names 图片名称列表 + */ + loadImagesFromZip( + url: string, + names: string, + toSave: Record, + onprogress?: (loaded: number, total: number) => void, + onfinished?: () => void + ): void; + + /** + * 加载一个音乐 + * @param name 要加载的音乐的名称 + */ + loadOneMusic(name: BgmIds): void; + + /** + * 加载一个音效 + * @param name 要加载的音效的名称 + */ + loadOneSound(name: SoundIds): void; + + /** + * 加载一个bgm + * @param name 加载的bgm的id或名称 + */ + loadBgm(name: BgmIds | NameMapIn): void; + + /** + * 释放一个bgm的缓存 + * @param name 要释放的bgm的id或名称 + */ + freeBgm(name: BgmIds | NameMapIn): void; +} + +declare const loader: new () => Loader; diff --git a/project/types/map.d.ts b/project/types/map.d.ts new file mode 100644 index 0000000..42a05aa --- /dev/null +++ b/project/types/map.d.ts @@ -0,0 +1,1349 @@ +type NotCopyPropertyInCompressedMap = + | 'firstArrive' + | 'eachArrive' + | 'blocks' + | 'parallelDo' + | 'map' + | 'bgmap' + | 'fgmap' + | 'events' + | 'changeFloor' + | 'beforeBattle' + | 'afterBattle' + | 'afterGetItem' + | 'afterOpenDoor' + | 'cannotMove' + | 'cannotMoveIn'; + +/** + * 压缩后的地图 + */ +type CompressedMap = Omit< + Floor, + NotCopyPropertyInCompressedMap +>; + +interface Block { + /** + * 横坐标 + */ + x: number; + + /** + * 纵坐标 + */ + y: number; + + /** + * 图块数字 + */ + id: N; + + /** + * 事件信息 + */ + event: { + /** + * 图块类型 + */ + cls: ClsOf; + + /** + * 图块id + */ + id: NumberToId[N]; + + /** + * 图块动画帧数 + */ + animate: FrameOf>; + + /** + * 图块是否不可通行 + */ + nopass: boolean; + + /** + * 图块高度 + */ + height: 32 | 48; + + /** + * 触发器 + */ + trigger?: MotaTrigger; + + /** + * 是否可被破 + */ + canBreak?: boolean; + + /** + * 门信息 + */ + doorInfo?: DoorInfo; + }; +} + +interface FloorBase { + /** + * 楼层id + */ + floorId: T; + + /** + * 楼层在状态栏的名称 + */ + name: string; + + /** + * 地图宝石倍率 + */ + ratio: number; + + /** + * 地图的宽度 + */ + width: number; + + /** + * 地图的高度 + */ + height: number; + + /** + * 地板样式 + */ + defaultGround: AllIds; + + /** + * 楼层贴图 + */ + image: FloorAnimate[]; + + /** + * 楼层名称 + */ + title: string; + + /** + * 是否能飞出 + */ + canFlyFrom: boolean; + + /** + * 是否能飞到 + */ + canFlyTo: boolean; + + /** + * 是否能使用快捷商店 + */ + canUseQuickShop: boolean; + + /** + * 是否不可浏览 + */ + cannotViewMap?: boolean; + + /** + * 是否是地下层 + */ + underGround?: boolean; + + /** + * 自动事件 + */ + autoEvent: Record; + + /** + * 天气 + */ + weather?: [type: string, level: WeatherLevel]; + + /** + * 事件层地图 + */ + map: number[][]; + + /** + * 并行脚本 + */ + parallelDo?: string; + + /** + * 色调 + */ + color?: Color; + + /** + * 背景音乐 + */ + bgm?: BgmIds | BgmIds[]; +} + +interface Floor extends FloorBase { + /** + * 图块信息 + */ + blocks: Block[]; +} + +interface ResolvedFloor extends FloorBase { + /** + * 战后事件 + */ + afterBattle: Record; + + /** + * 获得道具后事件 + */ + afterGetItem: Record; + + /** + * 开门后事件 + */ + afterOpenDoor: Record; + + /** + * 战前事件 + */ + beforeBattle: Record; + + /** + * 不可出方向 + */ + cannotMove: Record; + + /** + * 不可入方向 + */ + cannotMoveIn: Record; + + /** + * 普通事件 + */ + events: Record; + + /** + * 背景层 + */ + bgmap: number[][]; + + /** + * 前景层 + */ + fgmap: number[][]; + + /** + * 楼层切换 + */ + changeFloor: Record; + + /** + * 首次到达事件 + */ + firstArrive?: MotaEvent; + + /** + * 每次到达事件 + */ + eachArrive?: MotaEvent; +} + +interface BlockInfo { + /** + * 图块数字 + */ + number: T; + + /** + * 图块id + */ + id: NumberToId[T]; + + /** + * 图块类型 + */ + cls: ClsOf; + + /** + * 图块名称 + */ + name: string; + + /** + * 图片信息 + */ + image: HTMLImageElement; + + /** + * 图块所在图片的横坐标 + */ + posX: number; + + /** + * 图块所在图片的纵坐标 + */ + posY: number; + + /** + * 门信息 + */ + doorInfo: DoorInfo; + + /** + * 图片的高度 + */ + height: 32 | 48; + + /** + * faceId信息 + */ + faceIds: Record; + + /** + * 动画帧数 + */ + animate: FrameOf>; + + /** + * 朝向 + */ + face: Dir; + + /** + * 大怪物信息 + */ + bigImage: HTMLImageElement; +} + +interface DrawMapConfig { + /** + * 是否是重绘 + */ + redraw: boolean; + + /** + * 要绘制到的画布 + */ + ctx: CtxRefer; + + /** + * 是否是在地图画布上绘制的 + */ + onMap: boolean; +} + +interface DrawThumbnailConfig { + /** + * 勇士的位置 + */ + heroLoc: LocArr; + + /** + * 勇士的图标 + */ + heroIcon: ImageIds; + + /** + * 是否绘制显伤 + */ + damage: boolean; + + /** + * 变量信息,存读档时使用,可以无视 + */ + flags: Flags; + + /** + * 绘制到的画布 + */ + ctx: CtxRefer; + + /** + * 绘制位置的横坐标 + */ + x: number; + + /** + * 绘制位置的纵坐标 + */ + y: number; + + /** + * 绘制大小,比例数字,例如1代表与实际地图大小相同 + */ + size: number; + + /** + * 绘制全图 + */ + all: boolean; + + /** + * 绘制的视野中心横坐标 + */ + centerX: number; + + /** + * 绘制的视野中心纵坐标 + */ + centerY: number; + + /** + * 是否不是高清画布,存读档时使用,可以无视 + */ + noHD: boolean; + + /** + * 是否使用v2优化 + */ + v2: boolean; +} + +interface BlockFilter { + /** + * 高斯模糊 + */ + blur: number; + + /** + * 色相旋转 + */ + hue: number; + + /** + * 饱和度 + */ + grayscale: number; + + /** + * 反色 + */ + invert: boolean; + + /** + * 阴影 + */ + shadow: boolean; +} + +interface SearchedBlock { + /** + * 横坐标 + */ + x: number; + + /** + * 纵坐标 + */ + y: number; + + /** + * 楼层id + */ + floorId: FloorIds; + + /** + * 图块信息 + */ + block: Block; +} + +/** + * 负责一切和地图相关的处理内容 + */ +interface Maps { + /** + * 图块信息 + */ + blocksInfo: { + [P in keyof NumberToId]: MapDataOf

; + }; + + /** + * 加载某个楼层 + * @param floorId 楼层id + * @param map 地图信息,不填表示直接从原地图中获取 + */ + loadFloor( + floorId: T, + map?: number[][] | { map: number[][] } + ): ResolvedFloor; + + /** + * 解析地图信息 + * @param map 地图id或地图对象 + */ + extractBlocks(map?: FloorIds | ResolvedFloor): void; + + /** + * 根据需求为UI解析出blocks + * @param map 地图信息 + * @param flags 变量信息 + */ + extractBlocksForUI(map?: ResolvedFloor, flags?: Record): void; + + /** + * 根据图块id得到数字(地图矩阵中的值) + * @example core.getNumberById('yellowWall'); // 1 + * @param id 图块id + * @returns 图块的数字 + */ + getNumberById(id: T): IdToNumber[T]; + + /** + * 根据数字获得图块 + * @param number 图块数字 + */ + getBlockByNumber(number: T): Block; + + /** + * 根据ID获得图块 + * @param id 图块的id + */ + getBlockById(id: T): Block; + + /** + * 获得当前事件点的ID + */ + getIdOfThis(id?: 'this' | AllIds): string; + + /** + * 初始化一个图块 + * @param x 横坐标 + * @param y 纵坐标 + * @param id 图块的id + * @param addInfo 是否添加触发器信息等 + * @param eventFloor 所在地图信息 + */ + initBlock( + x: number, + y: number, + id: AllIds | AllNumbers, + addInfo?: boolean, + eventFloor?: ResolvedFloor + ): Block; + + /** + * 压缩地图 + * @param mapArr 地图数组 + * @param floorId 地图id + */ + compressMap(mapArr?: number[][], floorId?: FloorIds): number[][]; + + /** + * 设置图块的不透明度 + * @param opacity 不透明度 + * @param x 横坐标 + * @param y 纵坐标 + * @param floorId 楼层id + */ + setBlockOpacity( + opacity: number, + x: number, + y: number, + floorId?: FloorIds + ): void; + + /** + * 设置图块的滤镜 + * @param filter 滤镜信息 + * @param x 横坐标 + * @param y 纵坐标 + * @param floorId 楼层id + */ + setBlockFilter( + filter: string, + x: number, + y: number, + floorId?: FloorIds + ): void; + + /** + * 获取某个图块是否被强制启用或禁用 + * @param floorId 楼层id + * @param x 横坐标 + * @param y 纵坐标 + * @param flags 变量信息 + */ + isMapBlockDisabled( + floorId: FloorIds, + x: number, + y: number, + flags?: Record + ); + + /** + * 设置某个点的图块强制启用/禁用状态 + * @param floorId 楼层id + * @param x 横坐标 + * @param y 纵坐标 + * @param disable 是否禁用 + */ + setMapBlockDisabled( + floorId: FloorIds, + x: number, + y: number, + disable: boolean + ); + + /** + * 解压缩地图 + * @param mapArr 地图信息 + * @param floorId 地图id + */ + decompressMap(mapArr?: number[][], floorId: FloorIds): number[][]; + + /** + * 将所有地图重新变成数字,以便于存档 + */ + saveMap(): { [P in FloorIds]?: Partial> }; + /** + * 将某个地图重新变成数字,以便于存档 + */ + saveMap(floorId: FloorIds): Partial; + + /** + * 将存档中的地图信息重新读取出来 + * @param data 多个楼层的信息 + * @param floorId 在这里没有用 + * @param flags 变量信息 + */ + loadMap( + data: { [P in T]: Partial> }, + floorId?: undefined, + flags?: Record + ): { [P in T]: ResolvedFloor }; + /** + * 加载某个楼层的信息 + * @param data 多个楼层的信息 + * @param floorId 加载的楼层 + */ + loadMap( + data: { [P in T]?: Partial> }, + floorId: T + ): ResolvedFloor; + + /** + * 更改地图画布的尺寸 + * @param floorId 楼层id + */ + resizeMap(floorId?: FloorIds): void; + + /** + * 生成事件层矩阵 + * @example core.getMapArray('MT0'); // 生成主塔0层的事件层矩阵,隐藏的图块视为0 + * @param floorId 地图id,不填视为当前地图 + * @param noCache 是否清空缓存 + * @returns 事件层矩阵,注意对其阵元的访问是[y][x] + */ + getMapArray(floorId?: FloorIds, noCache?: boolean): AllNumbers[][]; + + /** + * 获取图块的事件层数字 + * @param x 横坐标 + * @param y 纵坐标 + * @param floorId 楼层id + * @param noCache 是否清空缓存 + */ + getMapNumber( + x: number, + y: number, + floorId?: FloorIds, + noCache?: boolean + ): AllNumbers; + + /** + * 以x,y的形式返回每个点的事件 + * @param floorId 楼层id + * @param noCache 是否不使用缓存 + */ + getMapBlocksObj( + floorId?: FloorIds, + noCache?: boolean + ): Record; + + /** + * 获取背景层的图块矩阵 + * @param floorId 楼层id + */ + getBgMapArray(floorId: FloorIds): AllNumbers[][]; + + /** + * 获取前景层的图块矩阵 + * @param floorId 楼层id + */ + getFgMapArray(floorId: FloorIds): AllNumbers[][]; + + /** + * 判定背景层的一个位置是什么 + * @example core.getBgNumber(); // 判断主角脚下的背景层图块的数字 + * @param x 横坐标,不填为当前勇士坐标 + * @param y 纵坐标,不填为当前勇士坐标 + * @param floorId 地图id,不填视为当前地图 + * @param noCache 是否不使用缓存 + */ + getBgNumber( + x?: number, + y?: number, + floorId?: FloorIds, + noCache?: boolean + ): AllNumbers; + + /** + * 判定前景层的一个位置是什么 + * @example core.getFgNumber(); // 判断主角脚下的前景层图块的数字 + * @param x 横坐标,不填为当前勇士坐标 + * @param y 纵坐标,不填为当前勇士坐标 + * @param floorId 地图id,不填视为当前地图 + * @param noCache 是否不使用缓存 + */ + getFgNumber( + x?: number, + y?: number, + floorId?: FloorIds, + noCache?: boolean + ): AllNumbers; + + /** + * 可通行性判定 + * @example core.generateMovableArray(); // 判断当前地图主角从各点能向何方向移动 + * @param floorId 地图id,不填视为当前地图 + * @returns 从各点可移动方向的三维数组 + */ + generateMovableArray(floorId?: FloorIds): Dir[][][]; + + /** + * 单点单朝向的可通行性判定,不判断nopass + * @exmaple core.canMoveHero(); // 判断主角是否可以前进一步 + * @param x 起点横坐标,不填视为主角当前的 + * @param y 起点纵坐标,不填视为主角当前的 + * @param direction 移动的方向,不填视为主角面对的方向 + * @param floorId 地图id,不填视为当前地图 + * @returns true表示可移动,false表示不可移动 + */ + canMoveHero( + x?: number, + y?: number, + direction?: Dir, + floorId?: FloorIds + ): boolean; + + /** + * 能否瞬移到某点,并求出节约的步数。 + * @example core.canMoveDirectly(0, 0); // 能否瞬移到地图左上角 + * @param destX 目标点的横坐标 + * @param destY 目标点的纵坐标 + * @returns 正数表示节约的步数,-1表示不可瞬移 + */ + canMoveDirectly(destX: number, destY: number): number; + + /** + * 获得某些点可否通行的信息 + * @param locs 目标路径 + * @param canMoveArray 可通行信息 + */ + canMoveDirectlyArray(locs: LocArr[], canMoveArray?: Dir[][][]): number[]; + + /** + * 自动寻路 + * @example core.automaticRoute(0, 0); // 自动寻路到地图左上角 + * @param destX 目标点的横坐标 + * @param destY 目标点的纵坐标 + * @returns 每步走完后主角的loc属性组成的一维数组 + */ + automaticRoute(destX: number, destY: number): DiredLoc[]; + + /** + * 绘制一个图块 + * @param block 要绘制的图块 + * @param animate 绘制图块的第几帧 + * @param ctx 绘制到的画布 + */ + drawBlock(block?: Block, animate?: number, ctx?: CtxRefer): void; + + /** + * 生成groundPattern + * @param floorId 楼层id + */ + generateGroundPattern(floorId?: FloorIds): void; + + /** + * 地图绘制 + * @example core.drawMap(); // 绘制当前地图 + * @param floorId 地图id,不填表示当前楼层 + */ + drawMap(floorId?: FloorIds): void; + + /** + * 重绘地图 + */ + redrawMap(): void; + + /** + * 绘制背景层(含贴图,其与背景层矩阵的绘制顺序可通过复写此函数来改变) + * @example core.drawBg(); // 绘制当前地图的背景层 + * @param floorId 地图id,不填视为当前地图 + * @param config 配置信息 + */ + drawBg(floorId?: FloorIds, config?: Partial): void; + + /** + * 绘制事件层 + * @example core.drawEvents(); // 绘制当前地图的事件层 + * @param floorId 地图id,不填视为当前地图 + * @param blocks 一般不需要 + * @param config 配置信息 + */ + drawEvents( + floorId?: FloorIds, + blocks?: Block[], + config?: Partial + ): void; + + /** + * 绘制前景层(含贴图,其与前景层矩阵的绘制顺序可通过复写此函数来改变) + * @example core.drawFg(); // 绘制当前地图的前景层 + * @param floorId 地图id,不填视为当前地图 + * @param config 配置信息 + */ + drawFg(floorId?: FloorIds, config?: Partial): void; + + /** + * 绘制缩略图 + * @example core.drawThumbnail(); // 绘制当前地图的缩略图 + * @param floorId 地图id,不填视为当前地图 + * @param blocks 一般不需要 + * @param options 额外的绘制项,可以增绘主角位置和朝向、采用不同于游戏中的主角行走图、增绘显伤、提供flags用于存读档 + */ + drawThumbnail( + floorId?: FloorIds, + blocks?: Block[], + options?: Partial + ): void; + + /** + * 判定某个点是否不可被踏入(不基于主角生命值和图块cannotIn属性) + * @example core.noPass(0, 0); // 判断地图左上角能否被踏入 + * @param x 目标点的横坐标 + * @param y 目标点的纵坐标 + * @param floorId 目标点所在的地图id,不填视为当前地图 + */ + noPass(x: number, y: number, floorId?: FloorIds): boolean; + + /** + * 某个点是否存在NPC + * @param x 横坐标 + * @param y 纵坐标 + * @param floorId 楼层id + */ + npcExists(x: number, y: number, floorId?: FloorIds): boolean; + + /** + * 某个点是否存在(指定的)地形 + * @param x 横坐标 + * @param y 纵坐标 + * @param id 地形的id + * @param floorId 楼层id + */ + terrainExists( + x: number, + y: number, + id?: AllIdsOf<'terrains'>, + floorId?: FloorIds + ): boolean; + + /** + * 某个点是否存在楼梯 + * @param x 横坐标 + * @param y 纵坐标 + * @param floorId 楼层id + */ + stairExists(x: number, y: number, floorId?: FloorIds): boolean; + + /** + * 当前位置是否在楼梯边;在楼传平面塔模式下对箭头也有效 + */ + nearStair(): boolean; + + /** + * 某个点是否存在(指定的)怪物 + * @param x 横坐标 + * @param y 纵坐标 + * @param id 怪物的id + * @param floorId 楼层id + */ + enemyExists( + x: number, + y: number, + id?: AllIdsOf<'enemys' | 'enemy48'>, + floorId?: FloorIds + ): boolean; + + /** + * 获得某个点的block + * @param x 横坐标 + * @param y 纵坐标 + * @param floorId 楼层id + * @param showDisable 被禁用的图块是否也能被获取 + */ + getBlock( + x: number, + y: number, + floorId?: FloorIds, + showDisable?: boolean + ): Block; + + /** + * 判定某个点的图块id + * @example + * // 一个简单的机关门事件,打败或炸掉这一对绿头怪和红头怪就开门 + * if ( + * core.getBlockId(x1, y1) !== 'greenSlime' && + * core.getBlockId(x2, y2) !== 'redSlime' + * ) + * core.openDoor(x3, y3); + * @param x 横坐标 + * @param y 纵坐标 + * @param floorId 地图id,不填视为当前地图 + * @param showDisable 被禁用的图块是否也能被获取 + * @returns 图块id,该点无图块则返回null + */ + getBlockId( + x: number, + y: number, + floorId?: FloorIds, + showDisable?: boolean + ): AllIds | null; + + /** + * 判定某个点的图块数字 + * @param x 横坐标 + * @param y 纵坐标 + * @param floorId 地图id,不填视为当前地图 + * @param showDisable 被禁用的图块是否也能被获取 + */ + getBlockNumber( + x: number, + y: number, + floorId?: FloorIds, + showDisable?: boolean + ): AllNumbers; + + /** + * 判定某个点的图块类型 + * @example + * // 另一个简单的机关门事件,打败或炸掉这一对不同身高的敌人就开门 + * if (core.getBlockCls(x1, y1) !== 'enemys' && core.getBlockCls(x2, y2) !== 'enemy48') core.openDoor(x3, y3); + * @param x 横坐标 + * @param y 纵坐标 + * @param floorId 地图id,不填视为当前地图 + * @param showDisable 被禁用的图块是否也能被获取 + */ + getBlockCls( + x: number, + y: number, + floorId?: FloorIds, + showDisable?: boolean + ): Cls | null; + + /** + * 获取图块的不透明度 + * @param x 横坐标 + * @param y 纵坐标 + * @param floorId 地图id,不填视为当前地图 + * @param showDisable 被禁用的图块是否也能被获取 + */ + getBlockOpacity( + x: number, + y: number, + floorId?: FloorIds, + showDisable?: boolean + ): number | null; + + /** + * 获取图块的滤镜 + * @param x 横坐标 + * @param y 纵坐标 + * @param floorId 地图id,不填视为当前地图 + * @param showDisable 被禁用的图块是否也能被获取 + */ + getBlockFilter( + x: number, + y: number, + floorId?: FloorIds, + showDisable?: boolean + ): BlockFilter | null; + + /** + * 获得某个图块或素材的信息 + * @param block 图块信息,可以填图块,数字,id + */ + getBlockInfo( + block?: Block | NumberToId[T] | T + ): BlockInfo; + + /** + * 搜索图块, 支持通配符 + * @example core.searchBlock('*Door'); // 搜索当前地图的所有门 + * @param id 图块id,支持星号表示任意多个(0个起)字符 + * @param floorId 地图id,不填视为当前地图 + * @param showDisable 隐藏点是否计入,true表示计入 + */ + searchBlock( + id: string, + floorId?: FloorIds | FloorIds[], + showDisable?: boolean + ): SearchedBlock[]; + + /** + * 根据给定的筛选函数搜索全部满足条件的图块 + * @example + * // 搜索当前地图的所有门 + * core.searchBlockWithFilter(function (block) { return block.event.id.endsWith('Door'); }); + * @param blockFilter 筛选函数,可接受block输入,应当返回一个boolean值 + * @param floorId 地图id,不填视为当前地图 + * @param showDisable 隐藏点是否计入,true表示计入 + * @returns 一个详尽的数组 + */ + searchBlockWithFilter( + blockFilter: (block: Block) => boolean, + floorId?: FloorIds | FloorIds[], + showDisable?: boolean + ): SearchedBlock[]; + + /** + * 获得某个图块对应行走图朝向向下的那一项的id,如果不存在行走图绑定则返回自身id + * @param block 要获得的图块 + */ + getFaceDownId(block: Block | AllIds | AllNumbers): AllIds; + + /** + * 显示(隐藏或显示的)图块,此函数将被“显示事件”指令和勾选了“不消失”的“移动/跳跃事件”指令(如阻击怪)的终点调用 + * @example core.showBlock(0, 0); // 显示地图左上角的图块 + * @param x 横坐标 + * @param y 纵坐标 + * @param floorId 地图id,不填视为当前地图 + */ + showBlock(x: number, y: number, floorId?: FloorIds): void; + + /** + * 隐藏一个图块,对应于「隐藏事件」且不删除 + * @example core.hideBlock(0, 0); // 隐藏地图左上角的图块 + * @param x 横坐标 + * @param y 纵坐标 + * @param floorId 地图id,不填视为当前地图 + */ + hideBlock(x: number, y: number, floorId?: FloorIds): void; + + /** + * 根据图块的索引来隐藏图块 + * @param index 要隐藏的图块的索引 + * @param floorId 地图id + */ + hideBlockByIndex(index: number, floorId?: FloorIds): void; + + /** + * 一次性隐藏多个block + * @param indexes 索引列表 + * @param floorId 地图id + */ + hideBlockByIndexes(indexes: number[], floorId?: FloorIds): void; + + /** + * 删除一个图块,对应于「隐藏事件」并同时删除 + * @example core.removeBlock(0, 0); // 尝试删除地图左上角的图块 + * @param x 横坐标 + * @param y 纵坐标 + * @param floorId 地图id,不填视为当前地图 + * @returns 有没有删除成功 + */ + removeBlock(x: number, y: number, floorId?: FloorIds): boolean; + + /** + * 根据block的索引(尽可能)删除该块 + * @param index 要删除的图块的索引 + * @param floorId 地图id + */ + removeBlockByIndex(index: number, floorId?: FloorIds): void; + + /** + * 一次性删除多个block + * @param indexes 索引列表 + * @param floorId 地图id + */ + removeBlockByIndexes(indexes: number[], floorId?: FloorIds): void; + + /** + * 显示前景/背景地图 + * @param name 图层名 + * @param loc 要显示的坐标列表 + * @param floorId 楼层id + * @param callback 显示完毕的回调函数 + */ + showBgFgMap( + name: 'bg' | 'bg2' | 'fg' | 'fg2', + loc: LocArr | LocArr[], + floorId?: FloorIds, + callback?: () => void + ): void; + + /** + * 隐藏前景/背景地图 + * @param name 图层名 + * @param loc 要显示的坐标列表 + * @param floorId 楼层id + * @param callback 显示完毕的回调函数 + */ + hideBgFgMap( + name: 'bg' | 'bg2' | 'fg' | 'fg2', + loc: LocArr | LocArr[], + floorId?: FloorIds, + callback?: () => void + ): void; + + /** + * 显示一个楼层贴图 + * @param loc 楼层贴图的位置 + * @param floorId 楼层id + * @param callback 显示完毕后的回调函数 + */ + showFloorImage( + loc?: LocArr | LocArr[], + floorId?: FloorIds, + callback?: () => void + ): void; + + /** + * 隐藏一个楼层贴图 + * @param loc 楼层贴图的位置 + * @param floorId 楼层id + * @param callback 显示完毕后的回调函数 + */ + hideFloorImage( + loc?: LocArr | LocArr[], + floorId?: FloorIds, + callback?: () => void + ): void; + + /** + * 转变图块 + * @example core.setBlock(1, 0, 0); // 把地图左上角变成黄墙 + * @param number 新图块的数字或id + * @param x 横坐标 + * @param y 纵坐标 + * @param floorId 地图id,不填视为当前地图 + */ + setBlock( + number: AllIds | AllNumbers | `${AllNumbers}`, + x: number, + y: number, + floorId?: FloorIds + ): void; + + /** + * 动画形式转变某点图块 + * @param number 要转变成的图块的数字或id + * @param x 横坐标 + * @param y 纵坐标 + * @param floorId 楼层id + * @param time 转变时间 + * @param callback 转变开始或完成后的回调函数 + */ + animateSetBlock( + number: AllIds | AllNumbers | `${AllNumbers}`, + x: number, + y: number, + floorId?: FloorIds, + time?: number, + callback?: () => void + ): void; + + /** + * 动画形式转变若干点图块 + * @param number 要转变成的图块的数字或id + * @param locs 坐标数组 + * @param floorId 楼层id + * @param time 转变时间 + * @param callback 转变开始或完成后的回调函数 + */ + animateSetBlocks( + number: AllIds | AllNumbers | `${AllNumbers}`, + locs: LocArr | LocArr[], + floorId?: FloorIds, + time?: number, + callback?: () => void + ): void; + + /** + * 某个图块转向 + * @param direction 转向的方向 + * @param x 图块所在横坐标 + * @param y 图块所在纵坐标 + * @param floorId 楼层id + */ + turnBlock( + direction: HeroTurnDir, + x: number, + y: number, + floorId?: FloorIds + ): void; + + /** + * 批量替换图块 + * @example core.replaceBlock(21, 22, core.floorIds); // 把游戏中地上当前所有的黄钥匙都变成蓝钥匙 + * @param fromNumber 旧图块的数字 + * @param toNumber 新图块的数字 + * @param floorId 地图id或其数组,不填视为当前地图 + */ + replaceBlock( + fromNumber: AllNumbers, + toNumber: AllNumbers, + floorId?: FloorIds | FloorIds[] + ): void; + + /** + * 转变图层块 + * @example core.setBgFgBlock('bg', 167, 6, 6); // 把当前地图背景层的中心块改为滑冰 + * @param name 背景还是前景 + * @param number 新图层块的数字或id + * @param x 横坐标 + * @param y 纵坐标 + * @param floorId 地图id,不填视为当前地图 + */ + setBgFgBlock( + name: 'bg' | 'fg' | 'bg2' | 'fg2', + number: AllIds | AllNumbers | `${AllNumbers}`, + x: number, + y: number, + floorId?: FloorIds + ): void; + + /** + * 重置地图,注意该功能原则上只用于调试,游戏中不应当出现 + * @param floorId 楼层id或数组 + */ + resetMap(floorId?: FloorIds | FloorIds[]): void; + + /** + * 移动图块 + * @example core.moveBlock(0, 0, ['down']); // 令地图左上角的图块下移一格,用时半秒,再花半秒淡出 + * @param x 起点的横坐标 + * @param y 起点的纵坐标 + * @param steps 步伐数组 + * @param time 单步和淡出用时,单位为毫秒。不填视为半秒 + * @param keep 是否不淡出,true表示不淡出 + * @param callback 移动或淡出后的回调函数 + */ + moveBlock( + x: number, + y: number, + steps: Step[], + time?: number, + keep?: boolean, + callback?: () => void + ): void; + + /** + * 跳跃图块;从V2.7开始不再有音效 + * @example core.jumpBlock(0, 0, 0, 0); // 令地图左上角的图块原地跳跃半秒,再花半秒淡出 + * @param sx 起点的横坐标 + * @param sy 起点的纵坐标 + * @param ex 终点的横坐标 + * @param ey 终点的纵坐标 + * @param time 单步和淡出用时,单位为毫秒。不填视为半秒 + * @param keep 是否不淡出,true表示不淡出 + * @param callback 落地或淡出后的回调函数 + */ + jumpBlock( + sx: number, + sy: number, + ex: number, + ey: number, + time?: number, + keep?: boolean, + callback?: () => void + ): void; + + /** + * 显示/隐藏某个块时的动画效果 + * @param loc 要显示或隐藏的坐标数组 + * @param type 显示还是隐藏还是移除,填数字表示设置不透明度 + * @param time 动画时间 + * @param callback 动画完毕后的回调函数 + */ + animateBlock( + loc: LocArr | LocArr[], + type: 'show' | 'hide' | 'remove' | number, + time: number, + callback?: () => void + ): void; + + /** + * 添加一个全局动画 + * @param block 图块信息 + */ + addGlobalAnimate(block?: Block): void; + + /** + * 删除所有全局动画 + */ + removeGlobalAnimate(): void; + /** + * 删除一个全局动画 + * @param x 横坐标 + * @param y 纵坐标 + */ + removeGlobalAnimate(x?: number, y?: number): void; + + /** + * 绘制UI层的box动画 + */ + drawBoxAnimate(): void; + + /** + * 播放动画,注意即使指定了主角的坐标也不会跟随主角移动,如有需要请使用core.drawHeroAnimate(name, callback)函数 + * @example core.drawAnimate('attack', core.nextX(), core.nextY(), false, core.vibrate); // 在主角面前一格播放普攻动画,动画停止后视野左右抖动1秒 + * @param name 动画文件名,不含后缀 + * @param x 绝对横坐标 + * @param y 绝对纵坐标 + * @param alignWindow 是否是相对窗口的坐标 + * @param callback 动画停止后的回调函数 + * @returns 一个数字,可作为core.stopAnimate()的参数来立即停止播放(届时还可选择是否执行此次播放的回调函数) + */ + drawAnimate( + name: AnimationIds | NameMapIn, + x: number, + y: number, + alignWindow: boolean, + callback?: () => void + ): number; + + /** + * 播放跟随勇士的动画 + * @param name 动画名 + * @param callback 动画停止后的回调函数 + * @returns 一个数字,可作为core.stopAnimate()的参数来立即停止播放(届时还可选择是否执行此次播放的回调函数) + */ + drawHeroAnimate( + name: AnimationIds | NameMapIn, + callback?: () => void + ): number; + + /** + * 获得当前正在播放的所有(指定)动画的id列表 + * @param name 指定名称 + */ + getPlayingAnimates(name?: AnimationIds): number[]; + + /** + * 立刻停止一个动画播放 + * @param id 播放动画的编号,即drawAnimate或drawHeroAnimate返回值,不填则停止所有的 + * @param doCallback 是否执行该动画的回调函数 + */ + stopAnimate(id?: number, doCallback?: boolean): void; +} + +declare const maps: new () => Maps; diff --git a/project/types/plugin.d.ts b/project/types/plugin.d.ts new file mode 100644 index 0000000..1562327 --- /dev/null +++ b/project/types/plugin.d.ts @@ -0,0 +1,191 @@ +// 这里包含所有插件导出的函数及变量声明,声明的函数会在类型标注中标注到core上 + +interface PluginDeclaration { + /** + * 添加函数 例:添加弹出文字,像这个就可以使用core.addPop或core.plugin.addPop调用 + * @param px 弹出的横坐标 + * @param py 弹出的纵坐标 + * @param value 弹出的文字 + */ + addPop(px: number, py: number, value: string): void; + + /** + * 添加变量 例:所有的正在弹出的文字,像这个就可以使用core.plugin.pop获取 + */ + pop: any[]; +} + +type Forward = { + [K in keyof T as T[K] extends Function + ? K extends `_${string}` + ? never + : K + : never]: T[K]; +}; + +type ForwardKeys = keyof Forward; + +type SpriteMouseEvent = (px: number, py: number) => void; + +type SpritKeyEvent = ( + key: string, + keyCode: number, + altKey: boolean, + ctrlKey: boolean, + shiftKey: boolean +) => void; + +type SpriteWheelEvent = ( + deltaY: number, + deltaX: number, + deltaZ: number +) => void; + +type SpriteTouchEvent = (...locs: [number, number][]) => void; + +interface SpriteEvent { + click: SpriteMouseEvent; + mousedown: SpriteMouseEvent; + mouseup: SpriteMouseEvent; + mouseenter: SpriteMouseEvent; + mouseleave: SpriteMouseEvent; + mousemove: SpriteMouseEvent; + keydown: SpritKeyEvent; + keyup: SpritKeyEvent; + keypress: SpritKeyEvent; + wheel: SpriteWheelEvent; + touchstart: SpriteTouchEvent; + touchend: SpriteTouchEvent; + touchmove: SpriteTouchEvent; + touchcancel: SpriteTouchEvent; +} + +declare class Sprite { + /** + * 递增的sprite标识符 + */ + static count: number; + + /** + * sprite的左上角横坐标 + */ + x: number; + + /** + * sprite的左上角纵坐标 + */ + y: number; + + /** + * sprite的宽度 + */ + width: number; + + /** + * sprite的高度 + */ + height: number; + + /** + * sprite的纵深 + */ + zIndex: number; + + /** + * sprite的相对模式,相对游戏还是相对窗口 + */ + reference: 'game' | 'window'; + + /** + * sprite的canvas元素 + */ + canvas: HTMLCanvasElement; + + /** + * sprite的context + */ + context: CanvasRenderingContext2D; + + /** + * sprite的名称 + */ + name: string; + + /** + * spirte的唯一标识符 + */ + readonly count: number; + + /** + * 创建一个sprite画布 + * @param reference 参考系,游戏画面或者窗口 + * @param name 可选,sprite的名称,方便通过core.dymCanvas获取 + */ + constructor( + x: number, + y: number, + w: number, + h: number, + z: number, + reference?: 'game' | 'window', + name?: string + ); + + /** + * 初始化 + */ + init(): void; + + /** + * @deprecated + * 设置css特效,使用css()代替 + */ + setCss(css: string): Sprite; + + /** + * 设置css特效 + */ + css(css: string): Sprite; + + /** + * 移动sprite + * @param isDelta 是否是相对位置,如果是,那么sprite会相对于原先的位置进行移动 + */ + move(x: number, y: number, isDelta?: boolean): Sprite; + + /** + * 重新设置sprite的大小 + * @param {boolean} styleOnly 是否只修改css效果,如果是,那么将会不高清,如果不是,那么会清空画布 + */ + resize(w: number, h: number, styleOnly?: boolean): Sprite; + + /** + * 旋转画布 + */ + rotate(angle: number, cx?: number, cy?: number): Sprite; + + /** + * 擦除画布 + */ + clear(x?: number, y?: number, w?: number, h?: number): Sprite; + + /** + * 删除 + */ + destroy(): void; + + /** + * 监听事件,与registerAction类似 + */ + on(type: K, handler: SpriteEvent[K]): void; + + /** + * 添加事件监听器 + */ + addEventListener: HTMLCanvasElement['addEventListener']; + + /** + * 删除事件监听器 + */ + removeEventListenr: HTMLCanvasElement['removeEventListener']; +} diff --git a/project/types/source.d.ts b/project/types/source.d.ts new file mode 100644 index 0000000..4fbcebd --- /dev/null +++ b/project/types/source.d.ts @@ -0,0 +1,98 @@ +/** + * 图块类型 + */ +type Cls = + | 'autotile' + | 'animates' + | 'enemys' + | 'items' + | 'npcs' + | 'terrains' + | 'enemy48' + | 'npc48' + | 'tilesets'; + +/** + * 所有的可动画图块类型 + */ +type AnimatableCls = Exclude; + +/** + * 道具类型 + */ +type ItemCls = 'tools' | 'items' | 'equips' | 'constants'; + +/** + * 所有的道具id + */ +type AllIds = keyof IdToNumber; + +/** + * 所有的道具数字 + */ +type AllNumbers = keyof NumberToId | 0; + +/** + * 某种类型的图块的id + */ +type AllIdsOf = keyof { + [P in keyof IdToCls as IdToCls[P] extends T ? P : never]: P; +}; + +/** + * 某种类型的道具的id + */ +type ItemIdOf = keyof { + [P in keyof ItemDeclaration as ItemDeclaration[P] extends T ? P : never]: P; +}; + +/** + * 某个道具的类型 + */ +type ItemClsOf> = ItemDeclaration[T]; + +/** + * 获取某个图块的类型 + */ +type ClsOf = IdToCls[T]; + +/** + * 某种类型的图块数字 + */ +type AllNumbersOf = IdToNumber[AllIdsOf]; + +/** + * 选取在一段字符串中的映射名称 + */ +type NameMapIn = keyof { + [P in keyof NameMap as NameMap[P] extends T ? P : never]: NameMap[P]; +}; + +/** + * 所有的怪物id + */ +type EnemyIds = AllIdsOf<'enemys' | 'enemy48'>; + +/** + * 各种图块的动画数量 + */ +interface FrameNumbers { + autotile: 4; + animates: 4; + enemys: 2; + items: 1; + npcs: 2; + terrains: 1; + enemy48: 4; + npc48: 4; +} + +/** + * 动画帧数 + */ +type FrameOf = FrameNumbers[T]; + +/** + * 所有的文件名 + */ +type SourceIds = ImageIds | AnimationIds | SoundIds | BgmIds | FontIds; diff --git a/project/types/status.d.ts b/project/types/status.d.ts new file mode 100644 index 0000000..9cfce80 --- /dev/null +++ b/project/types/status.d.ts @@ -0,0 +1,963 @@ +/** + * 怪物buff缓存 + */ +interface EnemyBuffCache { + /** + * 生命值提升量 + */ + hp_buff: number; + + /** + * 攻击提升量 + */ + atk_buff: number; + + /** + * 防御提升量 + */ + def_buff: number; + + /** + * 支援信息 + */ + guards: [number, number, string][]; +} + +interface CheckBlockStatus { + /** + * 捕捉信息 + */ + ambush: Record; + + /** + * 阻击信息 + */ + repulse: Record; + + /** + * 每点的伤害,小于等于0会不显示 + */ + damage: Record; + + /** + * 是否需要重算 + */ + needCache: boolean; + + /** + * 每点的伤害类型 + */ + type: Record>; + + /** + * 缓存信息,是每个怪物受到的光环加成 + */ + cache: Record>; +} + +interface DamageStatus { + /** + * v2优化下当前的偏移横坐标,单位格子 + */ + posX: number; + + /** + * v2优化下当前的偏移纵坐标,单位格子 + */ + posY: number; + + /** + * 显示的伤害信息 + */ + data: DamageStatusData[]; + + /** + * 地图伤害或其它在地图上显示的文字 + */ + extraData: DamageStatusExtraData[]; +} + +interface DamageStatusData { + /** + * 显示的文字 + */ + text: string; + + /** + * 显示横坐标,单位像素 + */ + px: number; + + /** + * 显示纵坐标,单位像素 + */ + py: number; + + /** + * 文字的颜色 + */ + color: Color; +} + +interface DamageStatusExtraData extends DamageStatusData { + /** + * 文字的不透明度 + */ + alpha: number; +} + +interface AutomaticRouteStatus { + /** + * 勇士是否正在移动 + */ + autoHeroMove: boolean; + + /** + * 不太清楚用处 + */ + autoStep: number; + + /** + * 自动寻路中已经走过的步数 + */ + movedStep: number; + + /** + * 自动寻路的总步数 + */ + destStep: number; + + /** + * 自动寻路的目标横坐标 + */ + destX: number; + + /** + * 自动寻路的目标纵坐标 + */ + destY: number; + + /** + * 自动寻路绘图时的偏移横坐标,单位像素 + */ + offsetX: number; + + /** + * 自动寻路绘图时的偏移纵坐标,单位像素 + */ + offsetY: number; + + /** + * 自动寻路的路线 + */ + autoStepRoutes: AutoStep[]; + + /** + * 剩下的自动寻路路线 + */ + moveStepBeforeStop: AutoStep[]; + + /** + * 上一步的勇士方向 + */ + lastDirection: Dir; + + /** + * 光标界面(按下E时的界面)的光标横坐标 + */ + cursorX: number; + + /** + * 光标界面(按下E时的界面)的光标纵坐标 + */ + cursorY: number; + + /** + * 是否瞬间移动 + */ + moveDirectly: boolean; +} + +interface AutoStep { + /** + * 当前步的步数 + */ + step: number; + + /** + * 当前步走向的方向 + */ + direction: Dir; +} + +interface ReplaySaveBase { + /** + * 录像播放时,剩下的要播放的录像内容 + */ + toReplay: string[]; + + /** + * 录像播放时,录像的完整信息 + */ + totalList: string[]; + + /** + * 不太清楚用处,应该是与录像回退有关的 + */ + steps: number; +} + +interface ReplayStatus extends ReplaySaveBase { + /** + * 当前是否正在播放录像,同core.isReplaying() + */ + replaying: boolean; + + /** + * 当前录像有没有暂停 + */ + pausing: boolean; + + /** + * 当前是否正在某段动画中 + */ + animate: boolean; + + /** + * 录像播放是否失败 + */ + failed: boolean; + + /** + * 当前的录像播放速度 + */ + speed: number; + + /** + * 录像的回退信息 + */ + save: ReplaySave[]; +} + +interface ReplaySave { + /** + * 回退的存档信息 + */ + data: Save; + + /** + * 回退的录像信息 + */ + replay: ReplaySaveBase; +} + +interface TextAttribute { + /** + * 文本框的位置 + */ + position: TextPosition; + + /** + * 文本的左右对齐方式 + */ + align: 'left' | 'center' | 'right'; + + /** + * 偏移像素 + */ + offset: number; + + /** + * 标题颜色 + */ + title: RGBArray; + + /** + * 背景颜色 + */ + background: RGBArray | ImageIds; + + /** + * 文字颜色 + */ + text: RGBArray; + + /** + * 标题字体大小 + */ + titlefont: number; + + /** + * 正文字体大小 + */ + textfont: number; + + /** + * 是否加粗 + */ + bold: boolean; + + /** + * 打字机时间,每隔多少毫秒显示一个字 + */ + time: number; + + /** + * 字符间距 + */ + letterSpacing: number; + + /** + * 淡入淡出时间 + */ + animateTime: number; + + /** + * 行距 + */ + lineHeight: number; +} + +interface StatusStyle { + /** + * 左侧状态栏背景,css的background属性 + */ + statusLeftBackground: string; + + /** + * 上部状态栏背景,css的background属性 + */ + statusTopBackground: string; + + /** + * 竖屏下的工具栏背景,css的background属性 + */ + toolsBackground: string; + + /** + * 游戏的边框颜色 + */ + borderColor: Color; + + /** + * 状态栏文字的颜色 + */ + statusBarColor: Color; + + /** + * 楼层切换样式,css字符串 + */ + floorChangingStyle: string; + + /** + * 全局字体 + */ + font: string; +} + +interface GlobalAttribute extends StatusStyle { + /** + * 装备栏名称 + */ + equipName: string[]; +} + +interface FloorAnimate { + /** + * 图片的目标画布 + */ + canvas: 'bg' | 'fg'; + + /** + * 图片的名称 + */ + name: ImageIds; + + /** + * 绘制横坐标 + */ + x: number; + + /** + * 绘制纵坐标 + */ + y: number; + + /** + * 裁剪横坐标 + */ + sx?: number; + + /** + * 裁剪纵坐标 + */ + sy?: number; + + /** + * 裁剪宽度 + */ + w?: number; + + /** + * 裁剪高度 + */ + h?: number; + + /** + * 绘制帧数 + */ + frame?: number; + + /** + * 图片翻转 + */ + reverse?: ':x' | ':y' | ':o'; + + /** + * 是否禁用 + */ + disable?: boolean; +} + +interface BoxAnimate { + /** + * 动画的帧数 + */ + animate: number; + + /** + * 背景的高度 + */ + bgHeight: number; + + /** + * 背景的宽度 + */ + bgWidth: number; + + /** + * 背景的左上角横坐标 + */ + bgx: number; + + /** + * 背景的左上角纵坐标 + */ + bgy: number; + + /** + * 动画图片的高度 + */ + height: 32 | 48; + + /** + * 图片信息 + */ + img: HTMLImageElement; + + /** + * 这个图块的图片在其素材图片的纵坐标 + */ + pos: number; + + /** + * 图块的横坐标 + */ + x: number; + + /** + * 图块的纵坐标 + */ + y: number; +} + +interface BigImageBoxAnimate { + /** + * 大图片的贴图信息 + */ + bigImage: HTMLImageElement; + + /** + * 贴图的朝向 + */ + face: Dir; + + /** + * 中心横坐标 + */ + centerX: number; + + /** + * 中心纵坐标 + */ + centerY: number; + + /** + * 最大宽度 + */ + max_width: number; + + /** + * 绘制到的画布 + */ + ctx: CtxRefer; +} + +interface AnimateObj { + /** + * 动画名称 + */ + name: AnimationIds; + + /** + * 动画的唯一标识符 + */ + id: number; + + /** + * 动画信息 + */ + animate: Animate; + + /** + * 中心横坐标 + */ + centerX: number; + + /** + * 中心纵坐标 + */ + centerY: number; + + /** + * 当前帧数 + */ + index: number; + + /** + * 回调函数 + */ + callback: () => void; +} + +interface ActionsPreview { + /** + * 大地图中当前是否正在拖拽 + */ + dragging: boolean; + + /** + * 大地图中是否允许拖拽 + */ + enabled: boolean; + + /** + * 大地图中当前是否已经按下了鼠标 + */ + prepareDragging: boolean; + + /** + * 当前鼠标的横坐标 + */ + px: number; + + /** + * 当前鼠标的纵坐标 + */ + py: number; +} + +interface RouteFolding { + /** + * 录像折叠信息中的勇士信息 + */ + hero: Omit, 'steps'>; + + /** + * 折叠的长度 + */ + length: number; +} + +/** + * 初始游戏状态 + */ +interface InitGameStatus { + /** + * 是否开始了游戏 + */ + played: false; + + /** + * 游戏是否结束 + */ + gameOver: false; + + /** + * 当前勇士状态信息。例如core.status.hero.atk就是当前勇士的攻击力数值 + */ + hero: {}; + + /** + * 当前层的floorId + */ + floorId: null; + + /** + * 所有楼层的地图信息 + */ + maps: { + [P in FloorIds]: Floor

; + }; + + /** + * 获得当前楼层信息,等价于core.status.maps[core.status.floorId] + */ + thisMap: null; + + /** + * 背景图块 + */ + bgmaps: Record; + + /** + * 前景图块 + */ + fgmaps: Record; + + /** + * 以坐标列举的图块 + */ + mapBlockObjs: Record>; + + /** + * 地图伤害 + */ + checkBlock: {}; + + /** + * 伤害显示信息 + */ + damage: DeepReadonly; + + /** + * 是否锁定了用户控制 + */ + lockControl: false; + + /** + * 勇士移动状态,每个数字干啥的自己去libs翻,这东西太复杂了,不过应该不会有人用这个东西吧( + */ + heroMoving: number; + + /** + * 勇士是否停下了 + */ + heroStop: boolean; + + /** + * 自动寻路状态 + */ + automaticRoute: DeepReadonly; + + /** + * 按键按下的时间,用于判定双击 + */ + downTime: number; + + /** + * ctrl键是否倍按下 + */ + ctrlDown: boolean; + + /** + * 当前录像信息 + */ + route: string[]; + + /** + * 当前的回放状态 + */ + replay: DeepReadonly; + + /** + * 当前的所有全局商店 + */ + shops: Record>; + + /** + * 当前的事件状态,样板最大的败笔之一,离谱到逆天 + */ + event: EventStatusOf; + + /** + * 当前的所有自动事件 + */ + autoEvents: DeepReadonly; + + /** + * 当前的全局剧情文本设置 + */ + textAttribute: TextAttribute; + + /** + * 部分全局属性,会跟随存档 + */ + globalAttribute: GlobalAttribute; + + /** + * 色调的颜色 + */ + curtainColor: Color; + + /** + * 全局动画对象 + */ + globalAnimateObjs: Block>>[]; + + /** + * 楼层贴图 + */ + floorAnimateObjs: FloorAnimate[]; + + /** + * 所有的BoxAnimate信息 + */ + boxAnimateObjs: (BoxAnimate | BigImageBoxAnimate)[]; + + /** + * 所有的自动元件动画 + */ + autotileAnimateObjs: Block>[]; + + /** + * 全局动画状态,每经过一个全局动画时间便加一 + */ + globalAnimateStatus: number; + + /** + * 所有绘制的动画 + */ + animateObjs: AnimateObj[]; + + /** + * 当前难度 + */ + hard: string; + + /** + * 勇士的中心 + */ + heroCenter: Record<'px' | 'py', number>; + + /** + * 当前按下的按键 + */ + holdingKeys: number[]; + + /** + * id转数字 + */ + id2number: IdToNumber; + + /** + * 数字转图块 + */ + number2block: { + [P in AllNumbers]: Block

; + }; + + /** + * 大地图中的拖拽处理 + */ + preview: ActionsPreview; + + /** + * 录像折叠信息 + */ + routeFolding: Record<`${LocString},${FirstCharOf

}`, RouteFolding>; +} + +/** + * 运行时的游戏状态 + */ +interface GameStatus extends InitGameStatus { + played: boolean; + gameOver: boolean; + floorId: FloorIds; + thisMap: ResolvedFloor; + checkBlock: Readonly; + lockControl: boolean; + hero: HeroStatus; +} + +interface Follower { + /** + * 跟随者的图片id + */ + name: ImageIds; +} + +interface HeroStatistics { + /** + * 击败的怪物数量 + */ + battle: number; + + /** + * 由于战斗损失的生命值 + */ + battleDamage: number; + + /** + * 当前游戏时间 + */ + currentTime: number; + + /** + * 获得的总经验值 + */ + exp: number; + + /** + * 由于地图伤害损失的生命值 + */ + extraDamage: number; + + /** + * 总共损失的生命值 + */ + hp: number; + + /** + * 由于瞬移少走的步数 + */ + ignoreSteps: number; + + /** + * 总共获得的金币数 + */ + money: number; + + /** + * 瞬移次数 + */ + moveDirectly: number; + + /** + * 中毒损失的生命值 + */ + poisonDamage: number; + + /** + * 本次游戏的开始时间 + */ + startTime: number; + + /** + * 游戏总时间 + */ + totalTime: number; +} + +/** + * 勇士状态 + */ +interface HeroStatus { + /** + * 勇士停止时及对话框中是否启用帧动画 + */ + animate: boolean; + + /** + * 勇士生命值 + */ + hp: number; + + /** + * 勇士生命上限 + */ + hpmax: number; + + /** + * 勇士的攻击 + */ + atk: number; + + /** + * 勇士的防御 + */ + def: number; + + /** + * 勇士的魔防 + */ + mdef: number; + + /** + * 勇士的等级 + */ + lv: number; + + /** + * 勇士的经验 + */ + exp: number; + + /** + * 勇士的金币 + */ + money: number; + + /** + * 勇士的魔法 + */ + mana: number; + + /** + * 勇士的魔法上限 + */ + manamax: number; + + /** + * 勇士的名称 + */ + name: string; + + /** + * 勇士移动过的步数 + */ + steps: number; + + /** + * 勇士的图片 + */ + image: ImageIds; + + /** + * 当前勇士的装备 + */ + equipment: ItemIdOf<'equips'>[]; + + /** + * 勇士当前的位置 + */ + loc: Loc; + + /** + * 当前的变量 + */ + flags: Flags; + + /** + * 勇士的跟随者 + */ + followers: Follower[]; + + /** + * 勇士拥有的道具 + */ + items: { + [P in Exclude]: Record, number>; + }; +} diff --git a/project/types/ui.d.ts b/project/types/ui.d.ts new file mode 100644 index 0000000..fb301dc --- /dev/null +++ b/project/types/ui.d.ts @@ -0,0 +1,827 @@ +/** + * 可以设置成的画布填充描边样式 + */ +type CanvasStyle = string | CanvasGradient | CanvasPattern; + +type ImageSource = + | CanvasImageSource + | ImageIds + | `${ImageIds}${ImageReverse}` + | NameMapIn + | `${NameMapIn}${ImageReverse}`; + +interface BackgroundPosInfo { + /** + * 横坐标 + */ + px: number; + + /** + * 纵坐标 + */ + py: number; + + /** + * 是否没有位置 + */ + noPeak: boolean; + + /** + * 横坐标偏移值 + */ + xoffset: number; + + /** + * 纵坐标偏移值 + */ + yoffset: number; + + /** + * 画布,默认是ui + */ + ctx: CtxRefer; + + /** + * 箭头指向是朝上还是朝下 + */ + position: 'up' | 'bottom'; +} + +interface TextContentConfig { + left: number; + top: number; + + /** + * 最大宽度 + */ + maxWidth: number; + + /** + * 颜色,不影响\r + */ + color: Color; + + /** + * 对齐方式 + */ + align: 'left' | 'center' | 'right'; + + /** + * 字体大小 + */ + fontSize: number; + + /** + * 行高 + */ + lineHeight: number; + + /** + * 打字机间隔 + */ + time: number; + + /** + * 字体名 + */ + font: string; + + /** + * 字符间距 + */ + letterSpacing: number; + + /** + * 是否加粗 + */ + bold: boolean; + + /** + * 是否斜体 + */ + italic: boolean; +} + +interface TextContentBlock { + left: number; + top: number; + width: number; + height: number; + line: number; + marginLeft: number; + marginTop: number; +} + +interface ReturnedTextContentConfig extends TextContentConfig { + right: number; + + /** + * 默认字体 + */ + defaultFont: string; + + /** + * 当前绘制的文字索引 + */ + index: number; + + /** + * 当前颜色 + */ + currcolor: Color; + + /** + * 当前字体 + */ + currfont: string; + + /** + * 每一行的间距 + */ + lineMargin: number; + + /** + * 每一行间距的一半 + */ + topMargin: number; + + /** + * 横坐标偏移量 + */ + offsetX: number; + + /** + * 纵坐标偏移量 + */ + offsetY: number; + + /** + * 当前行数 + */ + line: number; + + /** + * 所有的文字 + */ + blocks: TextContentBlock[]; + + /** + * 是否是高清画布 + */ + isHD: boolean; + + /** + * 这一行的最大高度 + */ + lineMaxHeight: number; + + /** + * 是否是强制换行 + */ + forceChangeLine: boolean; +} + +interface TextBoxConfig { + /** + * 画布 + */ + ctx: CtxRefer; + + /** + * 对话框位置 + */ + pos: TextBoxPos; + + /** + * 是否一次性全部显示 + */ + showAll: boolean; + + /** + * 是否异步显示 + */ + async: boolean; +} + +/** + * UI窗口的绘制,如对话框、怪物手册、楼传器、存读档界面等 + */ +interface Ui { + /** + * ui数据 + */ + uidata: UiData; + + /** + * 根据画布名找到一个画布的context;支持系统画布和自定义画布。如果不存在画布返回null。 + * 也可以传画布的context自身,则返回自己。 + */ + getContextByName(canvas: CtxRefer): CanvasRenderingContext2D | null; + + /** + * 清空某个画布图层 + * name为画布名,可以是系统画布之一,也可以是任意自定义动态创建的画布名;还可以直接传画布的context本身。(下同) + * 如果name也可以是'all',若为all则为清空所有系统画布。 + */ + clearMap( + name: CtxRefer, + x?: number, + y?: number, + w?: number, + h?: number + ): void; + + /** + * 在某个画布上绘制一段文字 + * @param text 要绘制的文本 + * @param style 绘制的样式 + * @param font 绘制的字体 + * @param maxWidth 文字整体的最大宽度,如果超过会自动缩小文字使其宽度小于这个值 + */ + fillText( + name: CtxRefer, + text: string, + x: number, + y: number, + style?: CanvasStyle, + font?: string, + maxWidth?: number + ): void; + + /** + * 根据最大宽度自动缩小字体 + * @param name 画布 + * @param text 文字 + * @param maxWidth 最大和宽度 + * @param font 字体 + */ + setFontForMaxWidth( + name: CtxRefer, + text: string, + maxWidth: number, + font?: string + ): void; + + /** + * 在某个画布上绘制一个描边文字 + * @param text 要绘制的文本 + * @param style 绘制的样式 + * @param strokeStyle 绘制的描边颜色 + * @param font 绘制的字体 + * @param lineWidth 描边的线宽 + */ + fillBoldText( + name: CtxRefer, + text: string, + x: number, + y: number, + style?: CanvasStyle, + strokeStyle?: CanvasStyle, + font?: string, + maxWidth?: number, + lineWidth?: number + ): void; + + /** + * 绘制一个矩形 + * @param style 绘制的样式 + * @param angle 旋转角度,弧度制 + */ + fillRect( + name: CtxRefer, + x: number, + y: number, + width: number, + height: number, + style?: CanvasStyle, + angle?: number + ): void; + + /** + * 绘制一个矩形的边框 + * @param style 绘制的样式 + * @param angle 旋转角度,单位弧度 + */ + strokeRect( + name: CtxRefer, + x: number, + y: number, + width: number, + height: number, + style?: CanvasStyle, + lineWidth?: number, + angle?: number + ): void; + + /** + * 在某个canvas上绘制一个圆角矩形 + */ + fillRoundRect( + name: CtxRefer, + x: number, + y: number, + width: number, + height: number, + radius: number, + style?: CanvasStyle, + angle?: number + ): void; + + /** + * 在某个canvas上绘制一个圆角矩形的边框 + */ + strokeRoundRect( + name: CtxRefer, + x: number, + y: number, + width: number, + height: number, + radius: number, + style?: CanvasStyle, + lineWidth?: number, + angle?: number + ): void; + + /** + * 在某个canvas上绘制一个多边形 + */ + fillPolygon( + name: CtxRefer, + nodes?: [x: number, y: number][], + style?: CanvasStyle + ): void; + + /** + * 在某个canvas上绘制一个多边形的边框 + */ + strokePolygon( + name: CtxRefer, + nodes?: [x: number, y: number][], + style?: CanvasStyle, + lineWidth?: number + ): void; + + /** + * 在某个canvas上绘制一个椭圆 + * @param a 横轴长度的一半 + * @param b 纵轴长度的一半 + * @param angle 旋转角度 + */ + fillEllipse( + name: CtxRefer, + x: number, + y: number, + a: number, + b: number, + angle?: number, + style?: CanvasStyle + ): void; + + /** + * 在某个canvas上绘制一个圆 + */ + fillCircle( + name: CtxRefer, + x: number, + y: number, + r: number, + style?: CanvasStyle + ): void; + + /** + * 在某个canvas上绘制一个椭圆的边框 + * @param a 横轴长度的一半 + * @param b 纵轴长度的一半 + * @param angle 旋转角度 + */ + strokeEllipse( + name: CtxRefer, + x: number, + y: number, + a: number, + b: number, + angle?: number, + style?: CanvasStyle, + lineWidth?: number + ): void; + + /** + * 在某个canvas上绘制一个圆的边框 + */ + strokeCircle( + name: CtxRefer, + x: number, + y: number, + r: any, + style?: CanvasStyle, + lineWidth?: number + ): void; + + /** + * 在某个canvas上绘制一个扇形 + */ + fillArc( + name: CtxRefer, + x: number, + y: number, + r: number, + start: number, + end: number, + style?: CanvasStyle + ): void; + + /** + * 在某个canvas上绘制一段弧 + */ + strokeArc( + name: CtxRefer, + x: number, + y: number, + r: number, + start: number, + end: number, + style?: CanvasStyle, + lineWidth?: number + ): void; + + /** + * 在某个canvas上绘制一条线 + */ + drawLine( + name: CtxRefer, + x1: number, + y1: number, + x2: number, + y2: number, + style?: CanvasStyle, + lineWidth?: number + ): void; + + /** + * 在某个canvas上绘制一个箭头 + */ + drawArrow( + name: CtxRefer, + x1: number, + y1: number, + x2: number, + y2: number, + style?: CanvasStyle, + lineWidth?: number + ): void; + + /** + * 设置某个canvas的文字字体 + */ + setFont(name: CtxRefer, font: string): void; + + /** + * 设置某个canvas的线宽度 + */ + setLineWidth(name: CtxRefer, lineWidth: number): void; + + /** + * 保存某个canvas状态 + */ + saveCanvas(name: CtxRefer): void; + + /** + * 回退某个canvas状态 + */ + loadCanvas(name: CtxRefer): void; + + /** + * 设置某个canvas的绘制不透明度 + * @returns 之前画布的不透明度 + */ + setAlpha(name: CtxRefer, alpha: number): number; + + /** + * 设置画布元素的不透明度 + */ + setOpacity(name: CtxRefer, opacity: number): void; + + /** + * 设置某个canvas的滤镜 + */ + setFilter(name: CtxRefer, filter?: string): void; + + /** + * 设置某个canvas的填充样式 + */ + setFillStyle(name: CtxRefer, style: CanvasStyle): void; + + /** + * 设置某个canvas描边样式 + */ + setStrokeStyle(name: CtxRefer, style: CanvasStyle): void; + + /** + * 设置某个canvas的文字左右对齐方式 + */ + setTextAlign(name: CtxRefer, align: CanvasTextAlign): void; + + /** + * 设置某个canvas的文字上下对齐方式 + */ + setTextBaseline(name: CtxRefer, baseline: CanvasTextBaseline): void; + + /** + * 计算某段文字的宽度,注意该函数会设置画布的字体 + */ + calWidth(name: CtxRefer, text: string, font?: string): number; + + /** + * 字符串自动换行的分割 + */ + splitLines( + name: CtxRefer, + text: string, + maxWidth?: number, + font?: string + ): string[]; + + /** + * 绘制图片 + * @param dx 绘制的横坐标 + * @param dy 绘制的纵坐标 + */ + drawImage(name: CtxRefer, image: ImageSource, dx: number, dy: number): void; + /** + * 绘制图片 + * @param dx 绘制的横坐标 + * @param dy 绘制的纵坐标 + * @param dw 绘制的宽度 + * @param dh 绘制的高度 + */ + drawImage( + name: CtxRefer, + image: ImageSource, + dx: number, + dy: number, + dw: number, + dh: number + ): void; + /** + * 绘制图片 + * @param sx 裁剪的横坐标 + * @param sy 裁剪的纵坐标 + * @param sw 裁剪的宽度 + * @param sh 裁剪的高度 + * @param dx 绘制的横坐标 + * @param dy 绘制的纵坐标 + * @param dw 绘制的宽度 + * @param dh 绘制的高度 + */ + drawImage( + name: CtxRefer, + image: ImageSource, + sx: number, + sy: number, + sw: number, + sh: number, + dx: number, + dy: number, + dw: number, + dh: number + ): void; + + /** + * 在某个canvas上绘制一个图标 + * @param frame 图标的第几帧 + */ + drawIcon( + name: CtxRefer, + id: AllIds, + x: number, + y: number, + w?: number, + h?: number, + frame?: number + ): void; + + /** + * 结束一切事件和绘制,关闭UI窗口,返回游戏进程 + */ + closePanel(): void; + + /** + * 清空UI层内容 + */ + clearUI(): void; + + /** + * 左上角绘制一段提示 + * @param text 要提示的文字内容 + * @param id 要绘制的图标ID + * @param frame 要绘制图标的第几帧 + */ + drawTip(text: string, id?: AllIds, frame?: number): void; + + /** + * 地图中间绘制一段文字 + */ + drawText(contents: string, callback?: () => void): void; + + /** + * 自绘选择光标 + */ + drawUIEventSelector( + code: number, + background: RGBArray | ImageIds, + x: number, + y: number, + w: number, + h: number, + z?: number + ): void; + + /** + * 清除一个或多个选择光标 + * @param code 要清除的选择光标,不填表示清除所有 + */ + clearUIEventSelector(code?: number | number[]): void; + + /** + * 绘制WindowSkin + * @param direction 指向箭头的方向 + */ + drawWindowSkin( + background: any, + ctx: CtxRefer, + x: number, + y: number, + w: number, + h: number, + direction?: 'up' | 'down', + px?: number, + py?: number + ): void; + + /** + * 绘制一个背景图,可绘制winskin或纯色背景;支持小箭头绘制 + */ + drawBackground( + left: string, + top: string, + right: string, + bottom: string, + posInfo?: Partial + ): void; + + /** + * 绘制一段文字到某个画布上面 + * @param ctx 要绘制到的画布 + * @param content 要绘制的内容;转义字符只允许保留 \n, \r[...], \i[...], \c[...], \d, \e + * @param config 绘制配置项 + * @returns 绘制信息 + */ + drawTextContent( + ctx: CtxRefer, + content: string, + config: Partial + ): ReturnedTextContentConfig; + + /** + * 获得某段文字的预计绘制高度 + */ + getTextContentHeight( + content: string, + config: Partial + ): number; + + /** + * 绘制一个对话框 + */ + drawTextBox(content: string, config?: TextBoxConfig): void; + + /** + * 绘制滚动字幕 + */ + drawScrollText( + content: string, + time?: number, + lineHeight?: number, + callback?: () => void + ): void; + + /** + * 文本图片化 + */ + textImage(content: string, lineHeight?: number): HTMLCanvasElement; + + /** + * 绘制一个选项界面 + */ + drawChoices( + content: string, + choices: string[], + width?: number, + ctx?: CtxRefer + ): void; + + /** + * 绘制一个确认框 + */ + drawConfirmBox( + text: string, + yesCallback?: () => void, + noCallback?: () => void, + ctx?: CtxRefer + ): void; + + /** + * 绘制等待界面 + */ + drawWaiting(text: string): void; + + /** + * 绘制分页 + */ + drawPagination(page: number, totalPage: number, y?: number): void; + + /** + * 绘制怪物手册 + */ + drawBook(index: number): void; + + /** + * 绘制楼层传送器 + */ + drawFly(page: number): void; + + /** + * 获得所有应该在道具栏显示的某个类型道具 + */ + getToolboxItems>(cls: T): ItemIdOf[]; + + /** + * 绘制状态栏 + */ + drawStatusBar(): void; + + /** + * 动态创建一个画布 + * @param name 画布名称,如果已存在则会直接取用当前存在的 + * @param x 横坐标 + * @param y 纵坐标 + * @param width 宽度 + * @param height 高度 + * @param zIndex 纵深 + * @param nonAntiAliasing 是否取消抗锯齿 + */ + createCanvas( + name: string, + x: number, + y: number, + width: number, + height: number, + zIndex?: number, + nonAntiAliasing?: boolean + ): CanvasRenderingContext2D; + + /** + * 重新定位一个自定义画布 + */ + relocateCanvas( + name: string, + x: number, + y: number, + useDelta?: boolean + ): void; + + /** + * 设置一个自定义画布的旋转角度 + */ + rotateCanvas( + name: CtxRefer, + angle: number, + centerX?: number, + centerY?: number + ): void; + + /** + * 重新设置一个自定义画布的大小 + * @param styleOnly 是否只修改style,而不修改元素上的长宽,如果是true,会出现模糊现象 + * @param isTempCanvas 是否是临时画布,如果填true,会将临时画布修改为高清画布 + */ + resizeCanvas( + name: string, + x?: number, + y?: number, + styleOnly?: boolean, + isTempCanvas?: boolean + ): void; + + /** + * 删除一个自定义画布 + */ + deleteCanvas(name: string | ((name: string) => boolean)): void; + + /** + * 清空所有的自定义画布 + */ + deleteAllCanvas(): void; +} + +declare const ui: new () => Ui; diff --git a/project/types/util.d.ts b/project/types/util.d.ts new file mode 100644 index 0000000..a5f21f2 --- /dev/null +++ b/project/types/util.d.ts @@ -0,0 +1,884 @@ +/** 工具类 主要用来进行一些辅助函数的计算 */ +interface Utils { + /** + * 四个方向的坐标增量 + */ + readonly scan: DeepReadonly; + + /** + * 八个方向的坐标增量 + */ + readonly scan2: DeepReadonly; + + /** + * 将一段文字中的${}(表达式)进行替换。很多情况下可以用模板字符串替代 + * @example + * // 把主角的生命值和持有的黄钥匙数量代入这句话 + * core.replaceText('衬衫的价格是${status:hp}镑${item:yellowKey}便士。'); + * @param text 模板字符串,可以使用${}计算js表达式 + * @param prefix 独立开关前缀 + * @returns 替换完毕后的字符串 + */ + replaceText(text: string, prefix?: string): string; + + /** + * 对一个表达式中的特殊规则进行替换,如status:xxx等。 + * 其中变量和全局存储会替换中文冒号,其余的不会替换 + * @example + * // 把这两个冒号表达式替换为core.getStatus('hp')和core.itemCount('yellowKey')这样的函数调用 + * core.replaceValue('衬衫的价格是${status:hp}镑${item:yellowKey}便士。'); + * @param value 模板字符串,注意独立开关不会被替换 + * @returns 替换完毕后的字符串 + */ + replaceValue(value: string): string; + + /** + * 计算一个表达式的值,支持status:xxx等的计算。 + * @example core.calValue('status:hp + status:def'); // 计算主角的生命值加防御力 + * @param value 待求值的表达式 + * @param prefix 独立开关前缀,一般可省略 + * @returns 求出的值 + */ + calValue(value: string | Function, prefix?: string): any; + + /** + * @deprecated + * 将b(可以是另一个数组)插入数组a的开头,用Array.unshift就行 + * @example core.unshift(todo, {type: 'unfollow'}); // 在事件指令数组todo的开头插入“取消所有跟随者”指令 + * @param a 原数组 + * @param b 待插入的新首项或前缀数组 + * @returns 插入完毕后的新数组,它是改变原数组a本身得到的 + */ + unshift(a: A, b: B): [...B, ...A]; + + /** + * @deprecated + * 将b(可以是另一个数组)插入数组a的末尾,用Array.push就行 + * @example core.push(todo, {type: 'unfollow'}); // 在事件指令数组todo的末尾插入“取消所有跟随者”指令 + * @param a 原数组 + * @param b 待插入的新末项或后缀数组 + * @returns 插入完毕后的新数组,它是改变原数组a本身得到的 + */ + push(a: A, b: B): [...A, ...B]; + + /** + * 解压缩一个数据,我也不知道这个解压的是什么 + * @param 要解压的内容,字符串 + */ + decompress(value: string): any; + + /** + * 设置本地存储 + * @param key 本地存储的名称 + * @param value 本地存储的值,不填代表删除 + */ + setLocalStorage(key: string, value?: any): void; + + /** + * 获得本地存储 + * @param key 获取的本地存储的名称 + * @param defaultValue 当不存在的时候的默认值 + */ + getLocalStorage(key: string, defaultValue?: T): T; + + /** + * 移除本地存储 + * @param key 要移除的本地存储的值 + */ + removeLocalStorage(key: string): void; + + /** + * 异步写入localforage + * @param key 写入的键 + * @param value 写入的值 + * @param successCallback 写入成功的回调函数 + * @param errorCallback 写入出错的回调函数 + */ + setLocalForage( + key: string, + value?: any, + successCallback?: () => void, + errorCallback?: (err: Error) => void + ): void; + + /** + * 从localforage读出一段数据 + */ + getLocalForage( + key: string, + defaultValue?: T, + successCallback?: (data: T) => void, + errorCallback?: (err: Error) => void + ): void; + + /** + * 移除localforage的数据 + */ + removeLocalForage( + key: string, + successCallback?: () => void, + errorCallback?: (err: Error) => void + ): void; + + /** + * 清除localforage所有的数据 + * @param callback 清除完毕的回调函数 + */ + clearLocalForage(callback?: (err?: Error) => void): void; + + /** + * 迭代localforage的数据 + * @param iteratee 迭代器 + * @param callback 迭代完毕的回调函数 + */ + iterateLocalForage( + iteratee: (value: T, key: string, iterationNumber: number) => U, + callback?: (err: any, result: U) => void + ): void; + + /** + * 获取localforage数据的所有的键 + * @param callback 回调函数 + */ + keysLocalForage(callback?: (err: any, keys: string[]) => void): void; + + /** + * 获取localforage数据的数据量 + * @param callback 回调函数 + */ + lengthLocalForage( + callback?: (err: any, numberOfKeys: number) => void + ): void; + + /** + * 设置一个全局存储,适用于global:xxx,录像播放时将忽略此函数。 + * @example core.setBlobal('一周目已通关', true); // 设置全局存储“一周目已通关”为true,方便二周目游戏中的新要素。 + * @param key 全局变量名称,支持中文 + * @param value 全局变量的新值,不填或null表示清除此全局存储 + */ + setGlobal(key: string, value?: any): void; + + /** + * 读取一个全局存储,适用于global:xxx,支持录像。 + * @example if (core.getGlobal('一周目已通关', false) === true) core.getItem('dagger'); // 二周目游戏进行到此处时会获得一把屠龙匕首 + * @param key 全局变量名称,支持中文 + * @param defaultValue 可选,当此全局变量不存在或值为null、undefined时,用此值代替 + * @returns 全局变量的值 + */ + getGlobal(key: string, defaultValue?: T): T; + + /** + * 深拷贝一个对象(函数将原样返回) + * @example core.clone(core.status.hero, (name, value) => (name == 'items' || typeof value == 'number'), false); // 深拷贝主角的属性和道具 + * @param data 待拷贝对象 + * @param filter 过滤器,可选,表示data为数组或对象时拷贝哪些项或属性,true表示拷贝 + * @param recursion 过滤器是否递归,可选。true表示过滤器也被递归 + * @returns 拷贝的结果,注意函数将原样返回 + */ + clone( + data: T, + filter?: (name: string, value: any) => boolean, + recursion?: boolean + ): T; + + /** + * 深拷贝一个1D或2D的数组 + * @param data 要拷贝的数据 + */ + cloneArray(data: T): T; + + /** + * 等比例切分一张图片 + * @example core.splitImage(core.material.images.images['npc48.png'], 32, 48); // 把npc48.png切分成若干32×48px的小人 + * @param image 图片名(支持映射前的中文名)或图片对象(参见上面的例子),获取不到时返回[] + * @param width 子图的宽度,单位为像素。原图总宽度必须是其倍数,不填视为32 + * @param height 子图的高度,单位为像素。原图总高度必须是其倍数,不填视为正方形 + * @returns 子图组成的数组,在原图中呈先行后列,从左到右、从上到下排列。 + */ + splitImage( + image: NameMapIn | ImageIds | HTMLImageElement, + width?: number, + height?: number + ): HTMLImageElement[]; + + /** + * 格式化日期为字符串 + * @param date 时间,不填代表当前时间 + * @returns 格式: yyyy-mm-dd hh:mm:ss + */ + formatDate(date?: Date): string; + + /** + * 格式化日期为最简字符串 + * @param date 时间,不填代表当前时间 + * @returns 格式: yyyymmddhhmmss + */ + formatDate2(date?: Date): string; + + /** + * 格式化时间 + * @param time 时间 + * @returns 格式: hh:mm:ss + */ + formatTime(time: number): string; + + /** + * @deprecated + * 设置成两位数显示,请使用setDigits代替 + */ + setTwoDigits(x: number): string; + + /** + * 设置一个数为n位数显示 + * @param x 要设置的数 + * @param n 设置成的位数 + */ + setDigits(x: number, n: number): string; + + /** + * 格式化文件大小 + * @param size 大小,字节数 + * @returns 格式为xx.xxB KB MB + */ + formatSize(size: number): string; + + /** + * 大数字格式化,单位为10000的倍数(w,e,z,j,g),末尾四舍五入 + * @example core.formatBigNumber(123456789); // "12346w" + * @param x 原数字 + * @param onMap 显示的字符数 + * @returns 格式化结果 + */ + formatBigNumber(x: number, onMap?: number): string; + + /** + * @deprecated + * 变速移动,完全可以用mutate-animate代替 + * @param mode 缓动模式 + */ + applyEasing(mode?: EaseMode): (x: number) => number; + + /** + * 颜色数组转十六进制 + * @example core.arrayToRGB([102, 204, 255]); // "#66ccff",加载画面的宣传色 + * @param color 一行三列的数组,各元素必须为不大于255的自然数 + * @returns 该颜色的十六进制表示,使用小写字母 + */ + arrayToRGB(color: RGBArray): string; + + /** + * 颜色数组转字符串 + * @example core.arrayToRGBA([102, 204, 255]); // "rgba(102,204,255,1)" + * @param color 一行三列或一行四列的数组,前三个元素必须为不大于255的自然数。 + * 第四个元素(如果有)必须为0或不大于1的数字,第四个元素不填视为1 + * @returns 该颜色的字符串表示 + */ + arrayToRGBA(color: RGBArray): string; + + /** + * 录像一压,其结果会被再次base64压缩 + * @example core.encodeRoute(core.status.route); // 一压当前录像 + * @param route 原始录像,自定义内容(不予压缩,原样写入)必须由0-9A-Za-z和下划线、冒号组成, + * 所以中文和数组需要用JSON.stringify预处理再base64压缩才能交由一压 + * @returns 一压的结果 + */ + encodeRoute(route: string[]): string; + + /** + * 录像解压的最后一步,即一压的逆过程 + * @example core.decodeRoute(core.encodeRoute(core.status.route)); // 一压当前录像再解压-_-| + * @param route 录像解压倒数第二步的结果,即一压的结果 + * @returns 原始录像 + */ + decodeRoute(route: string): string[]; + + /** + * 判断一个值是否不为null,undefined和NaN + * @example core.isset(0/0); // false,因为0/0等于NaN + * @param v 待测值 + * @returns false表示待测值为null、undefined、NaN或未填写,true表示为其他值 + */ + isset(v?: any): boolean; + + /** + * 判定一个数组是否为另一个数组的前缀,用于录像接续播放 + * @example core.subarray(['ad', '米库', '小精灵', '小破草', '小艾'], ['ad', '米库', '小精灵']); // ['小破草', '小艾'] + * @param a 可能的母数组,不填或比b短将返回null + * @param b 可能的前缀,不填或比a长将返回null + * @returns 如果b不是a的前缀将返回null,否则将返回a去掉此前缀后的剩余数组 + */ + subarray(a: any[], b: any[]): any[] | null; + + /** + * @deprecated + * 判定array是不是一个数组,以及element是否在该数组中。使用Array.includes代替 + * @param array 可能的数组,不为数组或不填将导致返回值为false + * @param element 待查找的元素 + * @returns 如果array为数组且具有element这项,就返回true,否则返回false + */ + inArray(array?: any, element?: any): boolean; + + /** + * 将x限定在[a,b]区间内,注意a和b可交换 + * @example core.clamp(1200, 1, 1000); // 1000 + * @param x 原始值,!x为true时x一律视为0 + * @param a 下限值,大于b将导致与b交换 + * @param b 上限值,小于a将导致与a交换 + */ + clamp(x: number, a: number, b: number): number; + + /** + * 访问浏览器cookie + */ + getCookie(name: string): string; + + /** + * 填写非自绘状态栏 + * @example + * // 更新状态栏中的主角生命,使用加载画面的宣传色 + * core.setStatusBarInnerHTML('hp', core.status.hero.hp, 'color: #66CCFF'); + * @param name 状态栏项的名称,如'hp', 'atk', 'def'等。必须是core.statusBar中的一个合法项 + * @param value 要填写的内容,大数字会被格式化为至多6个字符,无中文的内容会被自动设为斜体 + * @param css 额外的css样式,可选。如更改颜色等 + */ + setStatusBarInnerHTML( + name: string, + value: string | number, + css?: string + ): void; + + /** + * 求字符串的国标码字节数,也可用于等宽字体下文本的宽度测算。请注意样板的默认字体Verdana不是等宽字体 + * @example core.strlen('无敌ad'); // 6 + * @param str 待测字符串 + * @returns 字符串的国标码字节数,每个汉字为2,每个ASCII字符为1 + */ + strlen(str: string): number; + + /** + * 计算应当转向某个方向 + * @param turn 转向的方向 + * @param direction 当前方向,不填视为当前方向 + */ + turnDirection(turn: HeroTurnDir, direction?: Dir): string; + + /** + * 通配符匹配,用于搜索图块等批量处理。 + * @example core.playSound(core.matchWildcard('*Key', itemId) ? 'item.mp3' : 'door.mp3'); // 判断捡到的是钥匙还是别的道具,从而播放不同的音效 + * @param pattern 模式串,每个星号表示任意多个(0个起)字符 + * @param string 待测串 + * @returns true表示匹配成功,false表示匹配失败 + */ + matchWildcard(pattern: string, string: string): boolean; + + /** + * 是否满足正则表达式,一般可以直接用/RegExp/.test(str)代替 + * @param pattern 正则表达式 + * @param string 要匹配的字符串 + */ + matchRegex(pattern: string, string: string): string; + + /** + * base64加密 + * @example + * core.encodeBase64('If you found this note in a small wooden box with a heart on it'); + * // "SWYgeW91IGZvdW5kIHRoaXMgbm90ZSBpbiBhIHNtYWxsIHdvb2RlbiBib3ggd2l0aCBhIGhlYXJ0IG9uIGl0" + * @param str 明文 + * @returns 密文 + */ + encodeBase64(str: string): string; + + /** + * base64解密 + * @example + * core.decodeBase64('SWYgeW91IGZvdW5kIHRoaXMgbm90ZSBpbiBhIHNtYWxsIHdvb2RlbiBib3ggd2l0aCBhIGhlYXJ0IG9uIGl0'); + * // "If you found this note in a small wooden box with a heart on it" + * @param str 密文 + * @returns 明文 + */ + decodeBase64(str: string): string; + + /** + * 不支持SL的随机数 + * @exmaple 1 + core.rand(6); // 随机生成一个小于7的正整数,模拟骰子的效果 + * @param num 填正数表示生成小于num的随机自然数,否则生成小于1的随机正数 + * @returns 随机数,即使读档也不会改变结果 + */ + rand(num?: number): number; + + /** + * 支持SL的随机数,并计入录像 + * @exmaple 1 + core.rand2(6); // 随机生成一个小于7的正整数,模拟骰子的效果 + * @param num 正整数,0或不填会被视为2147483648 + * @returns 属于 [0, num) 的随机数 + */ + rand2(num?: number): number; + + /** + * 尝试请求读取一个本地文件内容 [异步] + * @param success 成功后的回调 + * @param error 失败后的回调 + * @param accept input元素的accept属性 + * @param readType 不设置则以文本读取,否则以DataUrl形式读取 + */ + readFile( + success: (obj: any) => void, + error: () => void, + accept: string, + readType: boolean + ): void; + + /** + * 文件读取完毕后的内容处理 [异步] + * @param content 读取的内容 + */ + readFileContent(content: string): void; + + /** + * 弹窗请求下载一个文本文件 + * @example core.download('route.txt', core.status.route); // 弹窗请求下载录像 + * @param filename 文件名 + * @param content 文件内容 + */ + download(filename: string, content: string | string[]): void; + + /** + * 尝试复制一段文本到剪切板 + * @param data 赋值的东西 + */ + copy(data: string): void; + + /** + * 显示确认框,类似core.drawConfirmBox() + * @example core.myconfirm('重启游戏?', core.restart); // 弹窗询问玩家是否重启游戏 + * @param hint 弹窗的内容 + * @param yesCallback 确定后的回调函数 + * @param noCallback 取消后的回调函数 + */ + myconfirm( + hint: string, + yesCallback: () => void, + noCallback?: () => void + ): void; + + /** + * 让用户输入一段文字 + */ + myprompt( + hint: string, + value: string, + callback?: (data?: string) => void + ): void; + + /** + * @deprecated + * 动画显示某对象,有vue了,你还用这个?Transition组件和css的transition比这个强得多 + */ + showWithAnimate( + obj?: HTMLElement, + speed?: number, + callback?: () => any + ): void; + + /** + * @deprecated + * 动画使某对象消失 + */ + hideWithAnimate( + obj?: HTMLElement, + speed?: number, + callback?: () => any + ): void; + + /** + * 获得浏览器唯一的guid + */ + getGuid(): string; + + /** + * 获取一个对象的哈希值 + * @param obj 要获取的对象 + */ + hashCode(obj: any): number; + + /** + * 判定深层相等, 会逐层比较每个元素 + * @example core.same(['1', 2], ['1', 2]); // true + */ + same(a: any, b: any): boolean; + + /** + * 解压一段内容 + */ + unzip( + blobOrUrl: string | Blob, + success?: (data: any) => void, + error?: (error: string) => void, + convertToText?: boolean, + onprogress?: (loaded: number, total: number) => void + ): void; + + /** + * 发送一个HTTP请求 [异步] + * @param type 请求类型 + * @param url 目标地址 + * @param formData 如果是POST请求则为表单数据 + * @param success 成功后的回调 + * @param error 失败后的回调 + */ + http( + type: 'GET' | 'POST', + url: string, + formData?: FormData, + success?: (res: any) => void, + error?: (err: string) => void, + mimeType?: string, + responseType?: XMLHttpRequestResponseType, + onProgress?: (loaded: number, total: number) => void + ): void; +} + +declare const utils: new () => Utils; + +/** + * 移动的方向 + */ +type Step = Move | 'backward'; + +/** + * 坐标字符串 + */ +type LocString = `${number},${number}`; + +type _RGBA = + | `rgb(${number},${number},${number})` + | `rgba(${number},${number},${number},${number})`; + +/** + * RGBA颜色数组 + */ +type RGBArray = [number, number, number, number?]; + +/** + * 样板的颜色字符串 + */ +type Color = `#${string}` | _RGBA | RGBArray; + +/** + * 四个方向 + */ +type Dir = 'up' | 'down' | 'left' | 'right'; + +/** + * 八个方向 + */ +type Dir2 = Dir | 'leftup' | 'rightup' | 'leftdown' | 'rightdown'; + +/** + * 转向的方向 + */ +type TurnDir = Dir | ':left' | ':right' | ':back'; + +/** + * 勇士转向 + */ +type HeroTurnDir = TurnDir | ':hero' | ':backhero'; + +/** + * 对话框的位置 + */ +type TextPosition = 'up' | 'center' | 'down'; + +/** + * 移动的方向 + */ +type Move = 'forward' | Dir; + +/** + * 缓动模式,不过在高级动画插件面前不堪一击( + */ +type EaseMode = 'linear' | 'easeIn' | 'easeOut' | 'easeInOut'; + +/** + * 事件执行的操作符\ + * += 增加并赋值\ + * -= 减少并赋值\ + * *= 相乘并赋值\ + * /= 相除并赋值\ + * //= 除以并取商\ + * **= 取幂\ + * %= 取余\ + * min= 取二者的最小值\ + * max= 取二者的最大值\ + * 其它的任意字符串都是赋值 + */ +type MotaOperator = + | '+=' + | '-=' + | '*=' + | '/=' + | '//=' + | '**=' + | '%=' + | 'min=' + | 'max=' + | '='; + +/** + * 位置数组 + */ +type LocArr = [x: number, y: number]; + +/** + * 位置 + */ +interface Loc { + /** + * 横坐标 + */ + x: number; + + /** + * 纵坐标 + */ + y: number; +} + +/** + * 带方向的位置 + */ +interface DiredLoc extends Loc { + /** + * 方向 + */ + direction: Dir; +} + +interface CompressedStep { + /** + * 移动方向 + */ + direction: Dir; + + /** + * 向该方向移动的步数 + */ + step: number; +} + +/** + * 四个方向的坐标增量 + */ +type Scan = { + [D in Dir]: Loc; +}; + +/** + * 八个方向的坐标增量 + */ +type Scan2 = { + [D in Dir2]: Loc; +}; + +/** + * 图片翻转 + */ +type ImageReverse = ':o' | ':x' | ':y'; + +/** + * 对话框的箭头方向 + */ +type TextBoxDir = 'up' | 'down'; + +/** + * 对话框的位置 + */ +type TextBoxPos = + | `${TextBoxDir},hero` + | `${TextBoxDir},${number},${number}` + | TextPosition; + +/** + * 画布信息 + */ +type CtxRefer = string | CanvasRenderingContext2D | HTMLCanvasElement; + +/** + * 触发器类型 + */ +type MotaTrigger = + | 'battle' + | 'pusBox' + | 'openDoor' + | 'ski' + | 'custom' + | 'getItem'; + +/** + * 切换楼层的目标坐标 + */ +type FloorChangeStair = + | 'upFloor' + | 'downFloor' + | ':symmetry' + | ':symmetry_x' + | ':symmetry_y' + | 'flyPoint'; + +/** + * 事件值的前缀 + */ +type EventValuePreffix = + | 'status' + | 'flag' + | 'item' + | 'buff' + | 'switch' + | 'temp' + | 'global'; + +interface Animate { + /** + * 动画的帧数s + */ + frame: number; + + /** + * 每帧的信息 + */ + frames: FrameObj[][]; + + /** + * 图片信息 + */ + images: HTMLImageElement[]; + + /** + * 缩放信息 + */ + ratio: number; + + /** + * 音效 + */ + se: string; +} + +type Save = DeepReadonly<{ + /** + * 存档所在的楼层id + */ + floorId: FloorIds; + + /** + * 存档的勇士信息 + */ + hero: HeroStatus; + + /** + * 难度信息 + */ + hard: number; + + /** + * 存档的地图信息,已经过压缩处理 + */ + maps: Record; + + /** + * 录像信息 + */ + route: string; + + /** + * 存档的全局变量信息 + */ + values: CoreValues; + + /** + * 游戏版本 + */ + version: string; + + /** + * 浏览器唯一guid + */ + guid: string; + + /** + * 存档时间 + */ + time: number; +}>; + +/** + * 深度只读一个对象,使其所有属性都只读 + */ +type DeepReadonly = { + readonly [P in keyof T]: T[P] extends number | string | boolean + ? T[P] + : DeepReadonly; +}; + +/** + * 深度可选一个对象,使其所有属性都 + */ +type DeepPartial = { + [P in keyof T]?: T[P] extends number | string | boolean + ? T[P] + : DeepReadonly; +}; + +/** + * 深度必选一个对象,使其所有属性都必选 + */ +type DeepRequired = { + [P in keyof T]-?: T[P] extends number | string | boolean + ? T[P] + : DeepReadonly; +}; + +/** + * 使一个对象的所有属性可写 + */ +type Writable = { + -readonly [P in keyof T]: P[T]; +}; + +/** + * 深度可写一个对象,使其所有属性都可写 + */ +type DeepWritable = { + -readonly [P in keyof T]: T[P] extends number | string | boolean + ? T[P] + : DeepReadonly; +}; + +/** + * 从一个对象中选择类型是目标类型的属性 + */ +type SelectType = { + [P in keyof R as R[P] extends T ? P : never]: R[P]; +}; + +/** + * 获取一段字符串的第一个字符 + */ +type FirstCharOf = T extends `${infer F}${infer A}` + ? F + : never; + +/** + * 非对象属性 + */ +type NonObject = number | string | boolean; + +/** + * 获取一个对象的非对象值 + */ +type NonObjectOf = SelectType; + +/** + * 以一个字符串结尾 + */ +type EndsWith = `${string}${T}`;