diff --git a/_docs/_sidebar.md b/_docs/_sidebar.md index a7960592..039c2ea0 100644 --- a/_docs/_sidebar.md +++ b/_docs/_sidebar.md @@ -3,5 +3,4 @@ - [元件说明](element) - [事件](event) - [个性化](personalization) -- [V2.0版本介绍](V2.0) - [附录:API列表](api) diff --git a/_docs/element.md b/_docs/element.md index 8d352fef..4fed9b92 100644 --- a/_docs/element.md +++ b/_docs/element.md @@ -1,6 +1,6 @@ # 元件说明 -?> 目前版本**v2.5.5**,上次更新时间:* {docsify-updated} * +?> 目前版本**v2.6**,上次更新时间:* {docsify-updated} * 在本章中,将对样板里的各个元件进行说明。各个元件主要包括道具、门、怪物、楼梯等等。 @@ -56,6 +56,8 @@ type为该装备的类型,必填,和上面装备栏一一对应。例如,0 atk/def/mdef为该装备分别增加的攻防魔防数值(支持负数);如果不加也可省略不写。 +从V2.6开始,可以拓展到任何勇士的属性,如hpmax, atk, def, mdef, experience等等;自行添加的属性包括攻速speed也能使用。 + animate为该装备的攻击动画,仅对type为0时有效。具体可参见[动画和天气系统](#动画和天气系统)。 percentage为该装备是否按比例增加属性。 @@ -151,49 +153,13 @@ yellowWall, blueWall, whiteWall 怪物的特殊属性所对应的数字(special)在脚本编辑中的`getSpecials`中定义,请勿对已有的属性进行修改。 -``` js -function() { - // 获得怪物的特殊属性,每一行定义一个特殊属性。 - // 分为三项,第一项为该特殊属性的数字,第二项为特殊属性的名字,第三项为特殊属性的描述 - // 可以直接写字符串,也可以写个function将怪物传进去 - return [ - [1, "先攻", "怪物首先攻击"], - [2, "魔攻", "怪物无视勇士的防御"], - [3, "坚固", "勇士每回合最多只能对怪物造成1点伤害"], - [4, "2连击", "怪物每回合攻击2次"], - [5, "3连击", "怪物每回合攻击3次"], - [6, function(enemy) {return (enemy.n||4)+"连击";}, function(enemy) {return "怪物每回合攻击"+(enemy.n||4)+"次";}], - [7, "破甲", "战斗前,怪物附加角色防御的"+Math.floor(100*core.values.breakArmor||0)+"%作为伤害"], - [8, "反击", "战斗时,怪物每回合附加角色攻击的"+Math.floor(100*core.values.counterAttack||0)+"%作为伤害,无视角色防御"], - [9, "净化", "战斗前,怪物附加勇士魔防的"+core.values.purify+"倍作为伤害"], - [10, "模仿", "怪物的攻防和勇士攻防相等"], - [11, "吸血", function (enemy) {return "战斗前,怪物首先吸取角色的"+Math.floor(100*enemy.value||0)+"%生命作为伤害"+(enemy.add?",并把伤害数值加到自身生命上":"");}], - [12, "中毒", "战斗后,勇士陷入中毒状态,每一步损失生命"+core.values.poisonDamage+"点"], - [13, "衰弱", "战斗后,勇士陷入衰弱状态,攻防暂时下降"+(core.values.weakValue>=1?core.values.weakValue+"点":parseInt(core.values.weakValue*100)+"%")], - [14, "诅咒", "战斗后,勇士陷入诅咒状态,战斗无法获得金币和经验"], - [15, "领域", function (enemy) {return "经过怪物周围"+(enemy.range||1)+"格时自动减生命"+(enemy.value||0)+"点";}], - [16, "夹击", "经过两只相同的怪物中间,勇士生命值变成一半"], - [17, "仇恨", "战斗前,怪物附加之前积累的仇恨值作为伤害"+(core.flags.hatredDecrease?";战斗后,释放一半的仇恨值":"")+"。(每杀死一个怪物获得"+(core.values.hatred||0)+"点仇恨值)"], - [18, "阻击", function (enemy) {return "经过怪物的十字领域时自动减生命"+(enemy.value||0)+"点,同时怪物后退一格";}], - [19, "自爆", "战斗后勇士的生命值变成1"], - [20, "无敌", "勇士无法打败怪物,除非拥有十字架"], - [21, "退化", function (enemy) {return "战斗后勇士永久下降"+(enemy.atkValue||0)+"点攻击和"+(enemy.defValue||0)+"点防御";}], - [22, "固伤", function (enemy) {return "战斗前,怪物对勇士造成"+(enemy.damage||0)+"点固定伤害,无视勇士魔防。";}], - [23, "重生", "怪物被击败后,角色转换楼层则怪物将再次出现"], - [24, "激光", function (enemy) {return "经过怪物同行或同列时自动减生命"+(enemy.value||0)+"点";}] - ]; -} -``` - 多属性可采用数组的写法,比如`'special': [1,3]`视为同时拥有先攻和坚固属性;`'special': [5,10,14,18]`视为拥有3连击、魔防、诅咒、阻击四个属性。 -怪物可以负伤,在`data.js`的全局变量`enableNegativeDamage`中指定。 - -下面的`getSpecialHint`函数则给定了每个特殊属性的详细描述。这个描述将在怪物手册中看到。 +怪物可以负伤,在全塔属性的全局变量`enableNegativeDamage`中指定。 打败怪物后可以进行加点操作。有关加点塔的制作可参见[加点事件](event#加点事件)。 -如果`data.js`中的enableExperience为false,即不启用经验的话,怪物手册里将不显示怪物的经验值,打败怪物也不获得任何经验。 +如果全塔属性中的enableExperience为false,即不启用经验的话,怪物手册里将不显示怪物的经验值,打败怪物也不获得任何经验。 拿到幸运金币后,打怪获得的金币将翻倍。 @@ -286,16 +252,12 @@ N连击怪物的special是6,且我们可以为它定义n代表实际连击数 ## 路障,楼梯,传送门 -血网的伤害数值、中毒后每步伤害数值、衰弱时暂时攻防下降的数值,都在 `data.js` 的values内定义。 +血网的伤害数值、中毒后每步伤害数值、衰弱时暂时攻防下降的数值,都在全塔属性的values内定义。 路障同样会尽量被自动寻路绕过。 有关楼梯和传送门,必须在该层样板的changeFloor里指定传送点的目标。 -![楼层转换](./img/changefloor.png) - -!> **请注意这里的`"x,y"`代表该点的横坐标为x,纵坐标为y;即从左到右第x列,从上到下的第y行(从0开始计算)。如(6,0)代表最上面一行的正中间一列。** - floorId指定的是目标楼层的唯一标识符(ID)。 也可以写`"floorId": ":before"`和`"floorId": ":next"`表示上一楼和下一楼。 @@ -347,7 +309,7 @@ floorId指定的是目标楼层的唯一标识符(ID)。 从V2.4开始,H5魔塔开始支持大地图。 -大地图在创建时可以指定宽高,要求**宽和高都不得小于13,且宽高之积不超过1000**。 +大地图在创建时可以指定宽高,要求**宽和高都不得小于13(15x15版本则是不小于15),且宽高之积不超过1000**。 大地图一旦创建成功则不得修改宽高数值。 @@ -355,13 +317,12 @@ floorId指定的是目标楼层的唯一标识符(ID)。 现在我们的H5魔塔支持播放动画,也支持天气系统了。 -要播放动画,你需要先使用“RM动画导出器”将动画导出,放在animates目录下,然后再data.js中定义。 +要播放动画,你需要先使用“RM动画导出器”将动画导出,放在animates目录下,然后在全塔属性的animates中定义。 ``` js -"animates": [// 在此存放所有可能使用的动画,必须是animate格式,在这里不写后缀名 - // 动画必须放在animates目录下;文件名不能使用中文,不能带空格或特殊字符 - "hand", "sword", "zone", "yongchang", "thunder" // 根据需求自行添加 -] +// 在此存放所有可能使用的动画,必须是animate格式,在这里不写后缀名 +// 动画必须放在animates目录下;文件名不能使用中文,不能带空格或特殊字符 +"animates": ["hand", "sword", "zone", "yongchang", "thunder"] ``` !> 动画必须是animate格式,名称不能使用中文,不能带空格或特殊字符。 @@ -376,9 +337,9 @@ floorId指定的是目标楼层的唯一标识符(ID)。 !> 播放录像时,将默认忽略所有动画。 -目前天气系统只支持雨和雪两种天气。 +目前天气系统支持雨和雪和雾两种天气。 -在每层楼的剧本文件里存在一个weather选项,表示该层楼的默认天气。 +在每层楼的楼层属性中存在一个weather选项,表示该层楼的默认天气。 ``` js // 该层的默认天气。本项可忽略表示晴天,如果写则第一项为"rain","snow"或"fog"代表雨雪雾,第二项为1-10之间的数代表强度。 @@ -394,24 +355,18 @@ floorId指定的是目标楼层的唯一标识符(ID)。 要播放音乐和音效,你需要将对应的文件放在sounds目录下,然后在全塔属性中进行定义 ``` js -"bgms": [ // 在此存放所有的bgm,和文件名一致。 - // 音频名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好 - 'bgm.mp3' -]; -"sounds": [ // 在此存放所有的SE,和文件名一致 - // 音频名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好 - 'floor.mp3', 'attack.mp3', 'door.mp3', 'item.mp3', 'zone.mp3' -] +// 在此存放所有的bgm,和文件名一致。 +// 音频名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好 +"bgms": ["bgm.mp3"] + +// 在此存放所有的SE,和文件名一致 +"sounds": ["floor.mp3", "attack.mp3", "door.mp3", "item.mp3", "zone.mp3"] ``` !> 音频名不能使用中文,不能带空格或特殊字符。 -目前BGM支持主流的音乐格式,如mp3, ogg,格式等。不支持mid格式的播放。 - 定义完毕后,我们可以调用`playBgm`/`playSound`事件来播放对应的音乐/音效,有关事件的详细介绍请参见[事件](event)。 **另外,考虑到用户的流量问题,将遵循如下规则:** @@ -443,7 +398,7 @@ HTML5魔塔一大亮点就是存在录像系统,可以很方便进行录像回 录像的回放主要有两种方式: 1. 保存成的录像文件(.h5route文件):在标题界面点录像回放,再选择文件即可。 -2. 游戏过程中时的当前录像:随时按R可以进行回放;手机端则长按任何位置3秒以上调出虚拟键盘,再按R。 +2. 游戏过程中时的当前录像:随时按R可以进行回放;手机端则可调出虚拟键盘,再按R。 录像播放过程中,可以进行如下操作: @@ -474,6 +429,9 @@ HTML5魔塔一大亮点就是存在录像系统,可以很方便进行录像回 ## 操作说明 +![](img/keyboard.png) + +   diff --git a/_docs/img/keyboard.png b/_docs/img/keyboard.png new file mode 100644 index 00000000..c2b9d241 Binary files /dev/null and b/_docs/img/keyboard.png differ diff --git a/_docs/index.md b/_docs/index.md index cb6a896c..d2f290e2 100644 --- a/_docs/index.md +++ b/_docs/index.md @@ -1,11 +1,10 @@ # HTML5 魔塔样板说明文档 -?> 目前版本**v2.5.5**,上次更新时间:* {docsify-updated} * +?> 目前版本**v2.6**,上次更新时间:* {docsify-updated} * 众所周知,魔塔的趋势是向移动端发展,贴吧中也常常能见到“求手机魔塔”的帖子。然而现有的工具中,NekoRPG有着比较大的局限性,游戏感较差,更是完全没法在iOS上运行。而一些APP的魔塔虽然可用,但是必须要下载安装,对于Android和iOS还必须开发不同的版本,非常麻烦。 但是,现在我们有了HTML5。 HTML5的画布(canvas)以及它被Android/iOS内置浏览器所支持的特性,可以让我们做出真正意义上的全平台覆盖的魔塔。 -事实上,在贴吧的试水发布也证明了,H5魔塔确实是可以成功的。两部即使是复刻的魔塔也受到了不少人的追捧,其流畅的手感和全平台支持的特性,也让很多没办法打开电脑的人爱不释手。 然而,一般而言使用非RMXP制作魔塔往往需要一定的编程技术,HTML5魔塔自然也不例外。但是,为了能让大家更加注重于“做塔”本身,而不用考虑做塔以外的各种脚本问题,我特意制作了这样一部HTML5的魔塔样板。 diff --git a/_docs/start.md b/_docs/start.md index a68ac244..004ea21f 100644 --- a/_docs/start.md +++ b/_docs/start.md @@ -1,6 +1,6 @@ # 快速上手 -?> 目前版本**v2.5.5**,上次更新时间:* {docsify-updated} * +?> 目前版本**v2.6**,上次更新时间:* {docsify-updated} * 在这一节中,将详细介绍做一部塔的流程。现在,让我们来做一部单层塔! @@ -28,6 +28,7 @@ * “地图编辑器”允许你以可视化的方式进行编辑地图。 * “便捷PS工具”能让你很方便的对自定义素材进行添加。参见[自定义素材](personalization#自定义素材)。 * “地图生成器”能让你从已有的截图(如RMXP项目)中立刻生成可被本样板识别的地图数据。 +* “怪物数据导出”能让你从RMXP中导出怪物数据而被H5魔塔使用。 * “RM动画导出器”能让你从RMXP中导出动画而被H5魔塔使用。 * “JS代码压缩工具”能对JS代码进行压缩,从而减少IO请求数和文件大小。 * “伤害和临界值计算器”是一个很便捷的小工具,能对怪物的伤害和临界值进行计算。 @@ -54,6 +55,8 @@ ### 从RMXP导入已有的地图 +!> 注:现在已经不推荐此方法,如需从RM刻塔请使用 [RM转H5刻塔器使用教程](https://www.bilibili.com/video/av43125840) 进行操作。 + 如果我们想复刻一个现有的,已经被RMXP所制作的塔,也有很便捷的方式,那就是用到我们的“地图生成器”。 首先,我们打开RMXP和对应的项目,可以看到它的地图。 @@ -176,7 +179,7 @@ 之后刷新编辑器即可。 -对于怪物和道具,我们也可以进行自动注册,只需要点击“自动注册”按钮,将对该栏下所有未注册的素材进行自动注册(自动分配ID和数字)。 +也可以进行自动注册,只需要点击“自动注册”按钮,将对该栏下所有未注册的素材进行自动注册(自动分配ID和数字)。 素材注册完毕后,即可在游戏中正常使用,也可以被地图生成器所识别(需要重开地图生成器)。 @@ -230,6 +233,18 @@ HTML5的塔都是可以进行控制台调试的。 更多API和详细参数介绍可参见[API列表](api)。 +## 编辑器的基本操作 + +- **Alt+0~9, Ctrl+0~9** 保存和读取当前选中图块 +- **W/A/S/D** 移动大地图 +- **Ctrl+Z** 撤销上次绘图 +- **Ctrl+Y** 重做上次绘图 +- **PgUp/PgDn** 切换楼层 +- **Ctrl+S** 保存事件编辑器/脚本编辑器 +- **地图上单击** 选中该点 +- **地图上双击** 选中该点图块 +- **地图上右键** 弹出菜单栏,包括选中、复制、清除等操作 +- **事件编辑器中Ctrl+C, Ctrl+X, 右键等** 执行相应操作 ## 报错处理 diff --git a/_server/MotaAction.g4 b/_server/MotaAction.g4 index 1fa52eba..bb3e0f44 100644 --- a/_server/MotaAction.g4 +++ b/_server/MotaAction.g4 @@ -85,13 +85,25 @@ shopcommonevent tooltip : 全局商店, 执行一个公共事件 helpUrl : https://h5mota.com/games/template/docs/#/ default : ["shop1","回收钥匙商店",false,"回收钥匙商店",""] +if (EvalString_2) { + if (EvalString_2.indexOf('"')>=0) + throw new Error('请勿在此处使用双引号!尝试使用单引号吧~'); + // 检查是不是数组 + try { + EvalString_2 = JSON.parse(EvalString_2.replace(/'/g, '"')); + if (!(EvalString_2 instanceof Array)) throw new Error(); + } + catch (e) { + throw new Error('参数列表必须是个有效的数组!'); + } +} var code = { 'id': IdString_0, 'textInList': EvalString_0, 'mustEnable': Bool_0, - 'commonEvent': EvalString_1, - 'args': EvalString_2 + 'commonEvent': EvalString_1 } +if (EvalString_2) code.args = EvalString_2; code=JSON.stringify(code,null,2)+',\n'; return code; */; @@ -322,7 +334,7 @@ action | callBook_s | callSave_s | callLoad_s - | unknow_s + | unknown_s | function_s | pass_s ; @@ -1746,17 +1758,19 @@ var code = '{"type": "callLoad"},\n'; return code; */; -unknow_s +unknown_s : '自定义事件' BGNL? RawEvalString -/* unknow_s +/* unknown_s tooltip : 通过脚本自定义的事件类型, 以及编辑器不识别的事件类型 helpUrl : https://h5mota.com/games/template/docs/#/ -default : ['{"type":"eventType1"}'] +default : ['{"type":"test", "data": "这是自定义的参数"}'] colour : this.dataColor -var tempobj={}; -eval("tempobj='"+RawEvalString_0+"'"); -var code = tempobj +',\n'; +try { + var tempobj = JSON.parse(RawEvalString_0); +} catch (e) {throw new Error("不合法的JSON格式!");} +if (!tempobj.type) throw new Error("自定义事件需要一个type:xxx"); +var code = JSON.stringify(tempobj) +',\n'; return code; */; @@ -2148,8 +2162,13 @@ ActionParser.prototype.parse = function (obj,type) { ]); } var buildcommentevent = function(obj,parser,next){ + if (obj.args instanceof Array) { + try { obj.args = JSON.stringify(obj.args).replace(/"/g, "'"); } + catch (e) {obj.args = '';} + } + else obj.args = null; return MotaActionBlocks['shopcommonevent'].xmlText([ - obj.id,parser.EvalString(obj.textInList),obj.mustEnable,parser.EvalString(obj.commonEvent),parser.EvalString(obj.args),next + obj.id,parser.EvalString(obj.textInList),obj.mustEnable,parser.EvalString(obj.commonEvent),obj.args,next ]); } var next=null; @@ -2651,13 +2670,8 @@ ActionParser.prototype.parseAction = function() { case "animateImage": // 兼容 animateImage break; default: - var rawdata = JSON.stringify(data,function(k,v){ - if(typeof(v)=='string')return v.split('\n').join('\\n'); - else return v; - },2); - rawdata=rawdata.split('\n').join('\\n'); - this.next = MotaActionBlocks['unknow_s'].xmlText([ - rawdata,this.next]); + this.next = MotaActionBlocks['unknown_s'].xmlText([ + JSON.stringify(data),this.next]); } this.parseAction(); return; diff --git a/_server/editor_blockly.js b/_server/editor_blockly.js index 92ecfee2..595a55ff 100644 --- a/_server/editor_blockly.js +++ b/_server/editor_blockly.js @@ -159,6 +159,7 @@ editor_blockly = function () { ], '原生脚本':[ MotaActionBlocks['function_s'].xmlText(), + MotaActionBlocks['unknown_s'].xmlText(), ], '值块':[ MotaActionBlocks['setValue_s'].xmlText([ @@ -588,7 +589,6 @@ function omitedcheckUpdateFunction(event) { 'showTextImage_s': 'EvalString_0', 'function_s': 'RawEvalString_0', 'shopsub': 'EvalString_3', - 'unknow_s': 'RawEvalString_0', } var f = b ? textStringDict[b.type] : null; if (f) { diff --git a/libs/actions.js b/libs/actions.js index ad1c3c1d..917af40f 100644 --- a/libs/actions.js +++ b/libs/actions.js @@ -717,7 +717,7 @@ actions.prototype._sys_keyDownCtrl = function () { } if (core.status.event.id == 'action' && core.status.event.data.type == 'sleep' && !core.status.event.data.current.noSkip) { - if (core.timeout.sleepTimeout && Object.keys(core.animateFrame.asyncId).length == 0) { + if (core.timeout.sleepTimeout && !core.hasAsync()) { clearTimeout(core.timeout.sleepTimeout); core.timeout.sleepTimeout = null; core.doAction(); @@ -752,7 +752,7 @@ actions.prototype._sys_longClick_lockControl = function (x, y) { // 长按可以跳过等待事件 if (core.status.event.id == 'action' && core.status.event.data.type == 'sleep' && !core.status.event.data.current.noSkip) { - if (core.timeout.sleepTimeout && Object.keys(core.animateFrame.asyncId).length == 0) { + if (core.timeout.sleepTimeout && !core.hasAsync()) { clearTimeout(core.timeout.sleepTimeout); core.timeout.sleepTimeout = null; core.doAction(); @@ -1198,35 +1198,21 @@ actions.prototype._keyUpShop = function (keycode) { ////// 快捷商店界面时的点击操作 ////// actions.prototype._clickQuickShop = function (x, y) { - var keys = []; - if (core.flags.quickCommonEvents) { - keys = core.getFlag("__commonEventList__", []); - } - else { - keys = Object.keys(core.status.shops).filter(function (shopId) { - return core.status.shops[shopId].visited || !core.status.shops[shopId].mustEnable - }); - } + var keys = Object.keys(core.status.shops).filter(function (shopId) { + return core.status.shops[shopId].visited || !core.status.shops[shopId].mustEnable + }); if (x >= this.CHOICES_LEFT && x <= this.CHOICES_RIGHT) { var topIndex = this.HSIZE - parseInt(keys.length / 2); if (y >= topIndex && y < topIndex + keys.length) { - if (core.flags.quickCommonEvents) { - var name = keys[y - topIndex]; - core.ui.closePanel(); - core.status.route.push("common:" + core.encodeBase64(name)); - core.insertAction(name); - } - else { - var reason = core.events.canUseQuickShop(keys[y - topIndex]); - if (!core.flags.enableDisabledShop && reason) { - core.drawText(reason); - return; - } - core.events.openShop(keys[y - topIndex], true); - if (core.status.event.id == 'shop') - core.status.event.data.fromList = true; + var reason = core.events.canUseQuickShop(keys[y - topIndex]); + if (!core.flags.enableDisabledShop && reason) { + core.drawText(reason); + return; } + core.events.openShop(keys[y - topIndex], true); + if (core.status.event.id == 'shop') + core.status.event.data.fromList = true; } // 离开 else if (y == topIndex + keys.length) @@ -1240,17 +1226,10 @@ actions.prototype._keyUpQuickShop = function (keycode) { core.ui.closePanel(); return; } - var length = 0; - if (core.flags.quickCommonEvents) { - length = core.getFlag("__commonEventList__", []).length; - } - else { - var shopList = core.status.shops, keys = Object.keys(shopList).filter(function (shopId) { - return shopList[shopId].visited || !shopList[shopId].mustEnable - }); - length = keys.length; - } - this._selectChoices(length + 1, keycode, this._clickQuickShop); + var keys = Object.keys(core.status.shops).filter(function (shopId) { + return core.status.shops[shopId].visited || !core.status.shops[shopId].mustEnable + }); + this._selectChoices(keys.length + 1, keycode, this._clickQuickShop); return; } diff --git a/libs/control.js b/libs/control.js index fa0eaf5a..7a1de28b 100644 --- a/libs/control.js +++ b/libs/control.js @@ -33,7 +33,6 @@ control.prototype._init = function () { this.registerReplayAction("fly", this._replayAction_fly); this.registerReplayAction("shop", this._replayAction_shop); this.registerReplayAction("turn", this._replayAction_turn); - this.registerReplayAction("common", this._replayAction_common); this.registerReplayAction("getNext", this._replayAction_getNext); this.registerReplayAction("moveDirectly", this._replayAction_moveDirectly); this.registerReplayAction("key", this._replayAction_key); @@ -169,25 +168,22 @@ control.prototype._animationFrame_animate = function (timestamp) { if (timestamp - core.animateFrame.animateTime < 50 || !core.status.animateObjs || core.status.animateObjs.length == 0) return; core.clearMap('animate'); // 更新帧 - var animateObjs = []; - for (var i=0;i 0 || (core.status.animateObjs || []).length > 0; +} + ////// 跟随 ////// events.prototype.follow = function (name) { core.status.hero.followers = core.status.hero.followers || []; @@ -2105,9 +2085,9 @@ events.prototype.openShop = function (shopId, needVisited) { shop.times = shop.times || 0; if (shop.commonTimes) shop.times = core.getFlag('commonTimes', 0); if (needVisited && !shop.visited) { - if (!core.flags.enableDisabledShop) { - if (shop.times == 0) core.drawTip("该商店尚未开启"); - else core.drawTip("该商店已失效"); + if (!core.flags.enableDisabledShop || shop.commonEvent) { + if (shop.times == 0) core.drawTip("该项尚未开启"); + else core.drawTip("该项已失效"); return; } else { @@ -2115,6 +2095,13 @@ events.prototype.openShop = function (shopId, needVisited) { } } else shop.visited = true; + + // --- 商店 + if (shop.commonEvent) { + core.status.route.push("shop:"+shopId+":0"); + core.insertAction({"type": "insert", "name": shop.commonEvent, "args": shop.args}); + return; + } core.ui.drawShop(shopId); } diff --git a/libs/maps.js b/libs/maps.js index 9d05a272..445fc113 100644 --- a/libs/maps.js +++ b/libs/maps.js @@ -30,12 +30,14 @@ maps.prototype.loadFloor = function (floorId, map) { map = {"map": map}; } var content = {}; + var notCopy = ["firstArrive", "eachArrive", "parallelDo", "map", "bgmap", "fgmap", + "events", "changeFloor", "afterBattle", "afterGetItem", "afterOpenDoor", "cannotMove"]; for (var name in floor) { - if (name != 'map' && name != 'bgmap' && name != 'fgmap' && floor[name] != null) + if (notCopy.indexOf(name) == -1 && floor[name] != null) content[name] = core.clone(floor[name]); } for (var name in map) { - if (name != 'map' && name != 'bgmap' && name != 'fgmap' && map[name] != null) + if (notCopy.indexOf(name) == -1 && map[name] != null) content[name] = core.clone(map[name]); } map = this.decompressMap(map.map, floorId); @@ -1832,18 +1834,17 @@ maps.prototype.drawAnimate = function (name, x, y, callback) { // 播放音效 core.playSound(animate.se); - var animateId = parseInt(Math.random() * 100000000); + var id = setTimeout(null); core.status.animateObjs.push({ + "id": id, "animate": animate, "centerX": centerX, "centerY": centerY, "index": 0, - "id": animateId, "callback": callback }); - core.animateFrame.asyncId[animateId] = true; - return animateId; + return id; } ////// 绘制动画的某一帧 ////// @@ -1881,7 +1882,6 @@ maps.prototype.stopAnimate = function (id, doCallback) { for (var i = 0; i < core.status.animateObjs.length; i++) { var obj = core.status.animateObjs[i]; if (obj.id == id) { - delete core.animateFrame.asyncId[obj.id]; if (doCallback) { (function (callback) { setTimeout(function () { @@ -1890,10 +1890,8 @@ maps.prototype.stopAnimate = function (id, doCallback) { })(obj.callback); } } - core.status.animateObjs.splice(i, 1); - if (core.status.animateObjs.length == 0) { - core.clearMap('animate'); - } - break; } + core.status.animateObjs = core.status.animateObjs.filter(function (x) { return x.id != id }); + if (core.status.animateObjs.length == 0) + core.clearMap('animate'); } diff --git a/libs/ui.js b/libs/ui.js index 7529f589..8a569922 100644 --- a/libs/ui.js +++ b/libs/ui.js @@ -1118,18 +1118,12 @@ ui.prototype.drawSettings = function () { ////// 绘制快捷商店选择栏 ////// ui.prototype.drawQuickShop = function () { core.status.event.id = 'selectShop'; - var choices; - if (core.flags.quickCommonEvents) { - choices = core.clone(core.getFlag("__commonEventList__", [])); - } - else { - var shopList = core.status.shops, keys = Object.keys(shopList).filter(function (shopId) { - return shopList[shopId].visited || !shopList[shopId].mustEnable - }); - choices = keys.map(function (shopId) { - return {"text": shopList[shopId].textInList, "color": shopList[shopId].visited?null:"#999999"}; - }); - } + var shopList = core.status.shops, keys = Object.keys(shopList).filter(function (shopId) { + return shopList[shopId].visited || !shopList[shopId].mustEnable + }); + var choices = keys.map(function (shopId) { + return {"text": shopList[shopId].textInList, "color": shopList[shopId].visited?null:"#999999"}; + }); choices.push("返回游戏"); this.drawChoices(null, choices); } diff --git a/libs/utils.js b/libs/utils.js index 4dbd3e34..d3bac9d3 100644 --- a/libs/utils.js +++ b/libs/utils.js @@ -467,8 +467,6 @@ utils.prototype._encodeRoute_encodeOne = function (t) { return "P" + t.substring(6); else if (t.indexOf('input2:') == 0) return "Q" + t.substring(7) + ":"; - else if (t.indexOf('common:') == 0) - return "c" + t.substring(7) + ":"; else if (t == 'no') return 'N'; else if (t.indexOf('move:') == 0) @@ -527,7 +525,7 @@ utils.prototype._decodeRoute_number2id = function (number) { } utils.prototype._decodeRoute_decodeOne = function (decodeObj, c) { - var nxt = (c == 'I' || c == 'e' || c == 'F' || c == 'S' || c == 'Q' || c == 't' || c == 'c') ? + var nxt = (c == 'I' || c == 'e' || c == 'F' || c == 'S' || c == 'Q' || c == 't') ? this._decodeRoute_getString(decodeObj) : this._decodeRoute_getNumber(decodeObj); var mp = {"U": "up", "D": "down", "L": "left", "R": "right"}; @@ -572,9 +570,6 @@ utils.prototype._decodeRoute_decodeOne = function (decodeObj, c) { case "Q": decodeObj.ans.push("input2:" + nxt); break; - case "c": - decodeObj.ans.push("common:" + nxt); - break; case "N": decodeObj.ans.push("no"); break; diff --git a/project/data.js b/project/data.js index 5b612081..096e2dc6 100644 --- a/project/data.js +++ b/project/data.js @@ -303,10 +303,9 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = }, { "id": "keyShop1", - "textInList": "1F回收钥匙商店", + "textInList": "回收钥匙商店", "mustEnable": false, - "commonEvent": "回收钥匙商店", - "args": "" + "commonEvent": "回收钥匙商店" } ], "levelUp": [ @@ -408,7 +407,6 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = "enableMoveDirectly": true, "enableDisabledShop": true, "disableShopOnDamage": false, - "quickCommonEvents": false, "checkConsole": false } } \ No newline at end of file