From 5ba580c85723fdc74ec123be6bf0329dcb8f3538 Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Sun, 15 Aug 2021 11:14:30 +0800 Subject: [PATCH 01/60] Fix 281 bugs --- _server/MotaAction.g4 | 4 ++-- _server/editor_blocklyconfig.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/_server/MotaAction.g4 b/_server/MotaAction.g4 index 2aff6d8d..d2676d2c 100644 --- a/_server/MotaAction.g4 +++ b/_server/MotaAction.g4 @@ -2804,7 +2804,7 @@ choices_s tooltip : choices: 给用户提供选项 helpUrl : /_docs/#/instruction previewBlock : true -default : ["","流浪者","trader",0,0,''] +default : ["","流浪者","trader",0,''] allIds : ['IdString_0'] var title=''; if (EvalString_0==''){ @@ -4115,7 +4115,7 @@ MoveMode_List NameMap_List : '确定'|'取消'|'操作失败'|'光标移动'|'打开界面'|'读档'|'存档'|'获得道具'|'回血'|'宝石'|'炸弹'|'飞行器'|'开关门'|'上下楼'|'跳跃'|'破墙镐'|'破冰镐'|'阻激夹域'|'穿脱装备'|'商店' - /*NameMap_List ['确定','取消','操作失败','光标移动','打开界面','读档','存档','获得道具','回血','宝石','炸弹','飞行器','开关门','上下楼','跳跃','破墙镐','破冰稿','阻激夹域','穿脱装备','商店']*/; + /*NameMap_List ['确定','取消','操作失败','光标移动','打开界面','读档','存档','获得道具','回血','宝石','炸弹','飞行器','开关门','上下楼','跳跃','破墙镐','破冰镐','阻激夹域','穿脱装备','商店']*/; //转blockly后不保留需要加" EvalString diff --git a/_server/editor_blocklyconfig.js b/_server/editor_blocklyconfig.js index fb003876..f460ac4b 100644 --- a/_server/editor_blocklyconfig.js +++ b/_server/editor_blocklyconfig.js @@ -108,7 +108,7 @@ editor_blocklyconfig=(function(){ MotaActionBlocks['tip_s'].xmlText(), MotaActionBlocks['confirm_s'].xmlText(), MotaActionBlocks['choices_s'].xmlText([ - '选择剑或者盾','流浪者','man',0,0,'',MotaActionBlocks['choicesContext'].xmlText([ + '选择剑或者盾','流浪者','man',0,'',MotaActionBlocks['choicesContext'].xmlText([ '剑','','',null,'','',MotaActionFunctions.actionParser.parseList([{"type": "openDoor", "loc": [3,3]}]), ]) ]), From 81349bfd8386fa02f207c0e581d7ba4fc6d59ed3 Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Sun, 15 Aug 2021 12:00:00 +0800 Subject: [PATCH 02/60] Fix 281 --- project/floors/sample0.js | 14 +++++--------- project/functions.js | 5 +++++ project/items.js | 18 +++++++++--------- project/maps.js | 2 +- project/sounds/error.mp3 | Bin 3387 -> 3178 bytes project/sounds/open_ui.mp3 | Bin 2760 -> 9448 bytes 6 files changed, 20 insertions(+), 19 deletions(-) diff --git a/project/floors/sample0.js b/project/floors/sample0.js index ec642e75..7ffc7566 100644 --- a/project/floors/sample0.js +++ b/project/floors/sample0.js @@ -12,7 +12,7 @@ main.floors.sample0= "ratio": 1, "map": [ [ 0, 0,220, 0, 0, 20, 87, 3, 58, 59, 60, 61, 64], - [ 0,246, 0,246, 0, 20, 0, 3, 57, 62, 63, 43, 44], + [ 0,246, 0,246, 0, 20, 0, 3, 57, 72, 63, 43, 44], [219, 0, 0, 0,219, 20, 0, 3, 53, 54, 55, 56, 69], [ 20, 20,125, 20, 20, 20, 0, 3, 49, 50, 51, 52, 68], [251,247,256,234,248, 6, 0, 3, 35, 36, 46, 47, 48], @@ -177,13 +177,13 @@ main.floors.sample0= }, "afterGetItem": { "9,1": [ - "样板给出的道具素材中有很多道具都是未定义甚至未注册的,需要自行实现功能。\n(比如屠龙匕首就是一个没有功能的道具)\n如果你想为未定的道具添加自定义功能,请参照样板中其他道具的写法;如果有更多疑问,请查阅帮助文档。" + "技能的支持需要依赖状态栏的“魔力”以及脚本编辑的“按键处理”,详见帮助文档“个性化”一节。" ], "12,2": [ - "跳跃本身没有音效,使用跳跃鞋时播放的音效是通过跳跃鞋的道具效果实现的。\n如果想为跳跃设置音效,请在 events.js 的 jumpHero 函数执行前插入一行代码,用 core.playSound 的方式来播放音效即可。\n如果想了解更多关于这方面的内容,请参与帮助文档中的“脚本——复写函数”章节。\n\n类似的是,敌人的“支援”技能也是通过在支援技能中播放音效实现的。" + "跳跃靴和支援怪的跳跃音效是用脚本额外添加的,\n如果想为任意跳跃指令添加音效,请查阅帮助文档中的“脚本——复写函数”章节。" ], "8,3": [ - "炸弹是只能炸面前的怪物还是四个方向的怪物,由其图块属性(快捷键C)中的“使用效果”决定。\n不能被炸的怪物请直接在该怪物的图块属性中勾选“不可炸”,可参见样板里黑衣魔王和黑暗大法师的写法。" + "炸弹是只能炸面前的怪物还是四个甚至八个方向的怪物,\n由其图块属性(快捷键C)中的“使用效果”决定。\n不能被炸的怪物请直接在该怪物的图块属性中勾选“不可炸”,\n可参见样板里黑衣魔王和黑暗大法师的写法。\nV2.8.1起,炸弹炸怪可以添加获得金经/触发战后事件,详见其使用效果中的注释。" ], "10,3": [ "“上楼”和“下楼”的目标层由全塔属性(快捷键B)的“楼层列表”顺序所决定。" @@ -209,11 +209,7 @@ main.floors.sample0= "在 2.8.1 版更新后,能够被破冰镐摧毁的冰块被移动到了 animates 下。\n如果想制作一个可以以特定触发器的方式移除特定图块的道具,可以参照破冰镐物品图块属性中\n useItemEffect 和 canUseItemEffect 的写法。" ], "11,8": [ - "由于状态栏放不下,铁门钥匙(根据全塔属性的系统开关勾选与否,可能还有绿钥匙)会被放入道具栏中。\n碰到绿门和铁门时仍然会自动使用钥匙开门。", - { - "type": "comment", - "text": "由于状态栏放不下,铁门钥匙(根据全塔属性的系统开关勾选与否,可能还有绿钥匙)会被放入道具栏中。\n碰到绿门和铁门仍然会自动使用钥匙(根据全塔属性的系统开关勾选与否,铁门可能不需要钥匙)开门。" - } + "由于状态栏放不下,铁门钥匙(根据全塔属性的系统开关勾选与否,可能还有绿钥匙)会被放入道具栏中。\n碰到绿门和铁门时仍然会自动使用钥匙开门。" ], "12,8": [ "该道具默认是大黄门钥匙,如需改为钥匙盒直接修改其图块属性(快捷键C)的“道具类别”为items即可。" diff --git a/project/functions.js b/project/functions.js index 020ae2ce..e43c4cd0 100644 --- a/project/functions.js +++ b/project/functions.js @@ -1141,11 +1141,14 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = core.setFlag('curse', true); } } else if (action == 'remove') { + var success = false; if (core.inArray(type, "poison") && core.hasFlag("poison")) { + success = true; // 移除毒效果 core.setFlag("poison", false); } if (core.inArray(type, "weak") && core.hasFlag("weak")) { + success = true; // 移除衰效果 core.setFlag("weak", false); if (core.values.weakValue >= 1) { @@ -1159,9 +1162,11 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = } } if (core.inArray(type, "curse") && core.hasFlag("curse")) { + success = true; // 移除咒效果 core.setFlag("curse", false); } + if (success) core.playSound('回血'); } }, "updateStatusBar": function () { diff --git a/project/items.js b/project/items.js index 289c494a..639bb668 100644 --- a/project/items.js +++ b/project/items.js @@ -297,7 +297,7 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a = "name": "圣水", "itemEffect": "core.status.hero.hp *= 2", "itemEffectTip": ",生命值翻倍", - "useItemEffect": "core.status.hero.hp *= 2;\ncore.playSound('回血');", + "useItemEffect": "core.status.hero.hp *= 2;core.playSound('回血');", "canUseItemEffect": "true", "text": "生命值翻倍" }, @@ -327,7 +327,7 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a = "cls": "constants", "name": "冰冻徽章", "text": "可以将面前的熔岩变成平地", - "useItemEffect": "(function () {\n\tvar success = false;\n\n\tvar snowFourDirections = false; // 是否四方向雪花;如果是将其改成true\n\tif (snowFourDirections) {\n\t\t// 四方向雪花\n\t\tfor (var direction in core.utils.scan) {\n\t\t\tvar delta = core.utils.scan[direction];\n\t\t\tvar nx = core.getHeroLoc('x') + delta.x,\n\t\t\t\tny = core.getHeroLoc('y') + delta.y;\n\t\t\tif (core.getBlockId(nx, ny) == 'lava') {\n\t\t\t\tcore.removeBlock(nx, ny);\n\t\t\t\tsuccess = true;\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif (core.getBlockId(core.nextX(), core.nextY()) == 'lava') {\n\t\t\tcore.removeBlock(core.nextX(), core.nextY());\n\t\t\tsuccess = true;\n\t\t}\n\t}\n\n\tif (success) {\n\t\tcore.playSound('打开界面');\n\t\tcore.drawTip(core.material.items[itemId].name + '使用成功');\n\t} else {\n\t\tcore.playSound('操作失败');\n\t\tcore.drawTip(\"当前无法使用\" + core.material.items[itemId].name);\n\t\tcore.addItem(itemId, 1);\n\t\treturn;\n\t}\n})();", + "useItemEffect": "(function () {\n\tvar success = false;\n\n\tvar snowFourDirections = false; // 是否多方向雪花;如果是将其改成true\n\tif (snowFourDirections) {\n\t\t// 多方向雪花\n\t\tfor (var direction in core.utils.scan) { // 多方向雪花默认四方向,如需改为八方向请将这两个scan改为scan2\n\t\t\tvar delta = core.utils.scan[direction];\n\t\t\tvar nx = core.getHeroLoc('x') + delta.x,\n\t\t\t\tny = core.getHeroLoc('y') + delta.y;\n\t\t\tif (core.getBlockId(nx, ny) == 'lava') {\n\t\t\t\tcore.removeBlock(nx, ny);\n\t\t\t\tsuccess = true;\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif (core.getBlockId(core.nextX(), core.nextY()) == 'lava') {\n\t\t\tcore.removeBlock(core.nextX(), core.nextY());\n\t\t\tsuccess = true;\n\t\t}\n\t}\n\n\tif (success) {\n\t\tcore.playSound('打开界面');\n\t\tcore.drawTip(core.material.items[itemId].name + '使用成功', itemId);\n\t} else {\n\t\tcore.playSound('操作失败');\n\t\tcore.drawTip(\"当前无法使用\" + core.material.items[itemId].name, itemId);\n\t\tcore.addItem(itemId, 1);\n\t\treturn;\n\t}\n})();", "canUseItemEffect": "true" }, "cross": { @@ -368,21 +368,21 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a = "cls": "tools", "name": "破墙镐", "text": "可以破坏勇士面前的墙", - "useItemEffect": "(function () {\n\tvar canBreak = function (x, y) {\n\t\tvar block = core.getBlock(x, y);\n\t\tif (block == null || block.disable) return false;\n\t\treturn block.event.canBreak;\n\t};\n\n\tvar success = false;\n\tvar pickaxeFourDirections = false; // 是否四方向破;如果是将其改成true\n\tif (pickaxeFourDirections) {\n\t\t// 四方向破\n\t\tfor (var direction in core.utils.scan) {\n\t\t\tvar delta = core.utils.scan[direction];\n\t\t\tvar nx = core.getHeroLoc('x') + delta.x,\n\t\t\t\tny = core.getHeroLoc('y') + delta.y;\n\t\t\tif (canBreak(nx, ny)) {\n\t\t\t\tcore.removeBlock(nx, ny);\n\t\t\t\tsuccess = true;\n\t\t\t}\n\t\t}\n\t} else {\n\t\t// 仅破当前\n\t\tif (canBreak(core.nextX(), core.nextY())) {\n\t\t\tcore.removeBlock(core.nextX(), core.nextY());\n\t\t\tsuccess = true;\n\t\t}\n\t}\n\n\tif (success) {\n\t\tcore.playSound('破墙镐');\n\t\tcore.drawTip(core.material.items[itemId].name + '使用成功');\n\t} else {\n\t\t// 无法使用\n\t\tcore.playSound('操作失败');\n\t\tcore.drawTip(\"当前无法使用\" + core.material.items[itemId].name);\n\t\tcore.addItem(itemId, 1);\n\t\treturn;\n\t}\n})();", + "useItemEffect": "(function () {\n\tvar canBreak = function (x, y) {\n\t\tvar block = core.getBlock(x, y);\n\t\tif (block == null || block.disable) return false;\n\t\treturn block.event.canBreak;\n\t};\n\n\tvar success = false;\n\tvar pickaxeFourDirections = false; // 是否多方向破;如果是将其改成true\n\tif (pickaxeFourDirections) {\n\t\t// 多方向破\n\t\tfor (var direction in core.utils.scan) { // 多方向破默认四方向,如需改成八方向请将这两个scan改为scan2\n\t\t\tvar delta = core.utils.scan[direction];\n\t\t\tvar nx = core.getHeroLoc('x') + delta.x,\n\t\t\t\tny = core.getHeroLoc('y') + delta.y;\n\t\t\tif (canBreak(nx, ny)) {\n\t\t\t\tcore.removeBlock(nx, ny);\n\t\t\t\tsuccess = true;\n\t\t\t}\n\t\t}\n\t} else {\n\t\t// 仅破当前\n\t\tif (canBreak(core.nextX(), core.nextY())) {\n\t\t\tcore.removeBlock(core.nextX(), core.nextY());\n\t\t\tsuccess = true;\n\t\t}\n\t}\n\n\tif (success) {\n\t\tcore.playSound('破墙镐');\n\t\tcore.drawTip(core.material.items[itemId].name + '使用成功', itemId);\n\t} else {\n\t\t// 无法使用\n\t\tcore.playSound('操作失败');\n\t\tcore.drawTip(\"当前无法使用\" + core.material.items[itemId].name, itemId);\n\t\tcore.addItem(itemId, 1);\n\t\treturn;\n\t}\n})();", "canUseItemEffect": "true" }, "icePickaxe": { "cls": "tools", "name": "破冰镐", "text": "可以破坏勇士面前的一堵冰墙", - "useItemEffect": "(function () {\n\tcore.openDoor(core.nextX(), core.nextY(), false);\n\tcore.playSound('破冰镐');\n\tcore.drawTip(core.material.items[itemId].name + '使用成功');\n})();", + "useItemEffect": "(function () {\n\tcore.drawTip(core.material.items[itemId].name + '使用成功', itemId);\n\tcore.insertAction({ \"type\": \"openDoor\", \"loc\": [\"core.nextX()\", \"core.nextY()\"] });\n})();", "canUseItemEffect": "(function () {\n\treturn core.getBlockId(core.nextX(), core.nextY()) == 'ice';\n})();" }, "bomb": { "cls": "tools", "name": "炸弹", "text": "可以炸掉勇士面前的怪物", - "useItemEffect": "(function () {\n\tvar bombList = []; // 炸掉的怪物坐标列表\n\tvar todo = []; // 炸弹后事件\n\tvar money = 0,\n\t\texp = 0; // 炸弹获得的金币和经验\n\n\tvar canBomb = function (x, y) {\n\t\tvar block = core.getBlock(x, y);\n\t\tif (block == null || block.disable || block.event.cls.indexOf('enemy') != 0) return false;\n\t\tvar enemy = core.material.enemys[block.event.id];\n\t\treturn enemy && !enemy.notBomb;\n\t};\n\n\tvar bomb = function (x, y) {\n\t\tif (!canBomb(x, y)) return;\n\t\tbombList.push([x, y]);\n\t\tvar id = core.getBlockId(x, y),\n\t\t\tenemy = core.material.enemys[id];\n\t\tmoney += core.getEnemyValue(enemy, 'money', x, y) || 0;\n\t\texp += core.getEnemyValue(enemy, 'exp', x, y) || 0;\n\t\tcore.push(todo, core.floors[core.status.floorId].afterBattle[x + \",\" + y]);\n\t\tcore.push(todo, enemy.afterBattle);\n\t\tcore.removeBlock(x, y);\n\t}\n\n\t// 如果要四方形可炸,把这里的false改成true\n\tif (false) {\n\t\tvar scan = core.utils.scan; // 如果要改成八方向炸可以改成 core.utils.scan2\n\t\tfor (var direction in scan) {\n\t\t\tvar delta = scan[direction];\n\t\t\tbomb(core.getHeroLoc('x') + delta.x, core.getHeroLoc('y') + delta.y);\n\t\t}\n\t} else {\n\t\t// 仅炸当前\n\t\tbomb(core.nextX(), core.nextY());\n\t}\n\n\tif (bombList.length > 0) {\n\t\tcore.playSound('炸弹');\n\t\tcore.drawTip(core.material.items[itemId].name + '使用成功');\n\t\t// 取消这里的注释可以炸弹后获得金币和经验\n\t\t// core.status.hero.money += money;\n\t\t// core.status.hero.exp += exp;\n\n\t\t// 取消这里的注释可以炸弹引发战后事件\n\t\t// if (todo.length > 0) core.insertAction(todo);\n\t} else {\n\t\tcore.playSound('操作失败');\n\t\tcore.drawTip('当前无法使用' + core.material.items[itemId].name);\n\t\tcore.addItem(itemId, 1);\n\t\treturn;\n\t}\n\n\t// 炸弹后事件\n\t// 这是一个使用炸弹也能开门的例子\n\t/*\n\tif (core.status.floorId=='xxx' && core.terrainExists(x0,y0,'specialDoor') // 某个楼层,该机关门存在\n\t\t&& !core.enemyExists(x1,y1) && !core.enemyExists(x2,y2)) // 且守门的怪物都不存在\n\t{\n\t\tcore.insertAction([ // 插入事件\n\t\t\t{\"type\": \"openDoor\", \"loc\": [x0,y0]} // 开门\n\t\t])\n\t}\n\t*/\n})();", + "useItemEffect": "(function () {\n\tvar bombList = []; // 炸掉的怪物坐标列表\n\tvar todo = []; // 炸弹后事件\n\tvar money = 0,\n\t\texp = 0; // 炸弹获得的金币和经验\n\n\tvar canBomb = function (x, y) {\n\t\tvar block = core.getBlock(x, y);\n\t\tif (block == null || block.disable || block.event.cls.indexOf('enemy') != 0) return false;\n\t\tvar enemy = core.material.enemys[block.event.id];\n\t\treturn enemy && !enemy.notBomb;\n\t};\n\n\tvar bomb = function (x, y) {\n\t\tif (!canBomb(x, y)) return;\n\t\tbombList.push([x, y]);\n\t\tvar id = core.getBlockId(x, y),\n\t\t\tenemy = core.material.enemys[id];\n\t\tmoney += core.getEnemyValue(enemy, 'money', x, y) || 0;\n\t\texp += core.getEnemyValue(enemy, 'exp', x, y) || 0;\n\t\tcore.push(todo, core.floors[core.status.floorId].afterBattle[x + \",\" + y]);\n\t\tcore.push(todo, enemy.afterBattle);\n\t\tcore.removeBlock(x, y);\n\t}\n\n\t// 如果要多方向可炸,把这里的false改成true\n\tif (false) {\n\t\tvar scan = core.utils.scan; // 多方向炸时默认四方向,如果要改成八方向炸可以改成 core.utils.scan2\n\t\tfor (var direction in scan) {\n\t\t\tvar delta = scan[direction];\n\t\t\tbomb(core.getHeroLoc('x') + delta.x, core.getHeroLoc('y') + delta.y);\n\t\t}\n\t} else {\n\t\t// 仅炸当前\n\t\tbomb(core.nextX(), core.nextY());\n\t}\n\n\tif (bombList.length > 0) {\n\t\tcore.playSound('炸弹');\n\t\tcore.drawTip(core.material.items[itemId].name + '使用成功', itemId);\n\t\t// 取消这里的注释可以炸弹后获得金币和经验\n\t\t// core.status.hero.money += money;\n\t\t// core.status.hero.exp += exp;\n\n\t\t// 取消这里的注释可以炸弹引发战后事件\n\t\t// if (todo.length > 0) core.insertAction(todo);\n\t} else {\n\t\tcore.playSound('操作失败');\n\t\tcore.drawTip('当前无法使用' + core.material.items[itemId].name, itemId);\n\t\tcore.addItem(itemId, 1);\n\t\treturn;\n\t}\n\n\t// 炸弹后事件\n\t// 这是一个使用炸弹也能开门的例子\n\t/*\n\tif (core.status.floorId=='xxx' && core.terrainExists(x0,y0,'specialDoor') // 某个楼层,该机关门存在\n\t\t&& !core.enemyExists(x1,y1) && !core.enemyExists(x2,y2)) // 且守门的怪物都不存在\n\t{\n\t\tcore.insertAction([ // 插入事件\n\t\t\t{\"type\": \"openDoor\", \"loc\": [x0,y0]} // 开门\n\t\t])\n\t}\n\t*/\n})();", "canUseItemEffect": "true" }, "centerFly": { @@ -417,28 +417,28 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a = "cls": "tools", "name": "解毒药水", "text": "可以解除中毒状态", - "useItemEffect": "core.triggerDebuff('remove', 'poison');\ncore.playSound('回血');", + "useItemEffect": "core.triggerDebuff('remove', 'poison');", "canUseItemEffect": "core.hasFlag('poison');" }, "weakWine": { "cls": "tools", "name": "解衰药水", "text": "可以解除衰弱状态", - "useItemEffect": "core.triggerDebuff('remove', 'weak');\ncore.playSound('回血');", + "useItemEffect": "core.triggerDebuff('remove', 'weak');", "canUseItemEffect": "core.hasFlag('weak');" }, "curseWine": { "cls": "tools", "name": "解咒药水", "text": "可以解除诅咒状态", - "useItemEffect": "core.triggerDebuff('remove', 'curse');\ncore.playSound('回血');", + "useItemEffect": "core.triggerDebuff('remove', 'curse');", "canUseItemEffect": "core.hasFlag('curse');" }, "superWine": { "cls": "tools", "name": "万能药水", "text": "可以解除所有不良状态", - "useItemEffect": "core.triggerDebuff('remove', ['poison', 'weak', 'curse']);\ncore.playSound('回血');", + "useItemEffect": "core.triggerDebuff('remove', ['poison', 'weak', 'curse']);", "canUseItemEffect": "(function() {\n\treturn core.hasFlag('poison') || core.hasFlag('weak') || core.hasFlag('curse');\n})();" }, "hammer": { diff --git a/project/maps.js b/project/maps.js index c8211a5e..6c8d0509 100644 --- a/project/maps.js +++ b/project/maps.js @@ -5,7 +5,7 @@ var maps_90f36752_8815_4be8_b32b_d7fad1d0542e = "3": {"cls":"animates","id":"blueWall","canBreak":true,"animate":1,"doorInfo":{"time":160,"openSound":"door.mp3","closeSound":"door.mp3","keys":{}}}, "4": {"cls":"animates","id":"star","name":"星空"}, "5": {"cls":"animates","id":"lava","name":"岩浆"}, - "6": {"cls":"animates","id":"ice","doorInfo":{"time":160,"openSound":"icepickaxe.mp3","closeSound":"door.mp3","keys":{"specialKey":1}},"animate":1}, + "6": {"cls":"animates","id":"ice","doorInfo":{"time":160,"openSound":"破冰镐","closeSound":"door.mp3","keys":{"icePickaxe":1}},"animate":1}, "7": {"cls":"terrains","id":"blueShopLeft"}, "8": {"cls":"terrains","id":"blueShopRight"}, "9": {"cls":"terrains","id":"pinkShopLeft"}, diff --git a/project/sounds/error.mp3 b/project/sounds/error.mp3 index 7d572668303b78a7fb0d33e5baed63ec79c8c4ee..329cca458198a0686ad1af9016a124b7b36c5374 100644 GIT binary patch literal 3178 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 literal 3387 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 diff --git a/project/sounds/open_ui.mp3 b/project/sounds/open_ui.mp3 index 31da851dd0b924df9e5234dd2076364a0115ea58..0282a089df2bbd2069a78d9ed621fc8895120e9c 100644 GIT binary patch literal 9448 zcmdVgXH-*L*eCEqXrV~2QbLuYNL3Jo(3>C~0gFI@qwYAO7&Aq*&BM>|t34YA?@ngOre!6qM@ev~b zy~+21%@-U#zx(_e?|A?K1i`?h8=#24^8yzNAfN;~-QGnb@w-wH_=_=s9H3#L0AR69 zP^E*eIm{t^m_9EC3wFg2%^gorM{MiBZxC_dptAa6`r<^F!;;waGXQ%4AiKl`(bLlC zmv?ffQ+}IM&;r)3XIl*W1`E!FL>nq9B)+ERY6(qn92R*nW&zi_U&i#uC`Y>1)$U>F z?ds>$ON()dak07bm(oa7G!8`6i`~9d1cS%pmA$0V59n?YZxaUlUb$bPE*v@RAv91p zpWl6a7d$q6Kn0+KL@g0F=kQ~{z%>UDK*w60qZtp8cn|)ENX|BVp0~FY(-Fq9_%O@1 zL$%B2F06Xb9hwAc&F^NS9*T9_u9SNFcwPFY?ksn_N) zBL}OTqIgw#7}B`f$T`fr{Q1VKIs>Ksoi#~Vb=2=s*IsMbajjM|fbWz1c}5KJw(4Cu z$tgMou_DpDqW6x;gcnai__#=a4Mz-cRe7F)y44I?^1zcTY-_k;;46$qWl*dqu~>DC z=z_HnyMKm5mwKUpdIK?|tf>eEYym!P_wzLupPAsJ$$GVL5?pmF2>t=3s&Gss9&5}j z91`0mx$8VmJ~XPXieyQ@!YXBwiAWj8$RcQMcA)LZ)o)(9zu!H)tI&{V#*P&USd(w0 zB>NC#&%_UtKjLlu&Ea!N>frv5fAXW@QrGNaK^^~LTDdpCMF=3AN0!>$atgW%pzWo; zKcY0kPo}>hvaDH;mBO;NGf=ir@7M2UyhJ$-T52N6asCob7;uRwN`qLXvP#I+?mqkd z$CZ^|obxuHDyJvyWAiG|`Q-(Kuun~L`Rb9{kBU{KAE+*ADME9#=gJ*a)FGkz@t(KS zbbixe7fOhlj0B0cB7W^|0ue36Lj!{O~Q0BCA|I}FPqAo~+@|h7~<$VgHux#KF@+3cCe>}7g z!ec^1%#}>c^j-gQ)v)5&R6ieG&*vA)gQLFHLginKTK$GxFGIUGWexLUBEqq12~@9s z`xmr2cvA@Hw}ew$<4jc=PudAKM`>J~%9BS>MvK7|oh-+K%oP0#(M;htY->H+67+aT z<)t3T*~5I;o^rf8K=Mg7gI|D_SgISWi zSn7eEO|V0G^W{3D9Ssc)*JZbiVd-b@Y?h7lw@u>F8)HRAa_)xycESDz`OFEg2}&e& zzRM=8Q@5@>_6)z+vgxt)^xMfTs&$rlhY-2_%8nFN3K<{73fe7WkjbG-YCy6Wvl+OI+ph4N~xrPAiD&c@+GV22}L}HE^xg;3RkMnv_2T;8C)K z$SV`6VJ<2u9xND(9|x}2w!7=OAZ>u8}N&-DESP;Z}#kvxS`aoZwp&@H)#6z zg2cwhjgNoQAPzH{CgJ|2rmq7MotyGNtVn1-p(;LC(;i#n3O|mFfoJ`hG+l2Z$#XW@ z{ah+ZV>SA9g);**A8K5#oy{NG%W<6m!Q32V^Md|DQf@x6dB!zWNo8X@MG^!%UqWu) zF!KfVH=r|=gYm_kflII7G7%QfX{A;b4=9-Dwmf|O;o_Fw157Kp5S^tSMjI@Xr7a1T zoq}w_cD7;nFlDD7PyaTBuhSmAsEzYE6f|3J?{FQussN}~4lKqump=%*rc_%V;Q83y zyvenr{j%rtd|v%nmkQTEyMtfso%_E%685zQce38tOkI`PRAsz{*uP{REiS3b^KqN` z8?nqR|I)NVvN}6_D1309K~Qjk%8nSCwrzQw(fzZ>a!?CH{atxX9+yiu3qHG4r3}(O z2eaJ-GZ4vSR6q~( zjpun&FjuS~g;qtzWW5SI-nihmPfrP(!#*IV;(l>58HKDfG=4o3%P18$FknrqN4DL%a_9F(S}K zHozszvFm#@S+t;sQEh zew^~^!?p5+^s%DQxUg7yLYg+V7%CcRDt0k0DLV>OO?%vKtHQk(@Ju~NYCX=+D}}8m z&lXEp0^gH-I{d)WlHQc}%()Ok007}Z&SGs867qBrZQK0R@y#Q=aA5`W-|6_3k>P{k zupOKK)SC6sk4(h_BQmX}`_CHyco5N0kk}b*1aP80(k53k5jLWIW2CBM^BZ+` zJY?9Yx8J+%4D`W#x8y@wnk77ddA)jNzHMS7k3@PI7?eseB6Ko!Ibk5vK)f&%8>n7t zu2F3BqZ!H)4;%v1pNWE9HFb~Q27eIStkr`GBVuwA?}WK5=fDISrTsWgZnYViH^KCMC3xfij+ zcU$!EpXP97hEvegZ+?hhc$)f%q}`?R&Qs7<_^z1rh!1rE*BOXxZ1+x&ydJ)Kq>%W< zX*fsYqR7&hKiuz!7X@IrtQTD`M$tDzXNqS&FHrzG`QFWqcbv(TihT@l=@+S-_vx(? zn|FVJR(XqEkBcaqAd2_{(O}JV7>Rd~V7@iYzN7q+J;On|3Tbc<#A7wkPmDf4SYy;% zv#Hb!1!#m+_eObHnx%_=M&m-O%3@7mC8d)~CUU8*D1CrJ(F|(#F?>9kZ{q!e;_s=a z-USx4q0Dv|uk?gHnJuzxznTLQdXT?Yf+mw&aGaplv zG~5J%?>D=vJ6`=^d>RGr7cbCKek4?bm5to5iQjsz)F-vIaeaG+SFls)nh$}rHLgI~ zt%nB!(5OIA3YyApSG^{2Y(zhfRSI~-dERYayD2hZdPseMRUFPvHSQ@4JOwR5&}LG1 zyw?6(`cP7i>e~M-!JpZ`3AwX0nVQ+H8rMfK>BrR;)>26A%}ynHJ;erJB;@^Fq8(?t zah+H+A|2dR8+l6>MTl=g020fk%h1`-{q;Ig>@H=OH`AMvO{zDo4*!Ju*4DIsM|yi3 zpuybaqCYPLF=@fq;e$)jSxIGDtWl*gEBmfiPQ$I3WeCl*jvA9iTI_cLf20%l5B%a7 zpvIU4+Z(4;Hm`9xzwIG8mU%Hk&1n-JoWl*S`lbX5Zr1^C{XbnKxC{W5^hvsuDxt{lZQUs)=;@4(&4|srQ!K_xrlKm|JnY#uGabEfFX?dh#D@3{ zcNTzDgxJnCOQGV;>C~j!ExRK}2GL5jr=Z_RG)lq5YssDK3`B7Sb7!S2uASTMj#=((btxu*sgWa2;=S66Q(&%Rqb67>xA|-u7a>$y97-#?h(gxp8 zIHvM``Rw~e|7$JaU)O%oI)XuOf!4x2AyA5@@KEy50;0m zJBRbhI=9A;2EGh09e7syBsF^&D}wqMQ+W^8fyJj){JTa$=MUTno6qNw?cYFO{X`;!6?pd=?%Dk z0Q=wz_JM|pndgYrEVip+E=U_1fCRQ&kns(flce!#@Y%(` zC5J>;NsUZV8=il#l5zE#EHsy#CuA4NCY{g` z?Ac_^f3xYRAQU>Llu>Ok|2>CXN7Z7YFXB(`-=@Gu z0&JFI?~baE+1L&>EyL& z;01Jb8ishBJcfV~e;^vH=S8w-UTw-fVZnD;3&-+mxEL4Lud|tNoZKvJaa#8J7IG*W z{kHN3lsi!AqgsC&h^h3*{d2Q*SoujDbi0+ls(70ch|tLw<)nM@^}l_zZ%*2 z=no9&Z%P;7BAJz=OuDfnT#fehyxhuB-sv~o+28A;pjQ`?v;t|K6X5vA<+tkM4s(h? zY)sPq?^lG=F}4OY;9(O*p)(6OkOF$_(+PwX1DXIK?y$qhLnfh!a9K#~Cf0j^Ng0r}gILQUg%jrG+!XuwJzYg;DOiqgy5k;p^8 zsid0s69isPUe{i@sSae*>+_9=ukLfsi9tL-3NryajG3CUqWqHbuhL*93h*+8mVw#F z!+nzK!&EXM$8?+_iaeP?3;-A|bb?Ewl@t#n-mw)PaX*dfknaE66aak54ezWo;h*#G z9C~)F)mwOY4zdq-N@s5o?<8lBOb*+-F{H!I@aMl4+Hu|DbIb6$pyjTxAM* zo9dUkb%%Ay*rYxqN(+&dDHAGYz2XWH;iFEV%FC~W>fSL=X0xbUu@nYROqT;ij4416 z>A@HOzR3G+px8J1ua3c8yEHj3>aevJrL|5$%Y^6-1$`B2m%TF(v};tOx0o7VE>cMR z;`EiOh1`_uB7aVxVh)5?zDV>aHRerUNp5xPVYJpdV!xI^N-M?CfqH}w@y`Gc!}K2$ zAefI=2_WQYgM&+E^6IpnqS`FHDbq$<-(R-R2*LbXPAFooJ->p3_g@S?Fo-stlb=4>S znT(J{d>xX+fG78mKF>=GS^{5LRaYSzWt-NAc&fp@``xj{$_@w8`lU1tJ)gbj-jXvo zeM1;uQ(kex2%JD+h~?Wc+>|PDenNNY5u}O?JOB(l(OCP+pZM0fLyoSWu2C*rnwsc! zmPWRy(J5#(4&AFb?CdJLeGXbZP$JE5!l&~$A-zXRG7RFg4kG`2{kb^&gca*gw434P zDjA6QM9dy5EIc?(^2_L_*OfGom|$ZS9y9b=!m$9n1i}9W1PafN*SGa@=i$$HOzn9P z=k7@}JaSN0Sdg>jAE{?<@v1@~aDS%(dy*8)e@!~ad^sD$7D^q@6g?NVEWYz8mPX1- z{v?Du>So|KXr8NkjhQj=yF-BBW*Tb3FXv1*SU0ZEw{Vauf zy`TxXGN6f(AQK}cxV&Jx`!@c12n%`Rl#8dR%n)(AKChQJyC08U3hEyqLls&>e^}p0<(ekH;f-214zE9z9DDIYEIZ3lT^F5~`I#ca>1~ib}4fwe%}` zlY{lB<(4t|bT2n$2KQ@kpJ3!Jm^W+uEja-FU31`*sImSz=s~|cQl1a*`Kvwp*hc;jD@tnBBzP#j!8anjGw*mmbdIpj5F6U9f z`(Vz8n_eXju+0L|iu9p=+AP!rMUsC?IEf7jCZ>~@bO|12_!*`fVhwn*GGrx@ z6>J@}QLS;MMI@)76#%^}eXGsPdHW0m?VFX0XkKYM1NnO7s=-_?igLsrBya z);f?2JV4mKr_NT9G+YnaXYVnP7#5J0#|(=;v{p&O$QLOW9s+Tt#h8JvV_r!&-?5PGgtK|DpfAZ z)*%J2feR3AK#}xUmUi2Gmpe-X7n63v#|txi(*D*|n@K@p(FbhtP@Kw0Y)3Z*&!Z>) zc0XfXQW#%4b_Q^kB|d&FL16Np!c~H$W`6EYR%a_OSw0^lDG^Y<)(N2-oqza@e)XpF zq&CAcB9>c`008XT0g>MILb$X^h4{WZAC69`WNulV?rqffQ_ychbOF4-y~)M%EFp^I zp8|ja|2e4cL{%4p)b10AvokLC^kP1;qcY#P%0kx__sZL6RN`pp&7bQAwbYAkq3Wh< z&c@bYy7b;HVF(RU3@Z_C!&x|vy&%wwiWN*7EwTHo!`WoE4J98C(9vCYz%@ULq0b8x zW=JM-Z8{Qq>=K4bOOj49{3Q77W@Y`Ols>Qh7Mbv4lttdB<_}Ft`zT2i)fXP0|Lh5Il%l0T%`i|7-wVltERG!PH zpj9L~LrSwl@4u2GFC1ovw){7Tn8g?b6I3BHsWpP@J02dmWp*#(^vNeo&F<;+Aa#_a zmqUs=uBA4F*vwV%&HhAu_5}jMatJ{BtA-fhQ0}^>Oe3;u8m^xPF|OYbxwDd!E_uCR zu#s7RLrq3PiAHuD{o0wJhATlVW8^6|W!yrf1pLZJ@StMsMprF!8ux$-Cb=%oyDwO2 zw-Gc;P*mVEb(nVX30ot>Ackq1L^M;7oG4a@mNsNRLw#QK-;yIlcS-diWrEHVBBPmw z5sUpso^`o`j7_C7{Z?nrdctdob}bOqKCksMJ^PE^m>-wlN`185iy%7T|IsEr2%o4= z0}|2@V>Kv(KzCI)tnvwEy@;&DP<*7trJ+a7i&{O6Up8$ypIg2gujfjvc7B<0$fLWO zTo&%|=>k)_lw(^@!-aR~i{z9DbH=OL$gnxh-FFfXaoJ@&tcMqrCGUXT9pOCMW>loU z+H(OB&T5{Q^S4m#A>ngrN)I(Pm1VBf{W=Bh5TJibca=4zo`WcXS@JT6Tjz5q|1mpj z$t#ysl^qtBOk9d;3Y49!V+6!+zXlTGM!N0AozS&eQTXOV5NJI1wtI1`uDi@nYR5^0 zj;ljWB=y&aDnA?rio+p|-Mv~Q__AKn?F!;|SLc?UUYq*d8bvJKWtN?3tXzGMjlgYGU}AuG~J&nB|R@U_8H&{$hQl&J_s>`;@-^^sq6BGMSMl%_Uu7Y6Q#% zY}EF&2B{=J{yZrE`}JXsVwYD&sXQp>97Gn|Pef*0+jo|bu8Ec@|Bv!7M-_CNCXS&d zTNsm8jD?PpuA1cOf2EZFkJ?TXTA@O>NXUmax#2d6j4{?MV`i+05hH6zqcJICZFDX1vrKMRLqnz{W6K^X z2?;kPQDeE5i*DH>SN7#bx3VOX`I&n-=l=Km`}aEMdp@7f^E~H#->>sLwpK(iAVm3u zt1D%@BDX&WuSkD=LmiTyjvgK_+}uI1%;xX*fNijU$o3#S4+j8PE}*u9$qvVM@ZKeI z2ks8}yHxMcy2H>ei#rH*5dM5SoR2V^k#N`rx7)ySaVe+zcc=eRw|!ax^$VI-2p5khTb+9JDYyt*rJtUU z`sf-t@VxI-IlL>_lGby`nIsgF(*-Bn$h`@$zPlR1RGjmNdUe~m4bm5z|F$2bo%S_g z`rXym#3nlIBj4sbNK8SG#1_$7Vm;a?NZsWAPO4F#52vLe>7xP1UPE72NBn>#h?`*1 z8P6_PIx7*r*|9i%T^R2^wX`15FLICl83O)xM-D)uhb@r*SFCGdSX&S3w4soHbYsV|Hw<9nI@kFW35a!ng}2 zMy=hcqRhkBh)*7v59XwtOK~)T5*94!mju-tBP2}fDv8wP=8PGt8Vk1AdI z$)eX+wlOfcptzzKyUb%9Xw4gd!=$8-1s)2EJ2#-U+G915)zeuToiI&T$$#VT3cZ`) z+h3Vpe;`6Aq^A3GnJH?L$E6>d!v&f!s=PxaM0m7xz@r!xm*2dW#WG`HT$1A1cZ%-i zs6JxHsn4x>qgxG5AhSP3dt20zYYS@r)LK3ucTRb1TVX>1rOKI;?mna}Ro^)4{mobn zE1*1DnZNMLTbppWw)1x-&P3=Fe~(|JZp}@U2d;t!gq+#^*Gecg&{r~$e@B9P;4gOSqzQ>vYJ`v9ODu5%`~hi zNQNKyLlZv>4P4{7{Eo2?|90Q)#a8ss0>OI`ypo9H63W;A98o{FEXX`0BfD|0$;`*F zq?nbiPA?k-FHOy(!vBL>FVt*IoH`UUd#dZEj}pmgZ7_*&!}@|jN%oSoDXaIdmAXWN zW2|dIJrL|Hh66whz0Mi;2-BR_vQ&y|11Zg+&T_D9tS0)%RK5&5 zhhrD}&RN`_4^{+bZX?mY%>hM4A;Q}kwUKGpvh(%uuo_y*t}BXE;8@^AZk>hdP+?H7 z*RkV;EXFlNO#ij9KS*YpD|gxR^aKPg<8!s_V!E%}=YyNwqn~|r{$6`>vphnDrd+3` z3fH2?+K~pxy|a-&L;Dwh^;a+))N_I`8?M&L_Nt}N(~W{3gY#CetJBA!90vZQRESsP{LT1moeM_FLp zIU>R67iAwDBKhX2#bC6RzKtPT5<=!lrvm-rkfqnXPlJ%5Kd#rfd@aa}FPH2YuApDfJAeBc`B#g| zS6z`4%jpIB+{en3z&r1UfB3tl5f(;S*k|FzdfLmMnI9sat0uMVf0{LN6*g&CLP{wg zc%PB0MLaU{p;vPFMQzQO!EPG<3_qr))NbzH>Qk#MR2~`wB*$`-#K&I2a=EV=|RYd$` zUG91Ci|ur^^n0;=DR8@fyc6W$h{^hWHwE>E;IeY+hC`7{<=gZm-|R_N9@}1&p~Y>j zOG=mQIw}x&v^jep@gsfQj@#|Vsk*fll747ry^<<3c4O;|&B7+Gu<9;O_7d##ovavq zHDzy2hFI3ZZ|OtTezG^#-OL5E4i=6SqK>h#j(*v{5ei+EZ#piT$9jAE-y8q0{eJ=b C{0m$F From dd96cbb9336267096c38abc8c8bc735e6d1f531d Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Thu, 19 Aug 2021 16:12:39 +0800 Subject: [PATCH 03/60] =?UTF-8?q?=E6=98=BE=E4=BC=A4=E9=AB=98=E6=B8=85=20&?= =?UTF-8?q?=20=E5=8F=AF=E9=80=9A=E8=A1=8C=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _server/editor.js | 88 +++++++++++++++++++++++++++++++++------------- libs/control.js | 23 ++++-------- libs/enemys.js | 8 +++-- libs/ui.js | 4 ++- project/plugins.js | 3 +- 5 files changed, 82 insertions(+), 44 deletions(-) diff --git a/_server/editor.js b/_server/editor.js index de4ca35e..8bf28c04 100644 --- a/_server/editor.js +++ b/_server/editor.js @@ -396,20 +396,40 @@ editor.prototype.drawEventBlock = function () { var directions = (movableArray[x]||{})[y]; if (directions == null) continue; if (!directions.includes('left') && x != 0) { - core.drawLine(fg, 32 * i + 1, 32 * j + 10, 32 * i + 1, 32 * j + 22, '#FF0000', 2); - core.fillPolygon(fg, [[32 * i + 9, 32 * j + 12], [32 * i + 1, 32 * j + 16], [32 * i + 9, 32 * j + 20]], '#FF0000'); + var ndirections = (movableArray[x-1]||{})[y]; + if (ndirections != null && !ndirections.includes('right')) { + core.drawLine(fg, 32 * i + 1, 32 * j + 6, 32 * i + 1, 32 * j + 26, '#FF0000', 2); + } else { + core.drawLine(fg, 32 * i + 1, 32 * j + 10, 32 * i + 1, 32 * j + 22, '#FF0000', 2); + core.fillPolygon(fg, [[32 * i + 9, 32 * j + 12], [32 * i + 1, 32 * j + 16], [32 * i + 9, 32 * j + 20]], '#FF0000'); + } } if (!directions.includes('right') && x != editor.currentFloorData.width - 1) { - core.drawLine(fg, 32 * i + 31, 32 * j + 10, 32 * i + 31, 32 * j + 22, '#FF0000', 2); - core.fillPolygon(fg, [[32 * i + 23, 32 * j + 12], [32 * i + 31, 32 * j + 16], [32 * i + 23, 32 * j + 20]], '#FF0000'); + var ndirections = (movableArray[x+1]||{})[y]; + if (ndirections != null && !ndirections.includes('left')) { + core.drawLine(fg, 32 * i + 31, 32 * j + 6, 32 * i + 31, 32 * j + 26, '#FF0000', 2); + } else { + core.drawLine(fg, 32 * i + 31, 32 * j + 10, 32 * i + 31, 32 * j + 22, '#FF0000', 2); + core.fillPolygon(fg, [[32 * i + 23, 32 * j + 12], [32 * i + 31, 32 * j + 16], [32 * i + 23, 32 * j + 20]], '#FF0000'); + } } if (!directions.includes('up') && y != 0) { - core.drawLine(fg, 32 * i + 10, 32 * j + 1, 32 * i + 22, 32 * j + 1, '#FF0000', 2); - core.fillPolygon(fg, [[32 * i + 12, 32 * j + 9], [32 * i + 16, 32 * j + 1], [32 * i + 20, 32 * j + 9]], '#FF0000'); + var ndirections = movableArray[x][y-1]; + if (ndirections != null && !ndirections.includes('down')) { + core.drawLine(fg, 32 * i + 6, 32 * j + 1, 32 * i + 26, 32 * j + 1, '#FF0000', 2); + } else { + core.drawLine(fg, 32 * i + 10, 32 * j + 1, 32 * i + 22, 32 * j + 1, '#FF0000', 2); + core.fillPolygon(fg, [[32 * i + 12, 32 * j + 9], [32 * i + 16, 32 * j + 1], [32 * i + 20, 32 * j + 9]], '#FF0000'); + } } if (!directions.includes('down') && y != editor.currentFloorData.height - 1) { - core.drawLine(fg, 32 * i + 10, 32 * j + 31, 32 * i + 22, 32 * j + 31, '#FF0000', 2); - core.fillPolygon(fg, [[32 * i + 12, 32 * j + 23], [32 * i + 16, 32 * j + 31], [32 * i + 20, 32 * j + 23]], '#FF0000'); + var ndirections = movableArray[x][y+1]; + if (ndirections != null && !ndirections.includes('up')) { + core.drawLine(fg, 32 * i + 6, 32 * j + 31, 32 * i + 26, 32 * j + 31, '#FF0000', 2); + } else { + core.drawLine(fg, 32 * i + 10, 32 * j + 31, 32 * i + 22, 32 * j + 31, '#FF0000', 2); + core.fillPolygon(fg, [[32 * i + 12, 32 * j + 23], [32 * i + 16, 32 * j + 31], [32 * i + 20, 32 * j + 23]], '#FF0000'); + } } } } @@ -471,28 +491,48 @@ editor.prototype._drawEventBlock_bigmap = function () { var directions = (movableArray[i]||{})[j]; if (directions == null) continue; if (!directions.includes('left') && i != 0) { - core.drawLine(fg, info.left + size * i, info.top + size * j + size / 3, info.left + size * i + 1, info.top + size * j + size * 2 / 3, '#FF0000', 2); - core.fillPolygon(fg, [[info.left + size * i + size / 4, info.top + size * j + size * 3 / 8], - [info.left + size * i, info.top + size * j + size / 2], - [info.left + size * i + size / 4, info.top + size * j + size * 5 / 8]], '#FF0000'); + var ndirections = (movableArray[i-1]||{})[j]; + if (ndirections != null && !ndirections.includes('right')) { + core.drawLine(fg, info.left + size * i, info.top + size * j + size / 4, info.left + size * i, info.top + size * j + size * 3 / 4, '#FF0000', 2); + } else { + core.drawLine(fg, info.left + size * i, info.top + size * j + size / 3, info.left + size * i, info.top + size * j + size * 2 / 3, '#FF0000', 2); + core.fillPolygon(fg, [[info.left + size * i + size / 4, info.top + size * j + size * 3 / 8], + [info.left + size * i, info.top + size * j + size / 2], + [info.left + size * i + size / 4, info.top + size * j + size * 5 / 8]], '#FF0000'); + } } if (!directions.includes('right') && i != editor.currentFloorData.width - 1) { - core.drawLine(fg, info.left + size * i + size, info.top + size * j + size / 3, info.left + size * i + size, info.top + size * j + size * 2 / 3, '#FF0000', 2); - core.fillPolygon(fg, [[info.left + size * i + size * 3 / 4, info.top + size * j + size * 3 / 8], - [info.left + size * i + size, info.top + size * j + size / 2], - [info.left + size * i + size * 3 / 4, info.top + size * j + size * 5 / 8]], '#FF0000'); + var ndirections = (movableArray[i+1]||{})[j]; + if (ndirections != null && !ndirections.includes('left')) { + core.drawLine(fg, info.left + size * i + size, info.top + size * j + size / 4, info.left + size * i + size, info.top + size * j + size * 3 / 4, '#FF0000', 2); + } else { + core.drawLine(fg, info.left + size * i + size, info.top + size * j + size / 3, info.left + size * i + size, info.top + size * j + size * 2 / 3, '#FF0000', 2); + core.fillPolygon(fg, [[info.left + size * i + size * 3 / 4, info.top + size * j + size * 3 / 8], + [info.left + size * i + size, info.top + size * j + size / 2], + [info.left + size * i + size * 3 / 4, info.top + size * j + size * 5 / 8]], '#FF0000'); + } } if (!directions.includes('up') && j != 0) { - core.drawLine(fg, info.left + size * i + size / 3, info.top + size * j, info.left + size * i + size * 2 / 3, info.top + size * j, '#FF0000', 2); - core.fillPolygon(fg, [[info.left + size * i + size * 3 / 8, info.top + size * j + size / 4], - [info.left + size * i + size / 2, info.top + size * j], - [info.left + size * i + size * 5 / 8, info.top + size * j + size / 4]], '#FF0000'); + var ndirections = movableArray[i][j-1]; + if (ndirections != null && !ndirections.includes('down')) { + core.drawLine(fg, info.left + size * i + size / 4, info.top + size * j, info.left + size * i + size * 3 / 4, info.top + size * j, '#FF0000', 2); + } else { + core.drawLine(fg, info.left + size * i + size / 3, info.top + size * j, info.left + size * i + size * 2 / 3, info.top + size * j, '#FF0000', 2); + core.fillPolygon(fg, [[info.left + size * i + size * 3 / 8, info.top + size * j + size / 4], + [info.left + size * i + size / 2, info.top + size * j], + [info.left + size * i + size * 5 / 8, info.top + size * j + size / 4]], '#FF0000'); + } } if (!directions.includes('down') && j != editor.currentFloorData.height - 1) { - core.drawLine(fg, info.left + size * i + size / 3, info.top + size * j + size - 1, info.left + size * i + size * 2 / 3, info.top + size * j + size - 1, '#FF0000', 2); - core.fillPolygon(fg, [[info.left + size * i + size * 3 / 8, info.top + size * j + size * 3 / 4], - [info.left + size * i + size / 2, info.top + size * j + size], - [info.left + size * i + size * 5 / 8, info.top + size * j + size * 3 / 4]], '#FF0000'); + var ndirections = movableArray[i][j+1]; + if (ndirections != null && !ndirections.includes('up')) { + core.drawLine(fg, info.left + size * i + size / 4, info.top + size * j + size, info.left + size * i + size * 3 / 4, info.top + size * j + size, '#FF0000', 2); + } else { + core.drawLine(fg, info.left + size * i + size / 3, info.top + size * j + size, info.left + size * i + size * 2 / 3, info.top + size * j + size, '#FF0000', 2); + core.fillPolygon(fg, [[info.left + size * i + size * 3 / 8, info.top + size * j + size * 3 / 4], + [info.left + size * i + size / 2, info.top + size * j + size], + [info.left + size * i + size * 5 / 8, info.top + size * j + size * 3 / 4]], '#FF0000'); + } } } } diff --git a/libs/control.js b/libs/control.js index 45588528..c3460ad0 100644 --- a/libs/control.js +++ b/libs/control.js @@ -1303,15 +1303,9 @@ control.prototype.drawDamage = function (ctx) { control.prototype._drawDamage_draw = function (ctx, onMap) { if (!core.hasItem('book')) return; - // 双缓冲 - var cacheCtx = core.bigmap.cacheCanvas; - cacheCtx.canvas.width = ctx.canvas.width; - cacheCtx.canvas.height = ctx.canvas.height; - cacheCtx.clearRect(0, 0, cacheCtx.canvas.width, cacheCtx.canvas.height); - if (onMap && core.bigmap.v2) cacheCtx.translate(32, 32); - core.setFont(cacheCtx, "bold 11px Arial"); - core.setTextAlign(cacheCtx, 'left'); + core.setFont(ctx, "bold 11px Arial"); + core.setTextAlign(ctx, 'left'); core.status.damage.data.forEach(function (one) { var px = one.px, py = one.py; if (onMap && core.bigmap.v2) { @@ -1320,10 +1314,10 @@ control.prototype._drawDamage_draw = function (ctx, onMap) { if (px < -32 * 2 || px > core.__PIXELS__ + 32 || py < -32 || py > core.__PIXELS__ + 32) return; } - core.fillBoldText(cacheCtx, one.text, px, py, one.color); + core.fillBoldText(ctx, one.text, px, py, one.color); }); - core.setTextAlign(cacheCtx, 'center'); + core.setTextAlign(ctx, 'center'); core.status.damage.extraData.forEach(function (one) { var px = one.px, py = one.py; if (onMap && core.bigmap.v2) { @@ -1332,13 +1326,10 @@ control.prototype._drawDamage_draw = function (ctx, onMap) { if (px < -32 || px > core.__PIXELS__ + 32 || py < -32 || py > core.__PIXELS__ + 32) return; } - var alpha = core.setAlpha(cacheCtx, one.alpha); - core.fillBoldText(cacheCtx, one.text, px, py, one.color); - core.setAlpha(cacheCtx, alpha); + var alpha = core.setAlpha(ctx, one.alpha); + core.fillBoldText(ctx, one.text, px, py, one.color); + core.setAlpha(ctx, alpha); }); - cacheCtx.translate(0, 0); - - core.drawImage(ctx, cacheCtx.canvas, onMap && core.bigmap.v2 ? -32 : 0, onMap && core.bigmap.v2 ? -32 : 0); } // ------ 录像相关 ------ // diff --git a/libs/enemys.js b/libs/enemys.js index 0fb5e49d..722e6287 100644 --- a/libs/enemys.js +++ b/libs/enemys.js @@ -460,11 +460,15 @@ enemys.prototype._getCurrentEnemys_addEnemy = function (enemyId, enemys, used, x e.damage = this.getDamage(enemy, x, y, floorId); e.critical = critical[0]; e.criticalDamage = critical[1]; - var ratio = core.status.maps[floorId || core.status.floorId].ratio || 1; - e.defDamage = this.getDefDamage(enemy, ratio, x, y, floorId); + e.defDamage = this._getCurrentEnemys_addEnemy_defDamage(enemy, x, y, floorId); enemys.push(e); } +enemys.prototype._getCurrentEnemys_addEnemy_defDamage = function (enemy, x, y, floorId) { + var ratio = core.status.maps[floorId || core.status.floorId].ratio || 1; + return this.getDefDamage(enemy, ratio, x, y, floorId); +} + enemys.prototype._getCurrentEnemys_sort = function (enemys) { return enemys.sort(function (a, b) { if (a.damage == b.damage) { diff --git a/libs/ui.js b/libs/ui.js index a359e5a4..279a580f 100644 --- a/libs/ui.js +++ b/libs/ui.js @@ -2069,6 +2069,7 @@ ui.prototype._drawCursor = function () { if (automaticRoute.cursorY == null) automaticRoute.cursorY = core.getHeroLoc('y'); automaticRoute.cursorX = core.clamp(automaticRoute.cursorX, 0, this.LAST); + automaticRoute.cursorY = core.clamp(automaticRoute.cursorY, 0, this.LAST); core.status.event.id = 'cursor'; core.lockControl(); core.clearUI(); @@ -2524,7 +2525,7 @@ ui.prototype.drawFly = function(page) { var lines = core.splitLines('ui', title, 120, this._buildFont(19, true)); var start_y = middle - (lines.length - 1) * 11; for (var i in lines) { - core.fillText('ui', lines[i], this.PIXEL - 60, start_y); + core.fillText('ui', lines[i], this.PIXEL - 60, start_y, '#FFFFFF'); start_y += 22; } @@ -3386,6 +3387,7 @@ ui.prototype.createCanvas = function (name, x, y, width, height, z) { newCanvas.style.top = y * core.domStyle.scale + 'px'; newCanvas.style.zIndex = z; newCanvas.style.position = 'absolute'; + newCanvas.style.pointerEvents = 'none'; core.dymCanvas[name] = newCanvas.getContext('2d'); core.maps._setHDCanvasSize(core.dymCanvas[name], width, height); core.dom.gameDraw.appendChild(newCanvas); diff --git a/project/plugins.js b/project/plugins.js index 254d451d..6c2b8969 100644 --- a/project/plugins.js +++ b/project/plugins.js @@ -356,7 +356,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = // 背景层2将会覆盖背景层 被事件层覆盖 前景层2将会覆盖前景层 // 另外 请注意加入两个新图层 会让大地图的性能降低一些 // 插件作者:ad - var __enable = false; + var __enable = true; if (!__enable) return; // 创建新图层 @@ -1054,6 +1054,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = core.ui.drawTip = _drawTip; core.control.playSound = _playSound; core.status.route = core.status.route.slice(0, routeLength); + core.control._bindRoutePush(); // 插入事件:改变角色行走图并进行楼层切换 var toFloorId = data.floorId || core.status.floorId; From 92ecb5210ce3737e1d1a2876882bf9d752026055 Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Fri, 20 Aug 2021 12:41:37 +0800 Subject: [PATCH 04/60] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=B4=A0=E6=9D=90?= =?UTF-8?q?=E5=8C=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _server/editor.js | 19 ++++++++++++++----- _server/editor_materialpanel.js | 4 ++-- editor.html | 23 +++++++++++------------ project/plugins.js | 7 +++++-- 4 files changed, 32 insertions(+), 21 deletions(-) diff --git a/_server/editor.js b/_server/editor.js index 8bf28c04..5afe7a24 100644 --- a/_server/editor.js +++ b/_server/editor.js @@ -769,9 +769,14 @@ editor.prototype.drawInitData = function (icons) { } var width = images[img].width, height = images[img].height, mh = height; if (editor.uivalues.folded) { - var per_height = (img == 'enemy48' || img == 'npc48' ? 48 : 32); - width = Math.ceil(height / per_height / editor.uivalues.foldPerCol) * 32; - if (width > 32) mh = per_height * editor.uivalues.foldPerCol; + if (img == 'terrains') { + width = Math.ceil((height / 32 + 2) / editor.uivalues.foldPerCol) * 32; + if (width > 32) mh = 32 * editor.uivalues.foldPerCol; + } else { + var per_height = (img == 'enemy48' || img == 'npc48' ? 48 : 32); + width = Math.ceil(height / per_height / editor.uivalues.foldPerCol) * 32; + if (width > 32) mh = per_height * editor.uivalues.foldPerCol; + } } editor.widthsX[img] = [img, sumWidth / 32, (sumWidth + width) / 32, height]; sumWidth += width; @@ -852,10 +857,14 @@ editor.prototype.drawInitData = function (icons) { })(editor.airwallImg,nowx); if (editor.uivalues.folded) { // --- 单列 & 折行 - var subimgs = core.splitImage(images[img], 32, editor.uivalues.foldPerCol * 32); + var canvas = document.createElement("canvas"); + canvas.width = 32; + canvas.height = images[img].height + 64; + canvas.getContext('2d').drawImage(images[img], 0, 64); + var subimgs = core.splitImage(canvas, 32, editor.uivalues.foldPerCol * 32); var frames = images[img].width / 32; for (var i = 0; i < subimgs.length; i+=frames) { - drawImage(subimgs[i], nowx, i==0?2*32:0, img); + drawImage(subimgs[i], nowx, 0, img); nowx += 32; } } diff --git a/_server/editor_materialpanel.js b/_server/editor_materialpanel.js index 8b7b8adb..cf18c927 100644 --- a/_server/editor_materialpanel.js +++ b/_server/editor_materialpanel.js @@ -150,10 +150,10 @@ editor_materialpanel_wrapper = function (editor) { } else { var height = editor.widthsX[spriter][3], col = height / ysize; + if (spriter == 'terrains') col += 2; if (editor.uivalues.folded && core.tilesets.indexOf(pos.images) == -1) { col = (pos.x == editor.widthsX[spriter][2] - 1) ? ((col - 1) % editor.uivalues.foldPerCol + 1) : editor.uivalues.foldPerCol; } - if (spriter == 'terrains' && pos.x == editor.widthsX[spriter][1]) col += 2; pos.y = Math.min(pos.y, col - 1); } @@ -177,7 +177,7 @@ editor_materialpanel_wrapper = function (editor) { if (editor.uivalues.folded) { y += editor.uivalues.foldPerCol * (pos.x - editor.widthsX[spriter][1]); } - if (pos.images == 'terrains' && pos.x == 0) y -= 2; + if (pos.images == 'terrains') y -= 2; editor.info = { 'images': pos.images, 'y': y } } diff --git a/editor.html b/editor.html index 0c0354c8..e3f5d4df 100644 --- a/editor.html +++ b/editor.html @@ -305,16 +305,16 @@
- + + + + + + + + + 通行度 前景层
-
+
-
diff --git a/project/plugins.js b/project/plugins.js index 6c2b8969..47e7b99d 100644 --- a/project/plugins.js +++ b/project/plugins.js @@ -438,13 +438,16 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = // 背景层2插入事件层前 parent.insertBefore(input, child); // 不能直接更改背景层2的innerText 所以创建文本节点 - var txt = document.createTextNode('背景层2'); + var txt = document.createTextNode('bg2'); // 插入事件层前(即新插入的背景层2前) parent.insertBefore(txt, child); // 向最后插入前景层2(即插入前景层后) parent.appendChild(input2); - var txt2 = document.createTextNode('前景层2'); + var txt2 = document.createTextNode('fg2'); parent.appendChild(txt2); + parent.childNodes[2].replaceWith("bg"); + parent.childNodes[6].replaceWith("事件"); + parent.childNodes[8].replaceWith("fg"); } else { var input = createCanvasBtn_mobile('bg2'); var input2 = createCanvasBtn_mobile('fg2'); From 3e8cb47dd9c9783fa8ae86a756346fb1a85840cf Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Fri, 20 Aug 2021 12:42:15 +0800 Subject: [PATCH 05/60] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=B4=A0=E6=9D=90?= =?UTF-8?q?=E5=8C=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- project/plugins.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.js b/project/plugins.js index 47e7b99d..6c5de0b1 100644 --- a/project/plugins.js +++ b/project/plugins.js @@ -356,7 +356,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = // 背景层2将会覆盖背景层 被事件层覆盖 前景层2将会覆盖前景层 // 另外 请注意加入两个新图层 会让大地图的性能降低一些 // 插件作者:ad - var __enable = true; + var __enable = false; if (!__enable) return; // 创建新图层 From 2592d293d34c7e43d30ab46af3a32903b2e2baf5 Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Fri, 20 Aug 2021 13:37:26 +0800 Subject: [PATCH 06/60] =?UTF-8?q?=E6=96=B0=E5=BB=BA=E6=A5=BC=E5=B1=82?= =?UTF-8?q?=E4=BF=9D=E7=95=99=E5=88=9B=E5=BB=BA=E7=9A=84=E5=B1=9E=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _server/MotaActionParser.js | 2 +- _server/editor_file.js | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/_server/MotaActionParser.js b/_server/MotaActionParser.js index 7f642a9f..b9ec1c6f 100644 --- a/_server/MotaActionParser.js +++ b/_server/MotaActionParser.js @@ -322,7 +322,7 @@ ActionParser.prototype.parseAction = function() { data.time, data.lineHeight||1.4, data.async||false, this.EvalString_Multi(data.text), this.next]); break; case "comment": // 注释 - this.next = MotaActionBlocks['comment_s'].xmlText([this.EvalString_Multi(data.text),this.next],null,data.text); + this.next = MotaActionBlocks['comment_s'].xmlText([this.EvalString_Multi(data.text),this.next]); break; case "setText": // 设置剧情文本的属性 data.title=this.Colour(data.title); diff --git a/_server/editor_file.js b/_server/editor_file.js index 14cee7db..519e1a2e 100644 --- a/_server/editor_file.js +++ b/_server/editor_file.js @@ -219,7 +219,15 @@ editor_file = function (editor, callback) { color: currData.color, weather: currData.weather, }:{}); - + // 继承配置表格新增的基本楼层属性 + if (saveStatus) { + for (var x in currData) { + if (editor.currentFloorData[x] == null && (typeof currData[x] == 'number' || typeof currData[x] == 'string')) { + editor.currentFloorData[x] = currData[x]; + } + } + } + Object.keys(editor.currentFloorData).forEach(function (t) { if (editor.currentFloorData[t] == null) delete editor.currentFloorData[t]; From 5473c22bfbaa2758bf64f84242b9dfc70ae3407d Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Fri, 20 Aug 2021 13:43:47 +0800 Subject: [PATCH 07/60] fix bug --- _server/MotaActionParser.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_server/MotaActionParser.js b/_server/MotaActionParser.js index b9ec1c6f..ed447206 100644 --- a/_server/MotaActionParser.js +++ b/_server/MotaActionParser.js @@ -1464,7 +1464,7 @@ MotaActionFunctions.PosString_pre = function(PosString){ if (!PosString || /^-?\d+$/.test(PosString)) return PosString; //if (!(MotaActionFunctions.pattern.id.test(PosString)))throw new Error(PosString+'中包含了0-9 a-z A-Z _ 和中文之外的字符,或者是没有以flag: 开头'); var comma = PosString.indexOf(','); - if (comma >= 0 && PosString.substring(0, comma).ifndexOf('(') < 0) throw '此处不可写多点坐标'; + if (comma >= 0 && PosString.substring(0, comma).indexOf('(') < 0) throw '此处不可写多点坐标'; return '"'+MotaActionFunctions.replaceFromName(PosString)+'"'; } From a95cc8c615f5345c79edb40b574c9c4a474869ca Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Sun, 22 Aug 2021 13:03:37 +0800 Subject: [PATCH 08/60] Remove useLocalForage --- _docs/api.md | 1 - _server/CodeMirror/defs.js | 1 - libs/actions.js | 29 +++++++---------------------- libs/control.js | 28 ++++++++++------------------ libs/core.js | 33 --------------------------------- libs/utils.js | 25 ------------------------- runtime.d.ts | 1 - 7 files changed, 17 insertions(+), 101 deletions(-) diff --git a/_docs/api.md b/_docs/api.md index 8513751f..b4723ae5 100644 --- a/_docs/api.md +++ b/_docs/api.md @@ -56,7 +56,6 @@ core.platform core.platform.isPC (是否是电脑端) core.platform.isAndroid (是否是安卓端) core.platform.isIOS (是否是iOS端) -core.platform.useLocalForage (是否开启了新版存档) core.domStyle diff --git a/_server/CodeMirror/defs.js b/_server/CodeMirror/defs.js index 0f4a426c..1a5f1c57 100644 --- a/_server/CodeMirror/defs.js +++ b/_server/CodeMirror/defs.js @@ -1824,7 +1824,6 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [ "isPC": "bool", "isAndroid": "bool", "isIOS": "bool", - "useLocalForage": "bool" }, "domStyle": { "!doc": "界面样式", diff --git a/libs/actions.js b/libs/actions.js index b8762467..31f66487 100644 --- a/libs/actions.js +++ b/libs/actions.js @@ -2817,14 +2817,8 @@ actions.prototype._clickStorageRemove_all = function () { core.removeLocalStorage('saveIndex'); core.drawText("\t[操作成功]你的所有存档已被清空。"); }; - if (core.platform.useLocalForage) { - core.ui.drawWaiting("正在清空,请稍候..."); - localforage.clear(done); - } - else { - localStorage.clear(); - done(); - } + core.ui.drawWaiting("正在清空,请稍候..."); + localforage.clear(done); }); } @@ -2843,20 +2837,11 @@ actions.prototype._clickStorageRemove_current = function () { core.removeLocalStorage('saveIndex'); core.drawText("\t[操作成功]当前塔的存档已被清空。"); } - if (core.platform.useLocalForage) { - core.ui.drawWaiting("正在清空,请稍候..."); - Object.keys(core.saves.ids).forEach(function (v) { - core.removeLocalForage("save" + v); - }); - core.removeLocalForage("autoSave", done); - } - else { - Object.keys(core.saves.ids).forEach(function (v) { - core.removeLocalStorage("save" + v); - }); - core.removeLocalStorage("autoSave"); - done(); - } + core.ui.drawWaiting("正在清空,请稍候..."); + Object.keys(core.saves.ids).forEach(function (v) { + core.removeLocalForage("save" + v); + }); + core.removeLocalForage("autoSave", done); }); } diff --git a/libs/control.js b/libs/control.js index c3460ad0..dc58a8e1 100644 --- a/libs/control.js +++ b/libs/control.js @@ -1989,12 +1989,7 @@ control.prototype._doSL_save = function (id) { core.drawTip('存档成功!'); }, function(err) { main.log(err); - if (core.platform.useLocalForage) { - alert("存档失败,错误信息:\n"+err); - } - else { - alert("存档失败,错误信息:\n"+err+"\n建议使用垃圾存档清理工具进行清理!"); - } + alert("存档失败,错误信息:\n"+err); }); core.removeFlag("__events__"); return; @@ -2290,19 +2285,16 @@ control.prototype.getAllSaves = function (callback) { ////// 获得所有存在存档的存档位 ////// control.prototype.getSaveIndexes = function (callback) { var indexes = {}; - if (core.platform.useLocalForage) { - localforage.iterate(function (value, key, n) { + localforage.keys(function (err, keys) { + if (err) { + main.log(err); + return callback(indexes); + } + keys.forEach(function (key) { core.control._getSaveIndexes_getIndex(indexes, key); - }, function () { - callback(indexes); - }); - } - else { - Object.keys(localStorage).forEach(function (key) { - core.control._getSaveIndexes_getIndex(indexes, key); - }); - callback(indexes); - } + }); + callback(indexes); + }); } control.prototype._getSaveIndexes_getIndex = function (indexes, name) { diff --git a/libs/core.js b/libs/core.js index abe42f11..5be2e626 100644 --- a/libs/core.js +++ b/libs/core.js @@ -82,7 +82,6 @@ function core() { 'isQQ': false, // 是否是QQ 'isChrome': false, // 是否是Chrome 'supportCopy': false, // 是否支持复制到剪切板 - 'useLocalForage': true, 'fileInput': null, // FileInput 'fileReader': null, // 是否支持FileReader @@ -402,7 +401,6 @@ core.prototype._init_platform = function () { core.platform.isSafari = /Safari/i.test(navigator.userAgent) && !/Chrome/i.test(navigator.userAgent); core.platform.isQQ = /QQ/i.test(navigator.userAgent); core.platform.isWeChat = /MicroMessenger/i.test(navigator.userAgent); - this._init_checkLocalForage(); if (window.FileReader) { core.platform.fileReader = new FileReader(); core.platform.fileReader.onload = function () { @@ -421,37 +419,6 @@ core.prototype._init_platform = function () { } } -core.prototype._init_checkLocalForage = function () { - core.platform.useLocalForage = core.getLocalStorage('useLocalForage', true); - var _error = function (e) { - main.log(e); - core.platform.useLocalForage = false; - }; - if (core.platform.useLocalForage) { - try { - core.setLocalForage("__test__", lzw_encode("__test__"), function () { - try { - core.getLocalForage("__test__", null, function (data) { - try { - if (lzw_decode(data) != "__test__") { - console.log("localForage unsupported!"); - core.platform.useLocalForage = false; - } - else { - console.log("localForage supported!"); - core.removeLocalForage("__test__"); - } - } - catch (e) {_error(e);} - }, _error) - } - catch (e) {_error(e);} - }, _error) - } - catch (e) {_error(e);} - } -} - core.prototype._init_others = function () { // 一些额外的东西 core.material.groundCanvas = document.createElement('canvas').getContext('2d'); diff --git a/libs/utils.js b/libs/utils.js index 7e04871e..800b2384 100644 --- a/libs/utils.js +++ b/libs/utils.js @@ -252,17 +252,6 @@ utils.prototype.removeLocalStorage = function (key) { } utils.prototype.setLocalForage = function (key, value, successCallback, errorCallback) { - - if (!core.platform.useLocalForage) { - if (this.setLocalStorage(key, value)) { - if (successCallback) successCallback(); - } - else { - if (errorCallback) errorCallback(); - } - return; - } - if (value == null) { this.removeLocalForage(key); return; @@ -286,13 +275,6 @@ utils.prototype.setLocalForage = function (key, value, successCallback, errorCal } utils.prototype.getLocalForage = function (key, defaultValue, successCallback, errorCallback) { - - if (!core.platform.useLocalForage) { - var value = this.getLocalStorage(key, defaultValue); - if (successCallback) successCallback(value); - return; - } - localforage.getItem(core.firstData.name + "_" + key, function (err, value) { if (err) { if (errorCallback) errorCallback(err); @@ -310,13 +292,6 @@ utils.prototype.getLocalForage = function (key, defaultValue, successCallback, e } utils.prototype.removeLocalForage = function (key, successCallback, errorCallback) { - - if (!core.platform.useLocalForage) { - this.removeLocalStorage(key); - if (successCallback) successCallback(); - return; - } - localforage.removeItem(core.firstData.name + "_" + key, function (err) { if (err) { if (errorCallback) errorCallback(err); diff --git a/runtime.d.ts b/runtime.d.ts index 9b411e29..d1cf7de3 100644 --- a/runtime.d.ts +++ b/runtime.d.ts @@ -2774,7 +2774,6 @@ type core = { /** 是否是QQ */isQQ: boolean /** 是否是Chrome */isChrome: boolean /** 是否支持复制到剪切板 */supportCopy: boolean - useLocalForage: boolean, fileInput: null /** 是否支持FileReader */fileReader: null From 654567fdd742ede34b2115a4710d562e8eb62114 Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Tue, 24 Aug 2021 15:28:33 +0800 Subject: [PATCH 09/60] =?UTF-8?q?=E9=80=89=E5=B1=82=20&=20=E6=90=9C?= =?UTF-8?q?=E7=B4=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _server/editor.js | 1 + _server/editor_listen.js | 1 + _server/editor_mappanel.js | 17 ++++++++ _server/editor_ui.js | 82 ++++++++++++++++++++++++++++++++++++++ editor-mobile.html | 3 +- editor.html | 3 +- 6 files changed, 105 insertions(+), 2 deletions(-) diff --git a/_server/editor.js b/_server/editor.js index 5afe7a24..9036c0d2 100644 --- a/_server/editor.js +++ b/_server/editor.js @@ -57,6 +57,7 @@ function editor() { showMovable: document.getElementById('showMovable'), gameInject: document.getElementById('gameInject'), undoFloor: document.getElementById('undoFloor'), + selectFloorBtn: document.getElementById('selectFloorBtn'), editorTheme: document.getElementById('editorTheme'), bigmapBtn : document.getElementById('bigmapBtn'), mapRowMark: document.getElementById('mapRowMark'), diff --git a/_server/editor_listen.js b/_server/editor_listen.js index 5f876bad..474c10cd 100644 --- a/_server/editor_listen.js +++ b/_server/editor_listen.js @@ -37,6 +37,7 @@ editor_listen_wrapper = function (editor) { editor.dom.clearEvent.onmouseup = editor.uifunctions.clearEvent_click editor.dom.clearLoc.onmouseup = editor.uifunctions.clearLoc_click editor.dom.undoFloor.onclick = editor.uifunctions.undoFloor_click + editor.dom.selectFloorBtn.onclick = editor.uifunctions.selectFloorBtn_click editor.dom.editorTheme.onchange = editor.uifunctions.editorTheme_onchange editor.dom.lastUsed.onmouseup = editor.uifunctions.lastUsed_click; diff --git a/_server/editor_mappanel.js b/_server/editor_mappanel.js index 2adb4cac..d451d3c7 100644 --- a/_server/editor_mappanel.js +++ b/_server/editor_mappanel.js @@ -452,6 +452,23 @@ editor_mappanel_wrapper = function (editor) { editor.changeFloor(toId); } + editor.uifunctions.selectFloorBtn_click = function () { + editor.uievent.selectFloor(null, '选择楼层', function (floorId) { + if (!floorId || floorId == editor.currentFloorId) return; + + var saveFloor = document.getElementById('saveFloor'); + if (saveFloor && saveFloor.classList.contains('highlight')) { + printe('请先保存地图!'); + return; + } + + editor_mode.onmode('nextChange'); + editor_mode.onmode('floor'); + editor.dom.selectFloor.value = floorId; + editor.changeFloor(floorId); + }) + } + editor.uifunctions.editorTheme_onchange = function () { var theme = editor.dom.editorTheme.value; editor.config.set('theme', theme); diff --git a/_server/editor_ui.js b/_server/editor_ui.js index 20b4d436..fc960d86 100644 --- a/_server/editor_ui.js +++ b/_server/editor_ui.js @@ -787,6 +787,88 @@ editor_ui_wrapper = function (editor) { return list; } + // ------ 选择楼层 ------ // + uievent.selectFloor = function (floorId, title, callback) { + uievent.isOpen = true; + uievent.elements.div.style.display = 'block'; + uievent.mode = 'selectFloor'; + uievent.elements.selectPoint.style.display = 'none'; + uievent.elements.yes.style.display = 'block'; + uievent.elements.title.innerText = title; + uievent.elements.selectBackground.style.display = 'none'; + uievent.elements.selectFloor.style.display = 'none'; + uievent.elements.selectPointBox.style.display = 'none'; + uievent.elements.canvas.style.display = 'none'; + uievent.elements.usedFlags.style.display = 'none'; + uievent.elements.extraBody.style.display = 'block'; + uievent.elements.body.style.overflow = "auto"; + + uievent.elements.yes.onclick = function () { + var floorId = uievent.values.floorId; + uievent.close(); + if (callback) callback(floorId); + } + + if (floorId instanceof Array) floorId = floorId[0]; + if (!floorId) floorId = editor.currentFloorId; + uievent.values.floorId = floorId; + + var html = "

"; + html += "搜索楼层:"; + html += "" + + one + '(' + floor.title + ')' + ""; + html += ""; + html += ""; + html += '
'; + }); + floorList.innerHTML = html; + } + + uievent._selectFloor_preview = function (button) { + var span = button.nextElementSibling; + while (span.firstChild) span.removeChild(span.lastChild); + var floorId = span.getAttribute('key'); + + if (span.style.display == 'none') { + button.innerText = '收起'; + span.style.display = 'inline'; + if (!uievent.values.dom) { + var canvas = document.createElement('canvas'); + canvas.style.position = 'relative'; + canvas.style.marginLeft = "-10px"; + canvas.style.marginTop = '5px'; + canvas.style.width = "100%" + canvas.width = canvas.height = core.__PIXELS__; + uievent.values.dom = canvas; + uievent.values.ctx = canvas.getContext('2d'); + } + span.appendChild(uievent.values.dom); + core.clearMap(uievent.values.ctx); + core.drawThumbnail(floorId, null, {ctx: uievent.values.ctx}); + } else { + button.innerText = '预览'; + span.style.display = 'none'; + } + } + // ------ 素材选择框 ------ // uievent.selectMaterial = function (value, title, directory, transform, callback) { var one = directory.split(':'); diff --git a/editor-mobile.html b/editor-mobile.html index 0356e7c5..2c117bd3 100644 --- a/editor-mobile.html +++ b/editor-mobile.html @@ -381,8 +381,9 @@

+ - +
+ - + From f6109f4adc493d225ca4c67c8b009c772e3ca775 Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Tue, 24 Aug 2021 16:40:18 +0800 Subject: [PATCH 10/60] =?UTF-8?q?=E4=BB=A5=E6=AD=A4=E7=B4=A0=E6=9D=90?= =?UTF-8?q?=E4=B8=BA=E7=9B=AE=E6=A0=87=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _server/editor_datapanel.js | 50 +++++++++++++++++++++++++++++++++++++ editor-mobile.html | 8 +++--- editor.html | 8 +++--- 3 files changed, 60 insertions(+), 6 deletions(-) diff --git a/_server/editor_datapanel.js b/_server/editor_datapanel.js index bf699656..3ae713c3 100644 --- a/_server/editor_datapanel.js +++ b/_server/editor_datapanel.js @@ -332,6 +332,9 @@ editor_datapanel_wrapper = function (editor) { window.location.reload(); }); } + newIdIdnum.children[6].onclick = function () { + editor.uifunctions.appendMaterialByInfo(editor_mode.info); + } } editor.uifunctions.changeId_func = function () { @@ -381,6 +384,9 @@ editor_datapanel_wrapper = function (editor) { window.location.reload(); }); } + changeId.children[3].onclick = function () { + editor.uifunctions.appendMaterialByInfo(editor_mode.info); + } } editor.uifunctions.copyPasteEnemyItem_func = function () { @@ -811,6 +817,10 @@ editor_datapanel_wrapper = function (editor) { } var loadImage = function (content, callback) { + if (content instanceof Image || content.getContext != null) { + callback(content); + return; + } var image = new Image(); try { image.onload = function () { @@ -1124,6 +1134,46 @@ editor_datapanel_wrapper = function (editor) { } reader.readAsDataURL(file); } + + editor.uifunctions.appendMaterialByInfo = function (info) { + if (info.isTile) { + printe('额外素材不支持此功能!'); + return; + } + var img = null; + var cls = info.images; + var height = cls == 'enemy48' || cls == 'npc48' ? 48 : 32; + + if (cls == 'autotile') { + img = core.material.images.autotile[info.id]; + } else { + var image = core.material.images[cls]; + var width = image.width; + img = document.createElement('canvas'); + img.width = width; + img.height = height; + img.getContext('2d').drawImage(image, 0, info.y * height, width, height, 0, 0, width, height); + } + + editor.mode.change('appendpic'); + editor.dom.selectAppend.value = cls; + editor.dom.selectAppend.onchange(); + + afterReadFile(img, function () { + changeColorInput.value = 0; + if (cls == 'autotile') return; + + editor_mode.appendPic.index = 0; + for (var ii = 0; ii < editor_mode.appendPic.num; ++ii) { + editor_mode.appendPic.selectPos[ii] = {x: ii, y: 0, ysize: height}; + editor.dom.appendPicSelection.children[ii].style = [ + 'left:', ii * 32, 'px;', + 'top:', 0, 'px;', + 'height:', height - 6, 'px;' + ].join(''); + } + }); + } } /////////////////////////////////////////////////////////////////////// diff --git a/editor-mobile.html b/editor-mobile.html index 2c117bd3..f27050ba 100644 --- a/editor-mobile.html +++ b/editor-mobile.html @@ -150,12 +150,14 @@
- + +
- + - + +
diff --git a/editor.html b/editor.html index e2bf7260..3ff596d3 100644 --- a/editor.html +++ b/editor.html @@ -147,12 +147,14 @@
- + +
- + - + +
From fba7f313097101f906dc003b94bc87588a0a2c34 Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Tue, 24 Aug 2021 18:43:16 +0800 Subject: [PATCH 11/60] Optimize _makeAutotileEdges --- libs/maps.js | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/libs/maps.js b/libs/maps.js index 11e74997..eaa0ddc8 100644 --- a/libs/maps.js +++ b/libs/maps.js @@ -1684,25 +1684,26 @@ maps.prototype._makeAutotileEdges = function () { ctx.msImageSmoothingEnabled = false; ctx.imageSmoothingEnabled = false; + var first = {}, second = {}; autotileIds.forEach(function (t) { var n = core.maps.getNumberById(t); - core.material.autotileEdges[n] = [n]; - core.clearMap(ctx, 0, 0, 32, 32); core.drawImage(ctx, core.material.images.autotile[t], 0, 0, 32, 32, 0, 0, 32, 32); - var data = canvas.toDataURL("image/png"); + first[n] = canvas.toDataURL("image/png"); + core.clearMap(ctx, 0, 0, 32, 32); + core.drawImage(ctx, core.material.images.autotile[t], 32, 0, 32, 32, 0, 0, 32, 32); + second[n] = canvas.toDataURL("image/png"); + }); - autotileIds.forEach(function (t2) { - if (t == t2) return; - var n2 = core.maps.getNumberById(t2); - - core.clearMap(ctx, 0, 0, 32, 32); - core.drawImage(ctx, core.material.images.autotile[t2], 32, 0, 32, 32, 0, 0, 32, 32); - if (data == canvas.toDataURL("image/png")) { + for (var n in first) { + core.material.autotileEdges[n] = [n]; + for (var n2 in second) { + if (n == n2) continue; + if (first[n] == second[n2]) { core.material.autotileEdges[n].push(n2); } - }); - }); + } + } } ////// 绘制缩略图 ////// From c70a466091baff51d2d811287092338f3cb947ef Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Tue, 24 Aug 2021 20:32:16 +0800 Subject: [PATCH 12/60] =?UTF-8?q?=E9=AB=98=E5=B1=82=E5=A1=94=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libs/loader.js | 16 ++++++++++++++++ main.js | 16 ++++++++++++++-- server.py | 22 ++++++++++++++++++++++ 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/libs/loader.js b/libs/loader.js index 1395d34f..8ca0868f 100644 --- a/libs/loader.js +++ b/libs/loader.js @@ -305,6 +305,22 @@ loader.prototype.loadImagesFromZip = function (url, names, toSave, onprogress, o loader.prototype._loadAnimates_sync = function () { this._setStartLoadTipText("正在加载动画文件..."); + if (main.supportBunch) { + if (core.animates.length > 0) { + core.http('GET', '__all_animates__?v=' + main.version + '&id=' + core.animates.join(','), null, function (content) { + var u = content.split('@@@~~~###~~~@@@'); + for (var i = 0; i < core.animates.length; ++i) { + if (u[i] != '') { + core.material.animates[core.animates[i]] = core.loader._loadAnimate(u[i]); + } else { + console.error('无法找到动画文件' + core.animates[i] + '!'); + } + } + }, "text/plain; charset=x-user-defined"); + } + return; + } + core.animates.forEach(function (t) { core.http('GET', 'project/animates/' + t + ".animate?v=" + main.version, null, function (content) { core.material.animates[t] = core.loader._loadAnimate(content); diff --git a/main.js b/main.js index 88379e9d..d610691a 100644 --- a/main.js +++ b/main.js @@ -290,8 +290,19 @@ main.prototype.loadFloors = function (callback) { main.dom.mainTips.style.display = 'none'; callback(); } + return; } - else { + + // 高层塔优化 + var script = document.createElement('script'); + script.src = '__all_floors__.js?v=' + this.version + '&id=' + main.floorIds.join(','); + script.onload = function () { + main.dom.mainTips.style.display = 'none'; + main.supportBunch = true; + callback(); + } + script.onerror = script.onabort = script.ontimeout = function (e) { + console.clear(); for (var i = 0; i < main.floorIds.length; i++) { main.loadFloor(main.floorIds[i], function (modName) { main.setMainTipsText("楼层 " + modName + '.js 加载完毕'); @@ -300,8 +311,9 @@ main.prototype.loadFloors = function (callback) { callback(); } }); - } + } } + main.dom.body.appendChild(script); } ////// 加载某一个楼层 ////// diff --git a/server.py b/server.py index 04533e94..cad5e4a1 100644 --- a/server.py +++ b/server.py @@ -60,6 +60,28 @@ def get_file(path): def root(): return static_file('index.html') +@app.route('/__all_floors__.js', methods=['GET']) +def all_floors(): + ids = request.args.get('id', '').split(',') + if len(ids) == 0: + abort(404) + return None + return Response('\n'.join([get_file('project/floors/%s.js' % id) for id in ids]), mimetype = 'text/javascript') + +@app.route('/__all_animates__', methods=['GET']) +def all_animates(): + ids = request.args.get('id', '').split(',') + if len(ids) == 0: + abort(404) + return None + content = [] + for id in ids: + animate = 'project/animates/%s.animate' % id + if os.path.exists(animate): + content.append(get_file(animate)) + else: content.append('') + return '@@@~~~###~~~@@@'.join(content) + @app.route('/', methods=['GET']) def static_file(path): if os.path.isdir(path): From ff1da6ebd96a1e5e054e6c62df48402c04bcdbe4 Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Tue, 24 Aug 2021 23:03:44 +0800 Subject: [PATCH 13/60] =?UTF-8?q?=E5=90=AF=E5=8A=A8=E6=9C=8D=E5=8A=A1=20&?= =?UTF-8?q?=20=E4=BC=98=E5=8C=96splitImage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _server/editor.js | 33 ++++++++++++++++++++++++++------- editor-mobile.html | 2 +- editor.html | 2 +- 启动服务.exe | Bin 56320 -> 56832 bytes 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/_server/editor.js b/_server/editor.js index 9036c0d2..df10f614 100644 --- a/_server/editor.js +++ b/_server/editor.js @@ -755,6 +755,27 @@ editor.prototype.drawInitData = function (icons) { }); var imgNames = ["terrains", "animates", "enemys", "enemy48", "items", "npcs", "npc48", "autotile"]; + var splitCanvas = document.createElement('canvas'); + var splitCtx = splitCanvas.getContext('2d'); + splitCtx.imageSmoothingEnabled = false; + + var splitImage = function (image, width, height) { + if (image.width == width && image.height == height) { + return [image]; + } + var ans = []; + for (var j = 0; j < image.height; j += h) { + var h = Math.min(height, image.height - j); + splitCanvas.width = width; + splitCanvas.height = h; + core.drawImage(splitCtx, image, 0, j, width, h, 0, 0, width, h); + var data = new Image(); + data.src = splitCanvas.toDataURL("image/png"); + ans.push(data); + } + return ans; + } + for (var ii = 0; ii < imgNames.length; ii++) { var img = imgNames[ii], tempy = 0; if (img == 'autotile') { @@ -862,9 +883,8 @@ editor.prototype.drawInitData = function (icons) { canvas.width = 32; canvas.height = images[img].height + 64; canvas.getContext('2d').drawImage(images[img], 0, 64); - var subimgs = core.splitImage(canvas, 32, editor.uivalues.foldPerCol * 32); - var frames = images[img].width / 32; - for (var i = 0; i < subimgs.length; i+=frames) { + var subimgs = splitImage(canvas, 32, editor.uivalues.foldPerCol * 32); + for (var i = 0; i < subimgs.length; i++) { drawImage(subimgs[i], nowx, 0, img); nowx += 32; } @@ -880,7 +900,7 @@ editor.prototype.drawInitData = function (icons) { var tempx = editor.uivalues.folded ? 32 : 96; for (var im in autotiles) { var tempy = editor.uivalues.folded ? 32 : autotiles[im].height; - var subimgs = core.splitImage(autotiles[im], tempx, tempy); + var subimgs = splitImage(autotiles[im], tempx, tempy); drawImage(subimgs[0], nowx, nowy, img); nowy += tempy; } @@ -890,9 +910,8 @@ editor.prototype.drawInitData = function (icons) { if (editor.uivalues.folded) { // --- 单列 & 折行 var per_height = img.endsWith('48') ? 48 : 32; - var subimgs = core.splitImage(images[img], 32, editor.uivalues.foldPerCol * per_height); - var frames = images[img].width / 32; - for (var i = 0; i < subimgs.length; i+=frames) { + var subimgs = splitImage(images[img], 32, editor.uivalues.foldPerCol * per_height); + for (var i = 0; i < subimgs.length; i++) { drawImage(subimgs[i], nowx, 0, img); nowx += 32; } diff --git a/editor-mobile.html b/editor-mobile.html index f27050ba..e40fe7d5 100644 --- a/editor-mobile.html +++ b/editor-mobile.html @@ -348,7 +348,7 @@ - diff --git a/editor.html b/editor.html index 3ff596d3..282440e2 100644 --- a/editor.html +++ b/editor.html @@ -307,7 +307,7 @@
- diff --git a/启动服务.exe b/启动服务.exe index 7c532394cae0cdeb32ec6ffa6f6bd84b1fc9ede7..5234a1e9baf261938d585f6e37bee07c95b91d90 100644 GIT binary patch delta 13543 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 delta 12873 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 Date: Sat, 28 Aug 2021 12:29:01 +0800 Subject: [PATCH 14/60] Update tools --- libs/enemys.js | 47 +++++++++++++++++++++++++++++++++-------------- libs/maps.js | 2 ++ libs/ui.js | 8 -------- 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/libs/enemys.js b/libs/enemys.js index 722e6287..5ab31a09 100644 --- a/libs/enemys.js +++ b/libs/enemys.js @@ -228,13 +228,12 @@ enemys.prototype.nextCriticals = function (enemy, number, x, y, floorId) { if (specialCriticals != null) return specialCriticals; var info = this.getDamageInfo(enemy, null, x, y, floorId); if (info == null) { // 如果未破防... - var enemyInfo = this.getEnemyInfo(enemy, null, x, y, floorId); - if (enemyInfo.def == null || enemyInfo.def < core.status.hero.atk) return []; - // 再次尝试获得破防后伤害 - info = this.getDamageInfo(enemy, {atk: enemyInfo.def + 1}, x, y, floorId); - if (info == null || info.mon_def != enemyInfo.def) return []; + var overAtk = this._nextCriticals_overAtk(enemy, x, y, floorId); + if (overAtk == null) return []; + if (typeof overAtk[1] == 'number') return [[overAtk[0], -overAtk[1]]]; + info = overAtk[1]; info.__over__ = true; - info.__overAtk__ = info.mon_def + 1 - core.status.hero.atk; + info.__overAtk__ = overAtk[0]; } if (typeof info == 'number') return [[0,0]]; @@ -255,6 +254,26 @@ enemys.prototype.nextCriticals = function (enemy, number, x, y, floorId) { } } +/// 未破防临界采用二分计算 +enemys.prototype._nextCriticals_overAtk = function (enemy, x, y, floorId) { + var calNext = function (currAtk, maxAtk) { + var start = currAtk, end = maxAtk; + if (start > end) return null; + + while (start < end) { + var mid = Math.floor((start + end) / 2); + if (mid - start > end - mid) mid--; + var nextInfo = core.enemys.getDamageInfo(enemy, {"atk": mid}, x, y, floorId); + if (nextInfo != null) end = mid; + else start = mid + 1; + } + var nextInfo = core.enemys.getDamageInfo(enemy, {"atk": start}, x, y, floorId); + return nextInfo == null ? null : [start - core.status.hero.atk, nextInfo]; + } + return calNext(core.status.hero.atk + 1, + core.getEnemyValue(enemy, 'hp', x, y, floorId) + core.getEnemyValue(enemy, 'def', x, y, floorId)); +} + enemys.prototype._nextCriticals_special = function (enemy, number, x, y, floorId) { if (this.hasSpecial(enemy.special, 10) || this.hasSpecial(enemy.special, 3)) return []; // 模仿or坚固临界 @@ -266,15 +285,15 @@ enemys.prototype._nextCriticals_useLoop = function (enemy, info, number, x, y, f var list = []; var start_atk = hero_atk; if (info.__over__) { - start_atk = mon_def + 1; + start_atk += info.__overAtk__; list.push([info.__overAtk__, -info.damage]); } for (var atk = start_atk + 1; atk <= mon_hp + mon_def; atk++) { - var nextInfo = this.getDamageInfo(enemy, {"atk": Math.ceil(atk / core.getBuff('atk'))}, x, y, floorId); + var nextInfo = this.getDamageInfo(enemy, {"atk": atk}, x, y, floorId); if (nextInfo == null || (typeof nextInfo == 'number')) break; if (pre > nextInfo.damage) { pre = nextInfo.damage; - list.push([Math.ceil(atk / core.getBuff('atk')) - hero_atk, info.damage - nextInfo.damage]); + list.push([atk - hero_atk, info.damage - nextInfo.damage]); if (nextInfo.damage <= 0 && !core.flags.enableNegativeDamage) break; if (list.length >= number) break; } @@ -288,7 +307,7 @@ enemys.prototype._nextCriticals_useBinarySearch = function (enemy, info, number, var list = []; var start_atk = hero_atk; if (info.__over__) { - start_atk = mon_def + 1; + start_atk += info.__overAtk__; list.push([info.__overAtk__, -info.damage]); } var calNext = function (currAtk, maxAtk) { @@ -298,12 +317,12 @@ enemys.prototype._nextCriticals_useBinarySearch = function (enemy, info, number, while (start < end) { var mid = Math.floor((start + end) / 2); if (mid - start > end - mid) mid--; - var nextInfo = core.enemys.getDamageInfo(enemy, {"atk": Math.ceil(mid / core.getBuff('atk'))}, x, y, floorId); + var nextInfo = core.enemys.getDamageInfo(enemy, {"atk": mid}, x, y, floorId); if (nextInfo == null || (typeof nextInfo == 'number')) return null; if (pre > nextInfo.damage) end = mid; else start = mid + 1; } - var nextInfo = core.enemys.getDamageInfo(enemy, {"atk": Math.ceil(start / core.getBuff('atk'))}, x, y, floorId); + var nextInfo = core.enemys.getDamageInfo(enemy, {"atk": start}, x, y, floorId); return nextInfo == null || (typeof nextInfo == 'number') || nextInfo.damage >= pre ? null : [start, nextInfo.damage]; } var currAtk = start_atk; @@ -312,7 +331,7 @@ enemys.prototype._nextCriticals_useBinarySearch = function (enemy, info, number, if (next == null) break; currAtk = next[0]; pre = next[1]; - list.push([Math.ceil(currAtk / core.getBuff('atk')) - hero_atk, info.damage - pre]); + list.push([currAtk - hero_atk, info.damage - pre]); if (pre <= 0 && !core.flags.enableNegativeDamage) break; if (list.length >= number) break; } @@ -330,7 +349,7 @@ enemys.prototype._nextCriticals_useTurn = function (enemy, info, number, x, y, f var list = [], pre = null; var start_atk = hero_atk; if (info.__over__) { - start_atk = mon_def + 1; + start_atk += info.__overAtk__; list.push([info.__overAtk__, -info.damage]); } for (var t = turn - 1; t >= 1; t--) { diff --git a/libs/maps.js b/libs/maps.js index eaa0ddc8..e292dec2 100644 --- a/libs/maps.js +++ b/libs/maps.js @@ -1696,8 +1696,10 @@ maps.prototype._makeAutotileEdges = function () { }); for (var n in first) { + n = parseInt(n); core.material.autotileEdges[n] = [n]; for (var n2 in second) { + n2 = parseInt(n2); if (n == n2) continue; if (first[n] == second[n2]) { core.material.autotileEdges[n].push(n2); diff --git a/libs/ui.js b/libs/ui.js index 279a580f..403fbc14 100644 --- a/libs/ui.js +++ b/libs/ui.js @@ -2482,14 +2482,6 @@ ui.prototype._drawBookDetail_turnAndCriticals = function (enemy, floorId, texts) }); while (criticals[0]=='0:0') criticals.shift(); texts.push("\r[#FF6A6A]\\d临界表:\\d\r[]"+JSON.stringify(criticals)); - var prevInfo = core.getDamageInfo(enemy.id, {atk: core.status.hero.atk-1}, null, null, floorId); - if (prevInfo != null && damageInfo != null) { - if (damageInfo.damage != null) damageInfo = damageInfo.damage; - if (prevInfo.damage != null) prevInfo = prevInfo.damage; - if (prevInfo > damageInfo) { - texts.push("(当前攻击力正位于临界点上)") - } - } } ui.prototype._drawBookDetail_drawContent = function (enemy, content, pos) { From 60656760073ff585938611b51c0049769c3396c1 Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Sat, 28 Aug 2021 13:22:00 +0800 Subject: [PATCH 15/60] =?UTF-8?q?=E5=A2=9E=E8=AE=BEsample2=E5=B1=82?= =?UTF-8?q?=E5=A4=A7=E6=80=AA=E7=89=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- project/data.js | 12 +++++++++++- project/enemys.js | 10 +++++++--- project/floors/sample2.js | 34 ++++++++++++++++------------------ project/icons.js | 26 +++++++------------------- project/images/bear.png | Bin 0 -> 14068 bytes project/images/dragon.png | Bin 0 -> 8662 bytes project/maps.js | 22 +++++----------------- project/materials/enemy48.png | Bin 9801 -> 39006 bytes project/materials/npcs.png | Bin 21322 -> 12971 bytes 9 files changed, 46 insertions(+), 58 deletions(-) create mode 100644 project/images/bear.png create mode 100644 project/images/dragon.png diff --git a/project/data.js b/project/data.js index d99ae5d6..d3abd830 100644 --- a/project/data.js +++ b/project/data.js @@ -9,7 +9,9 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = ], "floorPartitions": [], "images": [ + "bear.png", "bg.jpg", + "dragon.png", "hero.png", "winskin.png" ], @@ -150,7 +152,15 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = ], "floorChangingStyle": "background-color: black; color: white", "font": "Verdana" - } + }, + "splitImages": [ + { + "name": "dragon.png", + "width": 384, + "height": 96, + "prefix": "dragon_" + } + ] }, "firstData": { "title": "魔塔样板", diff --git a/project/enemys.js b/project/enemys.js index bac13fde..17cde5ac 100644 --- a/project/enemys.js +++ b/project/enemys.js @@ -35,7 +35,7 @@ var enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80 = "whiteHornSlime": {"name":"尖角怪","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0}, "redSwordsman": {"name":"剑王","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, "poisonZombie": {"name":"绿兽人","hp":100,"atk":120,"def":0,"money":13,"exp":0,"point":0,"special":[12]}, - "octopus": {"name":"血影","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0}, + "octopus": {"name":"血影","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0,"bigImage":"dragon_1.png"}, "princessEnemy": {"name":"假公主","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0}, "angel": {"name":"天使","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0}, "elemental": {"name":"元素生物","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0}, @@ -52,7 +52,7 @@ var enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80 = "magicMaster": {"name":"黑暗大法师","hp":100,"atk":120,"def":0,"money":12,"exp":0,"point":0,"special":11,"value":0.3333333333333333,"add":true,"notBomb":true}, "devilWarrior": {"name":"魔神武士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0}, "fairyEnemy": {"name":"仙子","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0}, - "dragon": {"name":"魔龙","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0}, + "dragon": {"name":"魔龙","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0,"bigImage":"dragon_0.png"}, "skeletonKnight": {"name":"骷髅武士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0}, "skeletonPresbyter": {"name":"骷髅巫师","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0}, "ironRock": {"name":"铁面人","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0}, @@ -76,5 +76,9 @@ var enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80 = "blueKing": {"name":"白衣武士","hp":100,"atk":120,"def":0,"money":17,"exp":0,"point":0,"special":16}, "keiskeiFairy": {"name":"铃兰花妖","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0}, "tulipFairy": {"name":"郁金香花妖","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0}, - "purpleBowman": {"name":"高级弓兵","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0} + "purpleBowman": {"name":"高级弓兵","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0}, + "bearDown": {"name":"熊出没","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[],"faceIds":{"down":"bearDown","left":"bearLeft","right":"bearRight","up":"bearUp"},"bigImage":"bear.png"}, + "bearLeft": {"name":"熊出没","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[],"faceIds":{"down":"bearDown","left":"bearLeft","right":"bearRight","up":"bearUp"}}, + "bearRight": {"name":"熊出没","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[],"faceIds":{"down":"bearDown","left":"bearLeft","right":"bearRight","up":"bearUp"}}, + "bearUp": {"name":"熊出没","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[],"faceIds":{"down":"bearDown","left":"bearLeft","right":"bearRight","up":"bearUp"}} } \ No newline at end of file diff --git a/project/floors/sample2.js b/project/floors/sample2.js index 821f594a..7e370e35 100644 --- a/project/floors/sample2.js +++ b/project/floors/sample2.js @@ -13,22 +13,22 @@ main.floors.sample2= "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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [ 0, 0, 1,121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [ 0, 0, 1, 0, 0, 0,202, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,202, 0, 0, 0, 0, 0, 0], - [ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [ 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0], - [ 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0], - [ 0, 0, 0, 0, 1, 1, 45, 0, 1, 0,202,202, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0,202,202, 0], - [ 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0], - [ 0, 0, 0, 0, 0, 0, 88, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], - [ 0, 0, 0, 0, 0,202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,202, 0, 0, 0, 0, 0, 0, 0], + [ 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [ 1, 27, 28, 29, 1, 0,202, 1, 27, 28, 29, 1, 0, 0, 0, 1, 0, 0, 0,202, 0, 0, 0, 0, 0, 0], + [ 1, 31, 32, 33, 1, 0, 0, 1, 31, 32, 33, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [ 1, 21,258, 22, 1, 0, 0, 1, 21,257, 22, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [ 1, 1, 82, 1, 1, 0, 0, 1, 1, 81, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0], + [ 0, 0, 22, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0], + [ 0, 0, 0, 0, 0, 0, 45, 0, 1, 0,202,202, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0,202,202, 0], + [ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0], + [ 0,327, 0, 0, 0, 0, 88, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], + [ 0, 0, 0, 0, 0,202, 0, 0, 0, 0,328, 0, 0, 0, 0, 0, 0, 0,202, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 0, 0, 87, 0, 0, 0, 0,122, 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], - [ 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [ 0, 0, 1, 0, 0, 0,202, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,202, 0, 0, 0, 0, 0, 0], + [ 0, 0, 0,329, 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,330, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,202, 0, 0, 0, 0, 0, 0], + [ 0, 0, 1, 0, 0,202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0], @@ -42,9 +42,6 @@ main.floors.sample2= "height": 26, "firstArrive": [], "events": { - "3,2": [ - "123" - ], "12,12": [ "234" ] @@ -71,5 +68,6 @@ main.floors.sample2= ], "autoEvent": {}, - "beforeBattle": {} + "beforeBattle": {}, + "cannotMoveIn": {} } \ No newline at end of file diff --git a/project/icons.js b/project/icons.js index fbff0263..c0d6eae8 100644 --- a/project/icons.js +++ b/project/icons.js @@ -109,24 +109,8 @@ var icons_4665ee12_3a1f_44a4_bea3_0fccba634dc1 = "expShop": 9, "moneyShop": 10, "princess": 11, - "greenMan": 28, - "blueTrader": 29, - "octopusLeftTop": 12, - "octopusTop": 13, - "octopusRightTop": 14, - "octopusLeft": 15, - "octopusCenter": 16, - "octopusRight": 17, - "octopusLeftBottom": 18, - "octopusRightBottom": 19, - "dragonLeftTop": 20, - "dragonTop": 21, - "dragonRightTop": 22, - "dragonLeft": 23, - "dragonCenter": 24, - "dragonRight": 25, - "dragonLeftBottom": 26, - "dragonRightBottom": 27 + "greenMan": 12, + "blueTrader": 13 }, "npc48": { "npc0": 0, @@ -219,7 +203,11 @@ var icons_4665ee12_3a1f_44a4_bea3_0fccba634dc1 = "angel": 0, "elemental": 1, "steelGuard": 2, - "evilBat": 3 + "evilBat": 3, + "bearDown": 4, + "bearLeft": 5, + "bearRight": 6, + "bearUp": 7 }, "items": { "yellowKey": 0, diff --git a/project/images/bear.png b/project/images/bear.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0ea543f7b47ea1f40eaa0932f5a0665a638d9f GIT binary patch literal 14068 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 I>DkNw10Ke literal 0 HcmV?d00001 diff --git a/project/images/dragon.png b/project/images/dragon.png new file mode 100644 index 0000000000000000000000000000000000000000..ad20aaae957a2d70e257f90df0ac738823b2a4e9 GIT binary patch literal 8662 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 R0lh%Gw*9`f&@J%q{{Y3HUgZD) literal 0 HcmV?d00001 diff --git a/project/maps.js b/project/maps.js index 6c8d0509..fbf881ca 100644 --- a/project/maps.js +++ b/project/maps.js @@ -118,22 +118,6 @@ var maps_90f36752_8815_4be8_b32b_d7fad1d0542e = "168": {"cls":"terrains","id":"flower","canPass":true}, "169": {"cls":"terrains","id":"box","trigger":"pushBox"}, "170": {"cls":"terrains","id":"boxed","trigger":"pushBox"}, - "181": {"cls":"npcs","id":"octopusLeftTop"}, - "182": {"cls":"npcs","id":"octopusTop"}, - "183": {"cls":"npcs","id":"octopusRightTop"}, - "184": {"cls":"npcs","id":"octopusLeft"}, - "185": {"cls":"npcs","id":"octopusCenter"}, - "186": {"cls":"npcs","id":"octopusRight"}, - "187": {"cls":"npcs","id":"octopusLeftBottom"}, - "188": {"cls":"npcs","id":"octopusRightBottom"}, - "189": {"cls":"npcs","id":"dragonLeftTop"}, - "190": {"cls":"npcs","id":"dragonTop"}, - "191": {"cls":"npcs","id":"dragonRightTop"}, - "192": {"cls":"npcs","id":"dragonLeft"}, - "193": {"cls":"npcs","id":"dragonCenter"}, - "194": {"cls":"npcs","id":"dragonRight"}, - "195": {"cls":"npcs","id":"dragonLeftBottom"}, - "196": {"cls":"npcs","id":"dragonRightBottom"}, "201": {"cls":"enemys","id":"greenSlime"}, "202": {"cls":"enemys","id":"redSlime"}, "203": {"cls":"enemys","id":"blackSlime"}, @@ -235,5 +219,9 @@ var maps_90f36752_8815_4be8_b32b_d7fad1d0542e = "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}}}, "325": {"cls":"enemys","id":"keiskeiFairy"}, - "326": {"cls":"enemys","id":"tulipFairy"} + "326": {"cls":"enemys","id":"tulipFairy"}, + "327": {"cls":"enemy48","id":"bearDown"}, + "328": {"cls":"enemy48","id":"bearLeft"}, + "329": {"cls":"enemy48","id":"bearRight"}, + "330": {"cls":"enemy48","id":"bearUp"} } \ No newline at end of file diff --git a/project/materials/enemy48.png b/project/materials/enemy48.png index a7f7d0cdcea267a3a8b76a901204650c94640eee..d18a129ae565c32104ec8b81db776ab3d1171816 100644 GIT binary patch literal 39006 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%0AA!p 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 I?>I#Lf9AkY761SM diff --git a/project/materials/npcs.png b/project/materials/npcs.png index e37d3498cb4912e2ba89e3aeb6f585331ba4c199..2bff0872689f5895a52879d97d660e1526175173 100644 GIT binary patch literal 12971 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 KeW=vfne{(3 Date: Mon, 30 Aug 2021 15:56:56 +0800 Subject: [PATCH 16/60] Update localforage to use jsinterface --- libs/actions.js | 7 ++--- libs/control.js | 2 +- libs/utils.js | 83 ++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 79 insertions(+), 13 deletions(-) diff --git a/libs/actions.js b/libs/actions.js index 31f66487..34a4d68d 100644 --- a/libs/actions.js +++ b/libs/actions.js @@ -2804,7 +2804,8 @@ actions.prototype._clickStorageRemove = function (x, y) { actions.prototype._clickStorageRemove_all = function () { core.myconfirm("你确定要清除【全部游戏】的所有本地存档?\n此行为不可逆!!!", function () { - var done = function () { + core.ui.drawWaiting("正在清空,请稍候..."); + core.clearLocalForage(function () { core.saves.ids = {}; core.saves.autosave.data = null; core.saves.autosave.updated = false; @@ -2816,9 +2817,7 @@ actions.prototype._clickStorageRemove_all = function () { core.control._updateFavoriteSaves(); core.removeLocalStorage('saveIndex'); core.drawText("\t[操作成功]你的所有存档已被清空。"); - }; - core.ui.drawWaiting("正在清空,请稍候..."); - localforage.clear(done); + }); }); } diff --git a/libs/control.js b/libs/control.js index dc58a8e1..60aa20ed 100644 --- a/libs/control.js +++ b/libs/control.js @@ -2285,7 +2285,7 @@ control.prototype.getAllSaves = function (callback) { ////// 获得所有存在存档的存档位 ////// control.prototype.getSaveIndexes = function (callback) { var indexes = {}; - localforage.keys(function (err, keys) { + core.keysLocalForage(function (err, keys) { if (err) { main.log(err); return callback(indexes); diff --git a/libs/utils.js b/libs/utils.js index 800b2384..9b707cbc 100644 --- a/libs/utils.js +++ b/libs/utils.js @@ -257,12 +257,11 @@ utils.prototype.setLocalForage = function (key, value, successCallback, errorCal return; } - // Save to localforage + var name = core.firstData.name + "_" + key; var str = JSON.stringify(value).replace(/[\u007F-\uFFFF]/g, function (chr) { return "\\u" + ("0000" + chr.charCodeAt(0).toString(16)).substr(-4) }); - var compressed = str.length > 100000 ? LZString.compress(str) : lzw_encode(str); - localforage.setItem(core.firstData.name + "_" + key, compressed, function (err) { + var callback = function (err) { if (err) { if (errorCallback) errorCallback(err); } @@ -271,11 +270,21 @@ utils.prototype.setLocalForage = function (key, value, successCallback, errorCal else if (/^save\d+$/.test(key)) core.saves.ids[parseInt(key.substring(4))] = true; if (successCallback) successCallback(); } - }); + } + + if (window.jsinterface && window.jsinterface.setLocalForage) { + var id = setTimeout(null); + core['__callback' + id] = callback; + window.jsinterface.setLocalForage(id, name, str); + } else { + var compressed = str.length > 100000 ? LZString.compress(str) : lzw_encode(str); + localforage.setItem(name, compressed, callback); + } } utils.prototype.getLocalForage = function (key, defaultValue, successCallback, errorCallback) { - localforage.getItem(core.firstData.name + "_" + key, function (err, value) { + var name = core.firstData.name + "_" + key; + var callback = function (err, value) { if (err) { if (errorCallback) errorCallback(err); } @@ -288,11 +297,20 @@ utils.prototype.getLocalForage = function (key, defaultValue, successCallback, e } successCallback(defaultValue); } - }) + }; + + if (window.jsinterface && window.jsinterface.getLocalForage) { + var id = setTimeout(null); + core['__callback' + id] = callback; + window.jsinterface.getLocalForage(id, name); + } else { + localforage.getItem(name, callback); + } } utils.prototype.removeLocalForage = function (key, successCallback, errorCallback) { - localforage.removeItem(core.firstData.name + "_" + key, function (err) { + var name = core.firstData.name + "_" + key; + var callback = function (err) { if (err) { if (errorCallback) errorCallback(err); } @@ -301,7 +319,56 @@ utils.prototype.removeLocalForage = function (key, successCallback, errorCallbac else if (/^save\d+$/.test(key)) delete core.saves.ids[parseInt(key.substring(4))]; if (successCallback) successCallback(); } - }) + } + + if (window.jsinterface && window.jsinterface.removeLocalForage) { + var id = setTimeout(null); + core['__callback' + id] = callback; + window.jsinterface.removeLocalForage(id, name); + } else { + localforage.removeItem(name, callback); + } +} + +utils.prototype.clearLocalForage = function (callback) { + if (window.jsinterface && window.jsinterface.clearLocalForage) { + var id = setTimeout(null); + core['__callback' + id] = callback; + window.jsinterface.clearLocalForage(id); + } else { + localforage.clear(callback); + } +} + +utils.prototype.iterateLocalForage = function (iter, callback) { + if (window.jsinterface && window.jsinterface.iterateLocalForage) { + var id = setTimeout(null); + core['__iter' + id] = iter; + core['__callback' + id] = callback; + window.jsinterface.iterateLocalForage(id); + } else { + localforage.iterate(iter, callback); + } +} + +utils.prototype.keysLocalForage = function (callback) { + if (window.jsinterface && window.jsinterface.keysLocalForage) { + var id = setTimeout(null); + core['__callback' + id] = callback; + window.jsinterface.keysLocalForage(id); + } else { + localforage.keys(callback); + } +} + +utils.prototype.lengthLocalForage = function (callback) { + if (window.jsinterface && window.jsinterface.lengthLocalForage) { + var id = setTimeout(null); + core['__callback' + id] = callback; + window.jsinterface.lengthLocalForage(id); + } else { + localforage.length(callback); + } } utils.prototype.setGlobal = function (key, value) { From 4081d7a3e7e124acb0ced605d63e21facc3bf557 Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Mon, 30 Aug 2021 17:28:49 +0800 Subject: [PATCH 17/60] =?UTF-8?q?=E5=85=A8=E5=B1=80=E5=95=86=E5=BA=97?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libs/actions.js | 7 ++++++- libs/events.js | 24 +++++++++++++++--------- libs/utils.js | 10 ++++++++-- project/floors/sample1.js | 13 ++++++++----- project/plugins.js | 11 ++++++++++- 5 files changed, 47 insertions(+), 18 deletions(-) diff --git a/libs/actions.js b/libs/actions.js index 34a4d68d..3e967d99 100644 --- a/libs/actions.js +++ b/libs/actions.js @@ -1084,7 +1084,12 @@ actions.prototype._clickAction = function (x, y, px, py) { var timeout = Math.max(0, core.status.event.timeout - new Date().getTime()) || 0; delete core.status.event.timeout; core.setFlag('timeout', timeout); - core.status.route.push("choices:" + (100 * timeout + y - topIndex)); + // 对全局商店特殊处理 + var index = y - topIndex; + if (index == choices.length - 1 && core.hasFlag('@temp@shop')) { + index = -1; + } + core.status.route.push("choices:" + (100 * timeout + index)); core.insertAction(choice.action); core.doAction(); } diff --git a/libs/events.js b/libs/events.js index ccac7a3b..57ffff6c 100644 --- a/libs/events.js +++ b/libs/events.js @@ -2037,9 +2037,7 @@ events.prototype._action_choices = function (data, x, y, prefix) { var action = core.status.replay.toReplay.shift(); if (action.indexOf('choices:') == 0 && !(action == 'choices:none' && !data.timeout)) { var index = action.substring(8); - if (index == 'none' || ((index = parseInt(index)) >= 0) && index % 100 < data.choices.length) { - this.__action_choices_replaying(data, index); - } else { + if (!this.__action_choices_replaying(data, index)) { core.control._replay_error(action); return; } @@ -2057,7 +2055,7 @@ events.prototype._action_choices = function (data, x, y, prefix) { return; } if (action != 'choices:none') core.status.replay.toReplay.unshift(action); // 首先归还刚才读出的下一步操作 - core.events.__action_choices_replaying(data, core.clamp(parseInt(value), 0, data.choices.length - 1)) + core.events.__action_choices_replaying(data, ((parseInt(value) || 0) + data.choices.length) % data.choices.length); }); } } @@ -2080,17 +2078,24 @@ events.prototype._action_choices = function (data, x, y, prefix) { } events.prototype.__action_choices_replaying = function (data, index) { + var selection = index; if (index != 'none') { - var timeout = Math.floor(index / 100) || 0; + selection = parseInt(index); + if (isNaN(selection)) return false; + if (selection < 0) selection += data.choices.length; + if (selection < 0) return false; + if (selection % 100 > 50) selection += data.choices.length; + if (selection % 100 > data.choices.length) return false; + var timeout = Math.floor(selection / 100) || 0; core.setFlag('timeout', timeout); - index %= 100; + selection %= 100; } else core.setFlag('timeout', 0); - core.status.event.selection = index; + core.status.event.selection = selection; setTimeout(function () { core.status.route.push("choices:"+index); - if (index != 'none') { + if (selection != 'none') { // 检查 - var choice = data.choices[index]; + var choice = data.choices[selection]; if (choice.need != null && choice.need != '' && !core.calValue(choice.need)) { // 无法选择此项 core.control._replay_error("无法选择项:"+index); @@ -2101,6 +2106,7 @@ events.prototype.__action_choices_replaying = function (data, index) { } core.doAction(); }, core.status.replay.speed == 24 ? 1 : 750 / Math.max(1, core.status.replay.speed)); + return true; } events.prototype._precompile_choices = function (data) { diff --git a/libs/utils.js b/libs/utils.js index 9b707cbc..b02b874f 100644 --- a/libs/utils.js +++ b/libs/utils.js @@ -677,8 +677,14 @@ utils.prototype.decodeRoute = function (route) { utils.prototype._decodeRoute_getNumber = function (decodeObj, noparse) { var num = ""; - while (decodeObj.index < decodeObj.route.length && !isNaN(decodeObj.route.charAt(decodeObj.index))) { - num += decodeObj.route.charAt(decodeObj.index++); + var first = true; + while (true) { + var ch = decodeObj.route.charAt(decodeObj.index); + if (ch >= '0' && ch <= '9') num += ch; + else if (ch == '-' && first) num += ch; + else break; + first = false; + decodeObj.index++; } if (num.length == 0) num = "1"; return noparse ? num : parseInt(num); diff --git a/project/floors/sample1.js b/project/floors/sample1.js index be0af792..a9280e0b 100644 --- a/project/floors/sample1.js +++ b/project/floors/sample1.js @@ -441,7 +441,10 @@ main.floors.sample1= } ], "false": [ - "\t[老人,trader]你的金钱不足!" + "\t[老人,trader]你的金钱不足!", + { + "type": "continue" + } ] } ] @@ -464,13 +467,13 @@ main.floors.sample1= "name": "item:blueKey", "operator": "+=", "value": "1" - }, - { - "type": "continue" } ], "false": [ - "\t[老人,trader]你的金钱不足!" + "\t[老人,trader]你的金钱不足!", + { + "type": "continue" + } ] } ] diff --git a/project/plugins.js b/project/plugins.js index 6c5de0b1..f4a00cc2 100644 --- a/project/plugins.js +++ b/project/plugins.js @@ -112,6 +112,8 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = return; } + _shouldProcessKeyUp = true; + // Step 4: 执行标准公共商店 core.insertAction(this._convertShop(shop)); return true; @@ -221,9 +223,16 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = return null; } + var _shouldProcessKeyUp = true; + /// 允许商店X键退出 core.registerAction('keyUp', 'shops', function (keycode) { if (!core.status.lockControl || !core.hasFlag("@temp@shop") || core.status.event.id != 'action') return false; + if ((keycode == 13 || keycode == 32) && !_shouldProcessKeyUp) { + _shouldProcessKeyUp = true; + return true; + } + if (core.status.event.data.type != 'choices') return false; var data = core.status.event.data.current; var choices = data.choices; @@ -232,7 +241,6 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = core.actions._clickAction(core.actions.HSIZE, topIndex + choices.length - 1); return true; } - if (keycode == 13 || keycode == 32) return true; return false; }, 60); @@ -245,6 +253,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = var topIndex = core.actions._getChoicesTopIndex(choices.length); if (keycode == 13 || keycode == 32) { // Space, Enter core.actions._clickAction(core.actions.HSIZE, topIndex + core.status.event.selection); + _shouldProcessKeyUp = false; return true; } return false; From c0851b7aba6dfdab5518703c2702f4cfd9fb34ce Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Mon, 30 Aug 2021 17:31:24 +0800 Subject: [PATCH 18/60] =?UTF-8?q?=E5=85=A8=E5=B1=80=E5=95=86=E5=BA=97?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- project/plugins.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/project/plugins.js b/project/plugins.js index f4a00cc2..793e4060 100644 --- a/project/plugins.js +++ b/project/plugins.js @@ -122,7 +122,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ////// 将一个全局商店转变成可预览的公共事件 ////// this._convertShop = function (shop) { return [ - { "type": "function", "function": "function() {core.setFlag('@temp@shop', true);}" }, + { "type": "function", "function": "function() {core.addFlag('@temp@shop', 1);}" }, { "type": "while", "condition": "true", @@ -156,7 +156,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = } ] }, - { "type": "function", "function": "function() {core.removeFlag('@temp@shop');}" } + { "type": "function", "function": "function() {core.addFlag('@temp@shop', -1);}" } ]; } From 78d4ef009aa7de5d688ad1403e5411e7499f8265 Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Mon, 30 Aug 2021 17:35:41 +0800 Subject: [PATCH 19/60] =?UTF-8?q?=E5=85=A8=E5=B1=80=E5=95=86=E5=BA=97?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- project/plugins.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/project/plugins.js b/project/plugins.js index 793e4060..730b7eed 100644 --- a/project/plugins.js +++ b/project/plugins.js @@ -227,13 +227,13 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = /// 允许商店X键退出 core.registerAction('keyUp', 'shops', function (keycode) { - if (!core.status.lockControl || !core.hasFlag("@temp@shop") || core.status.event.id != 'action') return false; + if (!core.status.lockControl || core.status.event.id != 'action') return false; if ((keycode == 13 || keycode == 32) && !_shouldProcessKeyUp) { _shouldProcessKeyUp = true; return true; } - if (core.status.event.data.type != 'choices') return false; + if (!core.hasFlag("@temp@shop") || core.status.event.data.type != 'choices') return false; var data = core.status.event.data.current; var choices = data.choices; var topIndex = core.actions._getChoicesTopIndex(choices.length); From 804e5a403953b6cf6f406ae5d30eff50f2a2b566 Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Mon, 30 Aug 2021 18:40:44 +0800 Subject: [PATCH 20/60] =?UTF-8?q?=E5=A4=A7=E9=87=8F=E7=BB=86=E8=8A=82?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _docs/element.md | 2 +- _server/editor_datapanel.js | 10 ++++++++++ _server/table/data.comment.js | 4 ++-- libs/control.js | 18 ++++++++---------- libs/events.js | 6 +++--- libs/maps.js | 18 +++++++++--------- libs/utils.js | 8 ++++---- project/floors/sample1.js | 9 ++++++++- project/items.js | 2 +- project/materials/keyboard.png | Bin 27655 -> 27646 bytes 10 files changed, 46 insertions(+), 31 deletions(-) diff --git a/_docs/element.md b/_docs/element.md index 22e2a058..f392ff0d 100644 --- a/_docs/element.md +++ b/_docs/element.md @@ -308,7 +308,7 @@ V2.8.1新增了怪物的大贴图绑定,编辑器1:1模式下大贴图会被 4. **额外素材:**`project/tilesets`中的文件名(需要后缀,只支持png)。 * 注册方法同上,最大的区别在于这个数组的顺序必须保持好。如果随意调换其中的顺序,或注销不在数组末尾的图片,就会导致地图上最终呈现的素材发生错位。因此,新勾选的图片总会被自动追加到数组的末尾。 * 比起常规素材,额外素材最大的好处有几点: - 1. 图片没有数量限制。常规素材的总数量最多只允许不到一万个,而额外素材每张图片上的图块数量最多允许一千个。 + 1. 图片没有数量限制。常规素材的总数量最多只允许不到10000个,而额外素材每张图片上的图块数量最多允许3000个。 2. 查看和绘制更为方便。常规素材每个图块独占一行,每列为一帧,导致不方便观察,且用多个图块拼图必须逐图块绘制。额外素材都是静止的,所以每个图块只占一格,多个图块可以在准备素材时就直接以相邻的样子绘制在同一张图片上,绘制地图时直接从素材区拖动来批量框选,再在地图区单击成片绘制或拖动平铺。 3. 批量替换也更为方便。譬如您如果想制作形如“一场大战/天灾过后/多年以后,村庄/城镇化为了一片废墟”的效果,可以预先准备两张甚至更多张相同规格的额外素材图片,然后在适当的时候遍历某个/某些楼层的图块ID,将以“X1”开头的图块统一替换为“X2”开头等。发布单机版游戏时,您也可以提供多张相同规格的额外素材图片供玩家直接替换皮肤风格。 5. **使用动画:**`project/animates`文件夹中的文件名(不含后缀,请注意与`animates.png`相区分)。 diff --git a/_server/editor_datapanel.js b/_server/editor_datapanel.js index 3ae713c3..9e064cff 100644 --- a/_server/editor_datapanel.js +++ b/_server/editor_datapanel.js @@ -301,6 +301,13 @@ editor_datapanel_wrapper = function (editor) { printe('不合法的id,请使用字母、数字或下划线,且不能以数字开头'); return; } + if (id == 'hero' || id == 'this' || id == 'none' || id == 'airwall') { + printe('不得使用保留关键字作为id!'); + return; + } + if (core.statusBar.icons[id] != null) { + alert('警告!此ID在状态栏图标中被注册;仍然允许使用,但是\\i[]等绘制可能出现冲突。'); + } editor.file.changeIdAndIdnum(id, idnum, editor_mode.info, function (err) { if (err) { printe(err); @@ -358,6 +365,9 @@ editor_datapanel_wrapper = function (editor) { printe('额外素材不可修改id!'); return; } + if (core.statusBar.icons[id] != null) { + alert('警告!此ID在状态栏图标中被注册;仍然允许使用,但是\\i[]等绘制可能出现冲突。'); + } editor.file.changeIdAndIdnum(id, null, editor_mode.info, function (err) { if (err) { printe(err); diff --git a/_server/table/data.comment.js b/_server/table/data.comment.js index 6a2031b9..4a2d26ea 100644 --- a/_server/table/data.comment.js +++ b/_server/table/data.comment.js @@ -490,10 +490,10 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_leaf": true, "_type": "select", "_select": { - "values": [1, 2, 3, 4] + "values": [1, 2, 3, 4, 5] }, "_docs": "竖状态栏自绘行数", - "_data": "竖屏模式下,顶端状态栏canvas化后的行数。\n此项将决定竖屏的状态栏高度,如果设置则不小于1且不大于4。\n仅在statusCanvas开启时才有效" + "_data": "竖屏模式下,顶端状态栏canvas化后的行数。\n此项将决定竖屏的状态栏高度,如果设置则不小于1且不大于5。\n仅在statusCanvas开启时才有效" }, "floorChangeTime": { "_leaf": true, diff --git a/libs/control.js b/libs/control.js index 60aa20ed..4a5aa417 100644 --- a/libs/control.js +++ b/libs/control.js @@ -2674,10 +2674,9 @@ control.prototype._weather_snow = function (level) { control.prototype._weather_fog = function (level) { if (!core.animateFrame.weather.fog) return; - var number = level * parseInt(20*core.bigmap.width*core.bigmap.height/(core.__SIZE__*core.__SIZE__)); core.animateFrame.weather.nodes = [{ 'image': core.animateFrame.weather.fog, - 'level': number, + 'level': 40 * level, 'x': 0, 'y': -core.__PIXELS__ / 2, 'dx': -Math.random() * 1.5, @@ -2688,10 +2687,9 @@ control.prototype._weather_fog = function (level) { control.prototype._weather_cloud = function (level) { if (!core.animateFrame.weather.cloud) return; - var number = level * parseInt(20*core.bigmap.width*core.bigmap.height/(core.__SIZE__*core.__SIZE__)); core.animateFrame.weather.nodes = [{ 'image': core.animateFrame.weather.cloud, - 'level': number, + 'level': 40 * level, 'x': 0, 'y': -core.__PIXELS__ / 2, 'dx': -Math.random() * 1.5, @@ -3229,9 +3227,9 @@ control.prototype.resize = function() { var statusDisplayArr = this._shouldDisplayStatus(), count = statusDisplayArr.length; var statusCanvas = core.flags.statusCanvas, statusCanvasRows = core.values.statusCanvasRowsOnMobile || 3; var col = statusCanvas ? statusCanvasRows : Math.ceil(count / 3); - if (col > 4) { - if (statusCanvas) alert("自绘状态栏的在竖屏下的行数应不超过4!"); - else alert("当前状态栏数目("+count+")大于12,请调整到不超过12以避免手机端出现显示问题。"); + if (col > 5) { + if (statusCanvas) alert("自绘状态栏的在竖屏下的行数应不超过5!"); + else alert("当前状态栏数目("+count+")大于15,请调整到不超过15以避免手机端出现显示问题。"); } var globalAttribute = core.status.globalAttribute || core.initStatus.globalAttribute; @@ -3241,7 +3239,7 @@ control.prototype.resize = function() { CANVAS_WIDTH: CANVAS_WIDTH, BORDER: BORDER, BAR_WIDTH: BAR_WIDTH, - TOOLBAR_HEIGHT: extendToolbar ? 38 : 44, + TOOLBAR_HEIGHT: 38, outerSize: CANVAS_WIDTH * core.domStyle.scale + 2 * BORDER, globalAttribute: globalAttribute, border: '3px ' + core.arrayToRGBA(globalAttribute.borderColor) + ' solid', @@ -3249,7 +3247,7 @@ control.prototype.resize = function() { count: count, col: col, statusBarHeightInVertical: core.domStyle.isVertical ? (32 * col + 6) * core.domStyle.scale + 2 * BORDER : 0, - toolbarHeightInVertical: core.domStyle.isVertical ? 44 * core.domStyle.scale + 2 * BORDER : 0, + toolbarHeightInVertical: core.domStyle.isVertical ? 38 * core.domStyle.scale + 2 * BORDER : 0, extendToolbar: extendToolbar, is15x15: core.__SIZE__ == 15 }; @@ -3456,7 +3454,7 @@ control.prototype._resize_tools = function (obj) { var style = core.dom.tools[i].style; style.height = toolsHeight + "px"; style.marginLeft = toolsMarginLeft + "px"; - style.marginTop = (obj.extendToolbar ? 3 : 6) * core.domStyle.scale + "px" + style.marginTop = 3 * core.domStyle.scale + "px" } core.dom.hard.style.lineHeight = toolsHeight + "px"; if (core.domStyle.isVertical || obj.extendToolbar) { diff --git a/libs/events.js b/libs/events.js index 57ffff6c..7fe9678c 100644 --- a/libs/events.js +++ b/libs/events.js @@ -1682,12 +1682,12 @@ events.prototype._precompile_scaleImage = function (data) { events.prototype._action_setCurtain = function (data, x, y, prefix) { if (data.async) { - core.setCurtain(data.color, data.time, data.moveMode); + core.setCurtain(data.color || core.status.thisMap.color, data.time, data.moveMode); if (data.color == null || data.keep) core.setFlag('__color__', data.color || null); core.doAction(); } else { - core.setCurtain(data.color, data.time, data.moveMode, function () { + core.setCurtain(data.color || core.status.thisMap.color, data.time, data.moveMode, function () { if (data.color == null || data.keep) core.setFlag('__color__', data.color || null); core.doAction(); }); @@ -3073,7 +3073,7 @@ events.prototype.setGlobalFlag = function (name, value) { core.setFlag("globalFlags", flags); core.resize(); if (name == 'blurFg') - core.drawMap(); + core.redrawMap(); } ////// 设置文件别名 ////// diff --git a/libs/maps.js b/libs/maps.js index e292dec2..e1d6094b 100644 --- a/libs/maps.js +++ b/libs/maps.js @@ -385,7 +385,7 @@ maps.prototype.setBlockOpacity = function (opacity, x, y, floorId) { block.opacity = opacity; if (floorId == core.status.floorId && !block.disable) { if (block.event.cls == 'autotile') { - core.drawMap(); + core.redrawMap(); } else { core.drawBlock(block); core.addGlobalAnimate(block); @@ -416,7 +416,7 @@ maps.prototype.setBlockFilter = function (filter, x, y, floorId) { block.filter = core.clone(filter); if (floorId == core.status.floorId && !block.disable) { if (block.event.cls == 'autotile') { - core.drawMap(); + core.redrawMap(); } else { core.drawBlock(block); core.addGlobalAnimate(block); @@ -2057,7 +2057,7 @@ maps.prototype.showBlock = function (x, y, floorId) { // 在本层,添加动画 if (floorId == core.status.floorId) { if (block.event.cls == 'autotile') { - core.drawMap(); + core.redrawMap(); } else { core.drawBlock(block); core.addGlobalAnimate(block); @@ -2107,7 +2107,7 @@ maps.prototype._removeBlockFromMap = function (floorId, block) { if (floorId != core.status.floorId) return; var filter = block.filter || {}; if (block.event.cls == 'autotile' || filter.blur > 0 || filter.shadow > 0) { - core.drawMap(); + core.redrawMap(); } else { var x = block.x, y = block.y; var px = 32 * x - core.bigmap.posX * 32; @@ -2196,7 +2196,7 @@ maps.prototype._triggerBgFgMap = function (type, name, loc, floorId, callback) { core.status[name + "maps"][floorId] = null; if (floorId == core.status.floorId) { - core.drawMap(floorId); + core.redrawMap(); } if (callback) callback(); } @@ -2228,7 +2228,7 @@ maps.prototype._triggerFloorImage = function (type, loc, floorId, callback) { }) if (floorId == core.status.floorId) { - core.drawMap(floorId); + core.redrawMap(); } if (callback) callback(); } @@ -2267,7 +2267,7 @@ maps.prototype.setBlock = function (number, x, y, floorId) { if (floorId == core.status.floorId) { // 有任何一个是autotile直接重绘地图 if ((originEvent != null && originEvent.cls == 'autotile') || block.event.cls == 'autotile') { - core.drawMap(); + core.redrawMap(); } else { if (originEvent != null) { this._removeBlockFromMap(floorId, {x: x, y: y, event: originEvent}); @@ -2418,7 +2418,7 @@ maps.prototype.replaceBlock = function (fromNumber, toNumber, floorId) { this._updateMapArray(floorId, block.x, block.y); } }, this); - if (floorId == core.status.floorId) core.drawMap(); + if (floorId == core.status.floorId) core.redrawMap(); } ////// 改变前景背景的图块 ////// @@ -2464,7 +2464,7 @@ maps.prototype.resetMap = function (floorId) { delete (core.status.mapBlockObjs || {})[t]; if (t == core.status.floorId) needRefresh = true; }); - if (needRefresh) this.drawMap(); + if (needRefresh) this.redrawMap(); core.drawTip("地图重置成功"); } diff --git a/libs/utils.js b/libs/utils.js index b02b874f..1601ca05 100644 --- a/libs/utils.js +++ b/libs/utils.js @@ -1243,10 +1243,10 @@ utils.prototype.same = function (a, b) { return true; } if (a instanceof Object && b instanceof Object) { - for (var i in a) { - if (!this.same(a[i], b[i])) return false; - } - for (var i in b) { + var obj = {}; + for (var i in a) obj[i] = true; + for (var i in b) obj[i] = true; + for (var i in obj) { if (!this.same(a[i], b[i])) return false; } return true; diff --git a/project/floors/sample1.js b/project/floors/sample1.js index a9280e0b..2d3f74a0 100644 --- a/project/floors/sample1.js +++ b/project/floors/sample1.js @@ -7,7 +7,14 @@ main.floors.sample1= "canFlyFrom": true, "canUseQuickShop": true, "defaultGround": "grass", - "images": null, + "images": [ + { + "name": "bg.jpg", + "canvas": "bg", + "x": 0, + "y": 0 + } + ], "weather": [ "snow", 6 diff --git a/project/items.js b/project/items.js index 639bb668..3406d3f4 100644 --- a/project/items.js +++ b/project/items.js @@ -410,7 +410,7 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a = "cls": "tools", "name": "地震卷轴", "text": "可以破坏当前层的所有墙", - "useItemEffect": "(function () {\n\tvar indexes = [];\n\tfor (var index in core.status.thisMap.blocks) {\n\t\tvar block = core.status.thisMap.blocks[index];\n\t\tif (!block.disable && block.event.canBreak) {\n\t\t\tindexes.push(index);\n\t\t}\n\t}\n\tcore.removeBlockByIndexes(indexes);\n\tcore.drawMap();\n\tcore.playSound('炸弹');\n\tcore.drawTip(core.material.items[itemId].name + '使用成功');\n})();", + "useItemEffect": "(function () {\n\tvar indexes = [];\n\tfor (var index in core.status.thisMap.blocks) {\n\t\tvar block = core.status.thisMap.blocks[index];\n\t\tif (!block.disable && block.event.canBreak) {\n\t\t\tindexes.push(index);\n\t\t}\n\t}\n\tcore.removeBlockByIndexes(indexes);\n\tcore.redrawMap();\n\tcore.playSound('炸弹');\n\tcore.drawTip(core.material.items[itemId].name + '使用成功');\n})();", "canUseItemEffect": "(function () {\n\treturn core.status.thisMap.blocks.filter(function (block) {\n\t\treturn !block.disable && block.event.canBreak;\n\t}).length > 0;\n})();" }, "poisonWine": { diff --git a/project/materials/keyboard.png b/project/materials/keyboard.png index 5928c832e77625f669c1ad790c2460c04d12efd2..55d5b2dccedc1c36557b00fdf51e676dfc46e286 100644 GIT binary patch delta 888 zcmV-;1Bd*F*a8060kBnI0hF^=VEPAtLqnEjFdmQ9+wroL)|W<`F3U2uKEArHJJByA z1<>`bxk-XPtA`672#HoG;6Sn_Qa+$Y(S9b{SFf1Kz1;ekU<7H7j&E+2c1}zYH<|Aq z!4{B-kHH}|>U6y%4!+-#Fu3isjF9m8^4wICUPcRUh(zphPButurhAQRz zHAUP$l2xXCn?eyZ!6Idp0Z`88FP!y*1=rVcFsg?(#(3G+qvslNE^SB{XuiJnTC2pD zj!T0DXFMLOEgx+?Bz)(-EHpx0#eReU)qGI4H z%jZ6feG7m#FhN6%U{T>H0(A#}n&s1OG!3I`d?iuQ%{`$KbZdH2gkM zl=iI~?%enUxUBs!>L3K);C5)-gWJ!SCT84$_LzNRBT{)Ot{!b8?HiZ!Sr3x9O8dL~ z+_s``t&Xv5iii-`=|~MMG1^Ir_{2a3j$5YNV#k0eF)lk=S1F%ZBx|DtO(GXUlhkQF zf1zp-36-e{DhU0T@~0M%Mo=_@#aUaa?l@oF-7?KPWQl0&;m%3udZZjz^qUYgF9ww+ zT;gTTxKV0dFupl7oW+3aM)!5ZG>V$YJnkI%_QCb@oj1)nrPc-&UJ)Lza|< zVK+x8lFOGa)(yv53BHCK=gs{OjUD-Ze{1vdAz5H$h>_-;hRO&DORQ^6+i?I$5Fkuw zYzRP}7ov43RZ%}$u4~k&2+{g-`GkZ6=j)5=b7+DVI026hzn03w^^MsUS`H!IFGU5= zSUpk)+ohlaO<7W2QvOmNv<`K+AB#|SU_)$vY60@i5z*|=^?XBl7O^z6b)!9Mf39xQ zJKi|!Nn0nWahJ-#+kItmb(PMA&zeZxmO|{kWvmu;jX(H;5x9ME5Q3DC+b;F$B}*XW zzSD+mYg}Kr&N1g&6N#v`p0ut@ib{aE2B&BP6`N;FUPT+ol=_F#q|`}D6H|8ET~=+c zpHVGbW3O#^IT7L9TbxBy_nN7y8PKVHk$d2=+lblbTH$9t0C0!!Qh^5&nPU-pM@c-yfs^ O0000U6y5ReSCFYSE64= z3ZUy#sMGb5IQV``!r->kGD5=V%X8C6dKqcRdf*x^>QbS3N#hzEk}zq18mg4< z*A#L4NLHElZ3;!u1dEhW20%HVzi`$M7F=J)!Ke?~7~^GMkDhD9xwIi+p!xdNYpoJr zIxY1%6_3bCI=zlZFJyU`rNi=JV3jzD+?0}e4yoM))y56 zUs*o)VeDG~w1Ej4Vg!o{M-ixhJJ2kj)j-oQy2e)$6;1vjBuj>?8x<3`&36oLdrZUc z6Gds?y5Y`^Pk^=iX;23t_y)H_;~w08zBDo84z$PY8yk_zOL6sR8)@ITl+SvQ#8ukg z<>$5)eQR}$Wm80ixK2lEV2ROgQp6_)DsbE~-4;6rM2T_P(Yi|c#3ES-B~6K3Oh-eL z(P=#arIQb8AAhlE>*3Cc_IhZDeihFV3|JSNTTdH&ZoGyYR8R5mOLf6;b7(m6!CzO! zVZV4^8YZm4?dwa!og?YI(fV=6=+K&N}(@{EPEz(RG?LWMypKP2FqF@HJj_0SOgDjrN|YzRP}7ov43 zRZ%}$u4@SCC%I{TxqKuyA4dA5g=Wl2axHRYr<_MFP0A-BLdzkf`$g;CHP(;R!FDOA zKvR~Kmz2Mh2dzUL?#Cij5!j$XEkM3GBAWfVD7jFcF%3>k14!$F;p!&6T2A4!3f;Gl6A(7tw`=C$%+ZN@3bM?TGv;K zkZ7%*)I5Bs1W0nZ#q3`+&zQW5HjpXx52ZNGR9>>A=WY11ON8b$G!(-7$L?=!@0R6H<@;Ri?qKlkRc^NLYsbF wF#$3R!!R1bK1gSg-5MTX0%RD5VKl=34 Date: Mon, 30 Aug 2021 20:11:12 +0800 Subject: [PATCH 21/60] =?UTF-8?q?=E4=BC=98=E5=8C=96blockly=E5=A4=9A?= =?UTF-8?q?=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _server/MotaAction.g4 | 16 ++++++++-------- _server/editor_blockly.js | 15 ++++++++++++++- _server/thirdparty/caret-position.js | 2 +- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/_server/MotaAction.g4 b/_server/MotaAction.g4 index d2676d2c..a831a758 100644 --- a/_server/MotaAction.g4 +++ b/_server/MotaAction.g4 @@ -2055,37 +2055,37 @@ return code; */; animate_s - : '显示动画' IdString '位置' 'x' PosString? 'y' PosString? '相对窗口坐标' Bool '不等待执行完毕' Bool Newline + : '显示动画' EvalString '位置' 'x' PosString? 'y' PosString? '相对窗口坐标' Bool '不等待执行完毕' Bool Newline /* animate_s tooltip : animate:显示动画,位置填hero或者1,2形式的位置,或者不填代表当前事件点 helpUrl : /_docs/#/instruction default : ["zone","","",false,false] -allAnimates : ['IdString_0'] -material : ["./project/animates/", "IdString_0"] +allAnimates : ['EvalString_0'] +material : ["./project/animates/", "EvalString_0"] menu : [['选择位置', 'editor_blockly.selectPoint(block, ["PosString_0", "PosString_1"])']] colour : this.soundColor var loc = PosString_0&&PosString_1?(', "loc": ['+PosString_0+','+PosString_1+']'):''; Bool_0 = Bool_0?', "alignWindow": true':''; Bool_1 = Bool_1?', "async": true':''; -var code = '{"type": "animate", "name": "'+IdString_0+'"'+loc+Bool_0+Bool_1+'},\n'; +var code = '{"type": "animate", "name": "'+EvalString_0+'"'+loc+Bool_0+Bool_1+'},\n'; return code; */; animate_1_s - : '显示动画并跟随角色' IdString '不等待执行完毕' Bool Newline + : '显示动画并跟随角色' EvalString '不等待执行完毕' Bool Newline /* animate_1_s tooltip : animate:显示动画并跟随角色 helpUrl : /_docs/#/instruction default : ["zone",false] -allAnimates : ['IdString_0'] -material : ["./project/animates/", "IdString_0"] +allAnimates : ['EvalString_0'] +material : ["./project/animates/", "EvalString_0"] colour : this.soundColor Bool_0 = Bool_0?', "async": true':''; -var code = '{"type": "animate", "name": "'+IdString_0+'", "loc": "hero"'+Bool_0+'},\n'; +var code = '{"type": "animate", "name": "'+EvalString_0+'", "loc": "hero"'+Bool_0+'},\n'; return code; */; diff --git a/_server/editor_blockly.js b/_server/editor_blockly.js index af5b87bc..7c477ff9 100644 --- a/_server/editor_blockly.js +++ b/_server/editor_blockly.js @@ -1188,4 +1188,17 @@ Blockly.FieldDropdown.prototype.doValueUpdate_ = function (newValue) { options.push([this.value_, this.value_]); this.selectedOption_ = options[options.length - 1]; } -}; \ No newline at end of file +}; + +Blockly.FieldMultilineInput.prototype.getDisplayText_ = function() { + var value = this.value_; + if (!value) return Blockly.Field.NBSP; + var curr = '', text = ''; + for (var i = 0; i < value.length; ++i) { + if (value[i] == '\n' || curr.length == this.maxDisplayLength) { + text += curr.replace(/\s/g, Blockly.Field.NBSP) + '\n'; + curr = value[i] == '\n' ? '' : value[i]; + } else curr += value[i]; + } + return text + curr; +}; diff --git a/_server/thirdparty/caret-position.js b/_server/thirdparty/caret-position.js index 8294e99f..b6e14aa6 100644 --- a/_server/thirdparty/caret-position.js +++ b/_server/thirdparty/caret-position.js @@ -109,7 +109,7 @@ } }); if (!isInput) - style.whiteSpace = 'pre'; + style.whiteSpace = 'pre-wrap'; if (isFirefox) { // Firefox lies about the overflow property for textareas: https://bugzilla.mozilla.org/show_bug.cgi?id=984275 From 55563c8a2b225cbdfec921a496802dac13270700 Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Mon, 30 Aug 2021 20:21:48 +0800 Subject: [PATCH 22/60] =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E6=80=AA=E7=89=A9?= =?UTF-8?q?=E5=B1=9E=E6=80=A7=E4=B8=8D=E5=88=B7=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _server/MotaAction.g4 | 35 ++++++++++++++++++++--------------- _server/MotaActionParser.js | 12 +++++++----- libs/events.js | 24 ++++++++++++------------ 3 files changed, 39 insertions(+), 32 deletions(-) diff --git a/_server/MotaAction.g4 b/_server/MotaAction.g4 index a831a758..fb846fdd 100644 --- a/_server/MotaAction.g4 +++ b/_server/MotaAction.g4 @@ -1255,19 +1255,20 @@ return code; setEnemy_s - : '设置怪物属性' ':' '怪物ID' IdString '的' EnemyId_List AssignOperator_List expression Newline + : '设置怪物属性' ':' '怪物ID' IdString '的' EnemyId_List AssignOperator_List expression '不刷新显伤' Bool Newline /* setEnemy_s tooltip : setEnemy:设置某个怪物的属性 helpUrl : /_docs/#/instruction -default : ["greenSlime", "atk", "="] +default : ["greenSlime", "atk", "=", "", false] allEnemys : ['IdString_0'] colour : this.dataColor if (AssignOperator_List_0 && AssignOperator_List_0 != '=') { AssignOperator_List_0 = ', "operator": "' + AssignOperator_List_0 + '"'; } else AssignOperator_List_0 = ''; -var code = '{"type": "setEnemy", "id": "'+IdString_0+'", "name": "'+EnemyId_List_0+'"'+AssignOperator_List_0+', "value": "'+expression_0+'"},\n'; +Bool_0 = Bool_0 ? ', "norefresh": true' : ''; +var code = '{"type": "setEnemy", "id": "'+IdString_0+'", "name": "'+EnemyId_List_0+'"'+AssignOperator_List_0+', "value": "'+expression_0+'"'+Bool_0+'},\n'; return code; */; @@ -1292,13 +1293,13 @@ return code; setEnemyOnPoint_s - : '设置某点怪物属性' ':' 'x' EvalString? ',' 'y' EvalString? '楼层' IdString? '的' EnemyPoint_List AssignOperator_List expression Newline + : '设置某点怪物属性' ':' 'x' EvalString? ',' 'y' EvalString? '楼层' IdString? '的' EnemyPoint_List AssignOperator_List expression '不刷新显伤' Bool Newline /* setEnemyOnPoint_s tooltip : setEnemyOnPoint:设置某个点上怪物的属性 helpUrl : /_docs/#/instruction -default : ["", "", "", "atk", "="] +default : ["", "", "", "atk", "=", "", false] selectPoint : ["EvalString_0", "EvalString_1", "IdString_0"] allFloorIds : ['IdString_0'] colour : this.dataColor @@ -1307,35 +1308,37 @@ if (AssignOperator_List_0 && AssignOperator_List_0 != '=') { AssignOperator_List_0 = ', "operator": "' + AssignOperator_List_0 + '"'; } else AssignOperator_List_0 = ''; IdString_0 = IdString_0 && (', "floorId": "'+IdString_0+'"'); -var code = '{"type": "setEnemyOnPoint"'+floorstr+IdString_0+', "name": "'+EnemyPoint_List_0+'"'+AssignOperator_List_0+', "value": "'+expression_0+'"},\n'; +Bool_0 = Bool_0 ? ', "norefresh": true' : ''; +var code = '{"type": "setEnemyOnPoint"'+floorstr+IdString_0+', "name": "'+EnemyPoint_List_0+'"'+AssignOperator_List_0+', "value": "'+expression_0+'"'+Bool_0+'},\n'; return code; */; resetEnemyOnPoint_s - : '重置某点怪物属性' ':' 'x' EvalString? ',' 'y' EvalString? '楼层' IdString? Newline + : '重置某点怪物属性' ':' 'x' EvalString? ',' 'y' EvalString? '楼层' IdString? '不刷新显伤' Bool Newline /* resetEnemyOnPoint_s tooltip : resetEnemyOnPoint:重置某个点上怪物的属性 helpUrl : /_docs/#/instruction -default : ["", "", ""] +default : ["", "", "", false] selectPoint : ["EvalString_0", "EvalString_1", "IdString_0"] allFloorIds : ['IdString_0'] colour : this.dataColor var floorstr = MotaActionFunctions.processMultiLoc(EvalString_0, EvalString_1); IdString_0 = IdString_0 && (', "floorId": "'+IdString_0+'"'); -var code = '{"type": "resetEnemyOnPoint"'+floorstr+IdString_0+'},\n'; +Bool_0 = Bool_0 ? ', "norefresh": true' : ''; +var code = '{"type": "resetEnemyOnPoint"'+floorstr+IdString_0+Bool_0+'},\n'; return code; */; moveEnemyOnPoint_s - : '移动某点怪物属性' ':' '起点' 'x' PosString? ',' 'y' PosString? '终点' 'x' PosString? 'y' PosString? '楼层' IdString? Newline + : '移动某点怪物属性' ':' '起点' 'x' PosString? ',' 'y' PosString? '终点' 'x' PosString? 'y' PosString? '楼层' IdString? '不刷新显伤' Bool Newline /* moveEnemyOnPoint_s tooltip : moveEnemyOnPoint:移动某个点上怪物的属性到其他点 helpUrl : /_docs/#/instruction -default : ["", "", "", "", ""] +default : ["", "", "", "", "", false] allFloorIds : ['IdString_0'] selectPoint : ["PosString_2", "PosString_3"] menu : [['选择起点位置','editor_blockly.selectPoint(block,["PosString_0", "PosString_1"])']] @@ -1343,25 +1346,27 @@ colour : this.dataColor IdString_0 = IdString_0 && (', "floorId": "'+IdString_0+'"'); var floorstr = PosString_0 && PosString_1 ? ', "from": ['+PosString_0+','+PosString_1+']' : ''; if (PosString_2 && PosString_3) floorstr += ', "to": ['+PosString_2+','+PosString_3+']' -var code = '{"type": "moveEnemyOnPoint"'+floorstr+IdString_0+'},\n'; +Bool_0 = Bool_0 ? ', "norefresh": true' : ''; +var code = '{"type": "moveEnemyOnPoint"'+floorstr+IdString_0+Bool_0+'},\n'; return code; */; moveEnemyOnPoint_1_s - : '移动某点怪物属性' ':' '起点' 'x' PosString? ',' 'y' PosString? '增量' 'dx' PosString? 'dy' PosString? '楼层' IdString? Newline + : '移动某点怪物属性' ':' '起点' 'x' PosString? ',' 'y' PosString? '增量' 'dx' PosString? 'dy' PosString? '楼层' IdString? '不刷新显伤' Bool Newline /* moveEnemyOnPoint_1_s tooltip : moveEnemyOnPoint:移动某个点上怪物的属性到其他点 helpUrl : /_docs/#/instruction -default : ["", "", "", "", ""] +default : ["", "", "", "", "", false] allFloorIds : ['IdString_0'] selectPoint : ["PosString_0", "PosString_1"] colour : this.dataColor IdString_0 = IdString_0 && (', "floorId": "'+IdString_0+'"'); var floorstr = PosString_0 && PosString_1 ? ', "from": ['+PosString_0+','+PosString_1+']' : ''; if (PosString_2 && PosString_3) floorstr += ', "dxy": ['+PosString_2+','+PosString_3+']' -var code = '{"type": "moveEnemyOnPoint"'+floorstr+IdString_0+'},\n'; +Bool_0 = Bool_0 ? ', "norefresh": true' : ''; +var code = '{"type": "moveEnemyOnPoint"'+floorstr+IdString_0+Bool_0+'},\n'; return code; */; diff --git a/_server/MotaActionParser.js b/_server/MotaActionParser.js index ed447206..3f9d6193 100644 --- a/_server/MotaActionParser.js +++ b/_server/MotaActionParser.js @@ -750,7 +750,8 @@ ActionParser.prototype.parseAction = function() { break; case "setEnemy": this.next = MotaActionBlocks['setEnemy_s'].xmlText([ - MotaActionFunctions.replaceToName_token(data.id), data.name, data["operator"]||'=', this.expandEvalBlock([data.value]), this.next]); + MotaActionFunctions.replaceToName_token(data.id), data.name, data["operator"]||'=', this.expandEvalBlock([data.value]), + data.norefresh||false, this.next]); break; case "setEnemyOnPoint": data.loc=data.loc||[]; @@ -762,7 +763,8 @@ ActionParser.prototype.parseAction = function() { y_str.push(t[1]); }) this.next = MotaActionBlocks['setEnemyOnPoint_s'].xmlText([ - x_str.join(','),y_str.join(','),data.floorId||'',data.name, data["operator"]||'=', this.expandEvalBlock([data.value]), this.next]); + x_str.join(','),y_str.join(','),data.floorId||'',data.name, data["operator"]||'=', this.expandEvalBlock([data.value]), + data.norefresh||false, this.next]); break; case "resetEnemyOnPoint": data.loc=data.loc||[]; @@ -774,17 +776,17 @@ ActionParser.prototype.parseAction = function() { y_str.push(t[1]); }) this.next = MotaActionBlocks['resetEnemyOnPoint_s'].xmlText([ - x_str.join(','),y_str.join(','), data.floorId||'',this.next]); + x_str.join(','),y_str.join(','), data.floorId||'',data.norefresh||false,this.next]); break; case "moveEnemyOnPoint": data.from=data.from||['',''] if (data.dxy) { this.next = MotaActionBlocks['moveEnemyOnPoint_1_s'].xmlText([ - data.from[0], data.from[1], data.dxy[0], data.dxy[1], data.floorId||'',this.next]); + data.from[0], data.from[1], data.dxy[0], data.dxy[1], data.floorId||'',data.norefresh||false,this.next]); } else { data.to=data.to||['',''] this.next = MotaActionBlocks['moveEnemyOnPoint_s'].xmlText([ - data.from[0], data.from[1], data.to[0], data.to[1], data.floorId||'',this.next]); + data.from[0], data.from[1], data.to[0], data.to[1], data.floorId||'',data.norefresh||false,this.next]); } break; case "setEquip": diff --git a/libs/events.js b/libs/events.js index 7fe9678c..b4672f9d 100644 --- a/libs/events.js +++ b/libs/events.js @@ -1871,14 +1871,14 @@ events.prototype._action_addValue = function (data, x, y, prefix) { } events.prototype._action_setEnemy = function (data, x, y, prefix) { - this.setEnemy(data.id, data.name, data.value, data.operator, prefix); + this.setEnemy(data.id, data.name, data.value, data.operator, prefix, data.norefresh); core.doAction(); } events.prototype._action_setEnemyOnPoint = function (data, x, y, prefix) { var loc = this.__action_getLoc2D(data.loc, x, y, prefix); loc.forEach(function (one) { - core.setEnemyOnPoint(one[0], one[1], data.floorId, data.name, data.value, data.operator, prefix); + core.setEnemyOnPoint(one[0], one[1], data.floorId, data.name, data.value, data.operator, prefix, data.norefresh); }); core.doAction(); } @@ -1886,7 +1886,7 @@ events.prototype._action_setEnemyOnPoint = function (data, x, y, prefix) { events.prototype._action_resetEnemyOnPoint = function (data, x, y, prefix) { var loc = this.__action_getLoc2D(data.loc, x, y, prefix); loc.forEach(function (one) { - core.resetEnemyOnPoint(one[0], one[1], data.floorId); + core.resetEnemyOnPoint(one[0], one[1], data.floorId, data.norefresh); }); core.doAction(); } @@ -1905,7 +1905,7 @@ events.prototype._action_moveEnemyOnPoint = function (data, x, y, prefix) { } else { to = this.__action_getLoc(data.to, x, y, prefix); } - this.moveEnemyOnPoint(from[0], from[1], to[0], to[1], data.floorId); + this.moveEnemyOnPoint(from[0], from[1], to[0], to[1], data.floorId, data.norefresh); core.doAction(); } @@ -2986,7 +2986,7 @@ events.prototype._setValue_setGlobal = function (name, value) { } ////// 设置一个怪物属性 ////// -events.prototype.setEnemy = function (id, name, value, operator, prefix) { +events.prototype.setEnemy = function (id, name, value, operator, prefix, norefresh) { if (!core.hasFlag('enemyInfo')) { core.setFlag('enemyInfo', {}); } @@ -2996,11 +2996,11 @@ events.prototype.setEnemy = function (id, name, value, operator, prefix) { value = this._updateValueByOperator(core.calValue(value, prefix), (core.material.enemys[id]||{})[name], operator); enemyInfo[id][name] = value; (core.material.enemys[id]||{})[name] = core.clone(value); - core.updateStatusBar(); + if (!norefresh) core.updateStatusBar(); } ////// 设置某个点上的怪物属性 ////// -events.prototype.setEnemyOnPoint = function (x, y, floorId, name, value, operator, prefix) { +events.prototype.setEnemyOnPoint = function (x, y, floorId, name, value, operator, prefix, norefresh) { floorId = floorId || core.status.floorId; var block = core.getBlock(x, y, floorId); if (block == null) return; @@ -3013,22 +3013,22 @@ events.prototype.setEnemyOnPoint = function (x, y, floorId, name, value, operato flags.enemyOnPoint[floorId] = flags.enemyOnPoint[floorId] || {}; flags.enemyOnPoint[floorId][x+","+y] = flags.enemyOnPoint[floorId][x+","+y] || {}; flags.enemyOnPoint[floorId][x+","+y][name] = value; - core.updateStatusBar(); + if (!norefresh) core.updateStatusBar(); } ////// 重置某个点上的怪物属性 ////// -events.prototype.resetEnemyOnPoint = function (x, y, floorId) { +events.prototype.resetEnemyOnPoint = function (x, y, floorId, norefresh) { delete ((flags.enemyOnPoint||{})[floorId||core.status.floorId]||{})[x+","+y]; - core.updateStatusBar(); + if (!norefresh) core.updateStatusBar(); } ////// 将某个点上已经设置的怪物属性移动到其他点 ////// -events.prototype.moveEnemyOnPoint = function (fromX, fromY, toX, toY, floorId) { +events.prototype.moveEnemyOnPoint = function (fromX, fromY, toX, toY, floorId, norefresh) { floorId = floorId || core.status.floorId; if (((flags.enemyOnPoint||{})[floorId]||{})[fromX+","+fromY]) { flags.enemyOnPoint[floorId][toX+","+toY] = flags.enemyOnPoint[floorId][fromX+","+fromY]; delete flags.enemyOnPoint[floorId][fromX+","+fromY]; - core.updateStatusBar(); + if (!norefresh) core.updateStatusBar(); } } From edb9d5037f3036700792798b9004ab40e0a14899 Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Mon, 30 Aug 2021 21:34:32 +0800 Subject: [PATCH 23/60] =?UTF-8?q?=E6=96=B0=E6=8B=93=E5=B1=95:=E5=AD=98?= =?UTF-8?q?=E6=A1=A3=E6=9C=AC=E5=9C=B0=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- extensions/localSave.js | 76 +++++++++++++++++++++++++++++++++++++++++ libs/core.js | 3 +- libs/utils.js | 37 ++++++++++++-------- server.py | 11 +++++- 4 files changed, 111 insertions(+), 16 deletions(-) create mode 100644 extensions/localSave.js diff --git a/extensions/localSave.js b/extensions/localSave.js new file mode 100644 index 00000000..455b36ce --- /dev/null +++ b/extensions/localSave.js @@ -0,0 +1,76 @@ +/** + * 离线游戏使用本地存储扩展。 + * 开启本拓展后,将会把所有存档存至 _saves 目录下。 + * 需配合样板V2.8.2+使用 + */ + +"use strict"; + +(function () { + // 将这一行改成 false 可以禁用本拓展 + var __enabled = true; + + if (window.jsinterface || !window.fs || !__enabled) return; + + function rewrite() { + core.utils._setLocalForage_set = function (name, str, callback) { + var data = LZString.compressToBase64(str); + core.saves.cache[name] = data; + fs.writeFile('_saves/' + name, data, 'utf-8', callback); + } + + core.utils._getLocalForage_get = function (name, callback) { + fs.readFile('_saves/' + name, 'utf-8', function (err, data) { + if (err) return callback(err); + callback(null, data); + }); + } + + core.utils.decompress = function (data) { + try { + return JSON.parse(LZString.decompressFromBase64(data)) + } catch (e) { + return null; + } + } + + core.utils._removeLocalForage_remove = function (name, callback) { + fs.deleteFile('_saves/' + name, callback); + } + + core.utils.clearLocalForage = function (name, callback) { + // Nothing to do + } + + core.utils.iterateLocalForage = function (iter, callback) { + fs.readdir('_saves', function (err, data) { + if (err) callback(err); + else { + data.forEach(function (one) { + iter(null, one, null); + }); + callback(); + } + }); + } + + core.utils.keysLocalForage = function (callback) { + fs.readdir('_saves', callback); + } + + core.utils.lengthLocalForage = function (callback) { + fs.readdir('_saves', function (err, data) { + if (err) callback(err); + else callback(null, data.length); + }); + } + } + + fs.mkdir('_saves', function (err) { + if (err) return; + rewrite(); + core.control.getSaveIndexes(function (indexes) { core.saves.ids = indexes; }); + }); +})(); + + diff --git a/libs/core.js b/libs/core.js index 5be2e626..8cb19316 100644 --- a/libs/core.js +++ b/libs/core.js @@ -125,7 +125,8 @@ function core() { "now": 0, }, "favorite": [], - "favoriteName": {} + "favoriteName": {}, + "cache": {} } this.initStatus = { 'played': false, diff --git a/libs/utils.js b/libs/utils.js index 1601ca05..5814ee78 100644 --- a/libs/utils.js +++ b/libs/utils.js @@ -214,18 +214,7 @@ utils.prototype.setLocalStorage = function (key, value) { var str = JSON.stringify(value).replace(/[\u007F-\uFFFF]/g, function (chr) { return "\\u" + ("0000" + chr.charCodeAt(0).toString(16)).substr(-4) }); - var compressed = lzw_encode(str); - - // test if we can save to localStorage - localStorage.setItem("__tmp__", compressed); - if (lzw_decode(localStorage.getItem("__tmp__")) == str) { - localStorage.setItem(core.firstData.name + "_" + key, compressed); - } - else { - // We cannot compress the data - localStorage.setItem(core.firstData.name + "_" + key, str); - } - localStorage.removeItem("__tmp__"); + localStorage.setItem(core.firstData.name + "_" + key, str); if (key == 'autoSave') core.saves.ids[0] = true; else if (/^save\d+$/.test(key)) core.saves.ids[parseInt(key.substring(4))] = true; @@ -240,8 +229,11 @@ utils.prototype.setLocalStorage = function (key, value) { ////// 获得本地存储 ////// utils.prototype.getLocalStorage = function (key, defaultValue) { - var res = this.decompress(localStorage.getItem(core.firstData.name + "_" + key)); - return res == null ? defaultValue : res; + try { + return JSON.parse(localStorage.getItem(core.firstData.name + "_" + key)); + } catch (e) { + return defaultValue; + } } ////// 移除本地存储 ////// @@ -271,13 +263,18 @@ utils.prototype.setLocalForage = function (key, value, successCallback, errorCal if (successCallback) successCallback(); } } + this._setLocalForage_set(name, str, callback); +} +utils.prototype._setLocalForage_set = function (name, str, callback) { if (window.jsinterface && window.jsinterface.setLocalForage) { var id = setTimeout(null); core['__callback' + id] = callback; + core.saves.cache[name] = str; window.jsinterface.setLocalForage(id, name, str); } else { var compressed = str.length > 100000 ? LZString.compress(str) : lzw_encode(str); + core.saves.cache[name] = compressed; localforage.setItem(name, compressed, callback); } } @@ -289,6 +286,7 @@ utils.prototype.getLocalForage = function (key, defaultValue, successCallback, e if (errorCallback) errorCallback(err); } else { + core.saves.cache[name] = value; if (!successCallback) return; if (value != null) { var res = core.utils.decompress(value); @@ -298,7 +296,13 @@ utils.prototype.getLocalForage = function (key, defaultValue, successCallback, e successCallback(defaultValue); } }; + if (core.saves.cache[name] != null) { + return callback(null, core.saves.cache[name]); + } + this._getLocalForage_get(name, callback); +} +utils.prototype._getLocalForage_get = function (name, callback) { if (window.jsinterface && window.jsinterface.getLocalForage) { var id = setTimeout(null); core['__callback' + id] = callback; @@ -320,7 +324,11 @@ utils.prototype.removeLocalForage = function (key, successCallback, errorCallbac if (successCallback) successCallback(); } } + delete core.saves.cache[name]; + this._removeLocalForage_remove(name, callback); +} +utils.prototype._removeLocalForage_remove = function (name, callback) { if (window.jsinterface && window.jsinterface.removeLocalForage) { var id = setTimeout(null); core['__callback' + id] = callback; @@ -331,6 +339,7 @@ utils.prototype.removeLocalForage = function (key, successCallback, errorCallbac } utils.prototype.clearLocalForage = function (callback) { + core.saves.cache = {}; if (window.jsinterface && window.jsinterface.clearLocalForage) { var id = setTimeout(null); core['__callback' + id] = callback; diff --git a/server.py b/server.py index cad5e4a1..0e7d5900 100644 --- a/server.py +++ b/server.py @@ -47,11 +47,12 @@ def get_mimetype(path): def get_file(path): if not os.path.isfile(path): + if path.startswith('_saves/'): + return '' abort(404) return None if not is_sub(path): abort(403) - return None with open(path, 'rb') as f: content = f.read() # str in py2 and bytes in py3 return content @@ -82,6 +83,10 @@ def all_animates(): else: content.append('') return '@@@~~~###~~~@@@'.join(content) +@app.route('/favicon.ico', methods=['GET']) +def favicon(): + return '' + @app.route('/', methods=['GET']) def static_file(path): if os.path.isdir(path): @@ -206,6 +211,10 @@ def deleteFile(): shutil.rmtree(name) return 'Success' +@app.route('/games/upload.php', methods=['POST']) +def upload(): + return '' + def port_used(port): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) result = True From f3f6a6ff75372f19d1fe8f08d53e29b84b98388d Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Mon, 30 Aug 2021 22:04:38 +0800 Subject: [PATCH 24/60] formatBigNumber --- libs/utils.js | 61 ++++++++++++++++++++++----------------------------- 1 file changed, 26 insertions(+), 35 deletions(-) diff --git a/libs/utils.js b/libs/utils.js index 5814ee78..71a0f1fd 100644 --- a/libs/utils.js +++ b/libs/utils.js @@ -510,41 +510,32 @@ utils.prototype.formatSize = function (size) { else return (size/1024/1024).toFixed(2) + "MB"; } -utils.prototype.formatBigNumber = function (x, onMap) { - x = Math.floor(parseFloat(x)); - if (!core.isset(x) || !Number.isFinite(x)) return '???'; - if (x > 1e24 || x < -1e24) return x.toExponential(2); - - var c = x < 0 ? "-" : ""; - x = Math.abs(x); - - if (x <= 99999 || (!onMap && x <= 999999)) return c + x; - - var all = [ - {"val": 1e20, "c": "g"}, - {"val": 1e16, "c": "j"}, - {"val": 1e12, "c": "z"}, - {"val": 1e8, "c": "e"}, - {"val": 1e4, "c": "w"}, - ] - - for (var i = 0; i < all.length; i++) { - var one = all[i]; - if (onMap) { - if (x >= one.val) { - var v = x / one.val; - return c + v.toFixed(Math.max(0, Math.floor(3 - Math.log10(v + 1)))) + one.c; - } - } - else { - if (x >= 10 * one.val) { - var v = x / one.val; - return c + v.toFixed(Math.max(0, Math.floor(4 - Math.log10(v + 1)))) + one.c; - } - } - } - - return c + x; +utils.prototype.formatBigNumber = function (x, digits) { + if (digits === true) digits = 5; // 兼容旧版onMap参数 + if (!digits || digits < 5) digits = 6; // 连同负号、小数点和后缀字母在内的总位数,至少需为5,默认为6 + x = Math.trunc(parseFloat(x)); // 尝试识别为小数,然后向0取整 + if (x == null || !Number.isFinite(x)) return '???'; // 无法识别的数或正负无穷大,显示'???' + var units = [ // 单位及其后缀字母,可自定义,如改成千进制下的K、M、G、T、P + { "val": 1e20, "suffix": "g" }, + { "val": 1e16, "suffix": "j" }, + { "val": 1e12, "suffix": "z" }, + { "val": 1e8, "suffix": "e" }, + { "val": 10000, "suffix": "w" }, + ]; + if (Math.abs(x) > units[0].val * Math.pow(10, digits - 2)) + return x.toExponential(0); // 绝对值过大以致于失去精度的数,直接使用科学记数法,系数只保留整数 + var sign = x < 0 ? '-' : ''; + if (sign) --digits; // 符号位单独处理,负号要占一位 + x = Math.abs(x); + if (x.toString().length <= digits) return sign + x; + for (var i = 0; i < units.length; ++i) { // 从大到小尝试选取合适的单位 + var each = units[i]; + if (x >= each.val) { + var v = x / each.val; + return sign + v.toFixed(Math.max(0, Math.floor(digits - 2 - Math.log10(v + 1)))) + each.suffix; + } + } + return sign + x; } ////// 变速移动 ////// From 575cd37ce3c1ce420453303f40eb6be7ca3b2180 Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Mon, 30 Aug 2021 23:05:41 +0800 Subject: [PATCH 25/60] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=90=AF=E5=8A=A8?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libs/utils.js | 4 +++- 启动服务.exe | Bin 56832 -> 57344 bytes 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/utils.js b/libs/utils.js index 71a0f1fd..4f3d243c 100644 --- a/libs/utils.js +++ b/libs/utils.js @@ -230,7 +230,9 @@ utils.prototype.setLocalStorage = function (key, value) { ////// 获得本地存储 ////// utils.prototype.getLocalStorage = function (key, defaultValue) { try { - return JSON.parse(localStorage.getItem(core.firstData.name + "_" + key)); + var value = JSON.parse(localStorage.getItem(core.firstData.name + "_" + key)); + if (value == null) return defaultValue; + return value; } catch (e) { return defaultValue; } diff --git a/启动服务.exe b/启动服务.exe index 5234a1e9baf261938d585f6e37bee07c95b91d90..95cfac400007d94ffcfdb1cf1ac7b4593ca57cca 100644 GIT binary patch delta 1515 zcmb7EYe-vX7=FGJbD~j`c$vB=lIU!*Hrj0JYE!1x#8$UyW4t77(JpJYR>+ocT(>`E z4RhFTh@F1BQOd|lJ9g=Qlp~vrQe^v4k^UIWN*S5-M@M1%QFKzIgR%Eqlnh$N4jj(= zT)y|b?|Z)UrLG!M^M?1&)cm#Pi9)|_qXzlR3oH|ntC0=s(_al)GJgUGRDvO6V_PEBH$yz5hGtT_gJkx4*m3WO9 zr6k2bks;wES&Bc(ztQSqQ{2(EyK!dAViMg0v}n7&_F}d$m?g~d$+imnt!z1*CI8N^ zwN+F;$d(Ug$pu4vwQbi3^;+W1!LQ1b>J_A#A!@CiS~H8DLQ(Q4&_}RdlzbGM1u3xU z$TxX%P42f8@vuqiRp^Jzq(z_5h@v-A1$9z_2AlAxVM<{el)6lAD#l!(xs@05OYPlz z{zo~2^ubnT>iQ@54i{_{ODdn)d!7aO&W_6R^uvqc(T?)Q8>E@?&bfnBj-&v0oT3YP z<&nZX)70qG8R;h?r6tAY{zftV!oTj=W8Zp}S#%#FdTVd2%=qht;;_0wdi+I}_AvFV zj#!Yo!aVM`@A%K*)NgLI5WnJojHUQ>|1M!d%UKpUMI6`Btg7+cu|kV@0Jn8?+E_~Hu8z3TPUxPB zKFUoOJH;UGt4PZk#NR5Ku83IQH3U&gX8|>+qqL(%ftyx`Dvr|+vyIYd#b{a|e7g1t zykZ~1F@Cwv?n~(8EIwrYcsnciz`vFcU`luP;u&!Omtr#^yWoh)RiV_0mhx8+#TyvK zQ6%sh8uSRxW5mCTmobK&IDsVMq(>1WM-s=8GoIW7=6J*w%U3%?;U+u`$`Q{J010VFA4(tCC;0F1aE zfEQl_v@@zyEQh#cIlC?wF1f;Ryg$PR**+uqC@~8l6F2#bSOX^fWhG5fXm48$VDSpP zr-5n|8`|77NSjlIXo}E@pZpGIPpaIQB45Bc0Y_eMs@$9+Ka65aU_ouRFAYwU>uhqv zN&hO@0Wx9Xy*6HYt6(|dEM9^bv|BjILW7!-E_h9Xr&AG&w$7)*g;EaA5y$71DjBnt zPJ(9*$yQBOs$p$K&7%L&gOiqxwo}(Xs90?sbwDbX|9E`zXn;(cc+aX-OEJaL@-a)i zCqi<1u5IQN!7Tku)dll0Pl#eFcv@+8(mbKbW)^|_Z#t8^_qzv=*uXG zMqu7INTVoc25pv|FMpyrbVHfF$5;)@u>mAtkIldb;h9dSiIzggT1^AH zfv*AAI*sm%z?P^VJ2Bb>oQ2x2NF98DSf3?XQZqdn~8I^tLy zc9#F4YQMly@bUFi{1=ZyaBU&{J!+I9?7TsrjMxM1^_7CCTlquD!hV{z1b65R@Y zbOrU%#S@N*kxRp^C1-aPR$qt@PkVQ&;((k?npjqje)lMDXDf48!kx>xhLG?7AlnB% P8o5A;ocZ(>OZbGZ(|0Gy From 83548759b5de552d03de72ab5bf868413e59921c Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Tue, 31 Aug 2021 10:26:31 +0800 Subject: [PATCH 26/60] compress h5save & h5route --- libs/actions.js | 16 +++++++++------- libs/control.js | 16 ++++++++++++++-- libs/events.js | 3 ++- libs/utils.js | 21 ++++++++++++--------- 4 files changed, 37 insertions(+), 19 deletions(-) diff --git a/libs/actions.js b/libs/actions.js index 3e967d99..323aab20 100644 --- a/libs/actions.js +++ b/libs/actions.js @@ -2759,7 +2759,8 @@ actions.prototype._clickLocalSaveSelect = function (x, y) { "version": core.firstData.version, "data": saves } - core.download(core.firstData.name + "_" + core.formatDate2(new Date()) + ".h5save", JSON.stringify(content)); + core.download(core.firstData.name + "_" + core.formatDate2(new Date()) + ".h5save", + LZString.compressToBase64(JSON.stringify(content))); } }; if (selection == 0) core.getAllSaves(callback); @@ -2913,12 +2914,13 @@ actions.prototype._clickReplay_replayRemain = function () { actions.prototype._clickReplay_download = function () { // if (core.hasFlag('debug')) return core.drawText("\t[系统提示]调试模式下无法下载录像"); - core.download(core.firstData.name + "_" + core.formatDate2() + ".h5route", JSON.stringify({ - 'name': core.firstData.name, - 'hard': core.status.hard, - 'seed': core.getFlag('__seed__'), - 'route': core.encodeRoute(core.status.route) - })); + core.download(core.firstData.name + "_" + core.formatDate2() + ".h5route", + LZString.compressToBase64(JSON.stringify({ + 'name': core.firstData.name, + 'hard': core.status.hard, + 'seed': core.getFlag('__seed__'), + 'route': core.encodeRoute(core.status.route) + }))); } diff --git a/libs/control.js b/libs/control.js index 4a5aa417..43212ef9 100644 --- a/libs/control.js +++ b/libs/control.js @@ -2136,7 +2136,7 @@ control.prototype._syncSave_http = function (type, saves) { var formData = new FormData(); formData.append('type', 'save'); formData.append('name', core.firstData.name); - formData.append('data', JSON.stringify(saves)); + formData.append('data', LZString.compressToBase64(JSON.stringify(saves))); formData.append('shorten', '1'); core.http("POST", "/games/sync.php", formData, function (data) { @@ -2181,7 +2181,19 @@ control.prototype._syncLoad_http = function (id, password) { core.http("POST", "/games/sync.php", formData, function (data) { var response = JSON.parse(data); if (response.code == 0) { - core.control._syncLoad_write(JSON.parse(response.msg)); + var msg = null; + try { + msg = JSON.parse(LZString.decompressFromBase64(response.msg)); + } catch (e) { + try { + msg = JSON.parse(response.msg); + } catch (e) {} + } + if (msg) { + core.control._syncLoad_write(msg); + } else { + core.drawText("出错啦!\n存档解析失败!"); + } } else { core.drawText("出错啦!\n无法从服务器同步存档。\n错误原因:"+response.msg); diff --git a/libs/events.js b/libs/events.js index b4672f9d..3585720e 100644 --- a/libs/events.js +++ b/libs/events.js @@ -217,7 +217,8 @@ events.prototype._gameOver_confirmDownload = function (ending) { 'seed': core.getFlag('__seed__'), 'route': core.encodeRoute(core.status.route) } - core.download(core.firstData.name + "_" + core.formatDate2(new Date()) + ".h5route", JSON.stringify(obj)); + core.download(core.firstData.name + "_" + core.formatDate2(new Date()) + ".h5route", + LZString.compressToBase64(JSON.stringify(obj))); core.events._gameOver_askRate(ending); }, function () { core.events._gameOver_askRate(ending); diff --git a/libs/utils.js b/libs/utils.js index 4f3d243c..b85395b9 100644 --- a/libs/utils.js +++ b/libs/utils.js @@ -1019,19 +1019,22 @@ utils.prototype.readFileContent = function (content) { core.platform.successCallback(content); return; } + // 检查base64 try { - obj = JSON.parse(content); - if (obj) { - if (core.platform.successCallback) - core.platform.successCallback(obj); - return; + obj = JSON.parse(LZString.decompressFromBase64(content)); + } catch (e) { + try { + obj = JSON.parse(content); + } catch (e) { + main.log(e) } } - catch (e) { - main.log(e); - alert(e); + + if (obj) { + if (core.platform.successCallback) + core.platform.successCallback(obj); + return; } - // alert("不是有效的JSON文件!"); if (core.platform.errorCallback) core.platform.errorCallback(); From 2803a24c7cb77a57472341af1136334696b71266 Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Tue, 31 Aug 2021 12:18:39 +0800 Subject: [PATCH 27/60] =?UTF-8?q?=E6=92=AD=E6=94=BE=E5=AD=98=E6=A1=A3?= =?UTF-8?q?=E5=89=A9=E4=BD=99=E5=BD=95=E5=83=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libs/actions.js | 29 +++++++++++++++++++++++++---- libs/control.js | 18 ++++++++++++++++-- libs/ui.js | 1 + 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/libs/actions.js b/libs/actions.js index 323aab20..0cfa4d37 100644 --- a/libs/actions.js +++ b/libs/actions.js @@ -286,6 +286,7 @@ actions.prototype._sys_keyDown_lockControl = function (keyCode) { case 'load': case 'replayLoad': case 'replayRemain': + case 'replaySince': this._keyDownSL(keyCode); break; case 'selectShop': @@ -388,6 +389,7 @@ actions.prototype._sys_keyUp_lockControl = function (keyCode, altKey) { case 'load': case 'replayLoad': case 'replayRemain': + case 'replaySince': this._keyUpSL(keyCode); break; case 'keyBoard': @@ -674,6 +676,7 @@ actions.prototype._sys_onclick_lockControl = function (x, y, px, py) { case 'load': case 'replayLoad': case 'replayRemain': + case 'replaySince': this._clickSL(x, y, px, py); break; case 'confirmBox': @@ -839,7 +842,7 @@ actions.prototype._sys_longClick_lockControl = function (x, y, px, py) { } } // 长按SL上下页快速翻页 - if (["save","load","replayLoad","replayRemain"].indexOf(core.status.event.id) >= 0) { + if (["save","load","replayLoad","replayRemain","replaySince"].indexOf(core.status.event.id) >= 0) { if ([this.HSIZE-2, this.HSIZE-3, this.HSIZE+2, this.HSIZE+3].indexOf(x) >= 0 && y == this.LAST) { this._clickSL(x, y); return true; @@ -2875,9 +2878,10 @@ actions.prototype._clickReplay = function (x, y) { case 0: core.playSound('确定'); return this._clickReplay_fromBeginning(); case 1: core.playSound('确定'); return this._clickReplay_fromLoad(); case 2: core.playSound('确定'); return this._clickReplay_replayRemain(); - case 3: core.playSound('确定'); return core.chooseReplayFile(); - case 4: core.playSound('确定'); return this._clickReplay_download(); - case 5: core.playSound('取消'); return core.ui.closePanel(); + case 3: core.playSound('确定'); return this._clickReplay_replaySince(); + case 4: core.playSound('确定'); return core.chooseReplayFile(); + case 5: core.playSound('确定'); return this._clickReplay_download(); + case 6: core.playSound('取消'); return core.ui.closePanel(); } } } @@ -2912,6 +2916,23 @@ actions.prototype._clickReplay_replayRemain = function () { }); } +actions.prototype._clickReplay_replaySince = function () { + core.closePanel(); + core.drawText([ + "\t[播放存档剩余录像]该功能为【接续播放录像】的简化版本,允许你播放\r[yellow]一个存档中剩余的录像\r,常常用于\r[yellow]录像局部优化\r。\n" + + "在录像正常播放中,你随时可以暂停并按S键进行存档;此时\r[yellow]剩余录像\r也会被记在存档中(在读档界面用\r[yellow][R]\r标识。)\n" + + "之后,你可以选择在路线优化后直接播放该存档的\r[yellow]剩余录像\r,而无需再像接续播放一样选择录像起点和终点。\n\n" + + "详细使用方法参见露珠录制的视频教程:\n\r[yellow]https://bilibili.com/video/BV1az4y1C78x", + "请选择一个存档。\n\n\r[yellow]该存档需为录像播放中存的,且坐标必须和当前勇士坐标完全相同。\r\n将尝试播放此存档的剩余录像。", + ], function () { + core.status.event.id = 'replaySince'; + core.lockControl(); + var saveIndex = core.saves.saveIndex; + var page = parseInt((saveIndex - 1) / 5), offset = saveIndex - 5 * page; + core.ui._drawSLPanel(10 * page + offset); + }); +} + actions.prototype._clickReplay_download = function () { // if (core.hasFlag('debug')) return core.drawText("\t[系统提示]调试模式下无法下载录像"); core.download(core.firstData.name + "_" + core.formatDate2() + ".h5route", diff --git a/libs/control.js b/libs/control.js index 43212ef9..c8d4c901 100644 --- a/libs/control.js +++ b/libs/control.js @@ -1968,6 +1968,7 @@ control.prototype.doSL = function (id, type) { case 'reload': this._doSL_reload(id, this._doSL_load_afterGet); break; case 'replayLoad': this._doSL_load(id, this._doSL_replayLoad_afterGet); break; case 'replayRemain': this._doSL_load(id, this._doSL_replayRemain_afterGet); break; + case 'replaySince': this._doSL_load(id, this._doSL_replaySince_afterGet); break; } } @@ -1979,7 +1980,11 @@ control.prototype._doSL_save = function (id) { // 在事件中的存档 if (core.status.event.interval != null) core.setFlag("__events__", core.status.event.interval); - core.setLocalForage("save"+id, core.saveData(), function() { + var data = core.saveData(); + if (core.isReplaying() && core.status.replay.toReplay.length > 0) { + data.__toReplay__ = core.encodeRoute(core.status.replay.toReplay); + } + core.setLocalForage("save"+id, data, function() { core.saves.saveIndex = id; core.setLocalStorage('saveIndex', core.saves.saveIndex); // 恢复事件 @@ -2088,7 +2093,6 @@ control.prototype._doSL_replayLoad_afterGet = function (id, data) { core.startReplay(route); core.drawTip("回退到存档节点"); }); - } control.prototype._doSL_replayRemain_afterGet = function (id, data) { @@ -2121,6 +2125,16 @@ control.prototype._doSL_replayRemain_afterGet = function (id, data) { }); } +control.prototype._doSL_replaySince_afterGet = function (id, data) { + if (data.floorId != core.status.floorId || data.hero.loc.x != core.getHeroLoc('x') || data.hero.loc.y != core.getHeroLoc('y')) + return alert("楼层或坐标不一致!"); + if (!data.__toReplay__) return alert('该存档没有剩余录像!'); + core.ui.closePanel(); + core.startReplay(core.decodeRoute(data.__toReplay__)); + core.drawTip("播放存档剩余录像"); + return; +} + ////// 同步存档到服务器 ////// control.prototype.syncSave = function (type) { core.ui.drawWaiting("正在同步,请稍候..."); diff --git a/libs/ui.js b/libs/ui.js index 403fbc14..d2f968db 100644 --- a/libs/ui.js +++ b/libs/ui.js @@ -3019,6 +3019,7 @@ ui.prototype._drawSLPanel_drawRecord = function(title, data, x, y, size, cho, hi var strokeColor = globalAttribute.selectColor; if (core.status.event.selection) strokeColor = '#FF6A6A'; if (!data || !data.floorId) highLight = false; + if (data && data.__toReplay__) title = '[R]' + title; core.fillText('ui', title, x, y, highLight?globalAttribute.selectColor:'#FFFFFF', this._buildFont(17, true)); core.strokeRect('ui', x-size/2, y+15, size, size, cho?strokeColor:'#FFFFFF', cho?6:2); From 3bac35cc365ad6e91ade6b34a2911740c165734d Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Tue, 31 Aug 2021 12:34:19 +0800 Subject: [PATCH 28/60] =?UTF-8?q?=E6=92=AD=E6=94=BE=E5=AD=98=E6=A1=A3?= =?UTF-8?q?=E5=89=A9=E4=BD=99=E5=BD=95=E5=83=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libs/ui.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/ui.js b/libs/ui.js index d2f968db..f2886cf5 100644 --- a/libs/ui.js +++ b/libs/ui.js @@ -2031,7 +2031,7 @@ ui.prototype._drawReplay = function () { core.status.event.id = 'replay'; core.playSound('打开界面'); this.drawChoices(null, [ - "从头回放录像", "从存档开始回放", "接续播放剩余录像", "选择录像文件", "下载当前录像", "返回游戏" + "从头回放录像", "从存档开始回放", "接续播放剩余录像", "播放存档剩余录像", "选择录像文件", "下载当前录像", "返回游戏" ]); } From 96477f77d0663fe643a7dd2d5c7b03793c746fac Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Tue, 31 Aug 2021 16:52:09 +0800 Subject: [PATCH 29/60] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=94=81=E5=AE=9A?= =?UTF-8?q?=E8=A7=86=E8=A7=92=E9=97=AA=E7=83=81=20&=20=E5=A4=A7=E6=80=AA?= =?UTF-8?q?=E7=89=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libs/control.js | 21 ++++++++------------- libs/events.js | 4 ++-- libs/maps.js | 49 +++++++++++++++++++++++++----------------------- project/items.js | 2 +- 4 files changed, 37 insertions(+), 39 deletions(-) diff --git a/libs/control.js b/libs/control.js index c8d4c901..3c6e2084 100644 --- a/libs/control.js +++ b/libs/control.js @@ -831,20 +831,16 @@ control.prototype.drawHero = function (status, offset, frame) { core.status.heroCenter.py = 32 * y + offsetY + 32 - core.material.icons.hero.height / 2; // 重置hero层画布 - var px = parseFloat(core.canvas.hero.canvas.getAttribute('_px')) || 0; - var py = parseFloat(core.canvas.hero.canvas.getAttribute('_py')) || 0; core.setGameCanvasTranslate('hero', 0, 0); - core.canvas.hero.canvas.removeAttribute('_px'); - core.canvas.hero.canvas.removeAttribute('_py'); - offset.px = px; - offset.py = py; + delete core.canvas.hero._px; + delete core.canvas.hero._py; if (!core.hasFlag('__lockViewport__')) { this._drawHero_updateViewport(x, y, offset); } if (!core.hasFlag('hideHero')) { this._drawHero_draw(direction, x, y, status, offset, frame); - } + } } control.prototype._drawHero_updateViewport = function (x, y, offset) { @@ -858,7 +854,7 @@ control.prototype._drawHero_draw = function (direction, x, y, status, offset, fr this._drawHero_getDrawObjs(direction, x, y, status, offset).forEach(function (block) { core.drawImage('hero', block.img, (block.heroIcon[block.status] + (frame || 0))%4*block.width, block.heroIcon.loc * block.height, block.width, block.height, - offset.px+block.posx+(32-block.width)/2, offset.py+block.posy+32-block.height, block.width, block.height); + block.posx+(32-block.width)/2, block.posy+32-block.height, block.width, block.height); }); } @@ -1015,14 +1011,13 @@ control.prototype.setViewport = function (px, py) { core.bigmap.offsetY = core.clamp(py, 0, 32 * core.bigmap.height - core.__PIXELS__); this.updateViewport(); // ------ hero层也需要! - var canvas = core.canvas.hero.canvas; - var px = parseFloat(canvas.getAttribute('_px')) || 0; - var py = parseFloat(canvas.getAttribute('_py')) || 0; + var px = parseFloat(core.canvas.hero._px) || 0; + var py = parseFloat(core.canvas.hero._py) || 0; px += originOffsetX - core.bigmap.offsetX; py += originOffsetY - core.bigmap.offsetY; core.control.setGameCanvasTranslate('hero', px, py); - core.canvas.hero.canvas.setAttribute('_px', px); - core.canvas.hero.canvas.setAttribute('_py', py); + core.canvas.hero._px = px; + core.canvas.hero._py = py; } ////// 移动视野范围 ////// diff --git a/libs/events.js b/libs/events.js index 3585720e..1ac07c1d 100644 --- a/libs/events.js +++ b/libs/events.js @@ -423,7 +423,7 @@ events.prototype._trigger_ignoreChangeFloor = function (block) { events.prototype._sys_battle = function (data, callback) { // 检查是否需要改变朝向 - if (data.x == core.nextX() && data.y == core.nextY()) { + /* if (data.x == core.nextX() && data.y == core.nextY()) { var dir = core.turnDirection(":back"); var id = data.event.id, toId = (data.event.faceIds || {})[dir]; if (toId && id != toId) { @@ -431,7 +431,7 @@ events.prototype._sys_battle = function (data, callback) { if (number > 0) core.setBlock(number, data.x, data.y); } - } + } */ // 检查战前事件 var beforeBattle = []; diff --git a/libs/maps.js b/libs/maps.js index e1d6094b..5663e92e 100644 --- a/libs/maps.js +++ b/libs/maps.js @@ -968,10 +968,9 @@ maps.prototype._getBigImageInfo = function (bigImage, face, animate) { } var dx, dy; switch (face) { - case "down": dx = 16 - per_width / 2; dy = 32 - per_height; break; - case "left": dx = 0; dy = 16 - per_height / 2; break; - case "right": dx = 32 - per_width; dy = 16 - per_height / 2; break; - case "up": dx = 16 - per_width / 2; dy = 0; break; + case "down": case "up": dx = 16 - per_width / 2; dy = 32 - per_height; break; + case "left": dx = 0; dy = 32 - per_height; break; + case "right": dx = 32 - per_width; dy = 32 - per_height; break; } return {sx: sx, sy: sy, per_width: per_width, per_height: per_height, face: face, dx: dx, dy: dy}; @@ -1034,41 +1033,34 @@ maps.prototype._drawBlockInfo_bigImage = function (blockInfo, x, y, ctx) { var dx = bigImageInfo.dx, dy = bigImageInfo.dy; switch (bigImageInfo.face) { - case "down": - core.createCanvas(header, px + dx, py + dy, per_width, per_height - 32, 51); + case "down": case "up": + core.createCanvas(header, px + dx, py + dy, per_width, -dy, 51); this._drawBlockInfo_drawWithFilter(blockInfo, header, function () { - core.drawImage(header, bigImage, sx, sy, per_width, per_height - 32, 0, 0, per_width, per_height - 32); + core.drawImage(header, bigImage, sx, sy, per_width, -dy, 0, 0, per_width, -dy); }); core.createCanvas(body, px + dx, py, per_width, 32, 31); this._drawBlockInfo_drawWithFilter(blockInfo, body, function () { - core.drawImage(body, bigImage, sx, sy + per_height - 32, per_width, 32, 0, 0, per_width, 32); + core.drawImage(body, bigImage, sx, sy - dy, per_width, 32, 0, 0, per_width, 32); }) break; case "left": - core.createCanvas(header, px + dx, py + dy, per_width, per_height / 2 - 16, 51); + core.createCanvas(header, px + dx, py + dy, per_width, -dy, 51); this._drawBlockInfo_drawWithFilter(blockInfo, header, function () { - core.drawImage(header, bigImage, sx, sy, per_width, per_height / 2 - 16, 0, 0, per_width, per_height / 2 - 16); + core.drawImage(header, bigImage, sx, sy, per_width, -dy, 0, 0, per_width, -dy); }); - core.createCanvas(body, px + dx, py, per_width, per_height / 2 + 16, 31); + core.createCanvas(body, px + dx, py, per_width, 32, 31); this._drawBlockInfo_drawWithFilter(blockInfo, body, function () { - core.drawImage(body, bigImage, sx, sy + per_height / 2 - 16, per_width, per_height / 2 + 16, 0, 0, per_width, per_height / 2 + 16); + core.drawImage(body, bigImage, sx, sy - dy, per_width, 32, 0, 0, per_width, 32); }); break; case "right": - core.createCanvas(header, px + dx, py + dy, per_width, per_height / 2 - 16, 51); + core.createCanvas(header, px + dx, py + dy, per_width, -dy, 51); this._drawBlockInfo_drawWithFilter(blockInfo, header, function () { - core.drawImage(header, bigImage, sx, sy, per_width, per_height / 2 - 16, 0, 0, per_width, per_height / 2 - 16); + core.drawImage(header, bigImage, sx, sy, per_width, -dy, 0, 0, per_width, -dy); }); core.createCanvas(body, px + dx, py, per_width, per_height / 2 + 16, 31); this._drawBlockInfo_drawWithFilter(blockInfo, body, function () { - core.drawImage(body, bigImage, sx, sy + per_height / 2 - 16, per_width, per_height / 2 + 16, 0, 0, per_width, per_height / 2 + 16); - }); - break; - case "up": - core.deleteCanvas(header); - core.createCanvas(body, px + dx, py, per_width, per_height, 31); - this._drawBlockInfo_drawWithFilter(blockInfo, body, function () { - core.drawImage(body, bigImage, sx, sy, per_width, per_height, 0, 0, per_width, per_height); + core.drawImage(body, bigImage, sx, sy - dy, per_width, 32, 0, 0, per_width, 32); }); break; } @@ -2525,7 +2517,18 @@ maps.prototype._moveDetachedBlock = function (blockInfo, nowX, nowY, opacity, ca } if (bodyCanvas) { if (blockInfo.bigImage) { - var bigImageInfo = this._getBigImageInfo(blockInfo.bigImage, blockInfo.face, blockInfo.posX); + var face = blockInfo.face; + if (!blockInfo.faceIds) face = 'down'; + else if (!blockInfo.faceIds[face]) { + // 维持此时朝向 + face = 'down'; + for (var f in blockInfo.faceIds) { + if (blockInfo.faceIds[f] == blockInfo.id) { + face = f; + } + } + } + var bigImageInfo = this._getBigImageInfo(blockInfo.bigImage, face, blockInfo.posX); var per_width = bigImageInfo.per_width, per_height = bigImageInfo.per_height; core.dymCanvas[bodyCanvas].clearRect(0, 0, bigImageInfo.per_width, bigImageInfo.per_height); core.dymCanvas[bodyCanvas].drawImage(blockInfo.bigImage, bigImageInfo.sx, bigImageInfo.sy, per_width, per_height, 0, 0, per_width, per_height); diff --git a/project/items.js b/project/items.js index 3406d3f4..6c2b4665 100644 --- a/project/items.js +++ b/project/items.js @@ -382,7 +382,7 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a = "cls": "tools", "name": "炸弹", "text": "可以炸掉勇士面前的怪物", - "useItemEffect": "(function () {\n\tvar bombList = []; // 炸掉的怪物坐标列表\n\tvar todo = []; // 炸弹后事件\n\tvar money = 0,\n\t\texp = 0; // 炸弹获得的金币和经验\n\n\tvar canBomb = function (x, y) {\n\t\tvar block = core.getBlock(x, y);\n\t\tif (block == null || block.disable || block.event.cls.indexOf('enemy') != 0) return false;\n\t\tvar enemy = core.material.enemys[block.event.id];\n\t\treturn enemy && !enemy.notBomb;\n\t};\n\n\tvar bomb = function (x, y) {\n\t\tif (!canBomb(x, y)) return;\n\t\tbombList.push([x, y]);\n\t\tvar id = core.getBlockId(x, y),\n\t\t\tenemy = core.material.enemys[id];\n\t\tmoney += core.getEnemyValue(enemy, 'money', x, y) || 0;\n\t\texp += core.getEnemyValue(enemy, 'exp', x, y) || 0;\n\t\tcore.push(todo, core.floors[core.status.floorId].afterBattle[x + \",\" + y]);\n\t\tcore.push(todo, enemy.afterBattle);\n\t\tcore.removeBlock(x, y);\n\t}\n\n\t// 如果要多方向可炸,把这里的false改成true\n\tif (false) {\n\t\tvar scan = core.utils.scan; // 多方向炸时默认四方向,如果要改成八方向炸可以改成 core.utils.scan2\n\t\tfor (var direction in scan) {\n\t\t\tvar delta = scan[direction];\n\t\t\tbomb(core.getHeroLoc('x') + delta.x, core.getHeroLoc('y') + delta.y);\n\t\t}\n\t} else {\n\t\t// 仅炸当前\n\t\tbomb(core.nextX(), core.nextY());\n\t}\n\n\tif (bombList.length > 0) {\n\t\tcore.playSound('炸弹');\n\t\tcore.drawTip(core.material.items[itemId].name + '使用成功', itemId);\n\t\t// 取消这里的注释可以炸弹后获得金币和经验\n\t\t// core.status.hero.money += money;\n\t\t// core.status.hero.exp += exp;\n\n\t\t// 取消这里的注释可以炸弹引发战后事件\n\t\t// if (todo.length > 0) core.insertAction(todo);\n\t} else {\n\t\tcore.playSound('操作失败');\n\t\tcore.drawTip('当前无法使用' + core.material.items[itemId].name, itemId);\n\t\tcore.addItem(itemId, 1);\n\t\treturn;\n\t}\n\n\t// 炸弹后事件\n\t// 这是一个使用炸弹也能开门的例子\n\t/*\n\tif (core.status.floorId=='xxx' && core.terrainExists(x0,y0,'specialDoor') // 某个楼层,该机关门存在\n\t\t&& !core.enemyExists(x1,y1) && !core.enemyExists(x2,y2)) // 且守门的怪物都不存在\n\t{\n\t\tcore.insertAction([ // 插入事件\n\t\t\t{\"type\": \"openDoor\", \"loc\": [x0,y0]} // 开门\n\t\t])\n\t}\n\t*/\n})();", + "useItemEffect": "(function () {\n\tvar bombList = []; // 炸掉的怪物坐标列表\n\tvar todo = []; // 炸弹后事件\n\tvar money = 0,\n\t\texp = 0; // 炸弹获得的金币和经验\n\n\tvar canBomb = function (x, y) {\n\t\tvar block = core.getBlock(x, y);\n\t\tif (block == null || block.disable || block.event.cls.indexOf('enemy') != 0) return false;\n\t\tvar enemy = core.material.enemys[block.event.id];\n\t\treturn enemy && !enemy.notBomb;\n\t};\n\n\tvar bomb = function (x, y) {\n\t\tif (!canBomb(x, y)) return;\n\t\tbombList.push([x, y]);\n\t\tvar id = core.getBlockId(x, y),\n\t\t\tenemy = core.material.enemys[id];\n\t\tmoney += core.getEnemyValue(enemy, 'money', x, y) || 0;\n\t\texp += core.getEnemyValue(enemy, 'exp', x, y) || 0;\n\t\tcore.push(todo, core.floors[core.status.floorId].afterBattle[x + \",\" + y]);\n\t\tcore.push(todo, enemy.afterBattle);\n\t\tcore.removeBlock(x, y);\n\t}\n\n\t// 如果要多方向可炸,把这里的false改成true\n\tif (false) {\n\t\tvar scan = core.utils.scan; // 多方向炸时默认四方向,如果要改成八方向炸可以改成 core.utils.scan2\n\t\tfor (var direction in scan) {\n\t\t\tvar delta = scan[direction];\n\t\t\tbomb(core.getHeroLoc('x') + delta.x, core.getHeroLoc('y') + delta.y);\n\t\t}\n\t} else {\n\t\t// 仅炸当前\n\t\tbomb(core.nextX(), core.nextY());\n\t}\n\n\tif (bomb.length == 0) {\n\t\tcore.playSound('操作失败');\n\t\tcore.drawTip('当前无法使用' + core.material.items[itemId].name, itemId);\n\t\tcore.addItem(itemId, 1);\n\t\treturn;\n\t}\n\n\tcore.playSound('炸弹');\n\tcore.drawTip(core.material.items[itemId].name + '使用成功', itemId);\n\n\t// 取消这里的注释可以炸弹后获得金币和经验\n\t// core.status.hero.money += money;\n\t// core.status.hero.exp += exp;\n\n\t// 取消这里的注释可以炸弹引发战后事件\n\t// if (todo.length > 0) core.insertAction(todo);\n\n})();", "canUseItemEffect": "true" }, "centerFly": { From e1f55d6e722104716e03e32b3e5e8f23808153d0 Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Tue, 31 Aug 2021 17:48:40 +0800 Subject: [PATCH 30/60] =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E5=8B=87=E5=A3=AB?= =?UTF-8?q?=E4=B8=8D=E9=80=8F=E6=98=8E=E5=BA=A6=20&=20=E5=A4=A7=E6=80=AA?= =?UTF-8?q?=E7=89=A9=E4=B8=AD=E4=B8=8B=E9=94=9A=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _docs/api.md | 6 ++-- _docs/instruction.md | 4 +-- _server/CodeMirror/defs.js | 6 ++-- _server/MotaAction.g4 | 33 ++++++-------------- _server/MotaActionParser.js | 10 ++---- _server/editor_blocklyconfig.js | 3 +- extensions/localSave.js | 6 ++-- libs/actions.js | 1 + libs/control.js | 54 +++++++++++++-------------------- libs/events.js | 20 ++++++------ libs/maps.js | 12 ++++---- runtime.d.ts | 4 +-- 12 files changed, 65 insertions(+), 94 deletions(-) diff --git a/_docs/api.md b/_docs/api.md index b4723ae5..b2493a82 100644 --- a/_docs/api.md +++ b/_docs/api.md @@ -610,6 +610,9 @@ noGather: 是否聚集跟随者 setHeroMoveInterval: fn(callback?: fn()) 设置行走的效果动画 +setHeroOpacity: fn(opacity?: number, moveMode?: string, time?: number, callback?: fn()) +改变勇士的不透明度 + setMusicBtn: fn() 设置音乐图标的显隐状态 @@ -682,9 +685,6 @@ triggerDebuff: fn(action: string, type: string|[string]) action: 要获得还是移除,'get'为获得,'remove'为移除 type: 获得或移除的内容(poison/weak/curse),可以为字符串或数组 -triggerHero: fn(type?: string, time?: number, callback?: fn()) -改变勇士的显隐状态 - triggerReplay: fn() 播放或暂停录像回放 diff --git a/_docs/instruction.md b/_docs/instruction.md index 790473dd..6c48588a 100644 --- a/_docs/instruction.md +++ b/_docs/instruction.md @@ -581,8 +581,8 @@ core.insertAction({"type": "changeFloor", "floorId": "MT" + core.rand2(20)}) * V2.8.1起,支持暂时锁定视角,视角锁定期间,只有上下楼后才会将视角重置到勇士身上(但依然保持锁定)。 4. **显隐状态栏:**如题,如果隐藏状态栏期间勇士需要恢复行动,则建议不隐藏竖屏工具栏以方便手机玩家。 * 实际调用`core.showStatusBar()`和`core.hideStatusBar(showToolbox)` -5. **显隐勇士:**如题,动画时间为淡入淡出时间,异步勾选框用法如前。 - * 实际调用`core.triggerHero(type, time, callback)` +5. **设置勇士不透明度:**如题,动画时间为淡入淡出时间,异步勾选框用法如前。 + * 实际调用`core.setHeroOpacity(opacity, moveMode, time, callback)` 6. **更改画面色调:**色调可以用调色器调配,“动画时间”为渐变的总时间。 * 请注意渐变是在RGBA颜色空间中直线运动(V2.8.1支持加速度),因此效果可能不好,画面闪烁同理。 * 如需在勇士自由行动时反复执行,请使用并行脚本或自我回调。 diff --git a/_server/CodeMirror/defs.js b/_server/CodeMirror/defs.js index 1a5f1c57..9ecbfc5a 100644 --- a/_server/CodeMirror/defs.js +++ b/_server/CodeMirror/defs.js @@ -2239,9 +2239,9 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [ "!doc": "半自动寻路,用于鼠标或手指拖动
例如:core.setAutomaticRoute(0, 0, [{direction: \"right\", x: 4, y: 9}, {direction: \"right\", x: 5, y: 9}]);
destX: 鼠标或手指的起拖点横坐标
destY: 鼠标或手指的起拖点纵坐标
stepPostfix: 拖动轨迹的数组表示,每项为一步的方向和目标点。", "!type": "fn(destX: number, destY: number, stepPostfix: [{x: number, y: number, direction: string}])" }, - "triggerHero": { - "!doc": "改变勇士的显隐状态", - "!type": "fn(type?: string, time?: number, callback?: fn())" + "setHeroOpacity": { + "!doc": "改变勇士的不透明度", + "!type": "fn(opacity?: number, moveMode?: string, time?: number, callback?: fn())" }, "gatherFollowers": { "!doc": "立刻聚集所有的跟随者", diff --git a/_server/MotaAction.g4 b/_server/MotaAction.g4 index fb846fdd..57ff4cb0 100644 --- a/_server/MotaAction.g4 +++ b/_server/MotaAction.g4 @@ -847,8 +847,7 @@ action | update_s | showStatusBar_s | hideStatusBar_s - | showHero_s - | hideHero_s + | setHeroOpacity_s | sleep_s | wait_s | waitAsync_s @@ -1780,33 +1779,19 @@ var code = '{"type": "hideStatusBar"'+Bool_0+'},\n'; return code; */; -showHero_s - : '显示勇士' '动画时间' IntString? '不等待执行完毕' Bool Newline +setHeroOpacity_s + : '设置勇士不透明度' Number '渐变方式' MoveMode_List '动画时间' IntString? '不等待执行完毕' Bool Newline - -/* showHero_s -tooltip : showHero: 显示勇士 +/* setHeroOpacity_s +tooltip : setHeroOpacity: 设置勇士不透明度 helpUrl : /_docs/#/instruction -default : ['',false] +default : [1,'','',false] colour : this.soundColor +if (Number_0 < 0 || Number_0 > 1) throw new Error('不透明度需要在0~1之间'); +MoveMode_List_0 = (MoveMode_List_0!=='') ? (', "moveMode": "'+MoveMode_List_0+'"'):''; IntString_0 = IntString_0 && (', "time": ' + IntString_0); Bool_0 = Bool_0 ? (', "async": true') : ''; -var code = '{"type": "showHero"'+IntString_0+Bool_0+'},\n'; -return code; -*/; - -hideHero_s - : '隐藏勇士' '动画时间' IntString? '不等待执行完毕' Bool Newline - - -/* hideHero_s -tooltip : hideHero: 隐藏勇士 -helpUrl : /_docs/#/instruction -default : ['',false] -colour : this.soundColor -IntString_0 = IntString_0 && (', "time": ' + IntString_0); -Bool_0 = Bool_0 ? (', "async": true') : ''; -var code = '{"type": "hideHero"'+IntString_0+Bool_0+'},\n'; +var code = '{"type": "setHeroOpacity", "opacity": '+Number_0+MoveMode_List_0+IntString_0+Bool_0+'},\n'; return code; */; diff --git a/_server/MotaActionParser.js b/_server/MotaActionParser.js index 3f9d6193..34937f6f 100644 --- a/_server/MotaActionParser.js +++ b/_server/MotaActionParser.js @@ -931,13 +931,9 @@ ActionParser.prototype.parseAction = function() { this.next = MotaActionBlocks['hideStatusBar_s'].xmlText([ data.toolbox||false,this.next]); break; - case "showHero": - this.next = MotaActionBlocks['showHero_s'].xmlText([ - data.time, data.async||false, this.next]); - break; - case "hideHero": - this.next = MotaActionBlocks['hideHero_s'].xmlText([ - data.time, data.async||false, this.next]); + case "setHeroOpacity": + this.next = MotaActionBlocks['setHeroOpacity_s'].xmlText([ + data.opacity, data.moveMode, data.time, data.async||false, this.next]); break; case "sleep": // 等待多少毫秒 this.next = MotaActionBlocks['sleep_s'].xmlText([ diff --git a/_server/editor_blocklyconfig.js b/_server/editor_blocklyconfig.js index f460ac4b..c1945512 100644 --- a/_server/editor_blocklyconfig.js +++ b/_server/editor_blocklyconfig.js @@ -204,8 +204,7 @@ editor_blocklyconfig=(function(){ MotaActionBlocks['lockViewport_s'].xmlText(), MotaActionBlocks['showStatusBar_s'].xmlText(), MotaActionBlocks['hideStatusBar_s'].xmlText(), - MotaActionBlocks['showHero_s'].xmlText(), - MotaActionBlocks['hideHero_s'].xmlText(), + MotaActionBlocks['setHeroOpacity_s'].xmlText(), MotaActionBlocks['setCurtain_0_s'].xmlText(), MotaActionBlocks['setCurtain_1_s'].xmlText(), MotaActionBlocks['screenFlash_s'].xmlText(), diff --git a/extensions/localSave.js b/extensions/localSave.js index 455b36ce..67071201 100644 --- a/extensions/localSave.js +++ b/extensions/localSave.js @@ -38,8 +38,10 @@ fs.deleteFile('_saves/' + name, callback); } - core.utils.clearLocalForage = function (name, callback) { - // Nothing to do + core.utils.clearLocalForage = function (callback) { + fs.deleteFile('_saves', function () { + fs.mkdir('_saves', callback); + }) } core.utils.iterateLocalForage = function (iter, callback) { diff --git a/libs/actions.js b/libs/actions.js index 0cfa4d37..f6cb78ea 100644 --- a/libs/actions.js +++ b/libs/actions.js @@ -2819,6 +2819,7 @@ actions.prototype._clickStorageRemove_all = function () { core.saves.autosave.data = null; core.saves.autosave.updated = false; core.saves.autosave.now = 0; + core.saves.cache = {}; core.ui.closePanel(); core.saves.saveIndex = 1; core.saves.favorite = []; diff --git a/libs/control.js b/libs/control.js index 3c6e2084..e61bc095 100644 --- a/libs/control.js +++ b/libs/control.js @@ -838,9 +838,7 @@ control.prototype.drawHero = function (status, offset, frame) { this._drawHero_updateViewport(x, y, offset); } - if (!core.hasFlag('hideHero')) { - this._drawHero_draw(direction, x, y, status, offset, frame); - } + this._drawHero_draw(direction, x, y, status, offset, frame); } control.prototype._drawHero_updateViewport = function (x, y, offset) { @@ -851,11 +849,13 @@ control.prototype._drawHero_updateViewport = function (x, y, offset) { control.prototype._drawHero_draw = function (direction, x, y, status, offset, frame) { offset = offset || {x: 0, y: 0, offset: 0, px: 0, py: 0}; + var opacity = core.setAlpha('hero', core.getFlag('__heroOpacity__', 1)) this._drawHero_getDrawObjs(direction, x, y, status, offset).forEach(function (block) { core.drawImage('hero', block.img, (block.heroIcon[block.status] + (frame || 0))%4*block.width, block.heroIcon.loc * block.height, block.width, block.height, block.posx+(32-block.width)/2, block.posy+32-block.height, block.width, block.height); }); + core.setAlpha('hero', opacity); } control.prototype._drawHero_getDrawObjs = function (direction, x, y, status, offset) { @@ -889,40 +889,28 @@ control.prototype._drawHero_getDrawObjs = function (direction, x, y, status, off }); } -control.prototype.triggerHero = function (type, time, callback) { - if (type == null) { - type = core.hasFlag('hideHero') ? 'show' : 'hide'; - } - if ((core.hasFlag('hideHero') && type != 'show') || (!core.hasFlag('hideHero') && type != 'hide')) { - if (callback) callback(); - return; - } - core.removeFlag('hideHero'); - - var cb = function () { - if (type == 'hide') core.setFlag('hideHero', true); - core.drawHero(); - if (callback) callback(); - return; - } - +control.prototype.setHeroOpacity = function (opacity, moveMode, time, callback) { time = time || 0; - if (time == 0) return cb(); - time /= Math.max(core.status.replay.speed, 1) - this._triggerHero_animate(type, 10 / time, cb); -} - -control.prototype._triggerHero_animate = function (type, delta, callback) { - var opacity = type != 'show' ? 1 : 0; - var animate = setInterval(function () { - opacity += type != 'show' ? -delta : delta; - core.setAlpha('hero', opacity); + if (time == 0) { + core.setFlag('__heroOpacity__', opacity); core.drawHero(); - core.setAlpha('hero', 1); - if (opacity >= 1 || opacity <= 0) { + if (callback) callback(); + return; + } + time /= Math.max(core.status.replay.speed, 1) + + var fromOpacity = core.getFlag('__heroOpacity__', 1); + var step = 0, steps = parseInt(time / 10); + if (steps <= 0) steps = 1; + var moveFunc = core.applyEasing(moveMode); + + var animate = setInterval(function () { + step++; + core.setFlag('__heroOpacity__', fromOpacity + (opacity - fromOpacity) * moveFunc(step / steps)); + core.drawHero(); + if (step == steps) { delete core.animateFrame.asyncId[animate]; clearInterval(animate); - core.drawHero(); if (callback) callback(); } }, 10); diff --git a/libs/events.js b/libs/events.js index 1ac07c1d..0cf4023d 100644 --- a/libs/events.js +++ b/libs/events.js @@ -2346,22 +2346,22 @@ events.prototype._action_hideStatusBar = function (data, x, y, prefix) { } events.prototype._action_showHero = function (data, x, y, prefix) { - data.time = data.time || 0; - if (data.time > 0) { - this.__action_doAsyncFunc(data.async, core.triggerHero, 'show', data.time); - } else { - core.removeFlag('hideHero'); - core.drawHero(); - core.doAction(); - } + data.opacity = 1; + return this._action_setHeroOpacity(data, x, y, prefix); } events.prototype._action_hideHero = function (data, x, y, prefix) { + data.opacity = 0; + return this._action_setHeroOpacity(data, x, y, prefix); +} + +events.prototype._action_setHeroOpacity = function (data, x, y, prefix) { data.time = data.time || 0; + if (data.opacity == null) data.opacity = 1; if (data.time > 0) { - this.__action_doAsyncFunc(data.async, core.triggerHero, 'hide', data.time); + this.__action_doAsyncFunc(data.async, core.setHeroOpacity, data.opacity, data.moveMode, data.time); } else { - core.setFlag('hideHero', true); + core.setFlag('__heroOpacity__', data.opacity); core.drawHero(); core.doAction(); } diff --git a/libs/maps.js b/libs/maps.js index 5663e92e..5b6b5798 100644 --- a/libs/maps.js +++ b/libs/maps.js @@ -968,9 +968,9 @@ maps.prototype._getBigImageInfo = function (bigImage, face, animate) { } var dx, dy; switch (face) { - case "down": case "up": dx = 16 - per_width / 2; dy = 32 - per_height; break; - case "left": dx = 0; dy = 32 - per_height; break; - case "right": dx = 32 - per_width; dy = 32 - per_height; break; + case "down": case "up": case "left": case "right": dx = 16 - per_width / 2; dy = 32 - per_height; break; + // case "left": dx = 0; dy = 32 - per_height; break; + // case "right": dx = 32 - per_width; dy = 32 - per_height; break; } return {sx: sx, sy: sy, per_width: per_width, per_height: per_height, face: face, dx: dx, dy: dy}; @@ -1033,7 +1033,7 @@ maps.prototype._drawBlockInfo_bigImage = function (blockInfo, x, y, ctx) { var dx = bigImageInfo.dx, dy = bigImageInfo.dy; switch (bigImageInfo.face) { - case "down": case "up": + case "down": case "up": case "left": case "right": core.createCanvas(header, px + dx, py + dy, per_width, -dy, 51); this._drawBlockInfo_drawWithFilter(blockInfo, header, function () { core.drawImage(header, bigImage, sx, sy, per_width, -dy, 0, 0, per_width, -dy); @@ -1043,7 +1043,7 @@ maps.prototype._drawBlockInfo_bigImage = function (blockInfo, x, y, ctx) { core.drawImage(body, bigImage, sx, sy - dy, per_width, 32, 0, 0, per_width, 32); }) break; - case "left": + /*case "left": core.createCanvas(header, px + dx, py + dy, per_width, -dy, 51); this._drawBlockInfo_drawWithFilter(blockInfo, header, function () { core.drawImage(header, bigImage, sx, sy, per_width, -dy, 0, 0, per_width, -dy); @@ -1062,7 +1062,7 @@ maps.prototype._drawBlockInfo_bigImage = function (blockInfo, x, y, ctx) { this._drawBlockInfo_drawWithFilter(blockInfo, body, function () { core.drawImage(body, bigImage, sx, sy - dy, per_width, 32, 0, 0, per_width, 32); }); - break; + break;*/ } if (core.dymCanvas[header]) { core.dymCanvas[header].canvas.setAttribute('_ox', 32 * x + dx); diff --git a/runtime.d.ts b/runtime.d.ts index d1cf7de3..57c9ee7b 100644 --- a/runtime.d.ts +++ b/runtime.d.ts @@ -638,8 +638,8 @@ declare class control { /** 瞬间移动 */ moveDirectly(destX?: any, destY?: any, ignoreSteps?: any): void - /** 改变勇士的显隐状态 */ - triggerHero(type?: 'show' | 'hide', time?: any, callback?: () => any): void + /** 改变勇士的不透明度 */ + setHeroOpacity(opacity?: number, moveMode?: string, time?: any, callback?: () => any): void /** 加减画布偏移 */ addGameCanvasTranslate(x?: number, y?: number): void From c3e1d2f7b40a399e5a52c11add8cb9d51b26c88f Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Tue, 31 Aug 2021 19:58:04 +0800 Subject: [PATCH 31/60] Tiny fix --- _server/MotaAction.g4 | 4 ++-- _server/editor_blocklyconfig.js | 18 +----------------- libs/utils.js | 2 ++ project/items.js | 2 +- 4 files changed, 6 insertions(+), 20 deletions(-) diff --git a/_server/MotaAction.g4 b/_server/MotaAction.g4 index 57ff4cb0..07105cb2 100644 --- a/_server/MotaAction.g4 +++ b/_server/MotaAction.g4 @@ -4060,8 +4060,8 @@ Direction_List /*Direction_List ['up','down','left','right']*/; DirectionEx_List - : '不变'|'朝上'|'朝下'|'朝左'|'朝右'|'左转'|'右转'|'背对' - /*DirectionEx_List ['null','up','down','left','right',':left',':right',':back']*/; + : '不变'|'朝上'|'朝下'|'朝左'|'朝右'|'左转'|'右转'|'背对'|'面对角色'|'背对角色' + /*DirectionEx_List ['null','up','down','left','right',':left',':right',':back',':hero',':backhero']*/; StepString : (Direction_List Int?)+ diff --git a/_server/editor_blocklyconfig.js b/_server/editor_blocklyconfig.js index c1945512..8ee847dd 100644 --- a/_server/editor_blocklyconfig.js +++ b/_server/editor_blocklyconfig.js @@ -361,23 +361,7 @@ editor_blocklyconfig=(function(){ } ] } - ], 'event'), - '', - MotaActionFunctions.actionParser.parse({ - "trigger": "action", - "displayDamage": true, - "data": [ - ' ... 战前剧情', - {"type": "battle", "id": "greenSlime"}, - ' ... 战后剧情;请注意上面的强制战斗不会使怪物消失', - '需要下一句来调用{"type": "hide"}来隐藏事件', - {"type": "hide"}, - ] - },'event'), - '', - MotaActionFunctions.actionParser.parse([ - {"type": "function", "function": "function(){var x=core.status.event.data.x,y=core.status.event.data.y;if(core.isset(x)&&core.isset(y)){core.insertAction([{type:'hide',loc:[[x-1,y-2],[x,y-2],[x+1,y-2],[x-1,y-1],[x,y-1],[x+1,y-1],[x-1,y],[x+1,y]]}]);}}"}, - ],'afterBattle'), + ], 'event'), '', MotaActionFunctions.actionParser.parse([ { diff --git a/libs/utils.js b/libs/utils.js index b85395b9..89428532 100644 --- a/libs/utils.js +++ b/libs/utils.js @@ -864,6 +864,8 @@ utils.prototype.turnDirection = function (turn, direction) { direction = direction || core.getHeroLoc('direction'); var directionList = ["left", "leftup", "up", "rightup", "right", "rightdown", "down", "leftdown"]; if (directionList.indexOf(turn) >= 0) return turn; + if (turn == ':hero') return this.turnDirection(':back', core.getHeroLoc('direction')); + if (turn == ':backhero') return core.getHeroLoc('direction'); if (typeof turn === 'number' && turn % 45 == 0) turn /= 45; else { switch (turn) { diff --git a/project/items.js b/project/items.js index 6c2b4665..d7ba487a 100644 --- a/project/items.js +++ b/project/items.js @@ -382,7 +382,7 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a = "cls": "tools", "name": "炸弹", "text": "可以炸掉勇士面前的怪物", - "useItemEffect": "(function () {\n\tvar bombList = []; // 炸掉的怪物坐标列表\n\tvar todo = []; // 炸弹后事件\n\tvar money = 0,\n\t\texp = 0; // 炸弹获得的金币和经验\n\n\tvar canBomb = function (x, y) {\n\t\tvar block = core.getBlock(x, y);\n\t\tif (block == null || block.disable || block.event.cls.indexOf('enemy') != 0) return false;\n\t\tvar enemy = core.material.enemys[block.event.id];\n\t\treturn enemy && !enemy.notBomb;\n\t};\n\n\tvar bomb = function (x, y) {\n\t\tif (!canBomb(x, y)) return;\n\t\tbombList.push([x, y]);\n\t\tvar id = core.getBlockId(x, y),\n\t\t\tenemy = core.material.enemys[id];\n\t\tmoney += core.getEnemyValue(enemy, 'money', x, y) || 0;\n\t\texp += core.getEnemyValue(enemy, 'exp', x, y) || 0;\n\t\tcore.push(todo, core.floors[core.status.floorId].afterBattle[x + \",\" + y]);\n\t\tcore.push(todo, enemy.afterBattle);\n\t\tcore.removeBlock(x, y);\n\t}\n\n\t// 如果要多方向可炸,把这里的false改成true\n\tif (false) {\n\t\tvar scan = core.utils.scan; // 多方向炸时默认四方向,如果要改成八方向炸可以改成 core.utils.scan2\n\t\tfor (var direction in scan) {\n\t\t\tvar delta = scan[direction];\n\t\t\tbomb(core.getHeroLoc('x') + delta.x, core.getHeroLoc('y') + delta.y);\n\t\t}\n\t} else {\n\t\t// 仅炸当前\n\t\tbomb(core.nextX(), core.nextY());\n\t}\n\n\tif (bomb.length == 0) {\n\t\tcore.playSound('操作失败');\n\t\tcore.drawTip('当前无法使用' + core.material.items[itemId].name, itemId);\n\t\tcore.addItem(itemId, 1);\n\t\treturn;\n\t}\n\n\tcore.playSound('炸弹');\n\tcore.drawTip(core.material.items[itemId].name + '使用成功', itemId);\n\n\t// 取消这里的注释可以炸弹后获得金币和经验\n\t// core.status.hero.money += money;\n\t// core.status.hero.exp += exp;\n\n\t// 取消这里的注释可以炸弹引发战后事件\n\t// if (todo.length > 0) core.insertAction(todo);\n\n})();", + "useItemEffect": "(function () {\n\tvar bombList = []; // 炸掉的怪物坐标列表\n\tvar todo = []; // 炸弹后事件\n\tvar money = 0,\n\t\texp = 0; // 炸弹获得的金币和经验\n\n\tvar canBomb = function (x, y) {\n\t\tvar block = core.getBlock(x, y);\n\t\tif (block == null || block.disable || block.event.cls.indexOf('enemy') != 0) return false;\n\t\tvar enemy = core.material.enemys[block.event.id];\n\t\treturn enemy && !enemy.notBomb;\n\t};\n\n\tvar bomb = function (x, y) {\n\t\tif (!canBomb(x, y)) return;\n\t\tbombList.push([x, y]);\n\t\tvar id = core.getBlockId(x, y),\n\t\t\tenemy = core.material.enemys[id];\n\t\tmoney += core.getEnemyValue(enemy, 'money', x, y) || 0;\n\t\texp += core.getEnemyValue(enemy, 'exp', x, y) || 0;\n\t\tcore.push(todo, core.floors[core.status.floorId].afterBattle[x + \",\" + y]);\n\t\tcore.push(todo, enemy.afterBattle);\n\t\tcore.removeBlock(x, y);\n\t}\n\n\t// 如果要多方向可炸,把这里的false改成true\n\tif (false) {\n\t\tvar scan = core.utils.scan; // 多方向炸时默认四方向,如果要改成八方向炸可以改成 core.utils.scan2\n\t\tfor (var direction in scan) {\n\t\t\tvar delta = scan[direction];\n\t\t\tbomb(core.getHeroLoc('x') + delta.x, core.getHeroLoc('y') + delta.y);\n\t\t}\n\t} else {\n\t\t// 仅炸当前\n\t\tbomb(core.nextX(), core.nextY());\n\t}\n\n\tif (bombList.length == 0) {\n\t\tcore.playSound('操作失败');\n\t\tcore.drawTip('当前无法使用' + core.material.items[itemId].name, itemId);\n\t\tcore.addItem(itemId, 1);\n\t\treturn;\n\t}\n\n\tcore.playSound('炸弹');\n\tcore.drawTip(core.material.items[itemId].name + '使用成功', itemId);\n\n\t// 取消这里的注释可以炸弹后获得金币和经验\n\t// core.status.hero.money += money;\n\t// core.status.hero.exp += exp;\n\n\t// 取消这里的注释可以炸弹引发战后事件\n\t// if (todo.length > 0) core.insertAction(todo);\n\n})();", "canUseItemEffect": "true" }, "centerFly": { From bf4c63a5147f2918ce7a57da81bb0889ee05fe7f Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Tue, 31 Aug 2021 20:14:25 +0800 Subject: [PATCH 32/60] =?UTF-8?q?=E5=AF=B9=E8=AF=9D=E6=A1=86=E4=B8=8D?= =?UTF-8?q?=E7=AD=89=E5=BE=85=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _server/MotaAction.g4 | 12 +++++++----- _server/MotaActionParser.js | 4 ++-- _server/editor_blockly.js | 2 +- libs/events.js | 10 ++++++++-- libs/ui.js | 2 +- 5 files changed, 19 insertions(+), 11 deletions(-) diff --git a/_server/MotaAction.g4 b/_server/MotaAction.g4 index 07105cb2..8b824a50 100644 --- a/_server/MotaAction.g4 +++ b/_server/MotaAction.g4 @@ -968,7 +968,7 @@ return code+',\n'; */; text_1_s - : '标题' EvalString? '图像' EvalString? '对话框效果' EvalString? '起点像素 px' PosString? 'py' PosString? '宽度' PosString? '对话框编号' Int BGNL? Newline EvalString_Multi Newline + : '标题' EvalString? '图像' EvalString? '对话框效果' EvalString? '起点 px' PosString? 'py' PosString? '宽' PosString? '编号' Int '不等待操作' Bool BGNL? Newline EvalString_Multi Newline /* text_1_s @@ -976,7 +976,7 @@ tooltip : text:显示一段文字(剧情),选项较多请右键点击帮 helpUrl : /_docs/#/instruction previewBlock : true allIds : ['EvalString_1'] -default : ["小妖精","fairy","","","","",0,"欢迎使用事件编辑器(双击方块可直接预览)"] +default : ["小妖精","fairy","","","","",0,false,"欢迎使用事件编辑器(双击方块可直接预览)"] var title=''; if (EvalString_0==''){ if (EvalString_1=='' )title=''; @@ -997,10 +997,11 @@ if(EvalString_2 && !(/^(up|center|down|hero|this)(,(hero|null|\d+,\d+|\d+))?$/.t } EvalString_2 = EvalString_2 && ('\\b['+EvalString_2+']'); var code = '"'+title+EvalString_2+EvalString_Multi_0+'"'; -if (block.isCollapsed() || !block.isEnabled() || pos || Int_0) { +if (block.isCollapsed() || !block.isEnabled() || pos || Int_0 || Bool_0) { code = '{"type": "text", "text": '+code; if (pos) code += ', "pos": ' + pos; if (Int_0) code += ', "code": ' + Int_0; + if (Bool_0) code += ', "async": true'; if (block.isCollapsed()) code += ', "_collapsed": true'; if (!block.isEnabled()) code += ', "_disabled": true'; code += '}'; @@ -1009,7 +1010,7 @@ return code+',\n'; */; text_2_s - : '标题' EvalString? '图像' EvalString? '对话框效果' EvalString? '起点像素 px' PosString? 'py' PosString? '宽度' PosString? '对话框编号' Int BGNL? Newline EvalString_Multi BGNL? Newline textDrawingList* Newline + : '标题' EvalString? '图像' EvalString? '对话框效果' EvalString? '起点 px' PosString? 'py' PosString? '宽' PosString? '编号' Int '不等待操作' Bool BGNL? Newline EvalString_Multi BGNL? Newline textDrawingList* Newline /* text_2_s @@ -1038,10 +1039,11 @@ if(EvalString_2 && !(/^(up|center|down|hero|this)(,(hero|null|\d+,\d+|\d+))?$/.t } EvalString_2 = EvalString_2 && ('\\b['+EvalString_2+']'); var code = '"'+title+EvalString_2+textDrawingList_0.replace(/\s/g, '')+EvalString_Multi_0+'"'; -if (block.isCollapsed() || !block.isEnabled() || pos || Int_0) { +if (block.isCollapsed() || !block.isEnabled() || pos || Int_0 || Bool_0) { code = '{"type": "text", "text": '+code; if (pos) code += ', "pos": ' + pos; if (Int_0) code += ', "code": ' + Int_0; + if (Bool_0) code += ', "async": true'; if (block.isCollapsed()) code += ', "_collapsed": true'; if (!block.isEnabled()) code += ', "_disabled": true'; code += '}'; diff --git a/_server/MotaActionParser.js b/_server/MotaActionParser.js index 34937f6f..aa2801b5 100644 --- a/_server/MotaActionParser.js +++ b/_server/MotaActionParser.js @@ -292,12 +292,12 @@ ActionParser.prototype.parseAction = function() { } data.pos = data.pos || []; this.next = MotaActionFunctions.xmlText('text_2_s', [ - info[0], info[1], info[2], data.pos[0], data.pos[1], data.pos[2], data.code||0, info[3], buildTextDrawing(textDrawing), this.next + info[0], info[1], info[2], data.pos[0], data.pos[1], data.pos[2], data.code||0, data.async||false, info[3], buildTextDrawing(textDrawing), this.next ], /* isShadow */false, /*comment*/ null, /*collapsed*/ data._collapsed, /*disabled*/ data._disabled); } else if (info[0] || info[1] || info[2] || data.pos || data.code) { data.pos = data.pos || []; this.next = MotaActionFunctions.xmlText('text_1_s',[ - info[0], info[1], info[2], data.pos[0], data.pos[1], data.pos[2], data.code||0, info[3], this.next], /* isShadow */false, /*comment*/ null, /*collapsed*/ data._collapsed, /*disabled*/ data._disabled); + info[0], info[1], info[2], data.pos[0], data.pos[1], data.pos[2], data.code||0, data.async||false, info[3], this.next], /* isShadow */false, /*comment*/ null, /*collapsed*/ data._collapsed, /*disabled*/ data._disabled); } else { this.next = MotaActionFunctions.xmlText('text_0_s', [info[3],this.next], diff --git a/_server/editor_blockly.js b/_server/editor_blockly.js index 7c477ff9..37937512 100644 --- a/_server/editor_blockly.js +++ b/_server/editor_blockly.js @@ -244,7 +244,7 @@ editor_blockly = function () { } } if (one.type == 'previewUI' && this.checkAsync(one.action)) return true; - if (one.async && one.type != 'animate' && one.type != 'function') hasAsync = true; + if (one.async && one.type != 'animate' && one.type != 'function' && one.type != 'text') hasAsync = true; if (one.type == 'waitAsync') hasAsync = false; } return hasAsync; diff --git a/libs/events.js b/libs/events.js index 0cf4023d..7abf9227 100644 --- a/libs/events.js +++ b/libs/events.js @@ -1359,12 +1359,18 @@ events.prototype._action_text = function (data, x, y, prefix) { if (core.getContextByName(ctx) && !data.showAll) { core.ui._animateUI('hide', ctx, function () { core.ui.drawTextBox(data.text, data); - core.ui._animateUI('show', ctx); + core.ui._animateUI('show', ctx, function () { + if (data.async) core.doAction(); + }); }); return; } core.ui.drawTextBox(data.text, data); - if (!data.showAll) core.ui._animateUI('show', ctx); + if (!data.showAll) { + core.ui._animateUI('show', ctx, function () { + if (data.async) core.doAction(); + }); + } } events.prototype._action_moveTextBox = function (data, x, y, prefix) { diff --git a/libs/ui.js b/libs/ui.js index f2886cf5..14439aa7 100644 --- a/libs/ui.js +++ b/libs/ui.js @@ -1463,7 +1463,7 @@ ui.prototype.drawTextBox = function(content, config) { // Step 5: 绘制正文 var config = this.drawTextContent(config.ctx || 'ui', content, { left: hPos.content_left, top: content_top, maxWidth: hPos.validWidth, - lineHeight: vPos.lineHeight, time: (config.showAll || textAttribute.time<=0 || core.status.event.id!='action')?0:textAttribute.time + lineHeight: vPos.lineHeight, time: (config.showAll || config.async || textAttribute.time<=0 || core.status.event.id!='action')?0:textAttribute.time }); // Step 6: 绘制光标 From 742f2c9fb05c385a5672e2fe3c3fdce8bb999785 Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Tue, 31 Aug 2021 20:22:57 +0800 Subject: [PATCH 33/60] fix turn --- _server/MotaAction.g4 | 2 +- libs/utils.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/_server/MotaAction.g4 b/_server/MotaAction.g4 index 8b824a50..f9d8374e 100644 --- a/_server/MotaAction.g4 +++ b/_server/MotaAction.g4 @@ -4062,7 +4062,7 @@ Direction_List /*Direction_List ['up','down','left','right']*/; DirectionEx_List - : '不变'|'朝上'|'朝下'|'朝左'|'朝右'|'左转'|'右转'|'背对'|'面对角色'|'背对角色' + : '不变'|'朝上'|'朝下'|'朝左'|'朝右'|'左转'|'右转'|'背对'|'角色同向'|'角色反向' /*DirectionEx_List ['null','up','down','left','right',':left',':right',':back',':hero',':backhero']*/; StepString diff --git a/libs/utils.js b/libs/utils.js index 89428532..0aafd4fd 100644 --- a/libs/utils.js +++ b/libs/utils.js @@ -864,8 +864,8 @@ utils.prototype.turnDirection = function (turn, direction) { direction = direction || core.getHeroLoc('direction'); var directionList = ["left", "leftup", "up", "rightup", "right", "rightdown", "down", "leftdown"]; if (directionList.indexOf(turn) >= 0) return turn; - if (turn == ':hero') return this.turnDirection(':back', core.getHeroLoc('direction')); - if (turn == ':backhero') return core.getHeroLoc('direction'); + if (turn == ':hero') return core.getHeroLoc('direction'); + if (turn == ':backhero') return this.turnDirection(':back', core.getHeroLoc('direction')); if (typeof turn === 'number' && turn % 45 == 0) turn /= 45; else { switch (turn) { From 5b3621313125c9afdba61e2e722589c8561dacb7 Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Tue, 31 Aug 2021 20:28:44 +0800 Subject: [PATCH 34/60] Add editor_uievent --- _server/editor.js | 1 + _server/editor_ui.js | 934 -------------------------------------- _server/editor_uievent.js | 934 ++++++++++++++++++++++++++++++++++++++ editor-mobile.html | 1 + editor.html | 1 + 5 files changed, 937 insertions(+), 934 deletions(-) create mode 100644 _server/editor_uievent.js diff --git a/_server/editor.js b/_server/editor.js index df10f614..fbbd9e6b 100644 --- a/_server/editor.js +++ b/_server/editor.js @@ -207,6 +207,7 @@ editor.prototype.init = function (callback) { editor_file_wrapper(editor); editor_table_wrapper(editor); editor_ui_wrapper(editor); + editor_uievent_wrapper(editor); editor_mappanel_wrapper(editor); editor_datapanel_wrapper(editor); editor_materialpanel_wrapper(editor); diff --git a/_server/editor_ui.js b/_server/editor_ui.js index fc960d86..4035d872 100644 --- a/_server/editor_ui.js +++ b/_server/editor_ui.js @@ -336,938 +336,4 @@ editor_ui_wrapper = function (editor) { "双击事件编辑器:长文本编辑/脚本编辑/地图选点/UI绘制预览" ); } - - - // ------ UI预览 & 地图选点相关 ------ // - - var uievent = { - elements: {}, - values: {}, - isOpen: false, - mode: "" - }; - - uievent.elements.div = document.getElementById('uieventDiv'); - uievent.elements.title = document.getElementById('uieventTitle'); - uievent.elements.yes = document.getElementById('uieventYes'); - uievent.elements.no = document.getElementById('uieventNo'); - uievent.elements.selectBackground = document.getElementById('uieventBackground'); - uievent.elements.selectPoint = document.getElementById('selectPoint'); - uievent.elements.selectFloor = document.getElementById('selectPointFloor'); - uievent.elements.selectPointBox = document.getElementById('selectPointBox'); - uievent.elements.body = document.getElementById('uieventBody'); - uievent.elements.selectPointButtons = document.getElementById('selectPointButtons'); - uievent.elements.canvas = document.getElementById('uievent'); - uievent.elements.usedFlags = document.getElementById('uieventUsedFlags'); - uievent.elements.extraBody = document.getElementById('uieventExtraBody'); - - uievent.close = function () { - uievent.isOpen = false; - uievent.elements.div.style.display = 'none'; - if (uievent.values.interval) { - clearTimeout(uievent.values.interval); - clearInterval(uievent.values.interval); - } - uievent.values = {}; - } - uievent.elements.no.onclick = uievent.close; - - uievent.elements.selectBackground.onchange = function () { - uievent.drawPreviewUI(); - } - - uievent.drawPreviewUI = function () { - core.setAlpha('uievent', 1); - core.clearMap('uievent'); - core.setFilter('uievent', null); - - // 绘制UI - var background = uievent.elements.selectBackground.value; - if (background == 'thumbnail') { - core.drawThumbnail(editor.currentFloorId, null, {ctx: 'uievent'}); - } - else { - core.fillRect('uievent', 0, 0, core.__PIXELS__, core.__PIXELS__, background); - } - - if (uievent.values.list instanceof Array) { - uievent.values.list.forEach(function (data) { - if (typeof data == 'string') data = { "type": "text", "text": data }; - var type = data.type; - if (type == "text") { - data.ctx = 'uievent'; - core.saveCanvas('uievent'); - core.drawTextBox(data.text, data); - core.loadCanvas('uievent'); - return; - } - else if (type == "choices") { - for (var i = 0; i < data.choices.length; i++) { - if (typeof data.choices[i] === 'string') - data.choices[i] = {"text": data.choices[i]}; - data.choices[i].text = core.replaceText(data.choices[i].text); - } - core.saveCanvas('uievent'); - core.status.event.selection = data.selected || 0; - core.drawChoices(core.replaceText(data.text), data.choices, data.width, 'uievent'); - core.status.event.selection = null; - core.loadCanvas('uievent'); - return; - } else if (type == "confirm") { - core.saveCanvas('uievent'); - core.drawConfirmBox(data.text, null, null, 'uievent'); - core.loadCanvas('uievent'); - } else if (core.ui["_uievent_" + type]) - core.ui["_uievent_" + type](data); - }) - } - } - - uievent.previewUI = function (list) { - uievent.isOpen = true; - uievent.elements.div.style.display = 'block'; - uievent.mode = 'previewUI'; - uievent.elements.selectPoint.style.display = 'none'; - uievent.elements.yes.style.display = 'none'; - uievent.elements.title.innerText = 'UI绘制预览'; - uievent.elements.selectBackground.style.display = 'inline'; - uievent.elements.selectBackground.value = 'thumbnail'; - uievent.elements.selectFloor.style.display = 'none'; - uievent.elements.selectPointBox.style.display = 'none'; - uievent.elements.canvas.style.display = 'block'; - uievent.elements.usedFlags.style.display = 'none'; - uievent.elements.extraBody.style.display = 'none'; - uievent.elements.body.style.overflow = "hidden"; - - uievent.values.list = list; - uievent.drawPreviewUI(); - } - - uievent.selectPoint = function (floorId, x, y, bigmap, callback) { - uievent.values.bigmap = bigmap; - uievent.values.size = editor.isMobile ? window.innerWidth / core.__SIZE__ : 32; - - uievent.isOpen = true; - uievent.elements.div.style.display = 'block'; - uievent.mode = 'selectPoint'; - uievent.elements.selectPoint.style.display = 'block'; - uievent.elements.yes.style.display = 'inline'; - uievent.elements.selectBackground.style.display = 'none'; - uievent.elements.selectFloor.style.display = 'inline'; - uievent.elements.selectPointBox.style.display = 'block'; - uievent.elements.canvas.style.display = 'block'; - uievent.elements.usedFlags.style.display = 'none'; - uievent.elements.extraBody.style.display = 'none'; - uievent.elements.body.style.overflow = "hidden"; - uievent.elements.yes.onclick = function () { - var floorId = uievent.values.floorId, x = uievent.values.x, y = uievent.values.y; - var multipoints = uievent.values.multipoints || []; - uievent.close(); - if (callback) { - if (multipoints.length > 0) { - callback(floorId, multipoints.map(function (one) { return one.split(',')[0]}).join(','), - multipoints.map(function (one) { return one.split(',')[1]}).join(',')); - } else { - callback(floorId, x, y); - } - } - } - - // Append children - var floors = ""; - core.floorIds.forEach(function (f) { - floors += ""; - }) - uievent.elements.selectFloor.innerHTML = floors; - // 检查多选点 - if (/^\d+(,\d+)+$/.test(x) && /^\d+(,\d+)+$/.test(y)) { - var xx = x.split(','), yy = y.split(','); - uievent.values.multipoints = []; - for (var i = 0; i < xx.length; ++i) { - uievent.values.multipoints.push(xx[i] + "," + yy[i]); - } - x = xx[xx.length - 1]; - y = yy[yy.length - 1]; - } - this.setPoint(floorId || editor.currentFloorId, core.calValue(x) || 0, core.calValue(y) || 0); - } - - uievent.updateSelectPoint = function (redraw) { - uievent.elements.title.innerText = '地图选点【右键多选】 (' + uievent.values.x + "," + uievent.values.y + ')'; - // 计算size - uievent.values.boxSize = uievent.values.size * - (uievent.values.bigmap ? (core.__SIZE__ / Math.max(uievent.values.width, uievent.values.height)) : 1); - uievent.values.boxLeft = uievent.values.bigmap ? - (core.__PIXELS__ * Math.max(0, (1 - uievent.values.width / uievent.values.height) / 2)) : 0; - uievent.values.boxTop = uievent.values.bigmap ? - (core.__PIXELS__ * Math.max(0, (1 - uievent.values.height / uievent.values.width) / 2)) : 0; - - if (uievent.values.bigmap) { - uievent.elements.selectPointBox.style.left = uievent.values.boxSize * uievent.values.x + uievent.values.boxLeft + "px"; - uievent.elements.selectPointBox.style.top = uievent.values.boxSize * uievent.values.y + uievent.values.boxTop + "px"; - } else { - uievent.elements.selectPointBox.style.left = uievent.values.boxSize * (uievent.values.x - uievent.values.left) + "px"; - uievent.elements.selectPointBox.style.top = uievent.values.boxSize * (uievent.values.y - uievent.values.top) + "px"; - } - uievent.elements.selectPointBox.style.width = uievent.values.boxSize - 6 + "px"; - uievent.elements.selectPointBox.style.height = uievent.values.boxSize - 6 + "px"; - - if (redraw) { - core.setAlpha('uievent', 1); - core.clearMap('uievent'); - core.drawThumbnail(uievent.values.floorId, null, { - ctx: 'uievent', centerX: uievent.values.left + core.__HALF_SIZE__, - centerY: uievent.values.top + core.__HALF_SIZE__, all: uievent.values.bigmap - }); - uievent.values.multipoints = uievent.values.multipoints || []; - core.setTextAlign('uievent', 'right'); - for (var i = 0; i < uievent.values.multipoints.length; ++i) { - var xy = uievent.values.multipoints[i].split(","), x = parseInt(xy[0]), y = parseInt(xy[1]); - core.fillBoldText('uievent', i + 1, - 32 * (x - uievent.values.left) + 28 , 32 * (y - uievent.values.top) + 26, '#FF7F00', null, '14px Verdana'); - } - core.setTextAlign('uievent', 'left'); - } - } - - uievent.setPoint = function (floorId, x, y) { - if (core.floorIds.indexOf(floorId) == -1) floorId = editor.currentFloorId; - uievent.values.floorId = floorId; - uievent.elements.selectFloor.value = floorId; - uievent.values.x = x != null ? x : (uievent.values.x || 0); - uievent.values.y = y != null ? y : (uievent.values.y || 0); - uievent.values.width = core.floors[uievent.values.floorId].width || core.__SIZE__; - uievent.values.height = core.floors[uievent.values.floorId].height || core.__SIZE__; - uievent.values.left = core.clamp(uievent.values.x - core.__HALF_SIZE__, 0, uievent.values.width - core.__SIZE__); - uievent.values.top = core.clamp(uievent.values.y - core.__HALF_SIZE__, 0, uievent.values.height - core.__SIZE__); - uievent.updateSelectPoint(true); - } - - uievent.elements.selectFloor.onchange = function () { - uievent.values.multipoints = []; - uievent.setPoint(uievent.elements.selectFloor.value); - } - - uievent.elements.selectPointBox.onclick = function (e) { - e.preventDefault(); - e.stopPropagation(); - return false; - } - - uievent.elements.body.onclick = function (e) { - if (uievent.mode != 'selectPoint') return; - if (uievent.values.bigmap) { - uievent.values.x = core.clamp(Math.floor((e.offsetX - uievent.values.boxLeft) / uievent.values.boxSize), 0, uievent.values.width - 1); - uievent.values.y = core.clamp(Math.floor((e.offsetY - uievent.values.boxTop) / uievent.values.boxSize), 0, uievent.values.height - 1); - } else { - uievent.values.x = uievent.values.left + Math.floor(e.offsetX / uievent.values.size); - uievent.values.y = uievent.values.top + Math.floor(e.offsetY / uievent.values.size); - } - uievent.updateSelectPoint(false); - } - - uievent.elements.body.oncontextmenu = function (e) { - e.preventDefault(); - e.stopPropagation(); - if (uievent.mode != 'selectPoint' || uievent.values.bigmap) return; - var x = uievent.values.left + Math.floor(e.offsetX / uievent.values.size); - var y = uievent.values.top + Math.floor(e.offsetY / uievent.values.size); - uievent.values.multipoints = uievent.values.multipoints || []; - if (uievent.values.multipoints.indexOf(x+","+y) >= 0) { - uievent.values.multipoints = uievent.values.multipoints.filter(function (o) { return o != x+","+y;}) - } else { - uievent.values.multipoints.push(x+","+y); - } - uievent.values.x = x; - uievent.values.y = y; - uievent.updateSelectPoint(true); - return false; - } - - uievent.move = function (dx, dy) { - if (uievent.mode != 'selectPoint') return; - if (uievent.values.bigmap) return; - uievent.values.left = core.clamp(uievent.values.left + dx, 0, uievent.values.width - core.__SIZE__); - uievent.values.top = core.clamp(uievent.values.top + dy, 0, uievent.values.height - core.__SIZE__); - this.updateSelectPoint(true); - }; - - uievent.triggerBigmap = function () { - if (uievent.mode != 'selectPoint') return; - uievent.values.bigmap = !uievent.values.bigmap; - uievent.values.multipoints = []; - uievent.setPoint(uievent.values.floorId); - }; - - (function () { - - var viewportButtons = uievent.elements.selectPointButtons; - var pressTimer = null; - for (var ii = 0, node; node = viewportButtons.children[ii]; ii++) { - if (ii == 4) { - node.onclick = uievent.triggerBigmap; - continue; - } - if (ii == 5) { - node.onclick = function () { - alert(core.copy(uievent.values.floorId) ? ('楼层ID '+uievent.values.floorId+' 已成功复制到剪切板') : '无法复制楼层ID'); - } - } - (function (x, y) { - var move = function () { - uievent.move(x, y); - } - node.onmousedown = function () { - clearTimeout(pressTimer); - pressTimer = setTimeout(function () { - pressTimer = -1; - var f = function () { - if (pressTimer != null) { - move(); - setTimeout(f, 150); - } - } - f(); - }, 500); - }; - node.onmouseup = function () { - if (pressTimer > 0) { - clearTimeout(pressTimer); - move(); - } - pressTimer = null; - } - })([-1, 0, 0, 1][ii], [0, -1, 1, 0][ii]); - } - })(); - - uievent.elements.div.onmousewheel = function (e) { - if (uievent.mode != 'selectPoint') return; - var index = core.floorIds.indexOf(uievent.values.floorId); - try { - if (e.wheelDelta) - index += Math.sign(e.wheelDelta); - else if (e.detail) - index += Math.sign(e.detail); - } catch (ee) { main.log(ee); } - index = core.clamp(index, 0, core.floorIds.length - 1); - uievent.values.multipoints = []; - uievent.setPoint(core.floorIds[index]); - } - - uievent.onKeyDown = function (e) { - if (e.keyCode == 27) editor.uievent.close(); - if (uievent.mode == 'selectPoint') { - if (e.keyCode == 87) editor.uievent.move(0, -1) - if (e.keyCode == 65) editor.uievent.move(-1, 0) - if (e.keyCode == 83) editor.uievent.move(0, 1); - if (e.keyCode == 68) editor.uievent.move(1, 0); - } - } - - // ------ 搜索变量出现的位置,也放在uievent好了 ------ // - - uievent.searchUsedFlags = function () { - uievent.isOpen = true; - uievent.elements.div.style.display = 'block'; - uievent.mode = 'searchUsedFlags'; - uievent.elements.selectPoint.style.display = 'none'; - uievent.elements.yes.style.display = 'none'; - uievent.elements.title.innerText = '搜索变量'; - uievent.elements.selectBackground.style.display = 'none'; - uievent.elements.selectFloor.style.display = 'none'; - uievent.elements.selectPointBox.style.display = 'none'; - uievent.elements.canvas.style.display = 'none'; - uievent.elements.usedFlags.style.display = 'inline'; - uievent.elements.extraBody.style.display = 'block'; - uievent.elements.body.style.overflow = "auto"; - - // build flags - var html = ""; - Object.keys(editor.used_flags).sort().forEach(function (v) { - v = "flag:" + v; - html += ""; - }); - uievent.elements.usedFlags.innerHTML = html; - - uievent.doSearchUsedFlags(); - } - - uievent.doSearchUsedFlags = function () { - var flag = uievent.elements.usedFlags.value; - - var html = "

该变量出现的所有位置如下:

    "; - var list = uievent._searchUsedFlags(flag); - list.forEach(function (x) { - html += "
  • " + x + "
  • "; - }); - html += "
"; - uievent.elements.extraBody.innerHTML = html; - } - - var hasUsedFlags = function (obj, flag) { - if (obj == null) return false; - if (typeof obj != 'string') return hasUsedFlags(JSON.stringify(obj), flag); - - var index = -1, length = flag.length; - while (true) { - index = obj.indexOf(flag, index + 1); - if (index < 0) return false; - if (!/^[a-zA-Z0-9_\u4E00-\u9FCC\u3040-\u30FF\u2160-\u216B\u0391-\u03C9]$/.test(obj.charAt(index + length))) return true; - } - } - - uievent._searchUsedFlags = function (flag) { - var list = []; - // 每个点的事件 - var events = ["events", "autoEvent", "changeFloor", "beforeBattle", "afterBattle", "afterGetItem", "afterOpenDoor"] - for (var floorId in core.floors) { - var floor = core.floors[floorId]; - if (hasUsedFlags(floor.firstArrive, flag)) list.push([floorId, "firstArrive"]); - if (hasUsedFlags(floor.eachArrive, flag)) list.push([floorId, "eachArrive"]); - events.forEach(function (e) { - if (floor[e]) { - for (var loc in floor[e]) { - if (hasUsedFlags(floor[e][loc], flag)) { - list.push(floorId + " 层 " + e + " 的 (" + loc + ") 点"); - } - } - } - }); - } - // 公共事件 - for (var name in events_c12a15a8_c380_4b28_8144_256cba95f760.commonEvent) { - if (hasUsedFlags(events_c12a15a8_c380_4b28_8144_256cba95f760.commonEvent[name], flag)) - list.push("公共事件 " + name); - } - // 道具 & 装备属性 - for (var id in items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a) { - var item = items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a[id]; - // 装备属性 - if (hasUsedFlags(item.equip, flag)) { - list.push("道具 " + (item.name || id) + " 的装备属性"); - } - // 使用事件 - if (hasUsedFlags(item.useItemEvent, flag)) { - list.push("道具 " + (item.name || id) + " 的使用事件"); - } - } - // 怪物战前 & 战后 - for (var id in enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80) { - var enemy = enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80[id]; - if (hasUsedFlags(enemy.beforeBattle, flag)) { - list.push("怪物 " + (enemy.name || id) + " 的战前事件"); - } - if (hasUsedFlags(enemy.afterBattle, flag)) { - list.push("怪物 " + (enemy.name || id) + " 的战后事件"); - } - } - // 图块的碰触 & 门信息 - for (var id in maps_90f36752_8815_4be8_b32b_d7fad1d0542e) { - var mapInfo = maps_90f36752_8815_4be8_b32b_d7fad1d0542e[id]; - if (hasUsedFlags(mapInfo.doorInfo, flag)) - list.push("图块 " + (mapInfo.name || mapInfo.id) + " 的门信息"); - if (hasUsedFlags(mapInfo.event, flag)) - list.push("图块 " + (mapInfo.name || mapInfo.id) + " 碰触事件"); - } - // 难度 & 标题事件 & 开场剧情 & 等级提升 - if (hasUsedFlags(data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.main.levelChoose, flag)) - list.push("难度分歧"); - if (hasUsedFlags(data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.firstData.startCanvas, flag)) - list.push("标题事件"); - if (hasUsedFlags(data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.firstData.startText, flag)) - list.push("开场剧情"); - if (hasUsedFlags(data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.firstData.levelUp, flag)) - list.push("等级提升"); - // 全局商店 - (data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.firstData.shops || []).forEach(function (shop) { - if (hasUsedFlags(shop, flag)) list.push("商店 " + shop.id); - }); - - return list; - } - - // ------ 选择楼层 ------ // - uievent.selectFloor = function (floorId, title, callback) { - uievent.isOpen = true; - uievent.elements.div.style.display = 'block'; - uievent.mode = 'selectFloor'; - uievent.elements.selectPoint.style.display = 'none'; - uievent.elements.yes.style.display = 'block'; - uievent.elements.title.innerText = title; - uievent.elements.selectBackground.style.display = 'none'; - uievent.elements.selectFloor.style.display = 'none'; - uievent.elements.selectPointBox.style.display = 'none'; - uievent.elements.canvas.style.display = 'none'; - uievent.elements.usedFlags.style.display = 'none'; - uievent.elements.extraBody.style.display = 'block'; - uievent.elements.body.style.overflow = "auto"; - - uievent.elements.yes.onclick = function () { - var floorId = uievent.values.floorId; - uievent.close(); - if (callback) callback(floorId); - } - - if (floorId instanceof Array) floorId = floorId[0]; - if (!floorId) floorId = editor.currentFloorId; - uievent.values.floorId = floorId; - - var html = "

"; - html += "搜索楼层:"; - html += "" - + one + '(' + floor.title + ')' + ""; - html += ""; - html += ""; - html += '
'; - }); - floorList.innerHTML = html; - } - - uievent._selectFloor_preview = function (button) { - var span = button.nextElementSibling; - while (span.firstChild) span.removeChild(span.lastChild); - var floorId = span.getAttribute('key'); - - if (span.style.display == 'none') { - button.innerText = '收起'; - span.style.display = 'inline'; - if (!uievent.values.dom) { - var canvas = document.createElement('canvas'); - canvas.style.position = 'relative'; - canvas.style.marginLeft = "-10px"; - canvas.style.marginTop = '5px'; - canvas.style.width = "100%" - canvas.width = canvas.height = core.__PIXELS__; - uievent.values.dom = canvas; - uievent.values.ctx = canvas.getContext('2d'); - } - span.appendChild(uievent.values.dom); - core.clearMap(uievent.values.ctx); - core.drawThumbnail(floorId, null, {ctx: uievent.values.ctx}); - } else { - button.innerText = '预览'; - span.style.display = 'none'; - } - } - - // ------ 素材选择框 ------ // - uievent.selectMaterial = function (value, title, directory, transform, callback) { - var one = directory.split(':'); - if (one.length > 1) directory = one[0]; - var appendedImages = one[1] == 'images' ? core.material.images.images : {}; - - fs.readdir(directory, function (err, data) { - if (err) { - printe(directory + '不存在!'); - throw (directory + '不存在!'); - } - if (!(data instanceof Array)) { - printe('没有可显示的内容') - return; - } - value = value || []; - data = (transform ? data.map(transform) : data).filter(function (one) {return one;}).sort(); - var data2 = Object.keys(appendedImages); - data2 = (transform ? data2.map(transform) : data2).filter(function (one) { - return one && data.indexOf(one) < 0; - }).sort(); - - uievent.isOpen = true; - uievent.elements.div.style.display = 'block'; - uievent.mode = 'selectMaterial'; - uievent.elements.selectPoint.style.display = 'none'; - uievent.elements.yes.style.display = 'block'; - uievent.elements.title.innerText = title; - uievent.elements.selectBackground.style.display = 'none'; - uievent.elements.selectFloor.style.display = 'none'; - uievent.elements.selectPointBox.style.display = 'none'; - uievent.elements.canvas.style.display = 'none'; - uievent.elements.usedFlags.style.display = 'none'; - uievent.elements.extraBody.style.display = 'block'; - uievent.elements.body.style.overflow = "auto"; - - uievent.elements.yes.onclick = function () { - var list = Array.from(document.getElementsByClassName('materialCheckbox')).filter(function (one) { - return one.checked; - }).map(function (one) {return one.getAttribute('key'); }); - uievent.close(); - if (callback) callback(list); - } - - var _isTileset = directory.indexOf('project/tilesets') >= 0; - - // 显示每一项内容 - var html = "

"; - html += ""+ - "
"; - if (_isTileset) { - html += "警告!额外素材一旦注册成功将不可删除,否则可能会导致素材错位风险!如果你不再想用某个额外素材," - +"但又不想让它出现在素材区,可以考虑使用空气墙同名替换该额外素材文件。
" - } - data.forEach(function (one) { - var checked = value.indexOf(one) >= 0? 'checked' : ''; - var disabled = _isTileset && value.indexOf(one) >= 0 ? 'disabled' : '' - html += ` ${one}`; - // 预览图片 - if (one.endsWith('.png') || one.endsWith('.jpg') || one.endsWith('.jpeg') || one.endsWith('.gif')) { - html += ""; - html += '
'; - } - // 试听音频 - if (one.endsWith('.mp3') || one.endsWith('.ogg') || one.endsWith('.wav') || one.endsWith('.m4a') || one.endsWith('.flac')) { - html += "" - html += " 音调:"; - html += `0:00 / 0:00
- - `; - } - // 预览动画 - if (directory.indexOf('animates') >= 0) { - html += ""; - html += ""; - } - html += '
'; - }); - data2.forEach(function (one) { - var checked = value.indexOf(one) >= 0? 'checked' : ''; - var disabled = _isTileset && value.indexOf(one) >= 0 ? 'disabled' : ''; - html += ` ${one}`; - // 预览图片 - if (one.endsWith('.png') || one.endsWith('.jpg') || one.endsWith('.jpeg') || one.endsWith('.gif')) { - html += ""; - html += '

'; - } - }) - html += "

"; - html += "

如果文件未在此列表显示,请检查文件名是否合法(只能由数字字母下划线横线和点组成),后缀名是否正确。

"; - uievent.elements.extraBody.innerHTML = html; - }); - } - - uievent._selectAllMaterial = function (checked) { - Array.from(document.getElementsByClassName('materialCheckbox')).forEach(function (one) { - if (!one.disabled) one.checked = checked; - }) - } - - uievent._previewMaterialImage = function (button) { - var br = button.nextElementSibling; - var img = br.nextElementSibling; - if (br.style.display == 'none') { - button.innerText = '折叠'; - br.style.display = 'block'; - img.style.display = 'block'; - img.src = img.getAttribute('key'); - } else { - button.innerText = '预览'; - br.style.display = 'none'; - img.style.display = 'none'; - } - } - - uievent._previewMaterialImage2 = function (button) { - var br = button.nextElementSibling; - if (br.style.display == 'none') { - button.innerText = '折叠'; - br.style.display = 'block'; - br.parentElement.insertBefore(core.material.images.images[br.getAttribute('key')], br.nextElementSibling); - } else { - button.innerText = '预览'; - br.style.display = 'none'; - br.parentElement.removeChild(core.material.images.images[br.getAttribute('key')]); - } - } - - uievent._previewMaterialAudio = function (button) { - var span = button.nextElementSibling.nextElementSibling; - var br = span.nextElementSibling; - var audio = br.nextElementSibling; - var progress = audio.nextElementSibling; - if (br.style.display == 'none') { - button.innerText = '暂停'; - br.style.display = 'block'; - progress.style.display = 'block'; - span.style.display = 'inline'; - audio.play(); - } else { - button.innerText = '播放'; - br.style.display = 'none'; - progress.style.display='none'; - span.style.display = 'none'; - audio.pause(); - } - } - - uievent._previewMaterialAudio_onPitchChange = function (input) { - var audio = input.parentElement.nextElementSibling.nextElementSibling.nextElementSibling; - audio.preservesPitch = false; - audio.playbackRate = core.clamp((parseInt(input.value) || 100) / 100, 0.3, 3.0); - } - - uievent._previewMaterialAudio_onTimeUpdate = function (audio) { - var _format = function (time) { return parseInt(time/60) + ":" + core.setTwoDigits(parseInt(time) % 60); } - if (audio.duration > 0) { - audio.previousElementSibling.previousElementSibling.innerText = _format(audio.currentTime) + " / " + _format(audio.duration); - audio.nextElementSibling.setAttribute('value', audio.currentTime / audio.duration); - } - } - - uievent._previewMaterialAudio_seek = function (element, event) { - var audio = element.previousElementSibling; - var value = event.offsetX * element.max / element.offsetWidth; - element.setAttribute("value", value); - audio.currentTime = audio.duration * value; - if (audio.paused) audio.play(); - } - - var _previewMaterialAnimate = function (span, content) { - _previewMaterialAnimate_buildSounds(span, content); - - // 创建dom - if (!uievent.values.dom) { - var dom = document.createElement('span'); - dom.style.position = "relative"; - dom.style.marginLeft = "-10px"; - var canvas = document.createElement('canvas'); - canvas.width = canvas.height = core.__PIXELS__; - canvas.style.position = 'absolute'; - core.drawThumbnail(editor.currentFloorId, null, {ctx: canvas.getContext('2d')}); - dom.appendChild(canvas); - var canvas2 = document.createElement('canvas'); - canvas2.style.position = 'absolute'; - canvas2.width = canvas2.height = core.__PIXELS__; - uievent.values.ctx = canvas2.getContext('2d'); - dom.appendChild(canvas2); - var canvas3 = document.createElement('canvas'); - canvas3.width = canvas3.height = core.__PIXELS__; - dom.appendChild(canvas3); - uievent.values.dom = dom; - } - - span.appendChild(uievent.values.dom); - clearInterval(uievent.values.interval); - var frame = 0; - uievent.values.interval = setInterval(function () { - if (span.style.display == 'none') { - clearInterval(uievent.values.interval); - uievent.values.interval = null; - return; - } - core.clearMap(uievent.values.ctx); - core.maps._drawAnimateFrame(uievent.values.ctx, content, core.__PIXELS__ / 2, core.__PIXELS__ / 2, frame++); - }, 50); - } - - var _previewMaterialAnimate_buildSounds = function (span, content) { - var sounds = content.se || {}; - if (typeof sounds == 'string') sounds = {1: sounds}; - var pitch = content.pitch || {}; - - span.appendChild(document.createElement('br')); - var dom = document.createElement('span'); - dom.setAttribute('frames', content.frame); - var html = ""; - Object.keys(sounds).forEach(function (frame) { - html += "" + _previewMaterialAnimate_buildSoundRow(frame, sounds[frame], content.frame, pitch[frame]) + ""; - }); - html += ''; - html += ''; - html += "

"; - dom.innerHTML = html; - span.appendChild(dom); - _previewMaterialAnimate_awesomplete(span); - } - - var _previewMaterialAnimate_buildSoundRow = function (index, se, frames, pitch) { - var audios = Object.keys(core.material.sounds).sort().join(","); - var html = ""; - html += "第 帧:"; - html += ''; - html += ''; - html += " 音调:"; - html += ''; - html += '
'; - return html; - } - - var _previewMaterialAnimate_awesomplete = function (span) { - var inputs = span.getElementsByClassName("_audio"); - for (var i = 0; i < inputs.length; ++i) { - var input = inputs[i]; - if (!input.hasAttribute('awesomplete')) { - input.setAttribute('awesomplete', '1'); - new Awesomplete(input); - } - } - } - - uievent._previewMaterialAnimate = function (button) { - var span = button.nextElementSibling; - while (span.firstChild) span.removeChild(span.lastChild); - var filename = span.getAttribute("key"); - uievent.values.animates = uievent.values.animates || {}; - if (span.style.display == 'none') { - button.innerText = '收起'; - span.style.display = 'inline'; - if (uievent.values.animates[filename]) { - _previewMaterialAnimate(span, uievent.values.animates[filename]); - } else { - fs.readFile(filename, 'utf-8', function (e, d) { - if (e) { - alert('无法打开动画文件!'+e); return; - } - uievent.values.animates[filename] = core.loader._loadAnimate(d); - if (uievent.values.animates[filename]) { - uievent.values.animates[filename + ':raw'] = JSON.parse(d); - _previewMaterialAnimate(span, uievent.values.animates[filename]); - } - }) - } - } else { - button.innerText = '预览'; - span.style.display = 'none'; - } - } - - uievent._previewMaterialAnimate_previewSound = function (button) { - var input = button.previousElementSibling; - if (input.tagName == 'DIV') input = input.firstChild; - if (!input.value) return; - if (!uievent.values.audio) - uievent.values.audio = new Audio(); - uievent.values.audio.src = './project/sounds/' + input.value; - uievent.values.audio.preservesPitch = false; - uievent.values.audio.playbackRate = core.clamp((parseInt(button.nextElementSibling.children[0].value) || 100) / 100, 0.3, 3.0); - uievent.values.audio.play(); - } - - uievent._previewMaterialAnimate_addSound = function (button) { - var parent = button.parentElement; - var span = document.createElement("span"); - span.innerHTML = _previewMaterialAnimate_buildSoundRow(1, "", parseInt(parent.getAttribute("frames"))); - parent.insertBefore(span, button); - _previewMaterialAnimate_awesomplete(parent); - } - - uievent._previewMaterialAnimate_deleteSound = function (button) { - var element = button.parentElement; - element.parentElement.removeChild(element); - } - - uievent._previewMaterialAnimate_saveSound = function (button) { - var span = button.parentElement; - var filename = span.parentElement.getAttribute("key"); - if (!filename || !uievent.values.animates[filename]) return; - var se = {}; - var pitch = {}; - - var audios = span.getElementsByClassName("_audio"); - for (var i = 0; i < audios.length; ++i) { - var audio = audios[i]; - var select = audio.parentElement.previousElementSibling; - if (audio.value && select.tagName == 'SELECT') { - se[select.value] = audio.value; - var p = audio.parentElement.nextElementSibling.nextElementSibling.children[0]; - pitch[select.value] = core.clamp(parseInt(p.value) || 100, 30, 300); - } - } - uievent.values.animates[filename].se = se; - uievent.values.animates[filename+':raw'].se = se; - uievent.values.animates[filename].pitch = pitch; - uievent.values.animates[filename+':raw'].pitch = pitch; - fs.writeFile(filename, JSON.stringify(uievent.values.animates[filename+':raw']), 'utf-8', function (e, d) { - if (e) alert('无法修改音效文件!'+e); - else { - alert('动画音效修改成功!别忘了在全塔属性中注册音效哦!'); - } - }) - } - - // ------ 多选框 ------ // - uievent.popCheckboxSet = function (value, comments, title, callback) { - if (value == null) value = []; - if (!(value instanceof Array)) { - if (value == 0) value = []; - else value = [value]; - } - - uievent.isOpen = true; - uievent.elements.div.style.display = 'block'; - uievent.mode = 'popCheckboxSet'; - uievent.elements.selectPoint.style.display = 'none'; - uievent.elements.yes.style.display = 'block'; - uievent.elements.title.innerText = title; - uievent.elements.selectBackground.style.display = 'none'; - uievent.elements.selectFloor.style.display = 'none'; - uievent.elements.selectPointBox.style.display = 'none'; - uievent.elements.canvas.style.display = 'none'; - uievent.elements.usedFlags.style.display = 'none'; - uievent.elements.extraBody.style.display = 'block'; - uievent.elements.body.style.overflow = "auto"; - - uievent.elements.yes.onclick = function () { - var list = Array.from(document.getElementsByClassName('uieventCheckboxSet')).filter(function (one) { - return one.checked; - }).map(function (one) { - var value = one.getAttribute('key'); - if (one.getAttribute('_type') == 'number') value = parseFloat(value); - return value; - }); - uievent.close(); - if (callback) callback(list); - } - - var keys=Array.from(comments.key) - var prefixStrings=Array.from(comments.prefix) - for (var index = 0; index < value.length; index++) { - if (keys.indexOf(value[index])==-1) { - prefixStrings.push(value[index]+': ') - keys.push(value[index]) - } - } - var table = ''; - - for (var index = 0; index < keys.length; index++) { - var one = keys[index]; - if (index % 3 == 0) { - table += ''; - } - table += ``; - if (index % 3 == 2) { - table += ''; - } - } - if (keys.length % 3 != 0) table += ''; - table += '
${prefixStrings[index]}= 0? 'checked' : ''}/>
'; - - uievent.elements.extraBody.innerHTML = "

"+table+"

"; - } - - editor.constructor.prototype.uievent=uievent; - } \ No newline at end of file diff --git a/_server/editor_uievent.js b/_server/editor_uievent.js new file mode 100644 index 00000000..ac29c3ed --- /dev/null +++ b/_server/editor_uievent.js @@ -0,0 +1,934 @@ +editor_uievent_wrapper = function (editor) { + + // ------ UI预览 & 地图选点相关 ------ // + + var uievent = { + elements: {}, + values: {}, + isOpen: false, + mode: "" + }; + + uievent.elements.div = document.getElementById('uieventDiv'); + uievent.elements.title = document.getElementById('uieventTitle'); + uievent.elements.yes = document.getElementById('uieventYes'); + uievent.elements.no = document.getElementById('uieventNo'); + uievent.elements.selectBackground = document.getElementById('uieventBackground'); + uievent.elements.selectPoint = document.getElementById('selectPoint'); + uievent.elements.selectFloor = document.getElementById('selectPointFloor'); + uievent.elements.selectPointBox = document.getElementById('selectPointBox'); + uievent.elements.body = document.getElementById('uieventBody'); + uievent.elements.selectPointButtons = document.getElementById('selectPointButtons'); + uievent.elements.canvas = document.getElementById('uievent'); + uievent.elements.usedFlags = document.getElementById('uieventUsedFlags'); + uievent.elements.extraBody = document.getElementById('uieventExtraBody'); + + uievent.close = function () { + uievent.isOpen = false; + uievent.elements.div.style.display = 'none'; + if (uievent.values.interval) { + clearTimeout(uievent.values.interval); + clearInterval(uievent.values.interval); + } + uievent.values = {}; + } + uievent.elements.no.onclick = uievent.close; + + uievent.elements.selectBackground.onchange = function () { + uievent.drawPreviewUI(); + } + + uievent.drawPreviewUI = function () { + core.setAlpha('uievent', 1); + core.clearMap('uievent'); + core.setFilter('uievent', null); + + // 绘制UI + var background = uievent.elements.selectBackground.value; + if (background == 'thumbnail') { + core.drawThumbnail(editor.currentFloorId, null, {ctx: 'uievent'}); + } + else { + core.fillRect('uievent', 0, 0, core.__PIXELS__, core.__PIXELS__, background); + } + + if (uievent.values.list instanceof Array) { + uievent.values.list.forEach(function (data) { + if (typeof data == 'string') data = { "type": "text", "text": data }; + var type = data.type; + if (type == "text") { + data.ctx = 'uievent'; + core.saveCanvas('uievent'); + core.drawTextBox(data.text, data); + core.loadCanvas('uievent'); + return; + } + else if (type == "choices") { + for (var i = 0; i < data.choices.length; i++) { + if (typeof data.choices[i] === 'string') + data.choices[i] = {"text": data.choices[i]}; + data.choices[i].text = core.replaceText(data.choices[i].text); + } + core.saveCanvas('uievent'); + core.status.event.selection = data.selected || 0; + core.drawChoices(core.replaceText(data.text), data.choices, data.width, 'uievent'); + core.status.event.selection = null; + core.loadCanvas('uievent'); + return; + } else if (type == "confirm") { + core.saveCanvas('uievent'); + core.drawConfirmBox(data.text, null, null, 'uievent'); + core.loadCanvas('uievent'); + } else if (core.ui["_uievent_" + type]) + core.ui["_uievent_" + type](data); + }) + } + } + + uievent.previewUI = function (list) { + uievent.isOpen = true; + uievent.elements.div.style.display = 'block'; + uievent.mode = 'previewUI'; + uievent.elements.selectPoint.style.display = 'none'; + uievent.elements.yes.style.display = 'none'; + uievent.elements.title.innerText = 'UI绘制预览'; + uievent.elements.selectBackground.style.display = 'inline'; + uievent.elements.selectBackground.value = 'thumbnail'; + uievent.elements.selectFloor.style.display = 'none'; + uievent.elements.selectPointBox.style.display = 'none'; + uievent.elements.canvas.style.display = 'block'; + uievent.elements.usedFlags.style.display = 'none'; + uievent.elements.extraBody.style.display = 'none'; + uievent.elements.body.style.overflow = "hidden"; + + uievent.values.list = list; + uievent.drawPreviewUI(); + } + + uievent.selectPoint = function (floorId, x, y, bigmap, callback) { + uievent.values.bigmap = bigmap; + uievent.values.size = editor.isMobile ? window.innerWidth / core.__SIZE__ : 32; + + uievent.isOpen = true; + uievent.elements.div.style.display = 'block'; + uievent.mode = 'selectPoint'; + uievent.elements.selectPoint.style.display = 'block'; + uievent.elements.yes.style.display = 'inline'; + uievent.elements.selectBackground.style.display = 'none'; + uievent.elements.selectFloor.style.display = 'inline'; + uievent.elements.selectPointBox.style.display = 'block'; + uievent.elements.canvas.style.display = 'block'; + uievent.elements.usedFlags.style.display = 'none'; + uievent.elements.extraBody.style.display = 'none'; + uievent.elements.body.style.overflow = "hidden"; + uievent.elements.yes.onclick = function () { + var floorId = uievent.values.floorId, x = uievent.values.x, y = uievent.values.y; + var multipoints = uievent.values.multipoints || []; + uievent.close(); + if (callback) { + if (multipoints.length > 0) { + callback(floorId, multipoints.map(function (one) { return one.split(',')[0]}).join(','), + multipoints.map(function (one) { return one.split(',')[1]}).join(',')); + } else { + callback(floorId, x, y); + } + } + } + + // Append children + var floors = ""; + core.floorIds.forEach(function (f) { + floors += ""; + }) + uievent.elements.selectFloor.innerHTML = floors; + // 检查多选点 + if (/^\d+(,\d+)+$/.test(x) && /^\d+(,\d+)+$/.test(y)) { + var xx = x.split(','), yy = y.split(','); + uievent.values.multipoints = []; + for (var i = 0; i < xx.length; ++i) { + uievent.values.multipoints.push(xx[i] + "," + yy[i]); + } + x = xx[xx.length - 1]; + y = yy[yy.length - 1]; + } + this.setPoint(floorId || editor.currentFloorId, core.calValue(x) || 0, core.calValue(y) || 0); + } + + uievent.updateSelectPoint = function (redraw) { + uievent.elements.title.innerText = '地图选点【右键多选】 (' + uievent.values.x + "," + uievent.values.y + ')'; + // 计算size + uievent.values.boxSize = uievent.values.size * + (uievent.values.bigmap ? (core.__SIZE__ / Math.max(uievent.values.width, uievent.values.height)) : 1); + uievent.values.boxLeft = uievent.values.bigmap ? + (core.__PIXELS__ * Math.max(0, (1 - uievent.values.width / uievent.values.height) / 2)) : 0; + uievent.values.boxTop = uievent.values.bigmap ? + (core.__PIXELS__ * Math.max(0, (1 - uievent.values.height / uievent.values.width) / 2)) : 0; + + if (uievent.values.bigmap) { + uievent.elements.selectPointBox.style.left = uievent.values.boxSize * uievent.values.x + uievent.values.boxLeft + "px"; + uievent.elements.selectPointBox.style.top = uievent.values.boxSize * uievent.values.y + uievent.values.boxTop + "px"; + } else { + uievent.elements.selectPointBox.style.left = uievent.values.boxSize * (uievent.values.x - uievent.values.left) + "px"; + uievent.elements.selectPointBox.style.top = uievent.values.boxSize * (uievent.values.y - uievent.values.top) + "px"; + } + uievent.elements.selectPointBox.style.width = uievent.values.boxSize - 6 + "px"; + uievent.elements.selectPointBox.style.height = uievent.values.boxSize - 6 + "px"; + + if (redraw) { + core.setAlpha('uievent', 1); + core.clearMap('uievent'); + core.drawThumbnail(uievent.values.floorId, null, { + ctx: 'uievent', centerX: uievent.values.left + core.__HALF_SIZE__, + centerY: uievent.values.top + core.__HALF_SIZE__, all: uievent.values.bigmap + }); + uievent.values.multipoints = uievent.values.multipoints || []; + core.setTextAlign('uievent', 'right'); + for (var i = 0; i < uievent.values.multipoints.length; ++i) { + var xy = uievent.values.multipoints[i].split(","), x = parseInt(xy[0]), y = parseInt(xy[1]); + core.fillBoldText('uievent', i + 1, + 32 * (x - uievent.values.left) + 28 , 32 * (y - uievent.values.top) + 26, '#FF7F00', null, '14px Verdana'); + } + core.setTextAlign('uievent', 'left'); + } + } + + uievent.setPoint = function (floorId, x, y) { + if (core.floorIds.indexOf(floorId) == -1) floorId = editor.currentFloorId; + uievent.values.floorId = floorId; + uievent.elements.selectFloor.value = floorId; + uievent.values.x = x != null ? x : (uievent.values.x || 0); + uievent.values.y = y != null ? y : (uievent.values.y || 0); + uievent.values.width = core.floors[uievent.values.floorId].width || core.__SIZE__; + uievent.values.height = core.floors[uievent.values.floorId].height || core.__SIZE__; + uievent.values.left = core.clamp(uievent.values.x - core.__HALF_SIZE__, 0, uievent.values.width - core.__SIZE__); + uievent.values.top = core.clamp(uievent.values.y - core.__HALF_SIZE__, 0, uievent.values.height - core.__SIZE__); + uievent.updateSelectPoint(true); + } + + uievent.elements.selectFloor.onchange = function () { + uievent.values.multipoints = []; + uievent.setPoint(uievent.elements.selectFloor.value); + } + + uievent.elements.selectPointBox.onclick = function (e) { + e.preventDefault(); + e.stopPropagation(); + return false; + } + + uievent.elements.body.onclick = function (e) { + if (uievent.mode != 'selectPoint') return; + if (uievent.values.bigmap) { + uievent.values.x = core.clamp(Math.floor((e.offsetX - uievent.values.boxLeft) / uievent.values.boxSize), 0, uievent.values.width - 1); + uievent.values.y = core.clamp(Math.floor((e.offsetY - uievent.values.boxTop) / uievent.values.boxSize), 0, uievent.values.height - 1); + } else { + uievent.values.x = uievent.values.left + Math.floor(e.offsetX / uievent.values.size); + uievent.values.y = uievent.values.top + Math.floor(e.offsetY / uievent.values.size); + } + uievent.updateSelectPoint(false); + } + + uievent.elements.body.oncontextmenu = function (e) { + e.preventDefault(); + e.stopPropagation(); + if (uievent.mode != 'selectPoint' || uievent.values.bigmap) return; + var x = uievent.values.left + Math.floor(e.offsetX / uievent.values.size); + var y = uievent.values.top + Math.floor(e.offsetY / uievent.values.size); + uievent.values.multipoints = uievent.values.multipoints || []; + if (uievent.values.multipoints.indexOf(x+","+y) >= 0) { + uievent.values.multipoints = uievent.values.multipoints.filter(function (o) { return o != x+","+y;}) + } else { + uievent.values.multipoints.push(x+","+y); + } + uievent.values.x = x; + uievent.values.y = y; + uievent.updateSelectPoint(true); + return false; + } + + uievent.move = function (dx, dy) { + if (uievent.mode != 'selectPoint') return; + if (uievent.values.bigmap) return; + uievent.values.left = core.clamp(uievent.values.left + dx, 0, uievent.values.width - core.__SIZE__); + uievent.values.top = core.clamp(uievent.values.top + dy, 0, uievent.values.height - core.__SIZE__); + this.updateSelectPoint(true); + }; + + uievent.triggerBigmap = function () { + if (uievent.mode != 'selectPoint') return; + uievent.values.bigmap = !uievent.values.bigmap; + uievent.values.multipoints = []; + uievent.setPoint(uievent.values.floorId); + }; + + (function () { + + var viewportButtons = uievent.elements.selectPointButtons; + var pressTimer = null; + for (var ii = 0, node; node = viewportButtons.children[ii]; ii++) { + if (ii == 4) { + node.onclick = uievent.triggerBigmap; + continue; + } + if (ii == 5) { + node.onclick = function () { + alert(core.copy(uievent.values.floorId) ? ('楼层ID '+uievent.values.floorId+' 已成功复制到剪切板') : '无法复制楼层ID'); + } + } + (function (x, y) { + var move = function () { + uievent.move(x, y); + } + node.onmousedown = function () { + clearTimeout(pressTimer); + pressTimer = setTimeout(function () { + pressTimer = -1; + var f = function () { + if (pressTimer != null) { + move(); + setTimeout(f, 150); + } + } + f(); + }, 500); + }; + node.onmouseup = function () { + if (pressTimer > 0) { + clearTimeout(pressTimer); + move(); + } + pressTimer = null; + } + })([-1, 0, 0, 1][ii], [0, -1, 1, 0][ii]); + } + })(); + + uievent.elements.div.onmousewheel = function (e) { + if (uievent.mode != 'selectPoint') return; + var index = core.floorIds.indexOf(uievent.values.floorId); + try { + if (e.wheelDelta) + index += Math.sign(e.wheelDelta); + else if (e.detail) + index += Math.sign(e.detail); + } catch (ee) { main.log(ee); } + index = core.clamp(index, 0, core.floorIds.length - 1); + uievent.values.multipoints = []; + uievent.setPoint(core.floorIds[index]); + } + + uievent.onKeyDown = function (e) { + if (e.keyCode == 27) editor.uievent.close(); + if (uievent.mode == 'selectPoint') { + if (e.keyCode == 87) editor.uievent.move(0, -1) + if (e.keyCode == 65) editor.uievent.move(-1, 0) + if (e.keyCode == 83) editor.uievent.move(0, 1); + if (e.keyCode == 68) editor.uievent.move(1, 0); + } + } + + // ------ 搜索变量出现的位置,也放在uievent好了 ------ // + + uievent.searchUsedFlags = function () { + uievent.isOpen = true; + uievent.elements.div.style.display = 'block'; + uievent.mode = 'searchUsedFlags'; + uievent.elements.selectPoint.style.display = 'none'; + uievent.elements.yes.style.display = 'none'; + uievent.elements.title.innerText = '搜索变量'; + uievent.elements.selectBackground.style.display = 'none'; + uievent.elements.selectFloor.style.display = 'none'; + uievent.elements.selectPointBox.style.display = 'none'; + uievent.elements.canvas.style.display = 'none'; + uievent.elements.usedFlags.style.display = 'inline'; + uievent.elements.extraBody.style.display = 'block'; + uievent.elements.body.style.overflow = "auto"; + + // build flags + var html = ""; + Object.keys(editor.used_flags).sort().forEach(function (v) { + v = "flag:" + v; + html += ""; + }); + uievent.elements.usedFlags.innerHTML = html; + + uievent.doSearchUsedFlags(); + } + + uievent.doSearchUsedFlags = function () { + var flag = uievent.elements.usedFlags.value; + + var html = "

该变量出现的所有位置如下:

    "; + var list = uievent._searchUsedFlags(flag); + list.forEach(function (x) { + html += "
  • " + x + "
  • "; + }); + html += "
"; + uievent.elements.extraBody.innerHTML = html; + } + + var hasUsedFlags = function (obj, flag) { + if (obj == null) return false; + if (typeof obj != 'string') return hasUsedFlags(JSON.stringify(obj), flag); + + var index = -1, length = flag.length; + while (true) { + index = obj.indexOf(flag, index + 1); + if (index < 0) return false; + if (!/^[a-zA-Z0-9_\u4E00-\u9FCC\u3040-\u30FF\u2160-\u216B\u0391-\u03C9]$/.test(obj.charAt(index + length))) return true; + } + } + + uievent._searchUsedFlags = function (flag) { + var list = []; + // 每个点的事件 + var events = ["events", "autoEvent", "changeFloor", "beforeBattle", "afterBattle", "afterGetItem", "afterOpenDoor"] + for (var floorId in core.floors) { + var floor = core.floors[floorId]; + if (hasUsedFlags(floor.firstArrive, flag)) list.push([floorId, "firstArrive"]); + if (hasUsedFlags(floor.eachArrive, flag)) list.push([floorId, "eachArrive"]); + events.forEach(function (e) { + if (floor[e]) { + for (var loc in floor[e]) { + if (hasUsedFlags(floor[e][loc], flag)) { + list.push(floorId + " 层 " + e + " 的 (" + loc + ") 点"); + } + } + } + }); + } + // 公共事件 + for (var name in events_c12a15a8_c380_4b28_8144_256cba95f760.commonEvent) { + if (hasUsedFlags(events_c12a15a8_c380_4b28_8144_256cba95f760.commonEvent[name], flag)) + list.push("公共事件 " + name); + } + // 道具 & 装备属性 + for (var id in items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a) { + var item = items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a[id]; + // 装备属性 + if (hasUsedFlags(item.equip, flag)) { + list.push("道具 " + (item.name || id) + " 的装备属性"); + } + // 使用事件 + if (hasUsedFlags(item.useItemEvent, flag)) { + list.push("道具 " + (item.name || id) + " 的使用事件"); + } + } + // 怪物战前 & 战后 + for (var id in enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80) { + var enemy = enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80[id]; + if (hasUsedFlags(enemy.beforeBattle, flag)) { + list.push("怪物 " + (enemy.name || id) + " 的战前事件"); + } + if (hasUsedFlags(enemy.afterBattle, flag)) { + list.push("怪物 " + (enemy.name || id) + " 的战后事件"); + } + } + // 图块的碰触 & 门信息 + for (var id in maps_90f36752_8815_4be8_b32b_d7fad1d0542e) { + var mapInfo = maps_90f36752_8815_4be8_b32b_d7fad1d0542e[id]; + if (hasUsedFlags(mapInfo.doorInfo, flag)) + list.push("图块 " + (mapInfo.name || mapInfo.id) + " 的门信息"); + if (hasUsedFlags(mapInfo.event, flag)) + list.push("图块 " + (mapInfo.name || mapInfo.id) + " 碰触事件"); + } + // 难度 & 标题事件 & 开场剧情 & 等级提升 + if (hasUsedFlags(data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.main.levelChoose, flag)) + list.push("难度分歧"); + if (hasUsedFlags(data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.firstData.startCanvas, flag)) + list.push("标题事件"); + if (hasUsedFlags(data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.firstData.startText, flag)) + list.push("开场剧情"); + if (hasUsedFlags(data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.firstData.levelUp, flag)) + list.push("等级提升"); + // 全局商店 + (data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.firstData.shops || []).forEach(function (shop) { + if (hasUsedFlags(shop, flag)) list.push("商店 " + shop.id); + }); + + return list; + } + + // ------ 选择楼层 ------ // + uievent.selectFloor = function (floorId, title, callback) { + uievent.isOpen = true; + uievent.elements.div.style.display = 'block'; + uievent.mode = 'selectFloor'; + uievent.elements.selectPoint.style.display = 'none'; + uievent.elements.yes.style.display = 'block'; + uievent.elements.title.innerText = title; + uievent.elements.selectBackground.style.display = 'none'; + uievent.elements.selectFloor.style.display = 'none'; + uievent.elements.selectPointBox.style.display = 'none'; + uievent.elements.canvas.style.display = 'none'; + uievent.elements.usedFlags.style.display = 'none'; + uievent.elements.extraBody.style.display = 'block'; + uievent.elements.body.style.overflow = "auto"; + + uievent.elements.yes.onclick = function () { + var floorId = uievent.values.floorId; + uievent.close(); + if (callback) callback(floorId); + } + + if (floorId instanceof Array) floorId = floorId[0]; + if (!floorId) floorId = editor.currentFloorId; + uievent.values.floorId = floorId; + + var html = "

"; + html += "搜索楼层:"; + html += "" + + one + '(' + floor.title + ')' + ""; + html += ""; + html += ""; + html += '
'; + }); + floorList.innerHTML = html; + } + + uievent._selectFloor_preview = function (button) { + var span = button.nextElementSibling; + while (span.firstChild) span.removeChild(span.lastChild); + var floorId = span.getAttribute('key'); + + if (span.style.display == 'none') { + button.innerText = '收起'; + span.style.display = 'inline'; + if (!uievent.values.dom) { + var canvas = document.createElement('canvas'); + canvas.style.position = 'relative'; + canvas.style.marginLeft = "-10px"; + canvas.style.marginTop = '5px'; + canvas.style.width = "100%" + canvas.width = canvas.height = core.__PIXELS__; + uievent.values.dom = canvas; + uievent.values.ctx = canvas.getContext('2d'); + } + span.appendChild(uievent.values.dom); + core.clearMap(uievent.values.ctx); + core.drawThumbnail(floorId, null, {ctx: uievent.values.ctx}); + } else { + button.innerText = '预览'; + span.style.display = 'none'; + } + } + + // ------ 素材选择框 ------ // + uievent.selectMaterial = function (value, title, directory, transform, callback) { + var one = directory.split(':'); + if (one.length > 1) directory = one[0]; + var appendedImages = one[1] == 'images' ? core.material.images.images : {}; + + fs.readdir(directory, function (err, data) { + if (err) { + printe(directory + '不存在!'); + throw (directory + '不存在!'); + } + if (!(data instanceof Array)) { + printe('没有可显示的内容') + return; + } + value = value || []; + data = (transform ? data.map(transform) : data).filter(function (one) {return one;}).sort(); + var data2 = Object.keys(appendedImages); + data2 = (transform ? data2.map(transform) : data2).filter(function (one) { + return one && data.indexOf(one) < 0; + }).sort(); + + uievent.isOpen = true; + uievent.elements.div.style.display = 'block'; + uievent.mode = 'selectMaterial'; + uievent.elements.selectPoint.style.display = 'none'; + uievent.elements.yes.style.display = 'block'; + uievent.elements.title.innerText = title; + uievent.elements.selectBackground.style.display = 'none'; + uievent.elements.selectFloor.style.display = 'none'; + uievent.elements.selectPointBox.style.display = 'none'; + uievent.elements.canvas.style.display = 'none'; + uievent.elements.usedFlags.style.display = 'none'; + uievent.elements.extraBody.style.display = 'block'; + uievent.elements.body.style.overflow = "auto"; + + uievent.elements.yes.onclick = function () { + var list = Array.from(document.getElementsByClassName('materialCheckbox')).filter(function (one) { + return one.checked; + }).map(function (one) {return one.getAttribute('key'); }); + uievent.close(); + if (callback) callback(list); + } + + var _isTileset = directory.indexOf('project/tilesets') >= 0; + + // 显示每一项内容 + var html = "

"; + html += ""+ + "
"; + if (_isTileset) { + html += "警告!额外素材一旦注册成功将不可删除,否则可能会导致素材错位风险!如果你不再想用某个额外素材," + +"但又不想让它出现在素材区,可以考虑使用空气墙同名替换该额外素材文件。
" + } + data.forEach(function (one) { + var checked = value.indexOf(one) >= 0? 'checked' : ''; + var disabled = _isTileset && value.indexOf(one) >= 0 ? 'disabled' : '' + html += ` ${one}`; + // 预览图片 + if (one.endsWith('.png') || one.endsWith('.jpg') || one.endsWith('.jpeg') || one.endsWith('.gif')) { + html += ""; + html += '
'; + } + // 试听音频 + if (one.endsWith('.mp3') || one.endsWith('.ogg') || one.endsWith('.wav') || one.endsWith('.m4a') || one.endsWith('.flac')) { + html += "" + html += " 音调:"; + html += `0:00 / 0:00
+ + `; + } + // 预览动画 + if (directory.indexOf('animates') >= 0) { + html += ""; + html += ""; + } + html += '
'; + }); + data2.forEach(function (one) { + var checked = value.indexOf(one) >= 0? 'checked' : ''; + var disabled = _isTileset && value.indexOf(one) >= 0 ? 'disabled' : ''; + html += ` ${one}`; + // 预览图片 + if (one.endsWith('.png') || one.endsWith('.jpg') || one.endsWith('.jpeg') || one.endsWith('.gif')) { + html += ""; + html += '

'; + } + }) + html += "

"; + html += "

如果文件未在此列表显示,请检查文件名是否合法(只能由数字字母下划线横线和点组成),后缀名是否正确。

"; + uievent.elements.extraBody.innerHTML = html; + }); + } + + uievent._selectAllMaterial = function (checked) { + Array.from(document.getElementsByClassName('materialCheckbox')).forEach(function (one) { + if (!one.disabled) one.checked = checked; + }) + } + + uievent._previewMaterialImage = function (button) { + var br = button.nextElementSibling; + var img = br.nextElementSibling; + if (br.style.display == 'none') { + button.innerText = '折叠'; + br.style.display = 'block'; + img.style.display = 'block'; + img.src = img.getAttribute('key'); + } else { + button.innerText = '预览'; + br.style.display = 'none'; + img.style.display = 'none'; + } + } + + uievent._previewMaterialImage2 = function (button) { + var br = button.nextElementSibling; + if (br.style.display == 'none') { + button.innerText = '折叠'; + br.style.display = 'block'; + br.parentElement.insertBefore(core.material.images.images[br.getAttribute('key')], br.nextElementSibling); + } else { + button.innerText = '预览'; + br.style.display = 'none'; + br.parentElement.removeChild(core.material.images.images[br.getAttribute('key')]); + } + } + + uievent._previewMaterialAudio = function (button) { + var span = button.nextElementSibling.nextElementSibling; + var br = span.nextElementSibling; + var audio = br.nextElementSibling; + var progress = audio.nextElementSibling; + if (br.style.display == 'none') { + button.innerText = '暂停'; + br.style.display = 'block'; + progress.style.display = 'block'; + span.style.display = 'inline'; + audio.play(); + } else { + button.innerText = '播放'; + br.style.display = 'none'; + progress.style.display='none'; + span.style.display = 'none'; + audio.pause(); + } + } + + uievent._previewMaterialAudio_onPitchChange = function (input) { + var audio = input.parentElement.nextElementSibling.nextElementSibling.nextElementSibling; + audio.preservesPitch = false; + audio.playbackRate = core.clamp((parseInt(input.value) || 100) / 100, 0.3, 3.0); + } + + uievent._previewMaterialAudio_onTimeUpdate = function (audio) { + var _format = function (time) { return parseInt(time/60) + ":" + core.setTwoDigits(parseInt(time) % 60); } + if (audio.duration > 0) { + audio.previousElementSibling.previousElementSibling.innerText = _format(audio.currentTime) + " / " + _format(audio.duration); + audio.nextElementSibling.setAttribute('value', audio.currentTime / audio.duration); + } + } + + uievent._previewMaterialAudio_seek = function (element, event) { + var audio = element.previousElementSibling; + var value = event.offsetX * element.max / element.offsetWidth; + element.setAttribute("value", value); + audio.currentTime = audio.duration * value; + if (audio.paused) audio.play(); + } + + var _previewMaterialAnimate = function (span, content) { + _previewMaterialAnimate_buildSounds(span, content); + + // 创建dom + if (!uievent.values.dom) { + var dom = document.createElement('span'); + dom.style.position = "relative"; + dom.style.marginLeft = "-10px"; + var canvas = document.createElement('canvas'); + canvas.width = canvas.height = core.__PIXELS__; + canvas.style.position = 'absolute'; + core.drawThumbnail(editor.currentFloorId, null, {ctx: canvas.getContext('2d')}); + dom.appendChild(canvas); + var canvas2 = document.createElement('canvas'); + canvas2.style.position = 'absolute'; + canvas2.width = canvas2.height = core.__PIXELS__; + uievent.values.ctx = canvas2.getContext('2d'); + dom.appendChild(canvas2); + var canvas3 = document.createElement('canvas'); + canvas3.width = canvas3.height = core.__PIXELS__; + dom.appendChild(canvas3); + uievent.values.dom = dom; + } + + span.appendChild(uievent.values.dom); + clearInterval(uievent.values.interval); + var frame = 0; + uievent.values.interval = setInterval(function () { + if (span.style.display == 'none') { + clearInterval(uievent.values.interval); + uievent.values.interval = null; + return; + } + core.clearMap(uievent.values.ctx); + core.maps._drawAnimateFrame(uievent.values.ctx, content, core.__PIXELS__ / 2, core.__PIXELS__ / 2, frame++); + }, 50); + } + + var _previewMaterialAnimate_buildSounds = function (span, content) { + var sounds = content.se || {}; + if (typeof sounds == 'string') sounds = {1: sounds}; + var pitch = content.pitch || {}; + + span.appendChild(document.createElement('br')); + var dom = document.createElement('span'); + dom.setAttribute('frames', content.frame); + var html = ""; + Object.keys(sounds).forEach(function (frame) { + html += "" + _previewMaterialAnimate_buildSoundRow(frame, sounds[frame], content.frame, pitch[frame]) + ""; + }); + html += ''; + html += ''; + html += "

"; + dom.innerHTML = html; + span.appendChild(dom); + _previewMaterialAnimate_awesomplete(span); + } + + var _previewMaterialAnimate_buildSoundRow = function (index, se, frames, pitch) { + var audios = Object.keys(core.material.sounds).sort().join(","); + var html = ""; + html += "第 帧:"; + html += ''; + html += ''; + html += " 音调:"; + html += ''; + html += '
'; + return html; + } + + var _previewMaterialAnimate_awesomplete = function (span) { + var inputs = span.getElementsByClassName("_audio"); + for (var i = 0; i < inputs.length; ++i) { + var input = inputs[i]; + if (!input.hasAttribute('awesomplete')) { + input.setAttribute('awesomplete', '1'); + new Awesomplete(input); + } + } + } + + uievent._previewMaterialAnimate = function (button) { + var span = button.nextElementSibling; + while (span.firstChild) span.removeChild(span.lastChild); + var filename = span.getAttribute("key"); + uievent.values.animates = uievent.values.animates || {}; + if (span.style.display == 'none') { + button.innerText = '收起'; + span.style.display = 'inline'; + if (uievent.values.animates[filename]) { + _previewMaterialAnimate(span, uievent.values.animates[filename]); + } else { + fs.readFile(filename, 'utf-8', function (e, d) { + if (e) { + alert('无法打开动画文件!'+e); return; + } + uievent.values.animates[filename] = core.loader._loadAnimate(d); + if (uievent.values.animates[filename]) { + uievent.values.animates[filename + ':raw'] = JSON.parse(d); + _previewMaterialAnimate(span, uievent.values.animates[filename]); + } + }) + } + } else { + button.innerText = '预览'; + span.style.display = 'none'; + } + } + + uievent._previewMaterialAnimate_previewSound = function (button) { + var input = button.previousElementSibling; + if (input.tagName == 'DIV') input = input.firstChild; + if (!input.value) return; + if (!uievent.values.audio) + uievent.values.audio = new Audio(); + uievent.values.audio.src = './project/sounds/' + input.value; + uievent.values.audio.preservesPitch = false; + uievent.values.audio.playbackRate = core.clamp((parseInt(button.nextElementSibling.children[0].value) || 100) / 100, 0.3, 3.0); + uievent.values.audio.play(); + } + + uievent._previewMaterialAnimate_addSound = function (button) { + var parent = button.parentElement; + var span = document.createElement("span"); + span.innerHTML = _previewMaterialAnimate_buildSoundRow(1, "", parseInt(parent.getAttribute("frames"))); + parent.insertBefore(span, button); + _previewMaterialAnimate_awesomplete(parent); + } + + uievent._previewMaterialAnimate_deleteSound = function (button) { + var element = button.parentElement; + element.parentElement.removeChild(element); + } + + uievent._previewMaterialAnimate_saveSound = function (button) { + var span = button.parentElement; + var filename = span.parentElement.getAttribute("key"); + if (!filename || !uievent.values.animates[filename]) return; + var se = {}; + var pitch = {}; + + var audios = span.getElementsByClassName("_audio"); + for (var i = 0; i < audios.length; ++i) { + var audio = audios[i]; + var select = audio.parentElement.previousElementSibling; + if (audio.value && select.tagName == 'SELECT') { + se[select.value] = audio.value; + var p = audio.parentElement.nextElementSibling.nextElementSibling.children[0]; + pitch[select.value] = core.clamp(parseInt(p.value) || 100, 30, 300); + } + } + uievent.values.animates[filename].se = se; + uievent.values.animates[filename+':raw'].se = se; + uievent.values.animates[filename].pitch = pitch; + uievent.values.animates[filename+':raw'].pitch = pitch; + fs.writeFile(filename, JSON.stringify(uievent.values.animates[filename+':raw']), 'utf-8', function (e, d) { + if (e) alert('无法修改音效文件!'+e); + else { + alert('动画音效修改成功!别忘了在全塔属性中注册音效哦!'); + } + }) + } + + // ------ 多选框 ------ // + uievent.popCheckboxSet = function (value, comments, title, callback) { + if (value == null) value = []; + if (!(value instanceof Array)) { + if (value == 0) value = []; + else value = [value]; + } + + uievent.isOpen = true; + uievent.elements.div.style.display = 'block'; + uievent.mode = 'popCheckboxSet'; + uievent.elements.selectPoint.style.display = 'none'; + uievent.elements.yes.style.display = 'block'; + uievent.elements.title.innerText = title; + uievent.elements.selectBackground.style.display = 'none'; + uievent.elements.selectFloor.style.display = 'none'; + uievent.elements.selectPointBox.style.display = 'none'; + uievent.elements.canvas.style.display = 'none'; + uievent.elements.usedFlags.style.display = 'none'; + uievent.elements.extraBody.style.display = 'block'; + uievent.elements.body.style.overflow = "auto"; + + uievent.elements.yes.onclick = function () { + var list = Array.from(document.getElementsByClassName('uieventCheckboxSet')).filter(function (one) { + return one.checked; + }).map(function (one) { + var value = one.getAttribute('key'); + if (one.getAttribute('_type') == 'number') value = parseFloat(value); + return value; + }); + uievent.close(); + if (callback) callback(list); + } + + var keys=Array.from(comments.key) + var prefixStrings=Array.from(comments.prefix) + for (var index = 0; index < value.length; index++) { + if (keys.indexOf(value[index])==-1) { + prefixStrings.push(value[index]+': ') + keys.push(value[index]) + } + } + var table = ''; + + for (var index = 0; index < keys.length; index++) { + var one = keys[index]; + if (index % 3 == 0) { + table += ''; + } + table += ``; + if (index % 3 == 2) { + table += ''; + } + } + if (keys.length % 3 != 0) table += ''; + table += '
${prefixStrings[index]}= 0? 'checked' : ''}/>
'; + + uievent.elements.extraBody.innerHTML = "

"+table+"

"; + } + + editor.constructor.prototype.uievent=uievent; +} \ No newline at end of file diff --git a/editor-mobile.html b/editor-mobile.html index e40fe7d5..5fef012a 100644 --- a/editor-mobile.html +++ b/editor-mobile.html @@ -449,6 +449,7 @@ + diff --git a/editor.html b/editor.html index 282440e2..ae05610b 100644 --- a/editor.html +++ b/editor.html @@ -434,6 +434,7 @@ + From 0a4940986384ab7dbf1051674a6b7627c8415c14 Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Wed, 1 Sep 2021 14:19:53 +0800 Subject: [PATCH 35/60] =?UTF-8?q?=E8=87=AA=E7=BB=98=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E6=A0=8F=E9=A2=84=E8=A7=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _server/MotaAction.g4 | 8 +- _server/editor_multi.js | 16 ++- _server/editor_table.js | 4 +- _server/editor_uievent.js | 179 +++++++++++++++++++++++++---- _server/table/functions.comment.js | 1 + editor-mobile.html | 8 +- editor.html | 8 +- libs/control.js | 2 +- libs/events.js | 3 + libs/utils.js | 4 + 10 files changed, 191 insertions(+), 42 deletions(-) diff --git a/_server/MotaAction.g4 b/_server/MotaAction.g4 index f9d8374e..aaa91f53 100644 --- a/_server/MotaAction.g4 +++ b/_server/MotaAction.g4 @@ -4026,8 +4026,8 @@ EquipValueType_List /*EquipValueType_List ['value','percentage']*/; Vibrate_List - : '左右'|'上下'|'左上-右下'|'左下-右上' - /*Vibrate_List ['horizontal','vertical','diagonal1','diagonal2']*/; + : '左右'|'上下'|'左上-右下'|'左下-右上'|'随机' + /*Vibrate_List ['horizontal','vertical','diagonal1','diagonal2','random']*/; Colour : 'sdeirughvuiyasdeb'+ //为了被识别为复杂词法规则 @@ -4102,8 +4102,8 @@ Move_List /*Move_List ['up','down','left','right','forward','backward','leftup','leftdown','rightup','rightdown','speed']*/; MoveMode_List - : '匀速移动'|'缓入快出'|'快入缓出'|'缓入缓出' - /*MoveMode_List ['', 'easeIn', 'easeOut', 'easeInOut']*/; + : '匀速移动'|'缓入快出'|'快入缓出'|'缓入缓出'|'随机' + /*MoveMode_List ['', 'easeIn', 'easeOut', 'easeInOut', 'random']*/; NameMap_List : '确定'|'取消'|'操作失败'|'光标移动'|'打开界面'|'读档'|'存档'|'获得道具'|'回血'|'宝石'|'炸弹'|'飞行器'|'开关门'|'上下楼'|'跳跃'|'破墙镐'|'破冰镐'|'阻激夹域'|'穿脱装备'|'商店' diff --git a/_server/editor_multi.js b/_server/editor_multi.js index dfce058d..8014ef2c 100644 --- a/_server/editor_multi.js +++ b/_server/editor_multi.js @@ -282,6 +282,18 @@ editor_multi = function () { }).length > 0; } + var _previewButton = document.getElementById('editor_multi_preview'); + + _previewButton.onclick = function () { + if (!editor_multi.preview) return; + _format(); + if (editor_multi.hasError()) { + alert("当前好像存在严重的语法错误,请处理后再预览。"); + return; + } + editor.uievent.previewEditorMulti(editor_multi.preview, codeEditor.getValue()); + } + editor_multi.import = function (id_, args) { var thisTr = document.getElementById(id_); if (!thisTr) return false; @@ -292,6 +304,8 @@ editor_multi = function () { editor_multi.id = id_; editor_multi.isString = false; editor_multi.lintAutocomplete = false; + editor_multi.preview = args.preview; + _previewButton.style.display = editor_multi.preview ? 'inline' : 'none'; if (args.lint === true) editor_multi.lintAutocomplete = true; if ((!input.value || input.value == 'null') && args.template) input.value = '"' + args.template + '"'; @@ -318,7 +332,7 @@ editor_multi = function () { _setValue(tstr || ''); } editor_multi.show(); - codeEditor.scrollTo(0, lastOffset[id_] || 0); + codeEditor.scrollTo(0, lastOffset[editor_multi.id] || 0); return true; } diff --git a/_server/editor_table.js b/_server/editor_table.js index 1797b7f5..341164f2 100644 --- a/_server/editor_table.js +++ b/_server/editor_table.js @@ -419,7 +419,7 @@ editor_table_wrapper = function (editor) { var cobj = JSON.parse(tr.children[1].getAttribute('cobj')); var input = tr.children[2].children[0].children[0]; if (cobj._type === 'event') editor_blockly.import(guid, { type: cobj._event }); - if (cobj._type === 'textarea') editor_multi.import(guid, { lint: cobj._lint, string: cobj._string, template: cobj._template }); + if (cobj._type === 'textarea') editor_multi.import(guid, { lint: cobj._lint, string: cobj._string, template: cobj._template, preview: cobj._preview }); if (cobj._type === 'material') editor.table.selectMaterial(input, cobj); if (cobj._type === 'color') editor.table.selectColor(input); if (cobj._type === 'point') editor.table.selectPoint(input); @@ -451,7 +451,7 @@ editor_table_wrapper = function (editor) { editor_table.prototype.dblclickfunc = function (guid, obj, commentObj, thisTr, input, field, cobj, modeNode) { if (editor_mode.doubleClickMode === 'change') { if (cobj._type === 'event') editor_blockly.import(guid, { type: cobj._event }); - if (cobj._type === 'textarea') editor_multi.import(guid, { lint: cobj._lint, string: cobj._string, template: cobj._template }); + if (cobj._type === 'textarea') editor_multi.import(guid, { lint: cobj._lint, string: cobj._string, template: cobj._template, preview: cobj._preview }); if (cobj._type === 'material') editor.table.selectMaterial(input, cobj); if (cobj._type === 'color') editor.table.selectColor(input); if (cobj._type === 'point') editor.table.selectPoint(input); diff --git a/_server/editor_uievent.js b/_server/editor_uievent.js index ac29c3ed..6f27691d 100644 --- a/_server/editor_uievent.js +++ b/_server/editor_uievent.js @@ -13,14 +13,13 @@ editor_uievent_wrapper = function (editor) { uievent.elements.title = document.getElementById('uieventTitle'); uievent.elements.yes = document.getElementById('uieventYes'); uievent.elements.no = document.getElementById('uieventNo'); - uievent.elements.selectBackground = document.getElementById('uieventBackground'); + uievent.elements.select = document.getElementById('uieventSelect'); uievent.elements.selectPoint = document.getElementById('selectPoint'); uievent.elements.selectFloor = document.getElementById('selectPointFloor'); uievent.elements.selectPointBox = document.getElementById('selectPointBox'); uievent.elements.body = document.getElementById('uieventBody'); uievent.elements.selectPointButtons = document.getElementById('selectPointButtons'); uievent.elements.canvas = document.getElementById('uievent'); - uievent.elements.usedFlags = document.getElementById('uieventUsedFlags'); uievent.elements.extraBody = document.getElementById('uieventExtraBody'); uievent.close = function () { @@ -34,17 +33,13 @@ editor_uievent_wrapper = function (editor) { } uievent.elements.no.onclick = uievent.close; - uievent.elements.selectBackground.onchange = function () { - uievent.drawPreviewUI(); - } - uievent.drawPreviewUI = function () { core.setAlpha('uievent', 1); core.clearMap('uievent'); core.setFilter('uievent', null); // 绘制UI - var background = uievent.elements.selectBackground.value; + var background = uievent.elements.select.value; if (background == 'thumbnail') { core.drawThumbnail(editor.currentFloorId, null, {ctx: 'uievent'}); } @@ -92,15 +87,21 @@ editor_uievent_wrapper = function (editor) { uievent.elements.selectPoint.style.display = 'none'; uievent.elements.yes.style.display = 'none'; uievent.elements.title.innerText = 'UI绘制预览'; - uievent.elements.selectBackground.style.display = 'inline'; - uievent.elements.selectBackground.value = 'thumbnail'; + uievent.elements.select.style.display = 'inline'; uievent.elements.selectFloor.style.display = 'none'; uievent.elements.selectPointBox.style.display = 'none'; uievent.elements.canvas.style.display = 'block'; - uievent.elements.usedFlags.style.display = 'none'; uievent.elements.extraBody.style.display = 'none'; uievent.elements.body.style.overflow = "hidden"; + uievent.elements.select.innerHTML = + '' + + '' + + ''; + uievent.elements.select.onchange = function () { + uievent.drawPreviewUI(); + } + uievent.values.list = list; uievent.drawPreviewUI(); } @@ -114,11 +115,10 @@ editor_uievent_wrapper = function (editor) { uievent.mode = 'selectPoint'; uievent.elements.selectPoint.style.display = 'block'; uievent.elements.yes.style.display = 'inline'; - uievent.elements.selectBackground.style.display = 'none'; + uievent.elements.select.style.display = 'none'; uievent.elements.selectFloor.style.display = 'inline'; uievent.elements.selectPointBox.style.display = 'block'; uievent.elements.canvas.style.display = 'block'; - uievent.elements.usedFlags.style.display = 'none'; uievent.elements.extraBody.style.display = 'none'; uievent.elements.body.style.overflow = "hidden"; uievent.elements.yes.onclick = function () { @@ -336,11 +336,10 @@ editor_uievent_wrapper = function (editor) { uievent.elements.selectPoint.style.display = 'none'; uievent.elements.yes.style.display = 'none'; uievent.elements.title.innerText = '搜索变量'; - uievent.elements.selectBackground.style.display = 'none'; + uievent.elements.select.style.display = 'inline'; uievent.elements.selectFloor.style.display = 'none'; uievent.elements.selectPointBox.style.display = 'none'; uievent.elements.canvas.style.display = 'none'; - uievent.elements.usedFlags.style.display = 'inline'; uievent.elements.extraBody.style.display = 'block'; uievent.elements.body.style.overflow = "auto"; @@ -350,13 +349,14 @@ editor_uievent_wrapper = function (editor) { v = "flag:" + v; html += ""; }); - uievent.elements.usedFlags.innerHTML = html; + uievent.elements.select.innerHTML = html; + uievent.elements.select.onchange = uievent.doSearchUsedFlags; uievent.doSearchUsedFlags(); } uievent.doSearchUsedFlags = function () { - var flag = uievent.elements.usedFlags.value; + var flag = uievent.elements.select.value; var html = "

该变量出现的所有位置如下: