diff --git a/_server/table/comment.js b/_server/table/comment.js index 5bac4a9b..93192161 100644 --- a/_server/table/comment.js +++ b/_server/table/comment.js @@ -295,6 +295,11 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_range": "thiseval==~~thiseval||thiseval==null", "_data": "该图块的全局动画帧数。\n如果此项为null,则对于除了npc48外,使用素材默认帧数;npc48默认是1帧(即静止)。" }, + "doorInfo": { + "_leaf": true, + "_type": "textarea", + "_data": "该图块的门信息,是一个三元数组。\n第一项为所需要的钥匙信息,第二项为开此门时的音效,第三项为关此门时的音效。仅对animates生效。" + }, "faceIds": { "_leaf": true, "_type": "textarea", @@ -452,9 +457,9 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_type": "object", "_leaf": false, "_action": function (args) { - args.vobj=args.vobj||{}; - for(var ii=0;ii<2;ii++){ - args.vobj[ii]=args.vobj[ii]||null; + args.vobj = args.vobj || {}; + for (var ii = 0; ii < 2; ii++) { + args.vobj[ii] = args.vobj[ii] || null; } }, "_data": function (key) { diff --git a/libs/events.js b/libs/events.js index 36c7eed4..5faa366f 100644 --- a/libs/events.js +++ b/libs/events.js @@ -409,39 +409,52 @@ events.prototype.openDoor = function (x, y, needKey, callback) { }); return; } - core.playSound("door.mp3"); this._openDoor_animate(id, x, y, callback); } events.prototype._openDoor_check = function (id, x, y, needKey) { - // 是否存在门或暗墙 - if (!core.terrainExists(x, y, id) || !(id.endsWith("Door") || id.endsWith("Wall")) - || core.material.icons.animates[id] == null) { + var clearAndReturn = function () { core.clearContinueAutomaticRoute(); return false; } + // 是否存在门或暗墙 + if (core.material.icons.animates[id] == null) { + return clearAndReturn(); + } + if (id == 'steelDoor' && core.flags.steelDoorWithoutKey) needKey = false; - - if (needKey && id.endsWith("Door")) { - var key = id.replace("Door", "Key"); - if (!core.hasItem(key)) { - if (key != "specialKey") - core.drawTip("你没有" + ((core.material.items[key] || {}).name || "钥匙"), null, true); - else core.drawTip("无法开启此门", null, true); - core.clearContinueAutomaticRoute(); - return false; + var doorInfo = core.getBlockById(id).event; + if (doorInfo == null || doorInfo.doorInfo == null) + return clearAndReturn(); + doorInfo = doorInfo.doorInfo; + // Check all keys + var keyInfo = doorInfo[0]; + if (needKey) { + if (keyInfo == null) { + core.drawTip("无法开启此门", null, true); + return clearAndReturn(); + } + for (var keyName in keyInfo) { + var keyValue = keyInfo[keyName]; + if (core.itemCount(keyName) < keyValue) { + core.drawTip("你没有" + ((core.material.items[keyName] || {}).name || "钥匙"), null, true); + return false; + } } if (!core.status.event.id) core.autosave(true); - core.removeItem(key); + for (var keyName in keyInfo) { + core.removeItem(keyName, keyInfo[keyName]); + } } + core.playSound(doorInfo[1] || 'door.mp3'); return true; } events.prototype._openDoor_animate = function (id, x, y, callback) { var door = core.material.icons.animates[id]; - var speed = id.endsWith("Door") ? 30 : 70; + var speed = 40; var locked = core.status.lockControl; core.lockControl(); @@ -2455,15 +2468,20 @@ events.prototype.setGlobalFlag = function (name, value) { events.prototype.closeDoor = function (x, y, id, callback) { id = id || ""; - if (!(id.endsWith("Door") || id.endsWith("Wall")) - || core.material.icons.animates[id] == null || core.getBlock(x, y) != null) { + if (core.material.icons.animates[id] == null || core.getBlock(x, y) != null) { if (callback) callback(); return; } + var doorInfo = (core.getBlockById(id).event || {}).doorInfo; + if (doorInfo == null) { + if (callback) callback(); + return; + } + // 关门动画 - core.playSound('door.mp3'); + core.playSound(doorInfo[2] || 'door.mp3'); var door = core.material.icons.animates[id]; - var speed = id.endsWith("Door") ? 30 : 70, state = 0; + var speed = 40, state = 0; var animate = window.setInterval(function () { state++; if (state == 4) { diff --git a/libs/maps.js b/libs/maps.js index b6fdeed3..eb2f8972 100644 --- a/libs/maps.js +++ b/libs/maps.js @@ -90,6 +90,10 @@ maps.prototype.getBlockByNumber = function (number) { return core.status.number2Block[number] = this.initBlock(null, null, number, true); } +maps.prototype.getBlockById = function (id) { + return this.getBlockByNumber(this.getNumberById(id)); +} + ////// 数字和ID的对应关系 ////// maps.prototype.initBlock = function (x, y, id, addInfo, eventFloor) { var disable = null; diff --git a/project/icons.js b/project/icons.js index 894f5fdc..bb14aa99 100644 --- a/project/icons.js +++ b/project/icons.js @@ -32,48 +32,39 @@ var icons_4665ee12_3a1f_44a4_bea3_0fccba634dc1 = "ground": 0, "grass": 1, "grass2": 2, - "yellowWall": 3, - "whiteWall": 4, - "blueWall": 5, - "snowGround": 6, - "ground2": 7, - "ground3": 8, - "ground4": 9, - "sand": 10, - "ground5": 11, - "yellowWall2": 12, - "whiteWall2": 13, - "blueWall2": 14, - "blockWall": 15, - "grayWall": 16, - "white": 17, - "ground6": 18, - "soil": 19, - "ground7": 20, - "ground8": 21, - "ice": 22, - "downFloor": 23, - "upFloor": 24, - "yellowDoor": 25, - "blueDoor": 26, - "redDoor": 27, - "greenDoor": 28, - "specialDoor": 29, - "steelDoor": 30, - "blueShopLeft": 31, - "blueShopRight": 32, - "pinkShopLeft": 33, - "pinkShopRight": 34, - "arrowUp": 35, - "arrowDown": 36, - "arrowLeft": 37, - "arrowRight": 38, - "light": 39, - "darkLight": 40, - "ski": 41, - "flower": 42, - "box": 43, - "boxed": 44 + "snowGround": 3, + "ground2": 4, + "ground3": 5, + "ground4": 6, + "sand": 7, + "ground5": 8, + "yellowWall2": 9, + "whiteWall2": 10, + "blueWall2": 11, + "blockWall": 12, + "grayWall": 13, + "white": 14, + "ground6": 15, + "soil": 16, + "ground7": 17, + "ground8": 18, + "ice": 19, + "downFloor": 20, + "upFloor": 21, + "blueShopLeft": 22, + "blueShopRight": 23, + "pinkShopLeft": 24, + "pinkShopRight": 25, + "arrowUp": 26, + "arrowDown": 27, + "arrowLeft": 28, + "arrowRight": 29, + "light": 30, + "darkLight": 31, + "ski": 32, + "flower": 33, + "box": 34, + "boxed": 35 }, "animates": { "star": 0, diff --git a/project/images/terrains.png b/project/images/terrains.png index 55239f66..2d24c3bb 100644 Binary files a/project/images/terrains.png and b/project/images/terrains.png differ diff --git a/project/maps.js b/project/maps.js index b407a02a..11cca708 100644 --- a/project/maps.js +++ b/project/maps.js @@ -1,8 +1,8 @@ var maps_90f36752_8815_4be8_b32b_d7fad1d0542e = { - "1": {"cls":"terrains","id":"yellowWall","canBreak":true}, - "2": {"cls":"terrains","id":"whiteWall","canBreak":true}, - "3": {"cls":"terrains","id":"blueWall","canBreak":true}, + "1": {"cls":"animates","id":"yellowWall","canBreak":true,"animate":1,"doorInfo":[null,"door.mp3","door.mp3"]}, + "2": {"cls":"animates","id":"whiteWall","canBreak":true,"animate":1,"doorInfo":[null,"door.mp3","door.mp3"]}, + "3": {"cls":"animates","id":"blueWall","canBreak":true,"animate":1,"doorInfo":[null,"door.mp3","door.mp3"]}, "4": {"cls":"animates","id":"star","noPass":true}, "5": {"cls":"animates","id":"lava","noPass":true}, "6": {"cls":"terrains","id":"ice"}, @@ -68,12 +68,12 @@ var maps_90f36752_8815_4be8_b32b_d7fad1d0542e = "71": {"cls":"items","id":"shield0"}, "72": {"cls":"items","id":"skill1"}, "73": {"cls":"items","id":"wand"}, - "81": {"cls":"terrains","id":"yellowDoor","trigger":"openDoor"}, - "82": {"cls":"terrains","id":"blueDoor","trigger":"openDoor"}, - "83": {"cls":"terrains","id":"redDoor","trigger":"openDoor"}, - "84": {"cls":"terrains","id":"greenDoor","trigger":"openDoor"}, - "85": {"cls":"terrains","id":"specialDoor","trigger":"openDoor"}, - "86": {"cls":"terrains","id":"steelDoor","trigger":"openDoor"}, + "81": {"cls":"animates","id":"yellowDoor","trigger":"openDoor","animate":1,"doorInfo":[{"yellowKey":1},"door.mp3","door.mp3"]}, + "82": {"cls":"animates","id":"blueDoor","trigger":"openDoor","animate":1,"doorInfo":[{"blueKey":1},"door.mp3","door.mp3"]}, + "83": {"cls":"animates","id":"redDoor","trigger":"openDoor","animate":1,"doorInfo":[{"redKey":1},"door.mp3","door.mp3"]}, + "84": {"cls":"animates","id":"greenDoor","trigger":"openDoor","animate":1,"doorInfo":[{"greenKey":1},"door.mp3","door.mp3"]}, + "85": {"cls":"animates","id":"specialDoor","trigger":"openDoor","animate":1,"doorInfo":[null,"door.mp3","door.mp3"]}, + "86": {"cls":"animates","id":"steelDoor","trigger":"openDoor","animate":1,"doorInfo":[{"steelKey":1},"door.mp3","door.mp3"]}, "87": {"cls":"terrains","id":"upFloor","noPass":false}, "88": {"cls":"terrains","id":"downFloor","noPass":false}, "89": {"cls":"animates","id":"portal","noPass":false}, diff --git a/v2.x-final更新.txt b/v2.x-final更新.txt index b90f8e4c..687fe05a 100644 --- a/v2.x-final更新.txt +++ b/v2.x-final更新.txt @@ -1,3 +1,37 @@ +(已完成!) 1.(来自鹿神)门和像三种基础墙一样的墙应当提供一个“需要消耗多少把哪种钥匙、开关门分别播放什么音效”的属性,如[{"yellowKey": 2, "blueKey": 1}, "door.mp3", "close.mp3"],多种钥匙之间的关系可以为&&或|| +2.(来自小艾)请求修复瞬移判定无视图块属性script项的bug +3. 请求修复(如果还没修复)core.drawTip()不能使用系统图标和clear参数的bug,建议增加一个参数来表示多帧图块绘制第几帧(“UI绘制”类事件中的“绘制图标”同理),增加另一个参数来表示32×48图块绘制哪2/3,手册同理(目前统一绘制最上面2/3) +4. 建议显示文章的\b[]提供top和bottom这两种新写法来实现在顶部或底部显示对话框,目前只有startText、firstArrive、eachArrive、useItemEvent和公共事件等没有当前点的事件中才能用up和down来临时实现这种效果,否则就得设置剧情文本的属性,这在频繁来回切换时是致命的,就像《无上之光》RMXP版地上40层一样 +5. 建议优化core.splitLines()来避免把单词打断和触犯标点禁则,如点号和右标号禁止用于行首,左标号禁止用于行尾 +6. core.drawAnimate()和对应的事件,建议增加一个boolean型参数来表示坐标是绝对坐标(即当前的实现)还是在视野中的相对坐标(以13*13为例相对坐标总是在0~12之间),以实现形如“在视野正中心播放某某动画”的需求(小地图可以写6,6,大地图怎么办) +7. 建议把core.playBgm(bgm, startTime)的startTime参数在事件中也提供出来,以用于一些演出(比如适当的剧情处直接从高潮开始)。同理可以让“暂停背景音乐”记录下当前播放到了第几秒,并在“恢复背景音乐”中自动从这个秒数恢复。作者还可以手动配合音量渐变效果 +8. 系统设置菜单中“音量”和“步时”的点击区并不是根据文本长度自动适配的,这导致作者修改文本(包括但不限于翻译)后玩家难以找到准确的点击区,建议优化 +9. 建议给“显示选择项”、“显示确认框”、“等待用户操作”这三个事件添加一个“若多少毫秒内不响应则触发的分支”,用来实现一些如新新2的QTE,录像中可以记录“choice: timeout”、“confirm: timeout”和“wait: timeout”来表示触发了超时分支 +10. 建议给“转变图块”事件增加一个淡入时间参数,用于原本是空地或空气墙的情况,目前这种效果必须借助存在安全隐患的红点 +11. 建议修复勇士后退时跟随者的鬼畜行为,并推出一套能够对跟随者位置和朝向进行读写的API甚至事件,且允许这些信息被计入存档,以实现一些演出效果甚至游戏要素,如新新2用公主占位防冰块 +12. “设置怪物属性”事件的下拉框目前只支持一部分,另一部分只能通过手敲json再解析来得到,希望提供完整支持 +13. 建议给core.moveAction(callback)提供对应的事件,用于在事件中让勇士像事件外一样移动,从而正常触发跑毒和阻激夹域捕等 +14. core.openShop()和对应的事件,建议在用于公共事件时简单地退化为“插入公共事件”而不要打断当前事件,把决定权交给作者 +15. “等待用户操作”虽然提供了场合块但还不支持将多个按键的场合合并(比如空格、回车和C键一般会被作者予以合并,执行内容如果只是大致相同也值得合并,在块内由作者根据flag再行分歧),建议支持一下 +16. “绘制描边文本”事件建议加一个“描边颜色”参数,目前只能描黑边 +17. “设置画布属性”的基准线建议增加'hanging'和'ideographic'这两种模式 +18. 建议修复“绘制多行文本”时行距比字号大不太多会导致各行下缘丢失的bug(加大行距又会导致第一行的纵坐标难以估计),此bug在道具商店和1.3倍行距英文看的很明显 +19.(来自群友)建议给第一代全局商店的子选项像“显示选择项”一样提供图标、颜色和出现条件(注意长按的适配) +20. 很多事件对应的脚本有默认参数,但在事件中省略参数却会变成0,建议修复 + +图块属性的nopass倒真可以改成勾选框,因为null一定表示不可通行(道具根本没有nopass) + + + + + + + + + + + + (不处理) 0. 部分文案的修改,如“地图编辑器”(启动服务.exe中)、“enemys”、“snipe” (造塔工具相关都给鹿神) 1. 便捷PS工具希望加入自定义单位宽高功能,希望把“白底转透明”增强为“纯色底转透明”(弹窗由作者输入RGB或RGBA值)。 (已修复) 2. 请求修复(如果还没修复)新建单张空白地图无法自定义宽高的bug @@ -79,4 +113,4 @@ 78. 建议移除core.setInitData()并将其内容写在startText以方便作者仿照修改 79. 建议给core.drawHero()添加纵横两个偏移参数(目前只有一个),以用于做一些斜向移动的演出 (文档都给秋橙) 80. 在线文档中“系统使用的flag变量”不够完整,建议加以补充 -(不处理,新增样板非常麻烦) 81. (来自群友)建议做一个17*13的纯横屏样板(大地图只能纵向实现),状态栏自绘在最右边四列,从而彻底摆脱乱七八糟的dom操作 \ No newline at end of file +(不处理,新增样板非常麻烦) 81. (来自群友)建议做一个17*13的纯横屏样板(大地图只能纵向实现),状态栏自绘在最右边四列,从而彻底摆脱乱七八糟的dom操作