diff --git a/API列表.txt b/API列表.txt index 2f846828..4a12de10 100644 --- a/API列表.txt +++ b/API列表.txt @@ -99,9 +99,9 @@ core.status.hero (勇士信息;此项和全塔属性中的hero大体是 core.status.hero.mana 当前魔力值 core.status.hero.atk 当前攻击力 core.status.hero.def 当前防御力 - core.status.hero.mdef 当前魔防值 + core.status.hero.mdef 当前护盾值 core.status.hero.money 当前金币值 - core.status.hero.experience 当前经验值 + core.status.hero.exp 当前经验值 core.status.hero.loc 当前的位置信息 core.status.hero.equipment 当前装上的装备 core.status.hero.items 当前拥有的道具信息 @@ -749,7 +749,7 @@ core.getDamage(enemy, x, y, floorId) core.getExtraDamage(enemy, x, y, floorId) -获得某个怪物的额外伤害值(不可被魔防减伤)。 +获得某个怪物的额外伤害值(不可被护盾减伤)。 目前暂时只包含了仇恨和固伤两者,如有需要可复写该函数。 @@ -815,12 +815,7 @@ core.startGame(hard, seed, route, callback) 开始新游戏。 hard为难度字符串,会被设置为core.status.hard。 seed为开始时要设置的的种子,route为要开始播放的录像,callback为回调函数。 -该函数将重置整个游戏,调用setInitData,执行startText事件,上传游戏人数统计信息等。 - - -core.setInitData() -根据难度分歧来初始化难度,包括设置flag:hard,设置初始属性等。 -该函数实际被转发到了脚本编辑中,执行脚本编辑中的内容。 +该函数将重置整个游戏,执行startText事件,上传游戏人数统计信息等。 core.win(reason, norank) @@ -1042,7 +1037,7 @@ core.follow(name) / core.unfollow(name) 跟随和取消跟随都会调用core.gatherFollowers()来聚集所有的跟随者。 -core.setValue(name, value, prefix) / core.addValue(name, value, prefix) +core.setValue(name, operator, value, prefix) / core.addValue(name, value, prefix) 设置/增减某个数值。name可以是status:xxx,item:xxx或flag:xxx。 value可以是一个表达式,将调用core.calValue()计算。prefix为前缀,独立开关使用,脚本中一般忽略。 @@ -1142,10 +1137,6 @@ core.tryUseItem(itemId) 对于怪物手册和楼传器,将分别调用core.openBook()和core.useFly()函数。 对于中心对称飞行器,则会调用core.drawCenterFly()函数。 对于其他的道具,将检查是否拥有,能否使用,并且进行使用。 - - -core.afterUseBomb() -使用炸弹或圣锤后的事件。实际被转发到了脚本编辑中。 ``` ## icons.js @@ -1242,7 +1233,7 @@ core.unloadEquip(equipType, callback) core.compareEquipment(compareEquipId, beComparedEquipId) 比较两个套装的差异。 -此函数将对所有的勇士属性包括生命魔力攻防魔防金币等进行比较。 +此函数将对所有的勇士属性包括生命魔力攻防护盾金币等进行比较。 如果存在差异的,将作为一个对象返回其差异内容。 @@ -1532,13 +1523,13 @@ core.removeBlock(x, y, floorId) 如果存在自定义事件,则简单的禁用它,以供以后可能的启用事件。 -core.removeBlockById(index, floorId) +core.removeBlockByIndex(index, floorId) 每个楼层的图块存成一个数组,index即为该数组中的索引,每个索引对应该地图中的一个图块 根据索引从地图的block数组中尽可能删除一个图块。floorId可不填或null表示当前楼层。 -core.removeBlockByIds(floorId, ids) -ids为由索引组成的数组,如[0,1]等 +core.removeBlockByIndexes(indexes, floorId) +indexes为由索引组成的数组,如[0,1]等 根据索引数组从地图的block数组中尽可能删除一系列图块。floorId可不填或null表示当前楼层。 @@ -1625,7 +1616,7 @@ core.drawBoxAnimate() 绘制UI层的box动画,如怪物手册和对话框中的帧动画等。 -core.drawAnimate(name, x, y, callback) +core.drawAnimate(name, x, y, alignWindow, callback) 绘制一个动画。name为动画名,x和y为绘制的基准坐标,callback为绘制完毕的回调函数。 此函数将播放动画音效,并异步开始绘制该动画。 此函数会返回一个动画id,可以通过core.stopAnimate()立刻停止该动画的播放。 @@ -1889,8 +1880,8 @@ core.drawStatistics() 绘制数据统计。将从脚本编辑中获得要统计的数据列表,再遍历所有地图进行统计。 -core.drawAbout() / core.drawPaint() / core.drawHelp() -绘制关于界面,绘图模式,帮助界面。 +core.drawAbout() / core.drawHelp() +绘制关于界面,帮助界面。 // ------ 动态创建画布相关的API ------ // @@ -2100,10 +2091,6 @@ core.encodeBase64(str) / core.decodeBase64(str) 可用于解压缩录像数据 -core.convertBase(str, fromBase, toBase) -任意进制转换。此函数可能执行的非常慢,慎用。 - - core.rand(num) 使用伪种子生成伪随机数。该随机函数能被录像支持。 num如果设置大于0,则生成一个[0, num-1]之间的数;否则生成一个0到1之间的浮点数。 @@ -2159,11 +2146,6 @@ core.showWithAnimate(obj, speed, callback) / core.hideWithAnimate(obj, speed, ca 动画淡入或淡出一个对象。 -core.consoleOpened() -检测当前的控制台是否处于开启状态。仅在全塔属性中的检查控制台开关开启时有效。 -此函数有可能会存在误伤行为,即没开过控制台仍认为开启过。 - - core.hashCode(obj) 计算一个对象的哈希值。 diff --git a/_docs/_api.md b/_docs/_api.md index 64362e3b..31880e51 100644 --- a/_docs/_api.md +++ b/_docs/_api.md @@ -52,7 +52,7 @@ core.updateStatusBar() core.setStatus('atk', 1000) -将攻击力设置为1000;这里把atk可以改成hp, def, mdef, money, experience等等。 +将攻击力设置为1000;这里把atk可以改成hp, def, mdef, money, exp等等。 本句等价于 core.status.hero.atk = 1000 @@ -287,7 +287,7 @@ core.closePanel() 结束一切事件和绘制,关闭UI窗口,返回游戏进程。 -core.replaceText(text) +core.replaceText(text, prefix, need, times) 将一段文字中的${}进行计算并替换。 @@ -385,10 +385,6 @@ core.enemys.getDamage(enemyId, x, y, floorId) 后面三个参数是怪物坐标和楼层。 -core.enemys.getExtraDamage(enemyId) -返回某个怪物会对勇士造成的额外伤害(不可被魔防抵消),例如仇恨、固伤等等。 - - core.enemys.nextCriticals(enemyId, number, x, y, floorId) 返回一个列表,为接下来number(可忽略,默认为1)个该怪物的临界值和临界减伤。 列表每一项类似 [x,y] 表示临界值为x,且临界减伤为y。 @@ -481,15 +477,15 @@ core.maps.canMoveDirectly(destX, destY) 该函数如果返回0则不可瞬间移动,大于0则可以瞬间移动,且返回值是跨度(即少走的步数)。 -core.maps.removeBlockById(index, floorId) +core.maps.removeBlockByIndexes(index, floorId) 根据索引删除或禁用某块。 -core.maps.removeBlockByIds(floorId, ids) +core.maps.removeBlockByIndexes(indexes, floorId) 根据索引删除或禁用若干块。 -core.maps.drawAnimate(name, x, y, callback) +core.maps.drawAnimate(name, x, y, alignWindow, callback) 播放一段动画,name为动画名(需在全塔属性注册),x和y为坐标(0-12之间),callback可选,为播放完毕的回调函数。 播放过程是异步的,如需等待播放完毕请使用insertAction插入一条type:waitAsync事件。 此函数将随机返回一个数字id,为此异步动画的唯一标识符。 diff --git a/_docs/api.md b/_docs/api.md index 4965d648..0519a600 100644 --- a/_docs/api.md +++ b/_docs/api.md @@ -99,9 +99,9 @@ core.status.hero (勇士信息;此项和全塔属性中的hero大体是 core.status.hero.mana 当前魔力值 core.status.hero.atk 当前攻击力 core.status.hero.def 当前防御力 - core.status.hero.mdef 当前魔防值 + core.status.hero.mdef 当前护盾值 core.status.hero.money 当前金币值 - core.status.hero.experience 当前经验值 + core.status.hero.exp 当前经验值 core.status.hero.loc 当前的位置信息 core.status.hero.equipment 当前装上的装备 core.status.hero.items 当前拥有的道具信息 @@ -747,11 +747,6 @@ core.getDamage(enemy, x, y, floorId) 如果没有破防或无法战斗则返回null,否则返回具体的伤害值。 -core.getExtraDamage(enemy, x, y, floorId) -获得某个怪物的额外伤害值(不可被魔防减伤)。 -目前暂时只包含了仇恨和固伤两者,如有需要可复写该函数。 - - core.getDamageString(enemy, x, y, floorId) 获得某个怪物伤害字符串和颜色信息,以便于在地图上绘制显伤。 @@ -814,12 +809,7 @@ core.startGame(hard, seed, route, callback) 开始新游戏。 hard为难度字符串,会被设置为core.status.hard。 seed为开始时要设置的的种子,route为要开始播放的录像,callback为回调函数。 -该函数将重置整个游戏,调用setInitData,执行startText事件,上传游戏人数统计信息等。 - - -core.setInitData() -根据难度分歧来初始化难度,包括设置flag:hard,设置初始属性等。 -该函数实际被转发到了脚本编辑中,执行脚本编辑中的内容。 +该函数将重置整个游戏,执行startText事件,上传游戏人数统计信息等。 core.win(reason, norank) @@ -1041,7 +1031,7 @@ core.follow(name) / core.unfollow(name) 跟随和取消跟随都会调用core.gatherFollowers()来聚集所有的跟随者。 -core.setValue(name, value, prefix) / core.addValue(name, value, prefix) +core.setValue(name, operator, value, prefix) / core.addValue(name, value, prefix) 设置/增减某个数值。name可以是status:xxx,item:xxx或flag:xxx。 value可以是一个表达式,将调用core.calValue()计算。prefix为前缀,独立开关使用,脚本中一般忽略。 @@ -1141,10 +1131,6 @@ core.tryUseItem(itemId) 对于怪物手册和楼传器,将分别调用core.openBook()和core.useFly()函数。 对于中心对称飞行器,则会调用core.drawCenterFly()函数。 对于其他的道具,将检查是否拥有,能否使用,并且进行使用。 - - -core.afterUseBomb() -使用炸弹或圣锤后的事件。实际被转发到了脚本编辑中。 ``` ## icons.js @@ -1241,7 +1227,7 @@ core.unloadEquip(equipType, callback) core.compareEquipment(compareEquipId, beComparedEquipId) 比较两个套装的差异。 -此函数将对所有的勇士属性包括生命魔力攻防魔防金币等进行比较。 +此函数将对所有的勇士属性包括生命魔力攻防护盾金币等进行比较。 如果存在差异的,将作为一个对象返回其差异内容。 @@ -1531,13 +1517,13 @@ core.removeBlock(x, y, floorId) 如果存在自定义事件,则简单的禁用它,以供以后可能的启用事件。 -core.removeBlockById(index, floorId) +core.removeBlockByIndex(index, floorId) 每个楼层的图块存成一个数组,index即为该数组中的索引,每个索引对应该地图中的一个图块 根据索引从地图的block数组中尽可能删除一个图块。floorId可不填或null表示当前楼层。 -core.removeBlockByIds(floorId, ids) -ids为由索引组成的数组,如[0,1]等 +core.removeBlockByIndexes(indexes, floorId) +indexes为由索引组成的数组,如[0,1]等 根据索引数组从地图的block数组中尽可能删除一系列图块。floorId可不填或null表示当前楼层。 @@ -1624,7 +1610,7 @@ core.drawBoxAnimate() 绘制UI层的box动画,如怪物手册和对话框中的帧动画等。 -core.drawAnimate(name, x, y, callback) +core.drawAnimate(name, x, y, alignWindow, callback) 绘制一个动画。name为动画名,x和y为绘制的基准坐标,callback为绘制完毕的回调函数。 此函数将播放动画音效,并异步开始绘制该动画。 此函数会返回一个动画id,可以通过core.stopAnimate()立刻停止该动画的播放。 @@ -1894,8 +1880,8 @@ core.drawStatistics() 绘制数据统计。将从脚本编辑中获得要统计的数据列表,再遍历所有地图进行统计。 -core.drawAbout() / core.drawPaint() / core.drawHelp() -绘制关于界面,绘图模式,帮助界面。 +core.drawAbout() / core.drawHelp() +绘制关于界面,帮助界面。 // ------ 动态创建画布相关的API ------ // @@ -2105,10 +2091,6 @@ core.encodeBase64(str) / core.decodeBase64(str) 可用于解压缩录像数据 -core.convertBase(str, fromBase, toBase) -任意进制转换。此函数可能执行的非常慢,慎用。 - - core.rand(num) 使用伪种子生成伪随机数。该随机函数能被录像支持。 num如果设置大于0,则生成一个[0, num-1]之间的数;否则生成一个0到1之间的浮点数。 @@ -2164,11 +2146,6 @@ core.showWithAnimate(obj, speed, callback) / core.hideWithAnimate(obj, speed, ca 动画淡入或淡出一个对象。 -core.consoleOpened() -检测当前的控制台是否处于开启状态。仅在全塔属性中的检查控制台开关开启时有效。 -此函数有可能会存在误伤行为,即没开过控制台仍认为开启过。 - - core.hashCode(obj) 计算一个对象的哈希值。 diff --git a/_docs/element.md b/_docs/element.md index 2b386a88..30ddded8 100644 --- a/_docs/element.md +++ b/_docs/element.md @@ -54,9 +54,9 @@ type为该装备的类型,必填,和上面装备栏一一对应。例如,0就是武器,2就是首饰等等。 -atk/def/mdef为该装备分别增加的攻防魔防数值(支持负数);如果不加也可省略不写。 +atk/def/mdef为该装备分别增加的攻防护盾数值(支持负数);如果不加也可省略不写。 -从V2.6开始,可以拓展到任何勇士的属性,如hpmax, atk, def, mdef, experience等等;自行添加的属性包括攻速speed也能使用。 +从V2.6开始,可以拓展到任何勇士的属性,如hpmax, atk, def, mdef, exp等等;自行添加的属性包括攻速speed也能使用。 animate为该装备的攻击动画,仅对type为0时有效。具体可参见[动画和天气系统](#动画和天气系统)。 @@ -68,9 +68,9 @@ percentage为该装备是否按比例增加属性。 {"type": 0, "atk": 10} // 装备类型是武器,效果是攻击+10,使用默认的攻击动画 {"type": 0, "atk": 40, "animate": "sword"} // 装备类型为武器,效果是攻击+10,攻击动画是sword {"type": 1, "def": 40, "percentage": true} // 装备类型是防具,效果是防御提升40% -{"type": 1, "def": 100, "mdef": 100} // 装备类型是防具,效果是防御和魔防各+100 -{"type": 3, "atk": -20, "def": 50, "mdef": 50} // 装备类型是魔杖,效果是攻击-20,防御和魔防各+50 -{"type": 2, "atk": -20, "def": 50, "mdef": 50, "percentage": true} // 装备类型是魔杖,效果是攻击下降20%,防御和魔防各提升50% +{"type": 1, "def": 100, "mdef": 100} // 装备类型是防具,效果是防御和护盾各+100 +{"type": 3, "atk": -20, "def": 50, "mdef": 50} // 装备类型是魔杖,效果是攻击-20,防御和护盾各+50 +{"type": 2, "atk": -20, "def": 50, "mdef": 50, "percentage": true} // 装备类型是魔杖,效果是攻击下降20%,防御和护盾各提升50% ``` 所有取值全部向下取整。 @@ -153,13 +153,13 @@ yellowWall, blueWall, whiteWall 怪物的特殊属性所对应的数字(special)在脚本编辑中的`getSpecials`中定义,请勿对已有的属性进行修改。 -多属性可采用数组的写法,比如`'special': [1,3]`视为同时拥有先攻和坚固属性;`'special': [5,10,14,18]`视为拥有3连击、魔防、诅咒、阻击四个属性。 +多属性可采用数组的写法,比如`'special': [1,3]`视为同时拥有先攻和坚固属性;`'special': [5,10,14,18]`视为拥有3连击、模仿、诅咒、阻击四个属性。 怪物可以负伤,在全塔属性的全局变量`enableNegativeDamage`中指定。 打败怪物后可以进行加点操作。有关加点塔的制作可参见[加点事件](event#加点事件)。 -如果全塔属性中的enableExperience为false,即不启用经验的话,怪物手册里将不显示怪物的经验值,打败怪物也不获得任何经验。 +如果全塔属性中的enableexp为false,即不启用经验的话,怪物手册里将不显示怪物的经验值,打败怪物也不获得任何经验。 拿到幸运金币后,打怪获得的金币将翻倍。 @@ -199,8 +199,6 @@ N连击怪物的special是6,且我们可以为它定义n代表实际连击数 退化怪需要设置'atkValue'和'defValue'表示退化的数值;也可以不设置默认为0。 -夹击可以通过全塔属性中的`betweenAttackCeil`设为true可以将伤害向上取整。 - **将`flag:no_betweenAttack`设置为true可以免疫夹击效果。** 固伤怪则需要设置`damage`选项,代表战前扣血数值。 @@ -282,13 +280,14 @@ floorId指定的是目标楼层的唯一标识符(ID)。 - 使用`${}`来计算一个表达式的值,如`${status:atk+status:def}`。 - 使用`\f[...]`来同时插入一张立绘图,如`\f[1.png,100,200]`。 - 使用`\\i[...]`来在对话框中绘制一个图标,如`\\i[fly]`。 -- 使用`\\c[...]`来修改字体大小,如`\\b[16]`。 +- 使用`\\c[...]`来修改字体大小,如`\\c[16]`。 - 使用`\\d`来加粗或者取消粗体。 - 使用`\\e`来加斜体或取消斜体。 +- 使用`\\z[...]`来添加打字中的暂停效果。 从V2.5.2开始,也允许绘制一张头像图在对话框中,只要通过`\t[1.png]`或`\t[标题,1.png]`的写法。 -**使用`\\i,\\c,\\d,\\e`时请注意:在事件块中,允许只写一个反斜杠`\`,系统会自动转义成`\\`;但是在脚本中必须两个反斜杠都写上!** +**使用`\\i,\\c,\\d,\\e,\\z`时请注意:在事件块中,允许只写一个反斜杠`\`,系统会自动转义成`\\`;但是在脚本中必须两个反斜杠都写上!** 详细信息请参见[剧情文本控制](event#text:显示一段文字(剧情))中的说明。 @@ -416,20 +415,6 @@ HTML5魔塔一大亮点就是存在录像系统,可以很方便进行录像回 如果录像出现问题,请加群539113091找小艾反馈Bug。 -## 绘图模式 - -从V2.5开始,样板提供了绘图模式,可以让玩家在画布上任意进行绘制,标记等。 - -使用M键,或在菜单栏中可以进入绘图模式。 - -**绘图的内容会自动保存,且以页面为生命周期,和存读档无关,返回标题并重新开始游戏后绘制的内容仍有效,但刷新页面就会消失。** - -你可以将绘制内容保存到文件,也可以从文件读取保存的绘制内容。 - -绘图模式下,状态栏的图标也会相应改变,铅笔为绘制模式,橡皮为擦除模式,存读档为保存和读取绘图文件,退出为返回默认值。 - -在浏览地图页面中也可以按楼传按钮或M键来开启/关闭该层的绘图显示。 - ## 操作说明 ![](img/keyboard.png) @@ -463,7 +448,6 @@ HTML5魔塔一大亮点就是存在录像系统,可以很方便进行录像回 - **[R]** 回放录像 - **[E]** 显示光标 - **[SPACE]** 轻按(仅在轻按开关打开时有效) -- **[M]** 绘图模式 - **[PgUp/PgDn]** 浏览地图 - **[1]** 快捷使用破墙镐 - **[2]** 快捷使用炸弹/圣锤 diff --git a/_docs/event.md b/_docs/event.md index cce0cbe6..4fd92d4e 100644 --- a/_docs/event.md +++ b/_docs/event.md @@ -332,7 +332,7 @@ ![](img/events/7.png) -- `status:xxx` 获取勇士属性时只能使用如下几个:hp(生命值),atk(攻击力),def(防御力),mdef(魔防值),money(金币),experience(经验),x(勇士的横坐标),y(勇士的纵坐标),direction(勇士的方向)。 +- `status:xxx` 获取勇士属性时只能使用如下几个:hp(生命值),atk(攻击力),def(防御力),mdef(护盾值),money(金币),exp(经验),x(勇士的横坐标),y(勇士的纵坐标),direction(勇士的方向)。 - `item:xxx` 中的xxx为道具ID。所有道具的ID定义在items.js中,请自行查看。例如,`item:centerFly` 代表中心对称飞行器的个数。 - `flag:xxx` 中的xxx为一个自定义的变量/Flag(支持中文);如果没有对其进行赋值则默认值为0。 - `global:xxx` 中的xxx为一个全局存储的名称(支持中文);如果没有对其进行赋值则默认值为0。 @@ -491,27 +491,6 @@ value是一个表达式,将通过这个表达式计算出的结果赋值给nam 在刷新的情况下,如果hp被设置成了0或以下,将触发lose事件,直接死亡。 -### addValue:增减勇士的某个属性、道具个数,或某个变量/Flag的值 - -和`{"type": "setValue"}`的写法完全相同,不过此项是可以直接将值加减到原始数值上。 - -即下面的写法是等价的: - -``` js -[ - {"type": "setValue", "name": "status:atk", "value": "status:atk+10" } // 攻击提高10点 - {"type": "addVakue", "name": "status:atk", "value": "10" } // 和上面写法等价 - {"type": "setValue", "name": "item:yellowKey", "value": "item:yellowKey-3" } // 黄钥匙个数-3 - {"type": "addValue", "name": "item:yellowKey", "value": "-3" } // 和上面写法等价 - {"type": "setValue", "name": "flag:door2", "value": "flag:door2+1" } // 将变量door值+1 - {"type": "addValue", "name": "flag:door2", "value": "01" } // 和上面写法等价 -] -``` - -![](img/events/14.jpg) - -从V2.6.5开始,当设置了`"norefresh": true`后可以不刷新状态栏、地图显伤和自动事件,从而加速事件执行。 - ### setEnemy:设置怪物属性 使用`{"type":"setEnemy"}`可以设置某个怪物的某个属性 @@ -528,7 +507,7 @@ value是一个表达式,将通过这个表达式计算出的结果赋值给nam id为必填项,代表要修改的怪物ID。 -name为必填项,代表要修改的项,例如`hp`, `atk`, `def`, `money`, `experience`, `point`, `special`, `name`。 +name为必填项,代表要修改的项,例如`hp`, `atk`, `def`, `money`, `exp`, `point`, `special`, `name`。 value为必填项,代表要修改到的内容。对于修改名称的,必须加单引号。 @@ -596,7 +575,7 @@ value为必填项,代表要修改到的结果。该项必须是个数值。 ``` js [ - {"type": "setGlobalFlag", "name": "enableMDef", "value": false}, // 不在状态栏显示魔防值 + {"type": "setGlobalFlag", "name": "enableMDef", "value": false}, // 不在状态栏显示护盾值 ] ``` @@ -1672,7 +1651,7 @@ text为提示文字,可以在这里给输入提示文字。这里同样可以 ], "false": [ // 条件不成立则执行false里的事件 "你当前攻击力为${status:atk}, 不足500!\n给你增加100点攻击力!", - {"type": "addValue", "name": "status:atk", "value": "100"}, // 攻击力加100, 接着会执行revisit事件 + {"type": "setValue", "name": "status:atk", "operator": "+=", "value": "100"}, // 攻击力加100, 接着会执行revisit事件 ] }, {"type", "revisit"}, // 立刻重启本事件, 直到攻击力大于500后结束 @@ -1874,7 +1853,7 @@ yes和no均为必填项,即用户点击确认或取消后执行的事件。 [ {"type":"while", "condition": "flag:i<=10", // 循环处理;注意flag未设置则默认为0 "data":[ - {"type": "addValue", "name": "flag:i", "value": "1"}, // 递增i + {"type": "setValue", "name": "flag:i", "operator": "+=", "value": "1"}, // 递增i "${flag:i}", // 输出i {"type": "sleep","time":1000}, // 等待1秒 ] @@ -1908,7 +1887,7 @@ yes和no均为必填项,即用户点击确认或取消后执行的事件。 [ {"type":"while", "condition": "true", // 循环处理;永远为真 "data":[ - {"type": "addValue", "name": "flag:i", "value": "1"}, // 递增i + {"type": "setValue", "name": "flag:i", "operator": "+=", "value": "1"}, // 递增i "${flag:i}", // 输出i {"type": "sleep","time":1000}, // 等待1秒 {"type": "if", "condition": "flag:i<10", // 测试i是否小于10 @@ -2544,7 +2523,7 @@ if (core.flags.enableAddPoint && point > 0) { "name": "贪婪之神", // 商店名称(标题) "icon": "blueShop", // 商店图标,blueShop为蓝色商店,pinkShop为粉色商店 "textInList": "1F金币商店", // 在快捷商店栏中显示的名称 - "use": "money", // 商店所要使用的。只能是"money"或"experience"。 + "use": "money", // 商店所要使用的。只能是"money"或"exp"。 "commonTimes": true, // 是否使用全局次数 "mustEnable": false, // 如果未开启则不显示在状态栏中 "need": "20+10*times*(times+1)", // 商店需要的金币/经验数值;可以是一个表达式,以times(访问次数)作为参数计算。 @@ -2553,7 +2532,7 @@ if (core.flags.enableAddPoint && point > 0) { // effect可以对status,item和flag进行操作;必须是X+=Y的形式,其中Y可以是一个表达式 {"text": "生命+800", "effect": "status:hp+=800"}, // 生命+800 {"text": "攻击+4", "need": 30, "effect": "status:atk+=4"}, // 规定具体的数值 - {"text": "防御+2,魔防+4", "effect": "status:def+=2;status:mdef+=4"}, // 多个效果用分号分开 + {"text": "防御+2,护盾+4", "effect": "status:def+=2;status:mdef+=4"}, // 多个效果用分号分开 ] } ], @@ -2565,7 +2544,7 @@ if (core.flags.enableAddPoint && point > 0) { - name 为商店的名称(打开商店后的标题) - icon 为商店的图标,在icons.js的npcs中定义。如woman可代表一个商人。 - textInList 为其在快捷商店栏中显示的名称,如"3楼金币商店"等 -- use 为消耗的类型,是金币(money)还是经验(experience)。 +- use 为消耗的类型,是金币(money)还是经验(exp)。 - commonTimes 是否使用全局次数;如果为true则可以多个快捷商店共享相同的次数 - mustEnable 是否必须是只在开启状态才在列表显示;如果此项为true则未开启的快捷商店不予显示 - need 是一个表达式,计算商店所需要用到的数值。 @@ -2665,26 +2644,6 @@ if (core.flags.enableAddPoint && point > 0) { 除此以外,每层楼还提供了`firstArrive`和`eachArrive`事件,分别为首次到达该楼层和每次到达该楼层时执行的事件。 -## 使用炸弹后的事件 - -上面的afterBattle事件只对和怪物进行战斗后才有会被处理。 - -如果我们想在使用炸弹后也能触发一些事件(如开门),则可以在脚本编辑里面的`afterUseBomb`函数进行处理: - -``` js -////// 使用炸弹/圣锤后的事件 ////// -"afterUseBomb": function () { - // 这是一个使用炸弹也能开门的例子 - if (core.status.floorId=='xxx' && core.terrainExists(x0,y0,'specialDoor') // 某个楼层,该机关门存在 - && !core.enemyExists(x1,y1) && !core.enemyExists(x2,y2)) // 且守门的怪物都不存在 - { - core.insertAction([ // 插入事件 - {"type": "openDoor", "loc": [x0,y0]} // 开门 - ]) - } -} -``` - ## 滑冰事件 从V2.6开始,滑冰事件被重写。现在的滑冰由公共事件执行。 @@ -2751,7 +2710,7 @@ if (core.flags.enableAddPoint && point > 0) { 本塔也支持经验升级,即用户杀怪获得经验后,可以到达某些数值自动进阶,全面提升属性。 -要经验升级,你需要先在`data.js`中的全局变量中启用。你需要将`enableExperience`启用经验,且`enableLevelUp`启用进阶。同时你也可以将`enableLv`置为true以在状态栏中显示当前等级(境界)。 +要经验升级,你需要先在`data.js`中的全局变量中启用。你需要将`enableExp`启用经验,且`enableLevelUp`启用进阶。同时你也可以将`enableLv`置为true以在状态栏中显示当前等级(境界)。 同时,你还需要在`data.js`中的`levelUp`来定义每一个进阶所需要的经验值,以及进阶时的效果。 diff --git a/_docs/index.html b/_docs/index.html index 10679f3f..3e9754eb 100644 --- a/_docs/index.html +++ b/_docs/index.html @@ -23,18 +23,16 @@ // basepath: '../docs/', // Search Support - // search: { - // maxAge: 43200000, // 过期时间,单位毫秒,默认一天 - // paths: 'auto', - // placeholder: { - // '/en/': 'Search', - // '/': '搜索', - // }, - // noData: { - // '/en/': 'No Results', - // '/': '找不到结果', - // }, - // }, + search: { + maxAge: 43200000, // 过期时间,单位毫秒,默认一天 + paths: 'auto', + placeholder: { + '/': '搜索文档...', + }, + noData: { + '/': '找不到结果', + }, + }, // load sidebar from _sidebar.md loadSidebar: '_sidebar', @@ -46,5 +44,6 @@ } + diff --git a/_docs/personalization.md b/_docs/personalization.md index ca4755ae..ec6f5863 100644 --- a/_docs/personalization.md +++ b/_docs/personalization.md @@ -19,7 +19,6 @@ HTML5魔塔是使用画布(canvas)来绘制,存在若干个图层,它们 - animate:动画层;主要用来绘制动画。 (z-index: 70) - weather**[D]**:天气层;主要用来绘制天气(雨/雪/雾) (z-index: 80) - route**[D]**:路线层;主要用来绘制勇士的行走路线图。 (z-index: 95) -- paint**[D]**:绘图层;主要用来进行绘图模式。(z-index: 95) - curtain:色调层;用来控制当前楼层的画面色调 (z-index: 125) - image1\~50**[D]**:图片层;用来绘制图片等操作。(z-index: 100+code, 101~150) - uievent**[D]**:自定义UI绘制层;用来进行自定义UI绘制等操作。(z-index:135,可以通过事件设置该值) @@ -495,11 +494,8 @@ this.myfunc = function(x) { 3. 在脚本编辑-updateStatusBar中可以直接替换技能栏的显示内容 ``` - // 设置技能栏 - if (core.flags.enableSkill) { - // 替换成你想显示的内容,比如你定义的一个flag:abc。 - core.setStatusBarInnerHTML('skill', core.getFlag("abc", 0)); - } + // 替换成你想显示的内容,比如你定义的一个flag:abc。 + core.setStatusBarInnerHTML('skill', core.getFlag("abc", 0)); ``` ### 额外新增新项目 @@ -569,22 +565,17 @@ core.statusBar.speed.innerHTML = core.getFlag('speed', 0); 在脚本编辑-updateStatusBar中,可以对状态栏显示内容进行修改。 ``` js -// 设置魔力值 -if (core.flags.enableMana) { - // status:manamax 只有在非负时才生效。 - if (core.status.hero.manamax != null && core.status.hero.manamax >= 0) { - core.status.hero.mana = Math.min(core.status.hero.mana, core.status.hero.manamax); - core.setStatusBarInnerHTML('mana', core.status.hero.mana + "/" + core.status.hero.manamax); - } - else { - core.setStatusBarInnerHTML("mana", core.status.hero.mana); - } +// 设置魔力值; status:manamax 只有在非负时才生效。 +if (core.status.hero.manamax != null && core.status.hero.manamax >= 0) { + core.status.hero.mana = Math.min(core.status.hero.mana, core.status.hero.manamax); + core.setStatusBarInnerHTML('mana', core.status.hero.mana + "/" + core.status.hero.manamax); +} +else { + core.setStatusBarInnerHTML("mana", core.status.hero.mana); } // 设置技能栏 -if (core.flags.enableSkill) { - // 可以用flag:skill表示当前开启的技能类型,flag:skillName显示技能名 - core.statusBar.skill.innerHTML = core.getFlag('skillName', '无'); -} +// 可以用flag:skill表示当前开启的技能类型,flag:skillName显示技能名 +core.statusBar.skill.innerHTML = core.getFlag('skillName', '无'); ``` ### 技能的触发 @@ -629,8 +620,8 @@ else { // 关闭技能 ``` js case 87: // W:开启技能“二倍斩” - // 检测技能栏是否开启,是否拥有“二倍斩”这个技能道具 - if (core.flags.enableSkill && core.hasItem('skill1')) { + // 是否拥有“二倍斩”这个技能道具 + if (core.hasItem('skill1')) { core.status.route.push("key:87"); core.useItem('skill1', true); } @@ -669,7 +660,7 @@ if (core.getFlag('skill', 0)==1) { // 开启了技能1 ``` js // 战后的技能处理,比如扣除魔力值 -if (core.flags.enableSkill) { +if (core.flags.statusBarItems.indexOf('enableSkill')>=0) { // 检测当前开启的技能类型 var skill = core.getFlag('skill', 0); if (skill==1) { // 技能1:二倍斩 @@ -704,13 +695,13 @@ if (core.flags.enableSkill) { - **`flag:heroIcon`**: 当前的勇士行走图名称。 - **`flag:saveEquips`**: 快速换装时保存的套装。 - **`flag:__visited__`**: 当前访问过的楼层。 -- **`flag:__atk_buff__`**, **`flag:__def_buff__`**, **`flag:__mdef_buff__`**: 当前攻防魔防的实际计算比例加成。 +- **`flag:__atk_buff__`**, **`flag:__def_buff__`**, **`flag:__mdef_buff__`**: 当前攻防护盾的实际计算比例加成。 - **`flag:__color__`**, **`flag:__weather__`**, **`flag:__volume__`**: 当前的画面色调、天气和音量。 - **`flag:__events__`**: 当前保存的事件列表,读档时会恢复(适用于在事件中存档) - **`flag:textAttribute`**, **`flag:globalAttribute`**, **`flag:globalFlags`**: 当前的剧情文本属性,当前的全局属性,当前的全局开关。 - **`flag:cannotMoveDirectly`**, **`flag:__noClickMove__`**: 当前是否不允许瞬间移动,当前用户是否开启了单击瞬移。 - **`flag:hideStatusBar`**, **`flag:showToolbox`**: 是否隐藏状态栏,是否显示工具栏。 -- **`flag:debug`**, **`flag:__consoleOpened__`**: 当前是否开启了调试模式,是否开启了控制台。 +- **`flag:debug`**: 当前是否开启了调试模式。 - **`flag:__seed__`**, **`flag:__rand__`**: 伪随机数生成种子和当前的状态 ========================================================================================== diff --git a/_server/MotaAction.g4 b/_server/MotaAction.g4 index 5bc7ce65..f720c1d3 100644 --- a/_server/MotaAction.g4 +++ b/_server/MotaAction.g4 @@ -1,3 +1,5 @@ +// 编辑此文件用的vscode插件: https://marketplace.visualstudio.com/items?itemName=zhaouv.vscode-mota-js-extension + grammar MotaAction; //===============parser=============== @@ -32,7 +34,7 @@ autoEvent_m /* autoEvent_m -tooltip : ????? +tooltip : 自动事件 helpUrl : https://h5mota.com/games/template/_docs/#/event default : ["flag:__door__==2",0,true,false,false,null] var code = { @@ -100,86 +102,52 @@ var code = ' \n'; return code; */; -shopcommonevent - : '公共事件版商店 id' IdString '快捷商店栏中名称' EvalString BGNL? '未开启状态则不显示在列表中' Bool BGNL? '执行的公共事件 id' EvalString '参数列表' EvalString? - -/* 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 -} -if (EvalString_2) code.args = EvalString_2; -code=JSON.stringify(code,null,2)+',\n'; -return code; -*/; - shopsub - : '商店 id' IdString '标题' EvalString '图标' IdString BGNL? Newline '快捷商店栏中名称' EvalString '共用times' Bool BGNL? Newline '未开启状态则不显示在列表中' Bool BGNL? Newline '使用' ShopUse_List '消耗' EvalString BGNL? Newline '显示文字' EvalString BGNL? Newline shopChoices+ BEND + : '商店 id' IdString '标题' EvalString? '图像' IdString? BGNL? Newline '文字' EvalString? BGNL? Newline '快捷名称' EvalString '未开启不显示' Bool '不可预览' Bool BGNL? Newline shopChoices+ BEND /* shopsub -tooltip : 全局商店,消耗填-1表示每个选项的消耗不同,正数表示消耗数值 +tooltip : 全局商店 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=%e5%85%a8%e5%b1%80%e5%95%86%e5%ba%97 -default : ["shop1","贪婪之神","blueShop","1F金币商店",false,false,null,"20+10*times*(times+1)","勇敢的武士啊, 给我${need}金币就可以:"] +default : ["shop1","贪婪之神","blueShop","勇敢的武士啊, 给我${20+2*flag:shop1}金币就可以:","金币商店",false,false] +var title=''; +if (EvalString_0==''){ + if (IdString_1=='') title=''; + else title='\t['+IdString_1+']'; +} else { + if (IdString_1=='')title='\t['+EvalString_0+']'; + else title='\t['+EvalString_0+','+IdString_1+']'; +} var code = { 'id': IdString_0, - 'name': EvalString_0, - 'icon': IdString_1, - 'textInList': EvalString_1, - 'commonTimes': Bool_0, - 'mustEnable': Bool_1, - 'use': ShopUse_List_0, - 'need': EvalString_2, - 'text': EvalString_3, + 'text': title+EvalString_1, + 'textInList': EvalString_2, + 'mustEnable': Bool_0, + 'disablePreview': Bool_1, 'choices': 'choices_asdfefw' } -code=JSON.stringify(code,null,2).split('"choices_asdfefw"').join('[\n'+shopChoices_0+']\n')+',\n'; +code=JSON.stringify(code,null,2).split('"choices_asdfefw"').join('[\n'+shopChoices_0+']')+',\n'; return code; */; shopChoices - : '商店选项' EvalString '消耗' EvalString? BGNL? Newline shopEffect+ + : '商店选项' EvalString '使用条件' EvalString BGNL? Newline '图标' IdString? '颜色' ColorString? Colour '出现条件' EvalString? BGNL? Newline action+ BEND /* shopChoices tooltip : 商店选项,商店消耗是-1时,这里的消耗对应各自选项的消耗,商店消耗不是-1时这里的消耗不填 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=%e5%85%a8%e5%b1%80%e5%95%86%e5%ba%97 -default : ["攻击+1",""] +default : ["攻击+1","status:money>=20+2*flag:shop1","","","rgba(255,255,255,1)",""] colour : this.subColor -EvalString_1 = EvalString_1 && (', "need": "'+EvalString_1+'"'); -var code = '{"text": "'+EvalString_0+'"'+EvalString_1+', "effect": "'+shopEffect_0.slice(2,-1)+'"},\n'; -return code; -*/; - -shopEffect - : idString_e '+=' expression - - -/* shopEffect -colour : this.subColor -var code = idString_e_0+'+='+expression_0+';' +ColorString_0 = ColorString_0 ? (', "color": ['+ColorString_0+']') : ''; +EvalString_2 = EvalString_2 && (', "condition": "'+EvalString_2+'"') +IdString_0 = IdString_0? (', "icon": "'+IdString_0+'"'):''; +var code = '{"text": "'+EvalString_0+'", "need": "'+EvalString_1+'"'+IdString_0+ColorString_0+EvalString_2+', "action": [\n'+action_0+']},\n'; return code; */; shopitem - : '道具商店 id' IdString '快捷商店栏中名称' EvalString BGNL? '未开启状态则不显示在列表中' Bool BGNL? Newline shopItemChoices+ BEND + : '道具商店 id' IdString '快捷名称' EvalString '未开启不显示' Bool BGNL? Newline shopItemChoices+ BEND /* shopitem @@ -193,12 +161,12 @@ var code = { 'mustEnable': Bool_0, 'choices': 'choices_aqwedsa' } -code=JSON.stringify(code,null,2).split('"choices_aqwedsa"').join('[\n'+shopItemChoices_0+']\n')+',\n'; +code=JSON.stringify(code,null,2).split('"choices_aqwedsa"').join('[\n'+shopItemChoices_0+']')+',\n'; return code; */; shopItemChoices - : '道具名' IdString '存量' EvalString? '买入价格' EvalString? '卖出价格' EvalString? '出现条件' EvalString? BEND + : '道具名' IdString '存量' IntString? '买入价格' EvalString? '卖出价格' EvalString? '出现条件' EvalString? BEND @@ -207,13 +175,34 @@ tooltip : 道具商店选项,每一项是道具名;买入或卖出可以不 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=%e5%85%a8%e5%b1%80%e5%95%86%e5%ba%97 default : ["yellowKey","","10","",""] colour : this.subColor -if (EvalString_0 && !/^\d+$/.test(EvalString_0)) throw "存量必须不填或非负整数"; -EvalString_0 = EvalString_0 ? (', "number": '+EvalString_0) : ''; -EvalString_1 = EvalString_1 ? (', "money": "'+EvalString_1+'"') : ''; -EvalString_2 = EvalString_2 ? (', "sell": "'+EvalString_2+'"') : ''; -if (!EvalString_1 && !EvalString_2) throw "买入金额和卖出金额至少需要填写一个"; -EvalString_3 = EvalString_3 ? (', "condition": "'+EvalString_3+'"') : ''; -var code = '{"id": "' + IdString_0 + '"' + EvalString_0 + EvalString_1 + EvalString_2 + EvalString_3 + '},\n'; +IntString_0 = IntString_0 ? (', "number": '+IntString_0) : ''; +EvalString_0 = EvalString_0 ? (', "money": "'+EvalString_0+'"') : ''; +EvalString_1 = EvalString_1 ? (', "sell": "'+EvalString_1+'"') : ''; +if (!EvalString_0 && !EvalString_1) throw "买入金额和卖出金额至少需要填写一个"; +EvalString_2 = EvalString_2 ? (', "condition": "'+EvalString_3+'"') : ''; +var code = '{"id": "' + IdString_0 + '"' + IntString_0 + EvalString_0 + EvalString_1 + EvalString_2 + '},\n'; +return code; +*/; + +shopcommonevent + : '公共事件商店 id' IdString '快捷名称' EvalString '未开启不显示' Bool BGNL? '执行的公共事件名' EvalString '参数列表' JsonEvalString? + +/* shopcommonevent +tooltip : 全局商店, 执行一个公共事件 +helpUrl : https://h5mota.com/games/template/_docs/#/ +default : ["shop1","回收钥匙商店",false,"回收钥匙商店",""] +if (JsonEvalString_0) { + if (!(JSON.parse(JsonEvalString_0) instanceof Array)) + throw new Error('参数列表必须是个有效的数组!'); +} +var code = { + 'id': IdString_0, + 'textInList': EvalString_0, + 'mustEnable': Bool_0, + 'commonEvent': EvalString_1 +} +if (JsonEvalString_0) code.args = JSON.parse(JsonEvalString_0); +code=JSON.stringify(code,null,2)+',\n'; return code; */; @@ -231,14 +220,17 @@ return code; //afterGetItem 事件编辑器入口之一 afterGetItem_m - : '获取道具后' BGNL? Newline action+ BEND + : '获取道具后' '轻按时不触发' Bool BGNL? Newline action+ BEND /* afterGetItem_m tooltip : 系统引发的自定义事件 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=%e7%b3%bb%e7%bb%9f%e5%bc%95%e5%8f%91%e7%9a%84%e8%87%aa%e5%ae%9a%e4%b9%89%e4%ba%8b%e4%bb%b6 -var code = '[\n'+action_0+']\n'; -return code; +if (Bool_0) { + return '{"disableOnGentleClick": true, "data": [\n'+action_0+']\n}'; +} else { + return '[\n'+action_0+']\n'; +} */; //afterOpenDoor 事件编辑器入口之一 @@ -279,22 +271,26 @@ return code; //changeFloor 事件编辑器入口之一 changeFloor_m - : '楼梯, 传送门' BGNL? Newline Floor_List IdString? Stair_List 'x' Number ',' 'y' Number '朝向' DirectionEx_List '动画时间' Int? '允许穿透' Bool BEND + : '楼梯, 传送门' BGNL? Newline Floor_List IdString? Stair_List 'x' Number ',' 'y' Number '朝向' DirectionEx_List '动画时间' IntString? '穿透性' IgnoreChangeFloor_List BEND /* changeFloor_m tooltip : 楼梯, 传送门, 如果目标楼层有多个楼梯, 写upFloor或downFloor可能会导致到达的楼梯不确定, 这时候请使用loc方式来指定具体的点位置 helpUrl : https://h5mota.com/games/template/_docs/#/element?id=%e8%b7%af%e9%9a%9c%ef%bc%8c%e6%a5%bc%e6%a2%af%ef%bc%8c%e4%bc%a0%e9%80%81%e9%97%a8 -default : [null,"MTx",null,0,0,null,500,null] +default : [null,"MTx",null,0,0,null,"",null] var toFloorId = IdString_0; if (Floor_List_0!='floorId') toFloorId = Floor_List_0; var loc = ', "loc": ['+Number_0+', '+Number_1+']'; if (Stair_List_0===':now') loc = ''; else if (Stair_List_0!=='loc')loc = ', "stair": "'+Stair_List_0+'"'; DirectionEx_List_0 = DirectionEx_List_0 && (', "direction": "'+DirectionEx_List_0+'"'); -Int_0 = (Int_0!=='') ?(', "time": '+Int_0):''; -Bool_0 = Bool_0 ?'':(', "ignoreChangeFloor": false'); -var code = '{"floorId": "'+toFloorId+'"'+loc+DirectionEx_List_0+Int_0+Bool_0+' }\n'; +IntString_0 = IntString_0 ?(', "time": '+IntString_0):''; +if (IgnoreChangeFloor_List_0!='null') { + IgnoreChangeFloor_List_0 = ', "ignoreChangeFloor": '+IgnoreChangeFloor_List_0; +} else { + IgnoreChangeFloor_List_0 = ''; +} +var code = '{"floorId": "'+toFloorId+'"'+loc+DirectionEx_List_0+IntString_0+IgnoreChangeFloor_List_0+' }\n'; return code; */; @@ -333,7 +329,6 @@ action | setText_s | tip_s | setValue_s - | addValue_s | setEnemy_s | setFloor_s | setGlobalAttribute_s @@ -344,7 +339,6 @@ action | trigger_s | insert_1_s | insert_2_s - | revisit_s | exit_s | setBlock_s | showFloorImg_s @@ -366,8 +360,7 @@ action | openDoor_s | closeDoor_s | changeFloor_s - | changePos_0_s - | changePos_1_s + | changePos_s | setViewport_s | moveViewport_s | useItem_s @@ -384,8 +377,7 @@ action | hideImage_s | showTextImage_s | moveImage_s - | showGif_0_s - | showGif_1_s + | showGif_s | setCurtain_0_s | setCurtain_1_s | screenFlash_s @@ -408,6 +400,8 @@ action | if_s | if_1_s | switch_s + | for_s + | forEach_s | while_s | dowhile_s | break_s @@ -459,7 +453,7 @@ return code; */; text_1_s - : '标题' EvalString? '图像' IdString? '对话框效果' EvalString? ':' EvalString Newline + : '标题' EvalString? '图像' EvalString? '对话框效果' EvalString? ':' EvalString Newline /* text_1_s @@ -468,17 +462,17 @@ helpUrl : https://h5mota.com/games/template/_docs/#/event?id=text%EF%BC%9A%E6%98 default : ["小妖精","fairy","","欢迎使用事件编辑器(双击方块进入多行编辑)"] var title=''; if (EvalString_0==''){ - if (IdString_0=='')title=''; - else title='\\t['+IdString_0+']'; + if (EvalString_1=='' )title=''; + else title='\\t['+EvalString_1+']'; } else { - if (IdString_0=='')title='\\t['+EvalString_0+']'; - else title='\\t['+EvalString_0+','+IdString_0+']'; + if (EvalString_1=='')title='\\t['+EvalString_0+']'; + else title='\\t['+EvalString_0+','+EvalString_1+']'; } -if(EvalString_1 && !(/^(up|center|down|hero|null)(,(hero|null|\d+,\d+|\d+))?$/.test(EvalString_1))) { +if(EvalString_2 && !(/^(up|center|down|hero|null)(,(hero|null|\d+,\d+|\d+))?$/.test(EvalString_2))) { throw new Error('对话框效果的用法请右键点击帮助'); } -EvalString_1 = EvalString_1 && ('\\b['+EvalString_1+']'); -var code = '"'+title+EvalString_1+EvalString_2+'",\n'; +EvalString_2 = EvalString_2 && ('\\b['+EvalString_2+']'); +var code = '"'+title+EvalString_2+EvalString_3+'",\n'; return code; */; @@ -496,7 +490,7 @@ return code; */; autoText_s - : '自动剧情文本: 标题' EvalString? '图像' IdString? '对话框效果' EvalString? '时间' Int BGNL? EvalString Newline + : '自动剧情文本: 标题' EvalString? '图像' EvalString? '对话框效果' EvalString? '时间' Int BGNL? EvalString Newline /* autoText_s @@ -505,17 +499,17 @@ helpUrl : https://h5mota.com/games/template/_docs/#/event?id=autotext%EF%BC%9A%E default : ["小妖精","fairy","",3000,"用户无法跳过自动剧情文本,大段剧情文本请添加“是否跳过剧情”的提示"] var title=''; if (EvalString_0==''){ - if (IdString_0=='')title=''; - else title='\\t['+IdString_0+']'; + if (EvalString_1=='' )title=''; + else title='\\t['+EvalString_1+']'; } else { - if (IdString_0=='')title='\\t['+EvalString_0+']'; - else title='\\t['+EvalString_0+','+IdString_0+']'; + if (EvalString_1=='')title='\\t['+EvalString_0+']'; + else title='\\t['+EvalString_0+','+EvalString_1+']'; } -if(EvalString_1 && !(/^(up|down)(,hero)?(,([+-]?\d+),([+-]?\d+))?$/.test(EvalString_1))) { +if(EvalString_2 && !(/^(up|down)(,hero)?(,([+-]?\d+),([+-]?\d+))?$/.test(EvalString_2))) { throw new Error('对话框效果的用法请右键点击帮助'); } -EvalString_1 = EvalString_1 && ('\\b['+EvalString_1+']'); -var code = '{"type": "autoText", "text": "'+title+EvalString_1+EvalString_2+'", "time" :'+Int_0+'},\n'; +EvalString_2 = EvalString_2 && ('\\b['+EvalString_2+']'); +var code = '{"type": "autoText", "text": "'+title+EvalString_2+EvalString_3+'", "time": '+Int_0+'},\n'; return code; */; @@ -533,57 +527,37 @@ return code; */; setText_s - : '设置剧情文本的属性' '位置' SetTextPosition_List '偏移像素' EvalString? '对齐' TextAlign_List? BGNL? '标题颜色' EvalString? Colour '正文颜色' EvalString? Colour '背景色' EvalString? Colour BGNL? '粗体' B_1_List '标题字体大小' EvalString? '正文字体大小' EvalString? '打字间隔' EvalString? '字符间距' EvalString? Newline + : '设置剧情文本的属性' '位置' SetTextPosition_List '偏移像素' IntString? '对齐' TextAlign_List? BGNL? '标题颜色' ColorString? Colour '正文颜色' ColorString? Colour '背景色' EvalString? Colour BGNL? '粗体' B_1_List '标题字体大小' IntString? '正文字体大小' IntString? '行距' IntString? '打字间隔' IntString? '字符间距' IntString? Newline /* setText_s tooltip : setText:设置剧情文本的属性,颜色为RGB三元组或RGBA四元组,打字间隔为剧情文字添加的时间间隔,为整数或不填,字符间距为字符之间的距离,为整数或不填。 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=settext%EF%BC%9A%E8%AE%BE%E7%BD%AE%E5%89%A7%E6%83%85%E6%96%87%E6%9C%AC%E7%9A%84%E5%B1%9E%E6%80%A7 -default : [null,"",null,"",'rgba(255,255,255,1)',"",'rgba(255,255,255,1)',"",'rgba(255,255,255,1)',null,"","","",""] +default : [null,"",null,"",'rgba(255,255,255,1)',"",'rgba(255,255,255,1)',"",'rgba(255,255,255,1)',null,"","","","",""] SetTextPosition_List_0 =SetTextPosition_List_0==='null'?'': ', "position": "'+SetTextPosition_List_0+'"'; TextAlign_List_0 = TextAlign_List_0==='null'?'': ', "align": "'+TextAlign_List_0+'"'; var colorRe = MotaActionFunctions.pattern.colorRe; +IntString_0 = IntString_0 ? (', "offset": '+IntString_0) : ''; +ColorString_0 = ColorString_0 ? (', "title": ['+ColorString_0+']') : ''; +ColorString_1 = ColorString_1 ? (', "text": ['+ColorString_1+']') : ''; if (EvalString_0) { - if (!/^\d+$/.test(EvalString_0))throw new Error('像素偏移量必须是整数或不填'); - EvalString_0 = ', "offset": '+EvalString_0; -} -if (EvalString_1) { - if (!colorRe.test(EvalString_1))throw new Error('颜色格式错误,形如:0~255,0~255,0~255,0~1'); - EvalString_1 = ', "title": ['+EvalString_1+']'; -} -if (EvalString_2) { - if (!colorRe.test(EvalString_2))throw new Error('颜色格式错误,形如:0~255,0~255,0~255,0~1'); - EvalString_2 = ', "text": ['+EvalString_2+']'; -} -if (EvalString_3) { - if (colorRe.test(EvalString_3)) { - EvalString_3 = ', "background": ['+EvalString_3+']'; + if (colorRe.test(EvalString_0)) { + EvalString_0 = ', "background": ['+EvalString_0+']'; } - else if (/^\w+\.png$/.test(EvalString_3)) { - EvalString_3 = ', "background": "'+EvalString_3+'"'; + else if (/^\w+\.png$/.test(EvalString_0)) { + EvalString_0 = ', "background": "'+EvalString_0+'"'; } else { throw new Error('背景格式错误,必须是形如0~255,0~255,0~255,0~1的颜色,或一个WindowSkin的png图片名称'); } } -if (EvalString_4) { - if (!/^\d+$/.test(EvalString_4))throw new Error('字体大小必须是整数或不填'); - EvalString_4 = ', "titlefont": '+EvalString_4; -} -if (EvalString_5) { - if (!/^\d+$/.test(EvalString_5))throw new Error('字体大小必须是整数或不填'); - EvalString_5 = ', "textfont": '+EvalString_5; -} -if (EvalString_6) { - if (!/^\d+$/.test(EvalString_6))throw new Error('打字时间间隔必须是整数或不填'); - EvalString_6 = ', "time": '+EvalString_6; -} -if (EvalString_7) { - if (!/^\d+$/.test(EvalString_7))throw new Error('字符间距必须是整数或不填'); - EvalString_7 = ', "interval": '+EvalString_7; -} +IntString_1 = IntString_1 ? (', "titlefont": '+IntString_1) : ''; +IntString_2 = IntString_2 ? (', "textfont": '+IntString_2) : ''; +IntString_3 = IntString_3 ? (', "lineHeight": '+IntString_3) : ''; +IntString_4 = IntString_4 ? (', "time": '+IntString_4) : ''; +IntString_5 = IntString_5 ? (', "interval": '+IntString_5) : ''; B_1_List_0 = B_1_List_0==='null'?'':', "bold": '+B_1_List_0; -var code = '{"type": "setText"'+SetTextPosition_List_0+EvalString_0+TextAlign_List_0+EvalString_1+EvalString_2+B_1_List_0+EvalString_3+EvalString_4+EvalString_5+EvalString_6+EvalString_7+'},\n'; +var code = '{"type": "setText"'+SetTextPosition_List_0+IntString_0+TextAlign_List_0+ColorString_0+ColorString_1+B_1_List_0+EvalString_0+IntString_1+IntString_2+IntString_3+IntString_4+IntString_5+'},\n'; return code; */; @@ -601,28 +575,18 @@ return code; */; setValue_s - : '数值操作' ':' '名称' idString_e '值' expression '不刷新状态栏' Bool Newline + : '数值操作' ':' '名称' idString_e AssignOperator_List expression '不刷新状态栏' Bool Newline /* setValue_s tooltip : setValue:设置勇士的某个属性、道具个数, 或某个变量/Flag的值 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=setvalue%EF%BC%9A%E8%AE%BE%E7%BD%AE%E5%8B%87%E5%A3%AB%E7%9A%84%E6%9F%90%E4%B8%AA%E5%B1%9E%E6%80%A7%E3%80%81%E9%81%93%E5%85%B7%E4%B8%AA%E6%95%B0%EF%BC%8C%E6%88%96%E6%9F%90%E4%B8%AA%E5%8F%98%E9%87%8Fflag%E7%9A%84%E5%80%BC colour : this.dataColor +if (AssignOperator_List_0 && AssignOperator_List_0 != '=') { + AssignOperator_List_0 = ', "operator": "' + AssignOperator_List_0 + '"'; +} else AssignOperator_List_0 = ''; Bool_0 = Bool_0 ? ', "norefresh": true' : ''; -var code = '{"type": "setValue", "name": "'+idString_e_0+'", "value": "'+expression_0+'"' + Bool_0 + '},\n'; -return code; -*/; - -addValue_s - : '数值增减' ':' '名称' idString_e '+=' expression '不刷新状态栏' Bool Newline - - -/* addValue_s -tooltip : addValue:增减勇士的某个属性、道具个数, 或某个变量/Flag的值 -helpUrl : https://h5mota.com/games/template/_docs/#/event?id=addValue%ef%bc%9a%e5%a2%9e%e5%87%8f%e5%8b%87%e5%a3%ab%e7%9a%84%e6%9f%90%e4%b8%aa%e5%b1%9e%e6%80%a7%e3%80%81%e9%81%93%e5%85%b7%e4%b8%aa%e6%95%b0%ef%bc%8c%e6%88%96%e6%9f%90%e4%b8%aa%e5%8f%98%e9%87%8f%2fFlag%e7%9a%84%e5%80%bc -colour : this.dataColor -Bool_0 = Bool_0 ? ', "norefresh": true' : ''; -var code = '{"type": "addValue", "name": "'+idString_e_0+'", "value": "'+expression_0+'"' + Bool_0 + '},\n'; +var code = '{"type": "setValue", "name": "'+idString_e_0+'"'+AssignOperator_List_0+', "value": "'+expression_0+'"' + Bool_0 + '},\n'; return code; */; @@ -634,7 +598,7 @@ setEnemy_s /* setEnemy_s tooltip : setEnemy:设置某个怪物的属性 default : ["greenSlime", "atk", "0"] -helpUrl : https://h5mota.com/games/template/_docs/#/event?id=addValue%ef%bc%9a%e5%a2%9e%e5%87%8f%e5%8b%87%e5%a3%ab%e7%9a%84%e6%9f%90%e4%b8%aa%e5%b1%9e%e6%80%a7%e3%80%81%e9%81%93%e5%85%b7%e4%b8%aa%e6%95%b0%ef%bc%8c%e6%88%96%e6%9f%90%e4%b8%aa%e5%8f%98%e9%87%8f%2fFlag%e7%9a%84%e5%80%bc +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=setEnemy%ef%bc%9a%e5%a2%9e%e5%87%8f%e5%8b%87%e5%a3%ab%e7%9a%84%e6%9f%90%e4%b8%aa%e5%b1%9e%e6%80%a7%e3%80%81%e9%81%93%e5%85%b7%e4%b8%aa%e6%95%b0%ef%bc%8c%e6%88%96%e6%9f%90%e4%b8%aa%e5%8f%98%e9%87%8f%2fFlag%e7%9a%84%e5%80%bc colour : this.dataColor var code = '{"type": "setEnemy", "id": "'+IdString_0+'", "name": "'+EnemyId_List_0+'", "value": "'+expression_0+'"},\n'; return code; @@ -691,7 +655,7 @@ setGlobalFlag_s /* setGlobalFlag_s tooltip : setGlobalFlag:设置系统开关 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=setGlobalFlag%ef%bc%9a%e8%ae%be%e7%bd%ae%e4%b8%80%e4%b8%aa%e7%b3%bb%e7%bb%9f%e5%bc%80%e5%85%b3 -default : ["enableFloor","true"] +default : ["s:enableFloor","true"] colour : this.dataColor var code = '{"type": "setGlobalFlag", "name": "'+Global_Flag_List_0+'", "value": '+Bool_0+'},\n'; return code; @@ -699,13 +663,13 @@ return code; show_s - : '显示事件' 'x' EvalString? ',' 'y' EvalString? '楼层' IdString? '动画时间' Int? '不等待执行完毕' Bool? Newline + : '显示事件' 'x' EvalString? ',' 'y' EvalString? '楼层' IdString? '动画时间' IntString? '不等待执行完毕' Bool? Newline /* show_s tooltip : show: 将禁用事件启用,楼层和动画时间可不填,xy可用逗号分隔表示多个点 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=show%EF%BC%9A%E5%B0%86%E4%B8%80%E4%B8%AA%E7%A6%81%E7%94%A8%E4%BA%8B%E4%BB%B6%E5%90%AF%E7%94%A8 -default : ["","","",500,false] +default : ["","","","",false] colour : this.mapColor var floorstr = ''; if (EvalString_0 && EvalString_1) { @@ -725,20 +689,20 @@ if (EvalString_0 && EvalString_1) { floorstr = ', "loc": ['+EvalString_0.join(',')+']'; } IdString_0 = IdString_0 && (', "floorId": "'+IdString_0+'"'); -Int_0 = Int_0!=='' ?(', "time": '+Int_0):''; +IntString_0 = IntString_0 ?(', "time": '+IntString_0):''; Bool_0 = Bool_0 ?', "async": true':''; -var code = '{"type": "show"'+floorstr+IdString_0+''+Int_0+Bool_0+'},\n'; +var code = '{"type": "show"'+floorstr+IdString_0+''+IntString_0+Bool_0+'},\n'; return code; */; hide_s - : '隐藏事件' 'x' EvalString? ',' 'y' EvalString? '楼层' IdString? '动画时间' Int? '不等待执行完毕' Bool? Newline + : '隐藏事件' 'x' EvalString? ',' 'y' EvalString? '楼层' IdString? '动画时间' IntString? '不等待执行完毕' Bool? Newline /* hide_s tooltip : hide: 将一个启用事件禁用,所有参数均可不填,代表禁用事件自身,xy可用逗号分隔表示多个点 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=hide%EF%BC%9A%E5%B0%86%E4%B8%80%E4%B8%AA%E5%90%AF%E7%94%A8%E4%BA%8B%E4%BB%B6%E7%A6%81%E7%94%A8 -default : ["","","",500,false] +default : ["","","","",false] colour : this.mapColor var floorstr = ''; if (EvalString_0 && EvalString_1) { @@ -758,9 +722,9 @@ if (EvalString_0 && EvalString_1) { floorstr = ', "loc": ['+EvalString_0.join(',')+']'; } IdString_0 = IdString_0 && (', "floorId": "'+IdString_0+'"'); -Int_0 = Int_0!=='' ?(', "time": '+Int_0):''; +IntString_0 = IntString_0 ?(', "time": '+IntString_0):''; Bool_0 = Bool_0 ?', "async": true':''; -var code = '{"type": "hide"'+floorstr+IdString_0+''+Int_0+Bool_0+'},\n'; +var code = '{"type": "hide"'+floorstr+IdString_0+''+IntString_0+Bool_0+'},\n'; return code; */; @@ -779,7 +743,7 @@ return code; */; insert_1_s - : '插入公共事件' EvalString '参数列表' EvalString? Newline + : '插入公共事件' EvalString '参数列表' JsonEvalString? Newline /* insert_1_s @@ -787,24 +751,17 @@ tooltip : insert: 插入公共事件并执行 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=insert%ef%bc%9a%e6%8f%92%e5%85%a5%e5%85%ac%e5%85%b1%e4%ba%8b%e4%bb%b6%e6%88%96%e5%8f%a6%e4%b8%80%e4%b8%aa%e5%9c%b0%e7%82%b9%e7%9a%84%e4%ba%8b%e4%bb%b6%e5%b9%b6%e6%89%a7%e8%a1%8c default : ["加点事件", ""] colour : this.eventColor -if (EvalString_1) { - if (EvalString_1.indexOf('"')>=0) - throw new Error('请勿在此处使用双引号!尝试使用单引号吧~'); - // 检查是不是数组 - try { - if (!(JSON.parse(EvalString_1.replace(/'/g, '"')) instanceof Array)) throw new Error(); - } - catch (e) { +if (JsonEvalString_0) { + if (!(JSON.parse(JsonEvalString_0) instanceof Array)) throw new Error('参数列表必须是个有效的数组!'); - } - EvalString_1 = ', "args": ' +EvalString_1; + JsonEvalString_0 = ', "args": ' +JsonEvalString_0; } -var code = '{"type": "insert", "name": "'+EvalString_0+'"'+EvalString_1+'},\n'; +var code = '{"type": "insert", "name": "'+EvalString_0+'"'+JsonEvalString_0+'},\n'; return code; */; insert_2_s - : '插入事件' 'x' PosString ',' 'y' PosString Event_List? '楼层' IdString? '参数列表' EvalString? Newline + : '插入事件' 'x' PosString ',' 'y' PosString Event_List? '楼层' IdString? '参数列表' JsonEvalString? Newline /* insert_2_s @@ -813,33 +770,15 @@ helpUrl : https://h5mota.com/games/template/_docs/#/event?id=insert%ef%bc%9a%e6% default : ["0","0",null,"",""] colour : this.eventColor IdString_0 = IdString_0 && (', "floorId": "'+IdString_0+'"'); -if (EvalString_0) { - if (EvalString_0.indexOf('"')>=0) - throw new Error('请勿在此处使用双引号!尝试使用单引号吧~'); - try { - if (!(JSON.parse(EvalString_0.replace(/'/g, '"')) instanceof Array)) throw new Error(); - } - catch (e) { +if (JsonEvalString_0) { + if (!(JSON.parse(JsonEvalString_0) instanceof Array)) throw new Error('参数列表必须是个有效的数组!'); - } - EvalString_0 = ', "args": ' +EvalString_0; + JsonEvalString_0 = ', "args": ' +JsonEvalString_0; } if (Event_List_0 && Event_List_0 !=='null') Event_List_0 = ', "which": "'+Event_List_0+'"'; else Event_List_0 = ''; -var code = '{"type": "insert", "loc": ['+PosString_0+','+PosString_1+']'+Event_List_0+IdString_0+EvalString_0+'},\n'; -return code; -*/; - -revisit_s - : '重启当前事件' Newline - - -/* revisit_s -tooltip : revisit: 立即重启当前事件 -helpUrl : https://h5mota.com/games/template/_docs/#/event?id=revisit%EF%BC%9A%E7%AB%8B%E5%8D%B3%E9%87%8D%E5%90%AF%E5%BD%93%E5%89%8D%E4%BA%8B%E4%BB%B6 -colour : this.eventColor -var code = '{"type": "revisit"},\n'; +var code = '{"type": "insert", "loc": ['+PosString_0+','+PosString_1+']'+Event_List_0+IdString_0+JsonEvalString_0+'},\n'; return code; */; @@ -1056,14 +995,16 @@ return code; */; update_s - : '更新状态栏和地图显伤' Newline + : '更新状态栏和地图显伤' '不检查自动事件' Bool Newline /* update_s tooltip : update: 立刻更新状态栏和地图显伤 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=update%EF%BC%9A%E7%AB%8B%E5%88%BB%E6%9B%B4%E6%96%B0%E7%8A%B6%E6%80%81%E6%A0%8F%E5%92%8C%E5%9C%B0%E5%9B%BE%E6%98%BE%E4%BC%A4 +default : [false] colour : this.dataColor -var code = '{"type": "update"},\n'; +Bool_0 = Bool_0 ? (', "doNotCheckAutoEvents": true') : '' +var code = '{"type": "update"'+Bool_0+'},\n'; return code; */; @@ -1202,48 +1143,36 @@ return code; */; changeFloor_s - : '楼层切换' IdString? 'x' PosString? ',' 'y' PosString? '朝向' DirectionEx_List '动画时间' Int? Newline + : '楼层切换' IdString? 'x' PosString? ',' 'y' PosString? '朝向' DirectionEx_List '动画时间' IntString? Newline /* changeFloor_s tooltip : changeFloor: 楼层切换,动画时间可不填 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=changefloor%EF%BC%9A%E6%A5%BC%E5%B1%82%E5%88%87%E6%8D%A2 -default : ["MTx","0","0",null,500] +default : ["MTx","0","0",null,""] colour : this.dataColor DirectionEx_List_0 = DirectionEx_List_0 && (', "direction": "'+DirectionEx_List_0+'"'); -Int_0 = (Int_0!=='') ?(', "time": '+Int_0):''; +IntString_0 = IntString_0 ?(', "time": '+IntString_0):''; var floorstr = ''; if (PosString_0 && PosString_1) { floorstr = ', "loc": ['+PosString_0+','+PosString_1+']'; } -var code = '{"type": "changeFloor", "floorId": "'+IdString_0+'"'+floorstr+DirectionEx_List_0+Int_0+' },\n'; +var code = '{"type": "changeFloor", "floorId": "'+IdString_0+'"'+floorstr+DirectionEx_List_0+IntString_0+' },\n'; return code; */; -changePos_0_s - : '位置切换' 'x' PosString ',' 'y' PosString '朝向' DirectionEx_List Newline +changePos_s + : '位置朝向切换' 'x' PosString? ',' 'y' PosString? '朝向' DirectionEx_List Newline -/* changePos_0_s +/* changePos_s tooltip : changePos: 当前位置切换 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=changepos%EF%BC%9A%E5%BD%93%E5%89%8D%E4%BD%8D%E7%BD%AE%E5%88%87%E6%8D%A2%E5%8B%87%E5%A3%AB%E8%BD%AC%E5%90%91 -default : ["0","0",null] +default : ["","",null] colour : this.dataColor +var loc = (PosString_0 && PosString_1) ? (', "loc": ['+PosString_0+','+PosString_1+']') : ''; DirectionEx_List_0 = DirectionEx_List_0 && (', "direction": "'+DirectionEx_List_0+'"'); -var code = '{"type": "changePos", "loc": ['+PosString_0+','+PosString_1+']'+DirectionEx_List_0+'},\n'; -return code; -*/; - -changePos_1_s - : '勇士转向' Direction_List Newline - - -/* changePos_1_s -tooltip : changePos: 勇士转向 -helpUrl : https://h5mota.com/games/template/_docs/#/event?id=changepos%EF%BC%9A%E5%BD%93%E5%89%8D%E4%BD%8D%E7%BD%AE%E5%88%87%E6%8D%A2%E5%8B%87%E5%A3%AB%E8%BD%AC%E5%90%91 -colour : this.dataColor -default : [null] -var code = '{"type": "changePos", "direction": "'+Direction_List_0+'"},\n'; +var code = '{"type": "changePos"'+loc+DirectionEx_List_0+'},\n'; return code; */; @@ -1287,15 +1216,16 @@ return code; */; openShop_s - : '打开全局商店' IdString Newline + : '启用全局商店' IdString '同时打开' Bool Newline /* openShop_s tooltip : 全局商店 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=openshop%EF%BC%9A%E6%89%93%E5%BC%80%E4%B8%80%E4%B8%AA%E5%85%A8%E5%B1%80%E5%95%86%E5%BA%97 colour : this.dataColor -default : ["shop1"] -var code = '{"type": "openShop", "id": "'+IdString_0+'"},\n'; +default : ["shop1", true] +Bool_0 = Bool_0 ? (', "open": true') : ''; +var code = '{"type": "openShop", "id": "'+IdString_0+'"'+Bool_0+'},\n'; return code; */; @@ -1355,13 +1285,13 @@ return code; */; animate_s - : '显示动画' IdString '位置' EvalString? '不等待执行完毕' Bool Newline + : '显示动画' IdString '位置' EvalString? '相对窗口坐标' Bool '不等待执行完毕' Bool Newline /* animate_s tooltip : animate:显示动画,位置填hero或者1,2形式的位置,或者不填代表当前事件点 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=animate%EF%BC%9A%E6%98%BE%E7%A4%BA%E5%8A%A8%E7%94%BB -default : ["zone","hero",false] +default : ["zone","hero",false,false] colour : this.soundColor if (EvalString_0) { if(MotaActionFunctions.pattern.id2.test(EvalString_0)) { @@ -1374,8 +1304,9 @@ if (EvalString_0) { throw new Error('此处只能填hero或者1,2形式的位置,或者不填代表当前事件点'); } } -var async = Bool_0?', "async": true':''; -var code = '{"type": "animate", "name": "'+IdString_0+'"'+EvalString_0+async+'},\n'; +Bool_0 = Bool_0?', "alignWindow": true':''; +var async = Bool_1?', "async": true':''; +var code = '{"type": "animate", "name": "'+IdString_0+'"'+EvalString_0+Bool_0+async+'},\n'; return code; */; @@ -1397,7 +1328,7 @@ return code; */; moveViewport_s - : '移动视角' '动画时间' Int? '不等待执行完毕' Bool BGNL? StepString Newline + : '移动视角' '动画时间' IntString '不等待执行完毕' Bool BGNL? StepString Newline /* moveViewport_s @@ -1405,9 +1336,9 @@ tooltip : moveViewport:移动视角 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=movehero%EF%BC%9A%E7%A7%BB%E5%8A%A8%E5%8B%87%E5%A3%AB default : [300,false,"上右3下2左"] colour : this.soundColor -Int_0 = Int_0!=='' ?(', "time": '+Int_0):''; +IntString_0 = IntString_0 ?(', "time": '+IntString_0):''; Bool_0 = Bool_0?', "async": true':''; -var code = '{"type": "moveViewport"'+Int_0+Bool_0+', "steps": '+JSON.stringify(StepString_0)+'},\n'; +var code = '{"type": "moveViewport"'+IntString_0+Bool_0+', "steps": '+JSON.stringify(StepString_0)+'},\n'; return code; */; @@ -1478,28 +1409,18 @@ var code = '{"type": "hideImage", "code": '+Int_0+', "time": '+Int_1+async+'},\n return code; */; -showGif_0_s - : '显示动图' EvalString '起点像素位置' 'x' PosString 'y' PosString Newline +showGif_s + : '显示动图' EvalString? '起点像素位置' 'x' PosString? 'y' PosString? Newline -/* showGif_0_s +/* showGif_s tooltip : showGif:显示动图 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=showgif%EF%BC%9A%E6%98%BE%E7%A4%BA%E5%8A%A8%E5%9B%BE -default : ["bg.gif","0","0"] +default : ["","",""] colour : this.printColor -var code = '{"type": "showGif", "name": "'+EvalString_0+'", "loc": ['+PosString_0+','+PosString_1+']},\n'; -return code; -*/; - -showGif_1_s - : '清除所有动图' Newline - - -/* showGif_1_s -tooltip : showGif:清除所有显示的动图 -helpUrl : https://h5mota.com/games/template/_docs/#/event?id=showgif%EF%BC%9A%E6%98%BE%E7%A4%BA%E5%8A%A8%E5%9B%BE -colour : this.printColor -var code = '{"type": "showGif"},\n'; +EvalString_0 = EvalString_0 ? (', "name": "'+EvalString_0+'"') : ''; +var loc = (PosString_0 && PosString_1) ? (', "loc": ['+PosString_0+','+PosString_1+']') : ''; +var code = '{"type": "showGif"'+EvalString_0+loc+'},\n'; return code; */; @@ -1524,24 +1445,23 @@ return code; */; setCurtain_0_s - : '更改画面色调' EvalString Colour '动画时间' Int? '不等待执行完毕' Bool Newline + : '更改画面色调' ColorString Colour '动画时间' IntString '持续到下一个本事件' Bool '不等待执行完毕' Bool Newline /* setCurtain_0_s tooltip : setCurtain: 更改画面色调,动画时间可不填 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=setcurtain%EF%BC%9A%E6%9B%B4%E6%94%B9%E7%94%BB%E9%9D%A2%E8%89%B2%E8%B0%83 -default : ["255,255,255,1",'rgba(255,255,255,1)',500,false] +default : ["255,255,255,1",'rgba(255,255,255,1)',500,true,false] colour : this.soundColor -var colorRe = MotaActionFunctions.pattern.colorRe; -if (!colorRe.test(EvalString_0))throw new Error('颜色格式错误,形如:0~255,0~255,0~255,0~1'); -Int_0 = Int_0!=='' ?(', "time": '+Int_0):''; -var async = Bool_0?', "async": true':''; -var code = '{"type": "setCurtain", "color": ['+EvalString_0+']'+Int_0 +async+'},\n'; +IntString_0 = IntString_0 ?(', "time": '+IntString_0):''; +Bool_0 = Bool_0 ? ', "keep": true' : ''; +var async = Bool_1?', "async": true':''; +var code = '{"type": "setCurtain", "color": ['+ColorString_0+']'+IntString_0 +Bool_0+async+'},\n'; return code; */; setCurtain_1_s - : '恢复画面色调' '动画时间' Int? '不等待执行完毕' Bool Newline + : '恢复画面色调' '动画时间' IntString? '不等待执行完毕' Bool Newline /* setCurtain_1_s @@ -1549,45 +1469,45 @@ tooltip : setCurtain: 恢复画面色调,动画时间可不填 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=setcurtain%EF%BC%9A%E6%9B%B4%E6%94%B9%E7%94%BB%E9%9D%A2%E8%89%B2%E8%B0%83 default : [500,false] colour : this.soundColor -Int_0 = Int_0!=='' ?(', "time": '+Int_0):''; +IntString_0 = IntString_0 ?(', "time": '+IntString_0):''; var async = Bool_0?', "async": true':''; -var code = '{"type": "setCurtain"'+Int_0 +async+'},\n'; +var code = '{"type": "setCurtain"'+IntString_0 +async+'},\n'; return code; */; screenFlash_s - : '画面闪烁' EvalString Colour '单次时间' Int '执行次数' Int? '不等待执行完毕' Bool Newline + : '画面闪烁' ColorString Colour '单次时间' Int '执行次数' IntString? '不等待执行完毕' Bool Newline /* screenFlash_s tooltip : screenFlash: 画面闪烁,动画时间可不填 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=screenFlash%EF%BC%9A%E7%94%BB%E9%9D%A2%E9%97%AA%E7%83%81 default : ["255,255,255,1",'rgba(255,255,255,1)',500,1,false] colour : this.soundColor -var colorRe = MotaActionFunctions.pattern.colorRe; -if (!colorRe.test(EvalString_0))throw new Error('颜色格式错误,形如:0~255,0~255,0~255,0~1'); -Int_1 = Int_1!=='' ?(', "times": '+Int_1):''; +if (ColorString_0 == '') throw new Error('颜色格式错误,形如:0~255,0~255,0~255,0~1'); +IntString_0 = IntString_0 ? (', "times": '+IntString_0):''; var async = Bool_0?', "async": true':''; -var code = '{"type": "screenFlash", "color": ['+EvalString_0+'], "time": '+Int_0 +Int_1+async+'},\n'; +var code = '{"type": "screenFlash", "color": ['+ColorString_0+'], "time": '+Int_0 +IntString_0+async+'},\n'; return code; */; setWeather_s - : '更改天气' Weather_List '强度' Int Newline + : '更改天气' Weather_List '强度' Int '持续到下个本事件' Bool Newline /* setWeather_s tooltip : setWeather:更改天气 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=setweather%EF%BC%9A%E6%9B%B4%E6%94%B9%E5%A4%A9%E6%B0%94 -default : [null,1] +default : [null,1,true] colour : this.soundColor if(Int_0<1 || Int_0>10) throw new Error('天气的强度等级, 在1-10之间'); -var code = '{"type": "setWeather", "name": "'+Weather_List_0+'", "level": '+Int_0+'},\n'; +Bool_0 = Bool_0 ? ', "keep": true' : '' +var code = '{"type": "setWeather", "name": "'+Weather_List_0+'", "level": '+Int_0+Bool_0+'},\n'; if(Weather_List_0===''||Weather_List_0==='null'||Weather_List_0==null)code = '{"type": "setWeather"},\n'; return code; */; move_s - : '移动事件' 'x' PosString? ',' 'y' PosString? '动画时间' Int? '不消失' Bool '不等待执行完毕' Bool BGNL? StepString Newline + : '移动事件' 'x' PosString? ',' 'y' PosString? '动画时间' IntString? '不消失' Bool '不等待执行完毕' Bool BGNL? StepString Newline /* move_s @@ -1599,30 +1519,30 @@ var floorstr = ''; if (PosString_0 && PosString_1) { floorstr = ', "loc": ['+PosString_0+','+PosString_1+']'; } -Int_0 = Int_0!=='' ?(', "time": '+Int_0):''; +IntString_0 = IntString_0 ?(', "time": '+IntString_0):''; Bool_0 = Bool_0?', "keep": true':''; Bool_1 = Bool_1?', "async": true':''; -var code = '{"type": "move"'+floorstr+Int_0+Bool_0+Bool_1+', "steps": '+JSON.stringify(StepString_0)+'},\n'; +var code = '{"type": "move"'+floorstr+IntString_0+Bool_0+Bool_1+', "steps": '+JSON.stringify(StepString_0)+'},\n'; return code; */; moveHero_s - : '移动勇士' '动画时间' Int? '不等待执行完毕' Bool BGNL? StepString Newline + : '移动勇士' '动画时间' IntString? '不等待执行完毕' Bool BGNL? StepString Newline /* moveHero_s tooltip : moveHero:移动勇士,用这种方式移动勇士的过程中将无视一切地形, 无视一切事件, 中毒状态也不会扣血 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=movehero%EF%BC%9A%E7%A7%BB%E5%8A%A8%E5%8B%87%E5%A3%AB -default : [500,false,"上右3下2后4左前2"] +default : ["",false,"上右3下2后4左前2"] colour : this.dataColor -Int_0 = Int_0!=='' ?(', "time": '+Int_0):''; +IntString_0 = IntString_0 ?(', "time": '+IntString_0):''; Bool_0 = Bool_0?', "async": true':''; -var code = '{"type": "moveHero"'+Int_0+Bool_0+', "steps": '+JSON.stringify(StepString_0)+'},\n'; +var code = '{"type": "moveHero"'+IntString_0+Bool_0+', "steps": '+JSON.stringify(StepString_0)+'},\n'; return code; */; jump_s - : '跳跃事件' '起始 x' PosString? ',' 'y' PosString? '终止 x' PosString? ',' 'y' PosString? '动画时间' Int? '不消失' Bool '不等待执行完毕' Bool Newline + : '跳跃事件' '起始 x' PosString? ',' 'y' PosString? '终止 x' PosString? ',' 'y' PosString? '动画时间' IntString? '不消失' Bool '不等待执行完毕' Bool Newline /* jump_s @@ -1637,15 +1557,15 @@ if (PosString_0 && PosString_1) { if (PosString_2 && PosString_3) { floorstr += ', "to": ['+PosString_2+','+PosString_3+']'; } -Int_0 = Int_0!=='' ?(', "time": '+Int_0):''; +IntString_0 = IntString_0 ?(', "time": '+IntString_0):''; Bool_0 = Bool_0?', "keep": true':''; Bool_1 = Bool_1?', "async": true':''; -var code = '{"type": "jump"'+floorstr+''+Int_0+Bool_0+Bool_1+'},\n'; +var code = '{"type": "jump"'+floorstr+''+IntString_0+Bool_0+Bool_1+'},\n'; return code; */; jumpHero_s - : '跳跃勇士' 'x' PosString? ',' 'y' PosString? '动画时间' Int? '不等待执行完毕' Bool Newline + : '跳跃勇士' 'x' PosString? ',' 'y' PosString? '动画时间' IntString? '不等待执行完毕' Bool Newline /* jumpHero_s @@ -1657,23 +1577,24 @@ var floorstr = ''; if (PosString_0 && PosString_1) { floorstr = ', "loc": ['+PosString_0+','+PosString_1+']'; } -Int_0 = Int_0!=='' ?(', "time": '+Int_0):''; +IntString_0 = IntString_0 ?(', "time": '+IntString_0):''; Bool_0 = Bool_0?', "async": true':''; -var code = '{"type": "jumpHero"'+floorstr+Int_0+Bool_0+'},\n'; +var code = '{"type": "jumpHero"'+floorstr+IntString_0+Bool_0+'},\n'; return code; */; playBgm_s - : '播放背景音乐' EvalString '持续到下个本事件' Bool Newline + : '播放背景音乐' EvalString '开始播放秒数' Int '持续到下个本事件' Bool Newline /* playBgm_s tooltip : playBgm: 播放背景音乐 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=playbgm%EF%BC%9A%E6%92%AD%E6%94%BE%E8%83%8C%E6%99%AF%E9%9F%B3%E4%B9%90 -default : ["bgm.mp3", true] +default : ["bgm.mp3", 0, true] colour : this.soundColor +Int_0 = Int_0 ? (', "startTime": '+Int_0) : ''; Bool_0 = Bool_0 ? ', "keep": true' : ''; -var code = '{"type": "playBgm", "name": "'+EvalString_0+'"'+Bool_0+'},\n'; +var code = '{"type": "playBgm", "name": "'+EvalString_0+'"'+Int_0+Bool_0+'},\n'; return code; */; @@ -1690,14 +1611,15 @@ return code; */; resumeBgm_s - : '恢复背景音乐' Newline + : '恢复背景音乐' '从暂停位置继续播放' Bool Newline /* resumeBgm_s tooltip : resumeBgm: 恢复背景音乐 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=resumebgm%EF%BC%9A%E6%81%A2%E5%A4%8D%E8%83%8C%E6%99%AF%E9%9F%B3%E4%B9%90 colour : this.soundColor -var code = '{"type": "resumeBgm"},\n'; +Bool_0 = Bool_0 ? ', "resume": true' : ''; +var code = '{"type": "resumeBgm"' + Bool_0 + '},\n'; return code; */; @@ -1754,7 +1676,7 @@ return code; */; setVolume_s - : '设置音量' Int '渐变时间' Int? '不等待执行完毕' Bool Newline + : '设置音量' Int '渐变时间' IntString? '不等待执行完毕' Bool Newline /* setVolume_s @@ -1762,9 +1684,9 @@ tooltip : setVolume: 设置音量 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=setvolume%EF%BC%9A%E8%AE%BE%E7%BD%AE%E9%9F%B3%E9%87%8F default : [90, 500, false] colour : this.soundColor -Int_1 = Int_1!==''?(', "time": '+Int_1):"" +IntString_0 = IntString_0 ?(', "time": '+IntString_0):''; var async = Bool_0?', "async": true':''; -var code = '{"type": "setVolume", "value": '+Int_0+Int_1+async+'},\n'; +var code = '{"type": "setVolume", "value": '+Int_0+IntString_0+async+'},\n'; return code; */; @@ -1890,13 +1812,13 @@ return code; */; choices_s - : '选项' ':' EvalString? BGNL? '标题' EvalString? '图像' IdString? BGNL? Newline choicesContext+ BEND Newline + : '选项' ':' EvalString? BGNL? '标题' EvalString? '图像' IdString? '超时毫秒数' Int BGNL? Newline choicesContext+ BEND Newline /* choices_s tooltip : choices: 给用户提供选项 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=choices%EF%BC%9A%E7%BB%99%E7%94%A8%E6%88%B7%E6%8F%90%E4%BE%9B%E9%80%89%E9%A1%B9 -default : ["","流浪者","woman"] +default : ["","流浪者","woman",0] var title=''; if (EvalString_1==''){ if (IdString_0=='')title=''; @@ -1907,14 +1829,15 @@ if (EvalString_1==''){ } EvalString_0 = title+EvalString_0; EvalString_0 = EvalString_0 ?(', "text": "'+EvalString_0+'"'):''; -var code = ['{"type": "choices"',EvalString_0,', "choices": [\n', +Int_0 = Int_0 ? (', "timeout": '+Int_0) : ''; +var code = ['{"type": "choices"',EvalString_0,Int_0,', "choices": [\n', choicesContext_0, ']},\n'].join(''); return code; */; choicesContext - : '子选项' EvalString '图标' IdString? '颜色' EvalString? Colour '出现条件' EvalString? BGNL? Newline action+ + : '子选项' EvalString '图标' IdString? '颜色' ColorString? Colour '出现条件' EvalString? BGNL? Newline action+ /* choicesContext @@ -1922,34 +1845,58 @@ tooltip : 选项的选择 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=choices%EF%BC%9A%E7%BB%99%E7%94%A8%E6%88%B7%E6%8F%90%E4%BE%9B%E9%80%89%E9%A1%B9 default : ["提示文字:红钥匙","","",""] colour : this.subColor -if (EvalString_1) { - var colorRe = MotaActionFunctions.pattern.colorRe; - if (colorRe.test(EvalString_1)) - EvalString_1 = ', "color": ['+EvalString_1+']'; - else - EvalString_1 = ', "color": "'+EvalString_1+'"'; -} -EvalString_2 = EvalString_2 && (', "condition": "'+EvalString_2+'"') +ColorString_0 = ColorString_0 ? (', "color": ['+ColorString_0+']') : ''; +EvalString_1 = EvalString_1 && (', "condition": "'+EvalString_1+'"') IdString_0 = IdString_0?(', "icon": "'+IdString_0+'"'):''; -var code = '{"text": "'+EvalString_0+'"'+IdString_0+EvalString_1+EvalString_2+', "action": [\n'+action_0+']},\n'; +var code = '{"text": "'+EvalString_0+'"'+IdString_0+ColorString_0+EvalString_1+', "action": [\n'+action_0+']},\n'; return code; */; confirm_s - : '显示确认框' ':' EvalString BGNL? '确定的场合' ':' '(默认选中' Bool ')' BGNL? Newline action+ '取消的场合' ':' BGNL? Newline action+ BEND Newline + : '显示确认框' ':' EvalString '超时毫秒数' Int BGNL? '确定的场合' ':' '(默认选中' Bool ')' BGNL? Newline action+ '取消的场合' ':' BGNL? Newline action+ BEND Newline /* confirm_s tooltip : 弹出确认框 helpUrl : https://h5mota.com/games/template/_docs/#/ -default : ["确认要xxx吗?",false] +default : ["确认要xxx吗?",0,false] Bool_0 = Bool_0?', "default": true':'' -var code = ['{"type": "confirm"'+Bool_0+', "text": "',EvalString_0,'",\n', +Int_0 = Int_0 ? (', "timeout": '+Int_0) : ''; +var code = ['{"type": "confirm"'+Int_0+Bool_0+', "text": "',EvalString_0,'",\n', '"yes": [\n',action_0,'],\n', '"no": [\n',action_1,']\n', '},\n'].join(''); return code; */; +for_s + : '循环遍历' ': ' expression '从' EvalString '到' EvalString '步增' EvalString BGNL? Newline action+ BEND Newline + +/* for_s +tooltip : for:循环遍历 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=while%ef%bc%9a%e5%89%8d%e7%bd%ae%e6%9d%a1%e4%bb%b6%e5%be%aa%e7%8e%af +colour : this.eventColor +if (!/^temp:[A-Z]$/.test(expression_0)) { + throw new Error('循环遍历仅允许使用临时变量!'); +} +return '{"type": "for", "name": "'+expression_0+'", "from": "'+EvalString_0+'", "to": "'+EvalString_1+'", "step": "'+EvalString_2+'",\n"data": [\n'+action_0+']},\n'; +*/; + +forEach_s + : '循环遍历' ': 以' expression '逐项读取列表' JsonEvalString BGNL? Newline action+ BEND Newline + +/* forEach_s +tooltip : forEach:循环遍历列表 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=while%ef%bc%9a%e5%89%8d%e7%bd%ae%e6%9d%a1%e4%bb%b6%e5%be%aa%e7%8e%af +colour : this.eventColor +if (!/^temp:[A-Z]$/.test(expression_0)) { + throw new Error('循环遍历仅允许使用临时变量!'); +} +if (JsonEvalString_0 == '' || !(JSON.parse(JsonEvalString_0) instanceof Array)) { + throw new Error('参数列表必须是个有效的数组!'); +} +return '{"type": "forEach", "name": "'+expression_0+'", "list": '+JsonEvalString_0 + ',\n"data": [\n'+action_0+']},\n'; +*/; + while_s : '前置条件循环' ':' '当' expression '时' BGNL? Newline action+ BEND Newline @@ -2000,15 +1947,17 @@ return code; wait_s - : '等待用户操作并获得按键或点击信息' BGNL? Newline waitContext* BEND Newline + : '等待用户操作并获得按键或点击信息' '超时毫秒数' Int BGNL? Newline waitContext* BEND Newline /* wait_s tooltip : wait: 等待用户操作并获得按键或点击信息 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=wait%EF%BC%9A%E7%AD%89%E5%BE%85%E7%94%A8%E6%88%B7%E6%93%8D%E4%BD%9C +default : [0] colour : this.soundColor +Int_0 = Int_0?(', "timeout": ' + Int_0):''; waitContext_0 = waitContext_0 ? (', "data": [\n' + waitContext_0 + ']') : ''; -var code = '{"type": "wait"' + waitContext_0 + '},\n'; +var code = '{"type": "wait"' + Int_0 + waitContext_0 + '},\n'; return code; */; @@ -2020,13 +1969,16 @@ waitContext waitContext_1 - : '按键的场合' '键值' Int BGNL? Newline action+ BEND Newline + : '按键的场合' '键值' EvalString BGNL? Newline action+ BEND Newline /* waitContext_1 tooltip : wait: 等待用户操作并获得按键或点击信息 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=wait%EF%BC%9A%E7%AD%89%E5%BE%85%E7%94%A8%E6%88%B7%E6%93%8D%E4%BD%9C colour : this.subColor -var code = '{"case": "keyboard", "keycode": ' + Int_0 + ', "action": [\n' + action_0 + ']},\n'; +if (!/^\d+(,\d+)*$/.test(EvalString_0)) { + throw new Error('键值必须是正整数,可以以逗号分隔'); +} +var code = '{"case": "keyboard", "keycode": "' + EvalString_0 + '", "action": [\n' + action_0 + ']},\n'; return code; */; @@ -2156,7 +2108,7 @@ return code; setAttribute_s - : '设置画布属性' '字体' EvalString? '填充样式' EvalString? Colour '边框样式' EvalString? Colour BGNL? '线宽度' EvalString? '不透明度' EvalString? '对齐' TextAlign_List '基准线' TextBaseline_List 'z值' EvalString? Newline + : '设置画布属性' '字体' FontString? '填充样式' ColorString? Colour '边框样式' ColorString? Colour BGNL? '线宽度' IntString? '不透明度' EvalString? '对齐' TextAlign_List '基准线' TextBaseline_List 'z值' IntString? Newline /* setAttribute_s tooltip : setAttribute:设置画布属性 @@ -2165,283 +2117,189 @@ colour : this.subColor default : ["","",'rgba(255,255,255,1)',"",'rgba(255,255,255,1)',"","",null,null,""] TextAlign_List_0 = TextAlign_List_0==='null'?'': ', "align": "'+TextAlign_List_0+'"'; TextBaseline_List_0 = TextBaseline_List_0==='null'?'': ', "baseline": "'+TextBaseline_List_0+'"'; -var colorRe = MotaActionFunctions.pattern.colorRe; -var fontRe = MotaActionFunctions.pattern.fontRe; +FontString_0 = FontString_0 ? (', "font": "' + FontString_0 + '"') : ''; +ColorString_0 = ColorString_0 ? (', "fillStyle": ['+ColorString_0+']') : ''; +ColorString_1 = ColorString_1 ? (', "strokeStyle": ['+ColorString_1+']') : ''; +IntString_0 = IntString_0 ? (', "lineWidth": '+IntString_0) : ''; if (EvalString_0) { - if (!fontRe.test(EvalString_0)) throw new Error('字体必须是 [italic] [bold] 14px Verdana 这种形式或不填'); - EvalString_0 = ', "font": "' + EvalString_0 + '"'; -} -if (EvalString_1) { - if (!colorRe.test(EvalString_1))throw new Error('颜色格式错误,形如:0~255,0~255,0~255,0~1'); - EvalString_1 = ', "fillStyle": ['+EvalString_1+']'; -} -if (EvalString_2) { - if (!colorRe.test(EvalString_2))throw new Error('颜色格式错误,形如:0~255,0~255,0~255,0~1'); - EvalString_2 = ', "strokeStyle": ['+EvalString_2+']'; -} -if (EvalString_3) { - if (!/^\d+$/.test(EvalString_3))throw new Error('线宽必须是整数或不填'); - EvalString_3 = ', "lineWidth": '+EvalString_3; -} -if (EvalString_4) { - var f = parseFloat(EvalString_4); + var f = parseFloat(EvalString_0); if (isNaN(f) || f<0 || f>1) throw new Error('不透明度必须是0到1的浮点数或不填'); - EvalString_4 = ', "alpha": '+EvalString_4; + EvalString_0 = ', "alpha": '+EvalString_0; } -if (EvalString_5) { - if (!/^\d+$/.test(EvalString_5))throw new Error('z值必须是整数或不填'); - EvalString_5 = ', "z": '+EvalString_5; -} -var code = '{"type": "setAttribute"'+EvalString_0+EvalString_1+EvalString_2+EvalString_3+EvalString_4+TextAlign_List_0+TextBaseline_List_0+EvalString_5+'},\n'; +IntString_1 = IntString_1 ? (', "z": '+IntString_1) : ''; +var code = '{"type": "setAttribute"'+FontString_0+ColorString_0+ColorString_1+IntString_0+ + EvalString_0+TextAlign_List_0+TextBaseline_List_0+IntString_1+'},\n'; return code; */; fillText_s - : '绘制文本' 'x' PosString 'y' PosString '样式' EvalString? Colour '字体' EvalString? '最大宽度' EvalString? BGNL? EvalString Newline + : '绘制文本' 'x' PosString 'y' PosString '样式' ColorString? Colour '字体' FontString? '最大宽度' IntString? BGNL? EvalString Newline /* fillText_s tooltip : fillText:绘制一行文本;可以设置最大宽度进行放缩 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=fillText%ef%bc%9a%e7%bb%98%e5%88%b6%e6%96%87%e6%9c%ac colour : this.subColor default : ["0","0","",'rgba(255,255,255,1)',"","","绘制一行文本"] -var colorRe = MotaActionFunctions.pattern.colorRe; -var fontRe = MotaActionFunctions.pattern.fontRe; -if (EvalString_0) { - if (!colorRe.test(EvalString_0))throw new Error('颜色格式错误,形如:0~255,0~255,0~255,0~1'); - EvalString_0 = ', "style": ['+EvalString_0+']'; -} -if (EvalString_1) { - if (!fontRe.test(EvalString_1)) throw new Error('字体必须是 [italic] [bold] 14px Verdana 这种形式或不填'); - EvalString_1 = ', "font": "' + EvalString_1 + '"'; -} -if (EvalString_2) { - if (!/^\d+$/.test(EvalString_2)) throw new Error('最大宽度必须是整数或不填'); - EvalString_2 = ', "maxWidth": ' + EvalString_2; -} -var code = '{"type": "fillText", "x": '+PosString_0+', "y": '+PosString_1+EvalString_0+EvalString_1+EvalString_2+', "text": "'+EvalString_3+'"},\n'; +ColorString_0 = ColorString_0 ? (', "style": ['+ColorString_0+']') : ''; +FontString_0 = FontString_0 ? (', "font": "' + FontString_0 + '"') : ''; +IntString_0 = IntString_0 ? (', "maxWidth": '+IntString_0) : ''; +var code = '{"type": "fillText", "x": '+PosString_0+', "y": '+PosString_1+ColorString_0+FontString_0+IntString_0+', "text": "'+EvalString_0+'"},\n'; return code; */; fillBoldText_s - : '绘制描边文本' 'x' PosString 'y' PosString '样式' EvalString? Colour '字体' EvalString? BGNL? EvalString Newline + : '绘制描边文本' 'x' PosString 'y' PosString '样式' ColorString? Colour '描边颜色' ColorString? Colour '字体' FontString? BGNL? EvalString Newline /* fillBoldText_s tooltip : fillBoldText:绘制一行描边文本 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=fillBoldText%ef%bc%9a%e7%bb%98%e5%88%b6%e6%8f%8f%e8%be%b9%e6%96%87%e6%9c%ac colour : this.subColor -default : ["0","0","",'rgba(255,255,255,1)',"","绘制一行描边文本"] -var colorRe = MotaActionFunctions.pattern.colorRe; -var fontRe = MotaActionFunctions.pattern.fontRe; -if (EvalString_0) { - if (!colorRe.test(EvalString_0))throw new Error('颜色格式错误,形如:0~255,0~255,0~255,0~1'); - EvalString_0 = ', "style": ['+EvalString_0+']'; -} -if (EvalString_1) { - if (!fontRe.test(EvalString_1)) throw new Error('字体必须是 [italic] [bold] 14px Verdana 这种形式或不填'); - EvalString_1 = ', "font": "' + EvalString_1 + '"'; -} -var code = '{"type": "fillBoldText", "x": '+PosString_0+', "y": '+PosString_1+EvalString_0+EvalString_1+', "text": "'+EvalString_2+'"},\n'; +default : ["0","0","",'rgba(255,255,255,1)',"",'rgba(0,0,0,1)',"","绘制一行描边文本"] +ColorString_0 = ColorString_0 ? (', "style": ['+ColorString_0+']') : ''; +ColorString_1 = ColorString_1 ? (', "strokeStyle": ['+ColorString_1+']') : ''; +FontString_0 = FontString_0 ? (', "font": "' + FontString_0 + '"') : ''; +var code = '{"type": "fillBoldText", "x": '+PosString_0+', "y": '+PosString_1+ColorString_0+ColorString_1+FontString_0+', "text": "'+EvalString_0+'"},\n'; return code; */; drawTextContent_s - : '绘制多行文本' EvalString BGNL? '起点像素' 'x' PosString 'y' PosString '最大宽度' EvalString? '颜色' EvalString? Colour BGNL? '对齐' TextAlign_List '字体大小' EvalString? '行距' EvalString? '粗体' Bool Newline + : '绘制多行文本' EvalString BGNL? '起点像素' 'x' PosString 'y' PosString '最大宽度' IntString? '颜色' ColorString? Colour BGNL? '对齐' TextAlign_List '字体大小' IntString? '行距' IntString? '粗体' Bool Newline /* drawTextContent_s tooltip : drawTextContent:绘制多行文本 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=drawTextContent%ef%bc%9a%e7%bb%98%e5%88%b6%e5%a4%9a%e8%a1%8c%e6%96%87%e6%9c%ac colour : this.subColor default : ["绘制多行文本\\n可双击编辑","0","0","","",'rgba(255,255,255,1)',null,"","",false] -var colorRe = MotaActionFunctions.pattern.colorRe; TextAlign_List_0 = TextAlign_List_0==='null'?'': ', "align": "'+TextAlign_List_0+'"'; Bool_0 = Bool_0 ? (', "bold": true') : ''; -if (EvalString_1) { - if (!/^\d+$/.test(EvalString_1)) throw new Error('最大宽度必须是整数或不填'); - EvalString_1 = ', "maxWidth": ' + EvalString_1; -} -if (EvalString_2) { - if (!colorRe.test(EvalString_2))throw new Error('颜色格式错误,形如:0~255,0~255,0~255,0~1'); - EvalString_2 = ', "color": ['+EvalString_2+']'; -} -if (EvalString_3) { - if (!/^\d+$/.test(EvalString_3)) throw new Error('字体大小必须是整数或不填'); - EvalString_3 = ', "fontSize": ' + EvalString_3; -} -if (EvalString_4) { - if (!/^\d+$/.test(EvalString_4)) throw new Error('行距必须是整数或不填'); - EvalString_4 = ', "lineHeight": ' + EvalString_4; -} -var code = '{"type": "drawTextContent", "text": "'+EvalString_0+'", "left": '+PosString_0+', "top": '+PosString_1+TextAlign_List_0+EvalString_1+EvalString_2+EvalString_3+EvalString_4+Bool_0+'},\n'; +IntString_0 = IntString_0 ? (', "maxWidth": '+IntString_0) : ''; +IntString_1 = IntString_1 ? (', "fontSize": '+IntString_1) : ''; +IntString_2 = IntString_2 ? (', "lineHeight": '+IntString_2) : ''; +ColorString_0 = ColorString_0 ? (', "color": ['+ColorString_0+']') : ''; +var code = '{"type": "drawTextContent", "text": "'+EvalString_0+'", "left": '+PosString_0+', "top": '+PosString_1+TextAlign_List_0+IntString_0+IntString_1+IntString_2+ColorString_0+Bool_0+'},\n'; return code; */; fillRect_s - : '绘制矩形' '起点像素' 'x' PosString 'y' PosString '宽' PosString '高' PosString '颜色' EvalString? Colour Newline + : '绘制矩形' '起点像素' 'x' PosString 'y' PosString '宽' PosString '高' PosString '颜色' ColorString? Colour Newline /* fillRect_s tooltip : fillRect:绘制矩形 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=fillRect%ef%bc%9a%e7%bb%98%e5%88%b6%e7%9f%a9%e5%bd%a2 colour : this.subColor default : ["0","0","flag:x","300","",null] -var colorRe = MotaActionFunctions.pattern.colorRe; -if (EvalString_0) { - if (!colorRe.test(EvalString_0))throw new Error('颜色格式错误,形如:0~255,0~255,0~255,0~1'); - EvalString_0 = ', "style": ['+EvalString_0+']'; -} -var code = '{"type": "fillRect", "x": '+PosString_0+', "y": '+PosString_1+', "width": '+PosString_2+', "height": '+PosString_3+EvalString_0+'},\n'; +ColorString_0 = ColorString_0 ? (', "style": ['+ColorString_0+']') : ''; +var code = '{"type": "fillRect", "x": '+PosString_0+', "y": '+PosString_1+', "width": '+PosString_2+', "height": '+PosString_3+ColorString_0+'},\n'; return code; */; strokeRect_s - : '绘制矩形边框' '起点像素' 'x' PosString 'y' PosString '宽' PosString '高' PosString '颜色' EvalString? Colour '线宽' EvalString? Newline + : '绘制矩形边框' '起点像素' 'x' PosString 'y' PosString '宽' PosString '高' PosString '颜色' ColorString? Colour '线宽' IntString? Newline /* strokeRect_s tooltip : strokeRect:绘制矩形边框 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=strokeRect%ef%bc%9a%e7%bb%98%e5%88%b6%e7%9f%a9%e5%bd%a2%e8%be%b9%e6%a1%86 colour : this.subColor default : ["0","0","flag:x","300","",null,""] -var colorRe = MotaActionFunctions.pattern.colorRe; -if (EvalString_0) { - if (!colorRe.test(EvalString_0))throw new Error('颜色格式错误,形如:0~255,0~255,0~255,0~1'); - EvalString_0 = ', "style": ['+EvalString_0+']'; -} -if (EvalString_1) { - if (!/^\d+$/.test(EvalString_1))throw new Error('线宽必须是整数或不填'); - EvalString_1 = ', "lineWidth": '+EvalString_1; -} -var code = '{"type": "strokeRect", "x": '+PosString_0+', "y": '+PosString_1+', "width": '+PosString_2+', "height": '+PosString_3+EvalString_0+EvalString_1+'},\n'; +ColorString_0 = ColorString_0 ? (', "style": ['+ColorString_0+']') : ''; +IntString_0 = IntString_0 ? (', "lineWidth": '+IntString_0) : ''; +var code = '{"type": "strokeRect", "x": '+PosString_0+', "y": '+PosString_1+', "width": '+PosString_2+', "height": '+PosString_3+ColorString_0+IntString_0+'},\n'; return code; */; drawLine_s - : '绘制线段' '起点像素' 'x' PosString 'y' PosString '终点像素' 'x' PosString 'y' PosString '颜色' EvalString? Colour '线宽' EvalString? Newline + : '绘制线段' '起点像素' 'x' PosString 'y' PosString '终点像素' 'x' PosString 'y' PosString '颜色' ColorString? Colour '线宽' IntString? Newline /* drawLine_s tooltip : drawLine:绘制线段 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=drawLine%ef%bc%9a%e7%bb%98%e5%88%b6%e7%ba%bf%e6%ae%b5 colour : this.subColor default : ["0","0","flag:x","300","",null,""] -var colorRe = MotaActionFunctions.pattern.colorRe; -if (EvalString_0) { - if (!colorRe.test(EvalString_0))throw new Error('颜色格式错误,形如:0~255,0~255,0~255,0~1'); - EvalString_0 = ', "style": ['+EvalString_0+']'; -} -if (EvalString_1) { - if (!/^\d+$/.test(EvalString_1))throw new Error('线宽必须是整数或不填'); - EvalString_1 = ', "lineWidth": '+EvalString_1; -} -var code = '{"type": "drawLine", "x1": '+PosString_0+', "y1": '+PosString_1+', "x2": '+PosString_2+', "y2": '+PosString_3+EvalString_0+EvalString_1+'},\n'; +ColorString_0 = ColorString_0 ? (', "style": ['+ColorString_0+']') : ''; +IntString_0 = IntString_0 ? (', "lineWidth": '+IntString_0) : ''; +var code = '{"type": "drawLine", "x1": '+PosString_0+', "y1": '+PosString_1+', "x2": '+PosString_2+', "y2": '+PosString_3+ColorString_0+IntString_0+'},\n'; return code; */; drawArrow_s - : '绘制箭头' '起点像素' 'x' PosString 'y' PosString '终点像素' 'x' PosString 'y' PosString '颜色' EvalString? Colour '线宽' EvalString? Newline + : '绘制箭头' '起点像素' 'x' PosString 'y' PosString '终点像素' 'x' PosString 'y' PosString '颜色' ColorString? Colour '线宽' IntString? Newline /* drawArrow_s tooltip : drawArrow:绘制箭头 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=drawArrow%ef%bc%9a%e7%bb%98%e5%88%b6%e7%ae%ad%e5%a4%b4 colour : this.subColor default : ["0","0","flag:x","300","",null,""] -var colorRe = MotaActionFunctions.pattern.colorRe; -if (EvalString_0) { - if (!colorRe.test(EvalString_0))throw new Error('颜色格式错误,形如:0~255,0~255,0~255,0~1'); - EvalString_0 = ', "style": ['+EvalString_0+']'; -} -if (EvalString_1) { - if (!/^\d+$/.test(EvalString_1))throw new Error('线宽必须是整数或不填'); - EvalString_1 = ', "lineWidth": '+EvalString_1; -} -var code = '{"type": "drawArrow", "x1": '+PosString_0+', "y1": '+PosString_1+', "x2": '+PosString_2+', "y2": '+PosString_3+EvalString_0+EvalString_1+'},\n'; +ColorString_0 = ColorString_0 ? (', "style": ['+ColorString_0+']') : ''; +IntString_0 = IntString_0 ? (', "lineWidth": '+IntString_0) : ''; +var code = '{"type": "drawArrow", "x1": '+PosString_0+', "y1": '+PosString_1+', "x2": '+PosString_2+', "y2": '+PosString_3+ColorString_0+IntString_0+'},\n'; return code; */; fillPolygon_s - : '绘制多边形' '顶点像素列表' 'x' EvalString 'y' EvalString '颜色' EvalString? Colour Newline + : '绘制多边形' '顶点像素列表' 'x' EvalString 'y' EvalString '颜色' ColorString? Colour Newline /* fillPolygon_s tooltip : fillPolygon:绘制多边形 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=fillPolygon%ef%bc%9a%e7%bb%98%e5%88%b6%e5%a4%9a%e8%be%b9%e5%bd%a2 colour : this.subColor default : ["0,0,100","0,100,0","",null] -var colorRe = MotaActionFunctions.pattern.colorRe; var pattern2 = /^([+-]?\d+)(,[+-]?\d+)*$/; if(!pattern2.test(EvalString_0) || !pattern2.test(EvalString_1))throw new Error('坐标格式错误,请右键点击帮助查看格式'); EvalString_0=EvalString_0.split(','); EvalString_1=EvalString_1.split(','); if(EvalString_0.length!==EvalString_1.length)throw new Error('坐标格式错误,请右键点击帮助查看格式'); for(var ii=0;ii'|'<'|'>='|'<='|'和'|'或' ; +AssignOperator_List + : '='|'+='|'-='|'*='|'/='|'**='|'//='|'%=' + ; + Weather_List : '无'|'雨'|'雪'|'雾' /*Weather_List ['null','rain','snow','fog']*/; @@ -2809,8 +2701,12 @@ Bg_Fg_List : '背景层'|'前景层' /*Bg_Fg_List ['bg','fg']*/; +IgnoreChangeFloor_List + : '全局默认值' | '可穿透' | '不可穿透' + /*IgnoreChangeFloor_List ['null','true','false']*/; + Event_List - : '事件'|'战后事件'|'道具后事件'|'开门后事件' + : '普通事件'|'战后事件'|'道具后事件'|'开门后事件' /*Event_List ['null','afterBattle','afterGetItem','afterOpenDoor']*/; Floor_Meta_List @@ -2822,13 +2718,13 @@ Global_Attribute_List /*Global_Attribute_List ['font','statusLeftBackground','statusTopBackground', 'toolsBackground', 'borderColor', 'statusBarColor', 'hardLabelColor', 'floorChangingBackground', 'floorChangingTextColor', 'equipName']*/; Global_Value_List - : '血网伤害'|'中毒伤害'|'衰弱效果'|'红宝石效果'|'蓝宝石效果'|'绿宝石效果'|'红血瓶效果'|'蓝血瓶效果'|'黄血瓶效果'|'绿血瓶效果'|'破甲比例'|'反击比例'|'净化比例'|'仇恨增加值'|'行走速度'|'动画时间'|'楼层切换时间' - /*Global_Value_List ['lavaDamage','poisonDamage','weakValue', 'redJewel', 'blueJewel', 'greenJewel', 'redPotion', 'bluePotion', 'yellowPotion', 'greenPotion', 'breakArmor', 'counterAttack', 'purify', 'hatred', 'moveSpeed', 'animateSpeed', 'floorChangeTime']*/; + : '血网伤害'|'中毒伤害'|'衰弱效果'|'红宝石效果'|'蓝宝石效果'|'绿宝石效果'|'红血瓶效果'|'蓝血瓶效果'|'黄血瓶效果'|'绿血瓶效果'|'破甲比例'|'反击比例'|'净化比例'|'仇恨增加值'|'动画时间' + /*Global_Value_List ['lavaDamage','poisonDamage','weakValue', 'redJewel', 'blueJewel', 'greenJewel', 'redPotion', 'bluePotion', 'yellowPotion', 'greenPotion', 'breakArmor', 'counterAttack', 'purify', 'hatred', 'animateSpeed']*/; Global_Flag_List - : '显示当前楼层'|'显示勇士图标'|'显示当前等级'|'启用生命上限'|'显示魔力值'|'显示魔防值'|'显示金币值'|'显示经验值'|'允许等级提升'|'升级扣除模式'|'显示钥匙数量'|'显示破炸飞'|'显示毒衰咒'|'显示当前技能'|'楼梯边才能楼传'|'楼传平面塔模式'|'破墙镐四方向'|'炸弹四方向'|'冰冻徽章四方向'|'铁门不需要钥匙'|'开启加点'|'开启负伤'|'仇恨怪战后扣减一半'|'夹击是否上整'|'夹击不超伤害值'|'循环计算临界'|'允许轻按'|'寻路算法不绕血瓶'|'允许走到将死领域'|'允许瞬间移动'|'允许查看禁用商店'|'阻激夹域后禁用快捷商店'|'虚化前景层'|'检查控制台' - /*Global_Flag_List ['enableFloor','enableName','enableLv', 'enableHPMax', 'enableMana', 'enableMDef', 'enableMoney', 'enableExperience', 'enableLevelUp', 'levelUpLeftMode', 'enableKeys', 'enablePZF', 'enableDebuff', 'enableSkill', 'flyNearStair', 'flyRecordPosition', 'pickaxeFourDirections', 'bombFourDirections', 'snowFourDirections', 'steelDoorWithoutKey', 'enableAddPoint', 'enableNegativeDamage', 'hatredDecrease', 'betweenAttackCeil', 'betweenAttackMax', 'useLoop', 'enableGentleClick', 'potionWhileRouting', 'canGoDeadZone', 'enableMoveDirectly', 'enableDisabledShop', 'disableShopOnDamage', 'blurFg', 'checkConsole']*/; + : '显示当前楼层'|'显示勇士图标'|'显示当前等级'|'启用生命上限'|'显示生命值'|'显示魔力值'|'显示攻击力'|'显示防御力'|'显示护盾值'|'显示金币值'|'显示经验值'|'允许等级提升'|'升级扣除模式'|'显示钥匙数量'|'显示绿钥匙'|'显示破炸飞'|'显示毒衰咒'|'显示当前技能'|'楼梯边才能楼传'|'楼传平面塔模式'|'铁门不需要钥匙'|'开启加点'|'开启负伤'|'夹击不超伤害值'|'循环计算临界'|'允许轻按'|'允许走到将死领域'|'允许瞬间移动'|'阻激夹域后禁用快捷商店'|'虚化前景层'|'检查控制台' + /*Global_Flag_List ['s:enableFloor','s:enableName','s:enableLv', 's:enableHPMax', 's:enableHP', 's:enableMana', 's:enableAtk', 's:enableDef', 's:enableMDef', 's:enableMoney', 's:enableExp', 's:enableLevelUp', 's:levelUpLeftMode', 's:enableKeys', 's:enableGreenKey', 's:enablePZF', 's:enableDebuff', 's:enableSkill', 'flyNearStair', 'flyRecordPosition', 'steelDoorWithoutKey', 'enableAddPoint', 'enableNegativeDamage', 'betweenAttackMax', 'useLoop', 'enableGentleClick', 'canGoDeadZone', 'enableMoveDirectly', 'disableShopOnDamage', 'blurFg']*/; Colour : 'sdeirughvuiyasdeb'+ //为了被识别为复杂词法规则 @@ -2873,16 +2769,16 @@ IdString ; FixedId_List - : '生命'|'攻击'|'防御'|'魔防'|'黄钥匙'|'蓝钥匙'|'红钥匙'|'金币'|'经验' - /*FixedId_List ['status:hp','status:atk','status:def','status:mdef','item:yellowKey','item:blueKey','item:redKey','status:money','status:experience']*/; + : '生命'|'攻击'|'防御'|'护盾'|'黄钥匙'|'蓝钥匙'|'红钥匙'|'金币'|'经验' + /*FixedId_List ['status:hp','status:atk','status:def','status:mdef','item:yellowKey','item:blueKey','item:redKey','status:money','status:exp']*/; Id_List - : '变量' | '状态' | '物品' | '独立开关' | '全局存储' - /*Id_List ['flag','status','item', 'switch', 'global']*/; + : '变量' | '状态' | '物品' | '独立开关' | '临时变量' |'全局存储' + /*Id_List ['flag','status','item', 'switch', 'temp', 'global']*/; EnemyId_List - : '生命'|'攻击'|'防御'|'金币'|'经验'|'加点'|'属性'|'名称' - /*EnemyId_List ['hp','atk','def','money','experience','point','special','name']*/; + : '生命'|'攻击'|'防御'|'金币'|'经验'|'加点'|'属性'|'名称'|'映射名'|'value'|'atkValue'|'defValue'|'notBomb'|'zoneSquare'|'range'|'n'|'add'|'damage' + /*EnemyId_List ['hp','atk','def','money','exp','point','special','name','displayInBook','value','atkValue','defValue','notBomb','zoneSquare','range','n','add','damage']*/; //转blockly后不保留需要加" EvalString @@ -2949,6 +2845,7 @@ this.block('idString_4_e').output='idString_e'; this.block('idString_5_e').output='idString_e'; this.block('idString_6_e').output='idString_e'; this.block('evFlag_e').output='idString_e'; +this.block('evTemp_e').output='idString_e'; */ /* Functions @@ -2982,10 +2879,16 @@ ActionParser.prototype.parse = function (obj,type) { obj.floorType=obj.floorId; delete obj.floorId; } - if (!this.isset(obj.time)) obj.time=500; return MotaActionBlocks['changeFloor_m'].xmlText([ obj.floorType||'floorId',obj.floorId,obj.stair||'loc',obj.loc[0],obj.loc[1],obj.direction, - obj.time,!this.isset(obj.ignoreChangeFloor) + obj.time,obj.ignoreChangeFloor + ]); + + case 'afterGetItem': + if (!obj) obj = []; + if (obj instanceof Array) obj = {'data': obj}; + return MotaActionBlocks['afterGetItem_m'].xmlText([ + obj.disableOnGentleClick||false, this.parseList(obj.data) ]); case 'level': @@ -3001,28 +2904,17 @@ ActionParser.prototype.parse = function (obj,type) { var buildsub = function(obj,parser,next){ var text_choices = null; for(var ii=obj.choices.length-1,choice;choice=obj.choices[ii];ii--) { - var text_effect = null; - var effectList = choice.effect.split(';'); - for(var jj=effectList.length-1,effect;effect=effectList[jj];jj--) { - if(effect.split('+=').length!==2){ - throw new Error('一个商店效果中必须包含恰好一个"+="'); - } - text_effect=MotaActionBlocks['shopEffect'].xmlText([ - MotaActionBlocks['idString_e'].xmlText([effect.split('+=')[0]]), - MotaActionBlocks['evalString_e'].xmlText([effect.split('+=')[1]]), - text_effect]); - } text_choices=MotaActionBlocks['shopChoices'].xmlText([ - choice.text,choice.need||'',text_effect,text_choices]); + choice.text,choice.need||'',choice.icon,choice.color,'rgba('+choice.color+')',choice.condition,parser.parseList(choice.action),text_choices]); } + var info = parser.getTitleAndPosition(obj.text || ''); return MotaActionBlocks['shopsub'].xmlText([ - obj.id,obj.name,obj.icon,obj.textInList,obj.commonTimes,obj.mustEnable,obj.use,obj.need,parser.EvalString(obj.text),text_choices,next + obj.id,obj[0],info[1],info[3],obj.textInList,obj.mustEnable,obj.disablePreview,text_choices,next ]); } var buildcommentevent = function(obj,parser,next){ if (obj.args instanceof Array) { - try { obj.args = JSON.stringify(obj.args).replace(/"/g, "'"); } - catch (e) {obj.args = '';} + obj.args = JSON.stringify(obj.args); } else obj.args = null; return MotaActionBlocks['shopcommonevent'].xmlText([ @@ -3132,7 +3024,7 @@ ActionParser.prototype.parseAction = function() { this.next = MotaActionBlocks['setText_s'].xmlText([ data.position,data.offset,data.align,data.title,'rgba('+data.title+')', data.text,'rgba('+data.text+')',data.background,'rgba('+data.background+')', - data.bold,data.titlefont,data.textfont,data.time,data.interval,this.next]); + data.bold,data.titlefont,data.textfont,data.lineHeight,data.time,data.interval,this.next]); break; case "tip": this.next = MotaActionBlocks['tip_s'].xmlText([ @@ -3148,7 +3040,7 @@ ActionParser.prototype.parseAction = function() { y_str.push(t[1]); }) this.next = MotaActionBlocks['show_s'].xmlText([ - x_str.join(','),y_str.join(','),data.floorId||'',data.time||0,data.async||false,this.next]); + x_str.join(','),y_str.join(','),data.floorId||'',data.time,data.async||false,this.next]); break; case "hide": // 消失 data.loc=data.loc||[]; @@ -3160,7 +3052,7 @@ ActionParser.prototype.parseAction = function() { y_str.push(t[1]); }) this.next = MotaActionBlocks['hide_s'].xmlText([ - x_str.join(','),y_str.join(','),data.floorId||'',data.time||0,data.async||false,this.next]); + x_str.join(','),y_str.join(','),data.floorId||'',data.time,data.async||false,this.next]); break; case "setBlock": // 设置图块 data.loc=data.loc||[]; @@ -3241,36 +3133,32 @@ ActionParser.prototype.parseAction = function() { case "move": // 移动事件 data.loc=data.loc||['','']; this.next = MotaActionBlocks['move_s'].xmlText([ - data.loc[0],data.loc[1],data.time||0,data.keep||false,data.async||false,this.StepString(data.steps),this.next]); + data.loc[0],data.loc[1],data.time,data.keep||false,data.async||false,this.StepString(data.steps),this.next]); break; case "moveHero": // 移动勇士 this.next = MotaActionBlocks['moveHero_s'].xmlText([ - data.time||0,data.async||false,this.StepString(data.steps),this.next]); + data.time,data.async||false,this.StepString(data.steps),this.next]); break; case "jump": // 跳跃事件 data.from=data.from||['','']; data.to=data.to||['','']; this.next = MotaActionBlocks['jump_s'].xmlText([ - data.from[0],data.from[1],data.to[0],data.to[1],data.time||0,data.keep||false,data.async||false,this.next]); + data.from[0],data.from[1],data.to[0],data.to[1],data.time,data.keep||false,data.async||false,this.next]); break; case "jumpHero": // 跳跃勇士 data.loc=data.loc||['',''] this.next = MotaActionBlocks['jumpHero_s'].xmlText([ - data.loc[0],data.loc[1],data.time||0,data.async||false,this.next]); + data.loc[0],data.loc[1],data.time,data.async||false,this.next]); break; case "changeFloor": // 楼层转换 data.loc=data.loc||['',''] this.next = MotaActionBlocks['changeFloor_s'].xmlText([ - data.floorId,data.loc[0],data.loc[1],data.direction,data.time||0,this.next]); + data.floorId,data.loc[0],data.loc[1],data.direction,data.time,this.next]); break; case "changePos": // 直接更换勇士位置, 不切换楼层 - if(this.isset(data.loc)){ - this.next = MotaActionBlocks['changePos_0_s'].xmlText([ - data.loc[0],data.loc[1],data.direction,this.next]); - } else { - this.next = MotaActionBlocks['changePos_1_s'].xmlText([ - data.direction,this.next]); - } + data.loc=data.loc||['',''] + this.next = MotaActionBlocks['changePos_s'].xmlText([ + data.loc[0],data.loc[1],data.direction,this.next]); break; case "follow": // 跟随勇士 this.next = MotaActionBlocks['follow_s'].xmlText([data.name||"", this.next]); @@ -3282,7 +3170,7 @@ ActionParser.prototype.parseAction = function() { var animate_loc = data.loc||''; if(animate_loc && animate_loc!=='hero')animate_loc = animate_loc[0]+','+animate_loc[1]; this.next = MotaActionBlocks['animate_s'].xmlText([ - data.name,animate_loc,data.async||false,this.next]); + data.name,animate_loc,data.alignWindow||false,data.async||false,this.next]); break; case "setViewport": // 设置视角 data.loc = data.loc||['','']; @@ -3291,7 +3179,7 @@ ActionParser.prototype.parseAction = function() { break; case "moveViewport": // 移动视角 this.next = MotaActionBlocks['moveViewport_s'].xmlText([ - data.time||0,data.async||false,this.StepString(data.steps),this.next]); + data.time,data.async||false,this.StepString(data.steps),this.next]); break; case "vibrate": // 画面震动 this.next = MotaActionBlocks['vibrate_s'].xmlText([data.time||0, data.async||false, this.next]); @@ -3324,33 +3212,28 @@ ActionParser.prototype.parseAction = function() { data.code, data.to[0], data.to[1], data.opacity, data.time||0, data.async||false, this.next]); break; case "showGif": // 显示动图 - if(this.isset(data.name)){ - this.next = MotaActionBlocks['showGif_0_s'].xmlText([ - data.name,data.loc[0],data.loc[1],this.next]); - } else { - this.next = MotaActionBlocks['showGif_1_s'].xmlText([ - this.next]); - } - break; - case "setFg": // 颜色渐变 - case "setCurtain": + data.loc=data.loc||['',''] + this.next = MotaActionBlocks['showGif_s'].xmlText([ + data.name,data.loc[0],data.loc[1],this.next]); + break; + case "setCurtain": // 颜色渐变 if(this.isset(data.color)){ data.color = this.Colour(data.color); this.next = MotaActionBlocks['setCurtain_0_s'].xmlText([ - data.color,'rgba('+data.color+')',data.time||0,data.async||false,this.next]); + data.color,'rgba('+data.color+')',data.time,data.keep||false,data.async||false,this.next]); } else { this.next = MotaActionBlocks['setCurtain_1_s'].xmlText([ - data.time||0,data.async||false,this.next]); + data.time,data.async||false,this.next]); } break; case "screenFlash": // 画面闪烁 data.color = this.Colour(data.color); this.next = MotaActionBlocks['screenFlash_s'].xmlText([ - data.color,'rgba('+data.color+')',data.time||500,data.times||1,data.async||false,this.next]); + data.color,'rgba('+data.color+')',data.time||500,data.times,data.async||false,this.next]); break; case "setWeather": // 更改天气 this.next = MotaActionBlocks['setWeather_s'].xmlText([ - data.name,data.level||1,this.next]); + data.name,data.level||1,data.keep||false,this.next]); break; case "openDoor": // 开一个门, 包括暗墙 data.loc=data.loc||['',''] @@ -3376,7 +3259,7 @@ ActionParser.prototype.parseAction = function() { break; case "openShop": // 打开一个全局商店 this.next = MotaActionBlocks['openShop_s'].xmlText([ - data.id,this.next]); + data.id,data.open||false,this.next]); break; case "disableShop": // 禁用一个全局商店 this.next = MotaActionBlocks['disableShop_s'].xmlText([ @@ -3399,8 +3282,7 @@ ActionParser.prototype.parseAction = function() { break; case "insert": // 强制插入另一个点的事件在当前事件列表执行,当前坐标和楼层不会改变 if (data.args instanceof Array) { - try { data.args = JSON.stringify(data.args).replace(/"/g, "'"); } - catch (e) {data.args = '';} + data.args = JSON.stringify(data.args); } else data.args = null; if (this.isset(data.name)) { @@ -3418,7 +3300,7 @@ ActionParser.prototype.parseAction = function() { break; case "playBgm": this.next = MotaActionBlocks['playBgm_s'].xmlText([ - data.name,data.keep||false,this.next]); + data.name,data.startTime||0,data.keep||false,this.next]); break case "pauseBgm": this.next = MotaActionBlocks['pauseBgm_s'].xmlText([ @@ -3426,7 +3308,7 @@ ActionParser.prototype.parseAction = function() { break case "resumeBgm": this.next = MotaActionBlocks['resumeBgm_s'].xmlText([ - this.next]); + data.resume||false,this.next]); break case "loadBgm": this.next = MotaActionBlocks['loadBgm_s'].xmlText([ @@ -3442,19 +3324,11 @@ ActionParser.prototype.parseAction = function() { break case "setVolume": this.next = MotaActionBlocks['setVolume_s'].xmlText([ - data.value, data.time||0, data.async||false, this.next]); + data.value, data.time, data.async||false, this.next]); break case "setValue": this.next = MotaActionBlocks['setValue_s'].xmlText([ - this.tryToUseEvFlag_e('idString_e', [data.name]), - MotaActionBlocks['evalString_e'].xmlText([data.value]), - data.norefresh || false, - this.next]); - break; - case "setValue2": - case "addValue": - this.next = MotaActionBlocks['addValue_s'].xmlText([ - this.tryToUseEvFlag_e('idString_e', [data.name]), + this.tryToUseEvFlag_e('idString_e', [data.name]), data["operator"]||'=', MotaActionBlocks['evalString_e'].xmlText([data.value]), data.norefresh || false, this.next]); @@ -3504,7 +3378,7 @@ ActionParser.prototype.parseAction = function() { break; case "confirm": // 显示确认框 this.next = MotaActionBlocks['confirm_s'].xmlText([ - this.EvalString(data.text), data["default"], + this.EvalString(data.text), data.timeout||0, data["default"], this.insertActionList(data["yes"]), this.insertActionList(data["no"]), this.next]); @@ -3530,18 +3404,32 @@ ActionParser.prototype.parseAction = function() { if (!this.isset(data.text)) data.text = ''; var info = this.getTitleAndPosition(data.text); this.next = MotaActionBlocks['choices_s'].xmlText([ - info[3],info[0],info[1],text_choices,this.next]); + info[3],info[0],info[1],data.timeout||0,text_choices,this.next]); + break; + case "for": // 循环遍历 + this.next = MotaActionBlocks['for_s'].xmlText([ + this.tryToUseEvFlag_e('evalString_e', [data.name]), + data.from || 0, data.to || 0, data.step || 0, + this.insertActionList(data.data), + this.next]); + break; + case "forEach": // 循环遍历列表 + this.next = MotaActionBlocks['forEach_s'].xmlText([ + this.tryToUseEvFlag_e('evalString_e', [data.name]), + JSON.stringify(data.list), + this.insertActionList(data.data), + this.next]); break; case "while": // 前置条件循环处理 this.next = MotaActionBlocks['while_s'].xmlText([ // MotaActionBlocks['evalString_e'].xmlText([data.condition]), this.tryToUseEvFlag_e('evalString_e', [data.condition]), - this.insertActionList(data["data"]), + this.insertActionList(data.data), this.next]); break; case "dowhile": // 后置条件循环处理 this.next = MotaActionBlocks['dowhile_s'].xmlText([ - this.insertActionList(data["data"]), + this.insertActionList(data.data), // MotaActionBlocks['evalString_e'].xmlText([data.condition]), this.tryToUseEvFlag_e('evalString_e', [data.condition]), this.next]); @@ -3574,7 +3462,7 @@ ActionParser.prototype.parseAction = function() { break; case "update": this.next = MotaActionBlocks['update_s'].xmlText([ - this.next]); + this.next, this.doNotCheckAutoEvents||false]); break; case "showStatusBar": this.next = MotaActionBlocks['showStatusBar_s'].xmlText([ @@ -3602,7 +3490,7 @@ ActionParser.prototype.parseAction = function() { for(var ii=data.data.length-1,caseNow;caseNow=data.data[ii];ii--) { if (caseNow["case"] == "keyboard") { case_waitList = MotaActionBlocks['waitContext_1'].xmlText([ - caseNow.keycode || 0, this.insertActionList(caseNow.action), case_waitList + caseNow.keycode || "0", this.insertActionList(caseNow.action), case_waitList ]); } else if (caseNow["case"] == "mouse") { case_waitList = MotaActionBlocks['waitContext_2'].xmlText([ @@ -3612,16 +3500,12 @@ ActionParser.prototype.parseAction = function() { } } this.next = MotaActionBlocks['wait_s'].xmlText([ - case_waitList, this.next]); + data.timeout||0,case_waitList, this.next]); break; case "waitAsync": // 等待所有异步事件执行完毕 this.next = MotaActionBlocks['waitAsync_s'].xmlText([ this.next]); break; - case "revisit": // 立刻重新执行该事件 - this.next = MotaActionBlocks['revisit_s'].xmlText([ - this.next]); - break; case "callBook": // 呼出怪物手册 this.next = MotaActionBlocks['callBook_s'].xmlText([ this.next]); @@ -3673,7 +3557,8 @@ ActionParser.prototype.parseAction = function() { case "fillBoldText": // 绘制一行描边文本 data.style = this.Colour(data.style); this.next = MotaActionBlocks['fillBoldText_s'].xmlText([ - data.x, data.y, data.style, 'rgba('+data.style+')', data.font, this.EvalString(data.text), this.next + data.x, data.y, data.style, 'rgba('+data.style+')', data.strokeStyle, 'rgba('+(data.strokeStyle||"0,0,0,1")+')', + data.font, this.EvalString(data.text), this.next ]); break; case "drawTextContent": // 绘制多行文本 @@ -3755,7 +3640,7 @@ ActionParser.prototype.parseAction = function() { break; case "drawIcon": // 绘制图标 this.next = MotaActionBlocks['drawIcon_s'].xmlText([ - data.id, data.x, data.y, data.width, data.height, this.next + data.id, data.frame||0, data.x, data.y, data.width, data.height, this.next ]); break; case "drawBackground": // 绘制背景 @@ -3811,16 +3696,25 @@ ActionParser.prototype.StepString = function(steplist) { 'forward': '前', 'backward': '后' } - var StepString = []; - for(var ii=0,obj;obj=steplist[ii];ii++) { - if(typeof(obj)===typeof('')) { - StepString.push(stepchar[obj]); + var StepString = ''; + var last = null, number = 0; + steplist.forEach(function (v) { + if (v != last) { + if (last != null) { + StepString += stepchar[last]; + if (number > 1) StepString += number; + } + last = v; + number = 1; } else { - StepString.push(stepchar[obj['direction']]); - StepString.push(obj['value']); + number++; } + }); + if (last != null) { + StepString += stepchar[last]; + if (number > 1) StepString += number; } - return StepString.join(''); + return StepString; } ActionParser.prototype.EvalString = function(EvalString) { @@ -3833,7 +3727,8 @@ ActionParser.prototype.getTitleAndPosition = function (string) { string = string.replace(/\\t\[(([^\],]+),)?([^\],]+)\]/g, function (s0, s1, s2, s3) { if (s3) title = s3; if (s2) { icon = s3; title = s2; } - if (icon && !/^[0-9a-zA-Z_][0-9a-zA-Z_:]*$/.test(icon)) { title += "," + icon; icon = ''; } + if (icon && !/^(.*)\.(jpg|jpeg|png)$/.test(icon) + && !/^[0-9a-zA-Z_][0-9a-zA-Z_:]*$/.test(icon)) { title += "," + icon; icon = ''; } return ""; }).replace(/\\b\[(.*?)\]/g, function (s0, s1) { position = s1; return ""; @@ -3851,6 +3746,11 @@ ActionParser.prototype.tryToUseEvFlag_e = function(defaultType, args, isShadow, args[0]=match[1] return MotaActionBlocks['evFlag_e'].xmlText(args, isShadow, comment); } + match=/^temp:([A-Z])$/.exec(args[0]) + if(match){ + args[0]=match[1] + return MotaActionBlocks['evTemp_e'].xmlText(args, isShadow, comment); + } return MotaActionBlocks[defaultType||'evalString_e'].xmlText(args, isShadow, comment); } @@ -3874,6 +3774,21 @@ MotaActionFunctions.EvalString_pre = function(EvalString){ return EvalString.replace(/([^\\])"/g,'$1\\"').replace(/^"/g,'\\"').replace(/""/g,'"\\"'); } +MotaActionFunctions.JsonEvalString_pre = function (JsonEvalString) { + if (JsonEvalString == '') return ''; + JsonEvalString = MotaActionFunctions.replaceFromName(JsonEvalString); + try { + return JSON.stringify(JSON.parse(JsonEvalString)); + } catch (e) { + throw new Error('此处需要填写一个合法的JSON内容'); + } +} + +MotaActionFunctions.IntString_pre = function (IntString) { + if (!/^\d*$/.test(IntString)) throw new Error('此项必须是整数或不填'); + return IntString; +} + MotaActionFunctions.IdString_pre = function(IdString){ if (IdString.indexOf('__door__')!==-1) throw new Error('请修改开门变量__door__,如door1,door2,door3等依次向后。请勿存在两个门使用相同的开门变量。'); IdString = MotaActionFunctions.replaceFromName(IdString); @@ -3926,6 +3841,18 @@ MotaActionFunctions.StepString_pre = function(StepString){ return ans; } +MotaActionFunctions.ColorString_pre = function (ColorString) { + if (ColorString && !MotaActionFunctions.pattern.colorRe.test(ColorString)) + throw new Error('颜色格式错误,形如:0~255,0~255,0~255,0~1'); + return ColorString; +} + +MotaActionFunctions.FontString_pre = function (FontString) { + if (FontString && !MotaActionFunctions.pattern.fontRe.test(FontString)) + throw new Error('字体必须是 [italic] [bold] 14px Verdana 这种形式或不填'); + return FontString; +} + MotaActionFunctions.pattern=MotaActionFunctions.pattern||{}; MotaActionFunctions.pattern.id=/^(flag|global):([a-zA-Z0-9_\u4E00-\u9FCC]+)$/; MotaActionFunctions.pattern.id2=/^flag:([a-zA-Z0-9_\u4E00-\u9FCC]+),flag:([a-zA-Z0-9_\u4E00-\u9FCC]+)$/; @@ -3942,11 +3869,11 @@ MotaActionFunctions.pattern.replaceStatusList = [ ["lv", "等级"], ["atk", "攻击"], ["def", "防御"], - ["mdef", "魔防"], + ["mdef", "护盾"], ["manamax", "魔力上限"], ["mana", "魔力"], ["money", "金币"], - ["experience", "经验"], + ["exp", "经验"], ["steps", "步数"], ]; @@ -4007,7 +3934,7 @@ MotaActionFunctions.pattern.replaceEnemyList = [ ["atk", "攻击"], ["def", "防御"], ["money", "金币"], - ["experience", "经验"], + ["exp", "经验"], ["point", "加点"], ["special", "属性"], ]; @@ -4030,7 +3957,7 @@ MotaActionFunctions.replaceToName = function (str) { str = str.replace(new RegExp("item:(" + list.join("|") + ")", "g"), function (a, b) { return map[b] ? ("物品:" + map[b]) : b; }).replace(/item:/g, "物品:"); - str = str.replace(/flag:/g, "变量:").replace(/switch:/g, "独立开关:").replace(/global:/g, "全局存储:"); + str = str.replace(/flag:/g, "变量:").replace(/switch:/g, "独立开关:").replace(/global:/g, "全局存储:").replace(/temp:/g, "临时变量:"); map = {}; list = []; MotaActionFunctions.pattern.replaceEnemyList.forEach(function (v) { @@ -4060,7 +3987,7 @@ MotaActionFunctions.replaceFromName = function (str) { str = str.replace(new RegExp("物品[::](" + list.join("|") + ")", "g"), function (a, b) { return map[b] ? ("item:" + map[b]) : b; }).replace(/物品[::]/g, "item:"); - str = str.replace(/变量[::]/g, "flag:").replace(/独立开关[::]/g, "switch:").replace(/全局存储[::]/g, "global:"); + str = str.replace(/临时变量[::]/g, "temp:").replace(/变量[::]/g, "flag:").replace(/独立开关[::]/g, "switch:").replace(/全局存储[::]/g, "global:"); map = {}; list = []; MotaActionFunctions.pattern.replaceEnemyList.forEach(function (v) { diff --git a/_server/config.json b/_server/config.json index fe6a45a9..9c9888dc 100644 --- a/_server/config.json +++ b/_server/config.json @@ -1 +1 @@ -{"lastUsed":[],"foldPerCol":50,"folded":false,"editorLastFloorId":null,"disableBlocklyReplace":false,"shortcut":{"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0}} \ No newline at end of file +{"lastUsed":[],"foldPerCol":50,"folded":false,"editorLastFloorId":"sample0","disableBlocklyReplace":false,"shortcut":{"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0}} \ No newline at end of file diff --git a/_server/css/editor_mode.css b/_server/css/editor_mode.css index 33f1a9bd..0db6dc94 100644 --- a/_server/css/editor_mode.css +++ b/_server/css/editor_mode.css @@ -130,7 +130,7 @@ .etable table th, .etable table td { - padding: 6px 13px; + padding: 5px; border: 1px solid #dfe2e5; } @@ -201,6 +201,12 @@ div.etableInputDiv { right: 0; } +div.checkboxSet { + position: relative !important; + max-height: 250px; + overflow: auto; +} + .etableInputDiv > * { margin: 0; padding: 0; @@ -210,11 +216,7 @@ div.etableInputDiv { border: none; } -.etableInputDiv input[type="text"] { - -} - -.etableInputDiv input[type="checkbox"] { +.etableInputDiv .checkbox { width: 16px; height: 16px; position: absolute; @@ -224,8 +226,10 @@ div.etableInputDiv { margin-top: -8px; } -.etableInputDiv select { - +.etableInputDiv .checkboxSetMember { + width: 16px; + height: 16px; + display: inline-block; } .etableInputDiv textarea { diff --git a/_server/css/editor_mode_mobile.css b/_server/css/editor_mode_mobile.css index bb680213..423a85ba 100644 --- a/_server/css/editor_mode_mobile.css +++ b/_server/css/editor_mode_mobile.css @@ -144,7 +144,7 @@ .etable table th, .etable table td { - padding: 6px 13px; + padding: 5px; border: 1px solid #dfe2e5; } @@ -172,11 +172,11 @@ } .etable tr > :nth-child(3) { - width: 30%; + width: 38%; } .etable tr > :nth-child(4) { - width: 30%; + width: 22%; text-align: center; } @@ -211,6 +211,12 @@ div.etableInputDiv { right: 0; } +div.checkboxSet { + position: relative !important; + max-height: 250px; + overflow: auto; +} + .etableInputDiv > * { margin: 0; padding: 0; @@ -220,11 +226,7 @@ div.etableInputDiv { border: none; } -.etableInputDiv input[type="text"] { - -} - -.etableInputDiv input[type="checkbox"] { +.etableInputDiv .checkbox { width: 16px; height: 16px; position: absolute; @@ -234,8 +236,10 @@ div.etableInputDiv { margin-top: -8px; } -.etableInputDiv select { - +.etableInputDiv .checkboxSetMember { + width: 16px; + height: 16px; + display: inline-block; } .etableInputDiv textarea { diff --git a/_server/editor.js b/_server/editor.js index 7ddc0f60..ab9abb3b 100644 --- a/_server/editor.js +++ b/_server/editor.js @@ -52,6 +52,7 @@ function editor() { left1 : document.getElementById('left1'), editModeSelect :document.getElementById('editModeSelect'), mid2 : document.getElementById('mid2'), + clearLastUsedBtn: document.getElementById('clearLastUsedBtn'), lastUsedDiv: document.getElementById('lastUsedDiv'), lastUsed: document.getElementById('lastUsed'), lastUsedCtx: document.getElementById('lastUsed').getContext('2d'), @@ -182,7 +183,6 @@ editor.prototype.init = function (callback) { core.changeFloor(lastFloorId, null, core.firstData.hero.loc, null, function () { afterCoreReset(); }, true); - core.events.setInitData(null); }); } @@ -298,7 +298,7 @@ editor.prototype.drawEventBlock = function () { && loc == firstData.hero.loc.x + "," + firstData.hero.loc.y) { fg.textAlign = 'center'; editor.game.doCoreFunc('fillBoldText', fg, 'S', - 32 * i + 16, 32 * j + 28, '#FFFFFF', 'bold 30px Verdana'); + 32 * i + 16, 32 * j + 28, '#FFFFFF', null, 'bold 30px Verdana'); } if (editor.currentFloorData.events[loc]) color.push('#FF0000'); @@ -329,7 +329,7 @@ editor.prototype.drawEventBlock = function () { if (index >= 0) { fg.textAlign = 'right'; editor.game.doCoreFunc("fillBoldText", fg, index + 1, - 32 * i + 28, 32 * j + 15, '#FF7F00', '14px Verdana'); + 32 * i + 28, 32 * j + 15, '#FF7F00', null, '14px Verdana'); } } } @@ -629,7 +629,7 @@ editor.prototype.buildMark = function(){ } } -editor.prototype.setSelectBoxFromInfo=function(thisevent){ +editor.prototype.setSelectBoxFromInfo=function(thisevent, scrollTo){ var pos={x: 0, y: 0, images: "terrains"}; var ysize = 32; if(thisevent==0){ @@ -646,6 +646,10 @@ editor.prototype.setSelectBoxFromInfo=function(thisevent){ } if(pos.x == 0) pos.y+=2; } + if (!editor.isMobile && scrollTo) { + editor.dom.iconLib.scrollLeft = pos.x * 32 - editor.dom.iconLib.offsetWidth / 2; + editor.dom.iconLib.scrollTop = pos.y * ysize - editor.dom.iconLib.offsetHeight / 2; + } editor.dom.dataSelection.style.left = pos.x * 32 + 'px'; editor.dom.dataSelection.style.top = pos.y * ysize + 'px'; editor.dom.dataSelection.style.height = ysize - 6 + 'px'; diff --git a/_server/editor_blockly.js b/_server/editor_blockly.js index aa221608..cf6e9248 100644 --- a/_server/editor_blockly.js +++ b/_server/editor_blockly.js @@ -38,16 +38,16 @@ editor_blockly = function () { },'autoEvent'), MotaActionBlocks['changeFloor_m'].xmlText(), MotaActionFunctions.actionParser.parse([{ - "id": "moneyShop1", - "name": "贪婪之神", - "icon": "blueShop", - "textInList": "1F金币商店", - "use": "money", - "need": "20+10*times*(times+1)", - "text": "勇敢的武士啊,给我\\\${need}金币就可以:", + "id": "shop1", + "text": "\t[贪婪之神,blueShop]勇敢的武士啊, 给我\${20+2*flag:shop1}金币就可以:", + "textInList": "1F金币商店", "choices": [ - {"text": "生命+800", "effect": "status:hp+=800"}, - {"text": "攻击+4", "effect": "status:atk+=4"}, + {"text": "生命+800", "need": "status:money>=20+2*flag:shop1", "action": [ + {"type": "comment", "text": "新版商店中需要手动扣减金币和增加访问次数"}, + {"type": "setValue", "name": "status:money", "operator": "-=", "value": "20+2*flag:shop1"}, + {"type": "setValue", "name": "flag:shop1", "operator": "+=", "value": "1"}, + {"type": "setValue", "name": "status:hp", "operator": "+=", "value": "800"} + ]} ] },{ "id": "itemShop", @@ -83,28 +83,21 @@ editor_blockly = function () { MotaActionBlocks['hideImage_s'].xmlText(), MotaActionBlocks['showTextImage_s'].xmlText(), MotaActionBlocks['moveImage_s'].xmlText(), - MotaActionBlocks['showGif_0_s'].xmlText(), - MotaActionBlocks['showGif_1_s'].xmlText(), + MotaActionBlocks['showGif_s'].xmlText(), MotaActionBlocks['tip_s'].xmlText(), MotaActionBlocks['win_s'].xmlText(), MotaActionBlocks['lose_s'].xmlText(), MotaActionBlocks['restart_s'].xmlText(), MotaActionBlocks['confirm_s'].xmlText(), MotaActionBlocks['choices_s'].xmlText([ - '选择剑或者盾','流浪者','man',MotaActionBlocks['choicesContext'].xmlText([ + '选择剑或者盾','流浪者','man',0,MotaActionBlocks['choicesContext'].xmlText([ '剑','','',null,'',MotaActionFunctions.actionParser.parseList([{"type": "openDoor", "loc": [3,3]}]), - MotaActionBlocks['choicesContext'].xmlText([ - '盾','','',null,'',MotaActionFunctions.actionParser.parseList([{"type": "openDoor", "loc": [9,3]}]), - ]) ]) ]), ], '数据相关':[ - MotaActionBlocks['addValue_s'].xmlText([ - MotaActionBlocks['idString_1_e'].xmlText(['status','生命']), '', false - ]), MotaActionBlocks['setValue_s'].xmlText([ - MotaActionBlocks['idString_1_e'].xmlText(['status','生命']), '', false + MotaActionBlocks['idString_1_e'].xmlText(['status','生命']), '=', '', false ]), MotaActionBlocks['setEnemy_s'].xmlText(), MotaActionBlocks['setFloor_s'].xmlText(), @@ -117,8 +110,7 @@ editor_blockly = function () { MotaActionBlocks['moveHero_s'].xmlText(), MotaActionBlocks['jumpHero_s'].xmlText(), MotaActionBlocks['changeFloor_s'].xmlText(), - MotaActionBlocks['changePos_0_s'].xmlText(), - MotaActionBlocks['changePos_1_s'].xmlText(), + MotaActionBlocks['changePos_s'].xmlText(), MotaActionBlocks['battle_s'].xmlText(), MotaActionBlocks['useItem_s'].xmlText(), MotaActionBlocks['loadEquip_s'].xmlText(), @@ -149,14 +141,14 @@ editor_blockly = function () { MotaActionBlocks['if_s'].xmlText(), MotaActionFunctions.actionParser.parseList({"type": "switch", "condition": "判别值", "caseList": [ {"action": [{"type": "comment", "text": "当判别值是值的场合执行此事件"}]}, - {"action": [], "nobreak": true}, {"case": "default", "action": [{"type": "comment", "text": "当没有符合的值的场合执行default事件"}]}, ]}), + MotaActionFunctions.actionParser.parseList({"type": "for", "name": "temp:A", "from": "0", "to": "12", "step": "1", "data": []}), + MotaActionFunctions.actionParser.parseList({"type": "forEach", "name": "temp:A", "list": ["status:atk","status:def"], "data": []}), MotaActionBlocks['while_s'].xmlText(), MotaActionBlocks['dowhile_s'].xmlText(), MotaActionBlocks['break_s'].xmlText(), MotaActionBlocks['continue_s'].xmlText(), - MotaActionBlocks['revisit_s'].xmlText(), MotaActionBlocks['exit_s'].xmlText(), MotaActionBlocks['trigger_s'].xmlText(), MotaActionBlocks['insert_1_s'].xmlText(), @@ -164,8 +156,8 @@ editor_blockly = function () { ], '特效/声音':[ MotaActionBlocks['sleep_s'].xmlText(), - MotaActionFunctions.actionParser.parseList({"type": "wait", "data": [ - {"case": "keyboard", "keycode": 13, "action": [{"type": "comment", "text": "当按下回车(keycode=13)时执行此事件"}]}, + MotaActionFunctions.actionParser.parseList({"type": "wait", "timeout": 0, "data": [ + {"case": "keyboard", "keycode": "13,32", "action": [{"type": "comment", "text": "当按下回车(keycode=13)或空格(keycode=32)时执行此事件"}]}, {"case": "mouse", "px": [0,32], "py": [0,32], "action": [{"type": "comment", "text": "当点击地图左上角时执行此事件"}]}, ]}), MotaActionBlocks['waitAsync_s'].xmlText(), @@ -222,14 +214,12 @@ editor_blockly = function () { MotaActionBlocks['unknown_s'].xmlText(), ], '值块':[ - MotaActionBlocks['addValue_s'].xmlText([ - MotaActionBlocks['idString_1_e'].xmlText(['status','生命']), '', false - ]), MotaActionBlocks['setValue_s'].xmlText([ - MotaActionBlocks['idString_1_e'].xmlText(['status','生命']), '', false + MotaActionBlocks['idString_1_e'].xmlText(['status','生命']), '=', '', false ]), MotaActionBlocks['expression_arithmetic_0'].xmlText(), MotaActionBlocks['evFlag_e'].xmlText(), + MotaActionBlocks['evTemp_e'].xmlText(), MotaActionBlocks['negate_e'].xmlText(), MotaActionBlocks['bool_e'].xmlText(), MotaActionBlocks['idString_e'].xmlText(), @@ -251,30 +241,30 @@ editor_blockly = function () { }), '', MotaActionFunctions.actionParser.parse([ - {"type": "choices", "text": "\\t[老人,man]少年,你需要钥匙吗?\\n我这里有大把的!", - "choices": [ - {"text": "黄钥匙(\\\${9+flag:shop_times}金币)", "color": [255,255,0,1], "action": [ - {"type": "if", "condition": "status:money>=9+flag:shop_times", - "true": [ - {"type": "addValue", "name": "status:money", "value": "-(9+flag:shop_times)"}, - {"type": "addValue", "name": "item:yellowKey", "value": "1"}, - ], - "false": [ - "\\t[老人,man]你的金钱不足!", - {"type": "revisit"} - ] - } - ]}, - {"text": "蓝钥匙(\\\${18+2*flag:shop_times}金币)", "color": [0,0,255,1], "action": [ - ]}, - {"text": "离开", "action": [ - {"type": "exit"} - ]} - ] - }, - {"type": "addValue", "name": "flag:shop_times", "value": "1"}, - {"type": "revisit"} - ], 'event'), + {"type": "while", "condition": "true", "data": [ + {"type": "choices", "text": "\\t[老人,man]少年,你需要钥匙吗?\\n我这里有大把的!", + "choices": [ + {"text": "黄钥匙(\\\${9+flag:shop_times}金币)", "color": [255,255,0,1], "action": [ + {"type": "if", "condition": "status:money>=9+flag:shop_times", + "true": [ + {"type": "setValue", "name": "status:money", "operator": "-=", "value": "9+flag:shop_times"}, + {"type": "setValue", "name": "item:yellowKey", "operator": "+=", "value": "1"}, + ], + "false": [ + "\\t[老人,man]你的金钱不足!", + {"type": "continue"} + ] + } + ]}, + {"text": "蓝钥匙(\\\${18+2*flag:shop_times}金币)", "color": [0,0,255,1], "action": [ + ]}, + {"text": "离开", "action": [ + {"type": "break"} + ]} + ] + }, + {"type": "setValue", "name": "flag:shop_times", "operator": "+=", "value": "1"} + ]}], 'event'), '', MotaActionFunctions.actionParser.parse({ "trigger": "action", @@ -295,7 +285,7 @@ editor_blockly = function () { ],'afterBattle'), '', MotaActionFunctions.actionParser.parse([ - {"type": "addValue", "name": "flag:__door__", "value": "1"}, + {"type": "setValue", "name": "flag:__door__", "operator": "+=", "value": "1"}, {"type": "if", "condition": "flag:__door__==2", "true": [ {"type": "openDoor", "loc": [10,5]} @@ -315,7 +305,7 @@ editor_blockly = function () { {"type": "if", "condition": "flag:hasSuperPotion", "true": [], "false": [ - {"type":"setValue", "name":"status:hp", "value":"status:hp*2"}, + {"type":"setValue", "name":"status:hp", "operator": "*=", "value": "2"}, {"type":"setBlock", "number": 1}, {"type":"setValue", "name":"flag:hasSuperPotion", "value": "true"} ] @@ -418,7 +408,7 @@ function omitedcheckUpdateFunction(event) { } } try { - var code = Blockly.JavaScript.workspaceToCode(workspace).replace(/\\\\(i|c|d|e)/g, '\\\\\\\\$1'); + var code = Blockly.JavaScript.workspaceToCode(workspace).replace(/\\\\(i|c|d|e|z)/g, '\\\\\\\\$1'); codeAreaHL.setValue(code); } catch (error) { codeAreaHL.setValue(String(error)); @@ -573,7 +563,7 @@ function omitedcheckUpdateFunction(event) { MotaActionFunctions.parse( eval('obj=' + codeAreaHL.getValue().replace(/[<>&]/g, function (c) { return {'<': '<', '>': '>', '&': '&'}[c]; - }).replace(/\\(r|f|i|c|d|e)/g,'\\\\$1')), + }).replace(/\\(r|f|i|c|d|e|z)/g,'\\\\$1')), document.getElementById('entryType').value ); } @@ -647,7 +637,7 @@ function omitedcheckUpdateFunction(event) { return; } var code = Blockly.JavaScript.workspaceToCode(editor_blockly.workspace); - code = code.replace(/\\(i|c|d|e)/g, '\\\\$1'); + code = code.replace(/\\(i|c|d|e|z)/g, '\\\\$1'); eval('var obj=' + code); if (this.checkAsync(obj) && confirm("警告!存在不等待执行完毕的事件但却没有用【等待所有异步事件处理完毕】来等待" + "它们执行完毕,这样可能会导致录像检测系统出问题。\n你要返回修改么?")) return; @@ -682,7 +672,7 @@ function omitedcheckUpdateFunction(event) { } } } - if (one.async && one.type != 'animate') hasAsync = true; + if (one.async && one.type != 'animate' && one.type != 'function') hasAsync = true; if (one.type == 'waitAsync') hasAsync = false; } return hasAsync; @@ -698,7 +688,7 @@ function omitedcheckUpdateFunction(event) { ]; if (b && types.indexOf(b.type)>=0) { try { - var code = "[" + Blockly.JavaScript.blockToCode(b).replace(/\\(i|c|d|e)/g, '\\\\$1') + "]"; + var code = "[" + Blockly.JavaScript.blockToCode(b).replace(/\\(i|c|d|e|z)/g, '\\\\$1') + "]"; eval("var obj="+code); if (obj.length > 0 && b.type == 'waitContext_2') { var dt = obj[0]; @@ -736,7 +726,7 @@ function omitedcheckUpdateFunction(event) { 'choices_s': 'EvalString_0', 'showTextImage_s': 'EvalString_0', 'function_s': 'RawEvalString_0', - 'shopsub': 'EvalString_3', + 'shopsub': 'EvalString_1', 'confirm_s': 'EvalString_0', 'drawTextContent_s': 'EvalString_0', } @@ -757,14 +747,14 @@ function omitedcheckUpdateFunction(event) { 'comment_s', 'show_s', 'hide_s', - 'addValue_s', + 'setValue_s', 'if_s', + 'while_s', 'battle_s', 'openDoor_s', 'choices_s', 'setText_s', 'exit_s', - 'revisit_s', 'sleep_s', 'setBlock_s', 'insert_1_s' @@ -837,7 +827,7 @@ function omitedcheckUpdateFunction(event) { "changeFloor_m": ["Number_0", "Number_1", "IdString_0", true], "jumpHero_s": ["PosString_0", "PosString_1"], "changeFloor_s": ["PosString_0", "PosString_1", "IdString_0", true], - "changePos_0_s": ["PosString_0", "PosString_1"], + "changePos_s": ["PosString_0", "PosString_1"], "battle_1_s": ["PosString_0", "PosString_1"], "openDoor_s": ["PosString_0", "PosString_1", "IdString_0"], "closeDoor_s": ["PosString_0", "PosString_1"], @@ -891,9 +881,11 @@ function omitedcheckUpdateFunction(event) { }); } - editor_blockly.getAutoCompletions = function (content) { + editor_blockly.getAutoCompletions = function (content, type, name) { // --- content为当前框中输入内容;将返回一个列表,为后续所有可补全内容 + // console.log(type, name); + // 检查 status:xxx,item:xxx和flag:xxx var index = Math.max(content.lastIndexOf(":"), content.lastIndexOf(":")); if (index >= 0) { @@ -936,7 +928,7 @@ function omitedcheckUpdateFunction(event) { if (index2 >= 0) { before = content.substring(0, index2); if (before.endsWith("怪物") || (ch == ':' && ch2 == ':' && before.endsWith("enemy"))) { - var list = ["name", "hp", "atk", "def", "money", "experience", "point", "special"]; + var list = ["name", "hp", "atk", "def", "money", "exp", "point", "special"]; if (before.endsWith("怪物") && MotaActionFunctions) { list = MotaActionFunctions.pattern.replaceEnemyList.map(function (v) { return v[1]; @@ -985,6 +977,105 @@ function omitedcheckUpdateFunction(event) { }).sort(); } + var allIds = core.getAllIconIds(); + var allIconIds = allIds.concat(Object.keys(core.statusBar.icons).filter(function (x) { + return core.statusBar.icons[x] instanceof Image; + })); + var allImages = Object.keys(core.material.images.images); + var allEnemys = Object.keys(core.material.enemys); + var allItems = Object.keys(core.material.items); + var allAnimates = Object.keys(core.material.animates); + var allBgms = Object.keys(core.material.bgms); + var allSounds = Object.keys(core.material.sounds); + var allShops = Object.keys(core.status.shops); + var allColors = ["aqua(青色)", "black(黑色)", "blue(蓝色)", "fuchsia(品红色)", "gray(灰色)", "green(深绿色)", "lime(绿色)", + "maroon(深红色)", "navy(深蓝色)", "gold(金色)", "olive(黄褐色)", "orange(橙色)", "purple(品红色)", + "red(红色)", "silver(淡灰色)", "teal(深青色)", "white(白色)", "yellow(黄色)"]; + var filter = function (list, content) { + return list.filter(function (one) { + return one != content && one.startsWith(content); + }).sort(); + } + + // 对任意图块提供补全 + if ((type == 'text_1_s' && name == 'EvalString_1') || (type == 'autoText_s' && name == 'EvalString_1') + || (type == 'choices_s' && name == 'IdString_0') || (type == 'choicesContext' && name == 'IdString_0') + || (type == 'closeDoor_s' && name == 'IdString_0') || (type == 'setBlock_s' && name == 'EvalString_0') + || (type == 'setBgFgBlock_s' && name == 'EvalString_0') || (type == 'drawIcon_s' && name == 'IdString_0') + || (type == 'shopsub' && name == 'IdString_1') || (type == 'shopChoices' && name == 'IdString_0')) { + return filter(allIds, content); + } + + // 对怪物ID提供补全 + if ((type == 'idString_3_e' || type == 'battle_s' || type == 'setEnemy_s') && name == 'IdString_0') { + return filter(allEnemys, content); + } + + // 对道具ID进行补全 + if ((type == 'useItem_s' || type == 'loadEquip_s') && name == 'IdString_0') { + return filter(allItems, content); + } + + // 对图片名进行补全 + if ((type == 'showImage_s' || type == 'showImage_1_s' || type == 'showGif_s' || type == 'setHeroIcon_s' + || type == 'follow_s' || type == 'unfollow_s' || type == 'drawImage_s' || type == 'drawImage_1_s') && name == 'EvalString_0') { + return filter(allImages, content); + } + + // 对动画进行补全 + if (type == 'animate_s' && name == 'IdString_0') { + return filter(allAnimates, content); + } + + // 对音乐进行补全 + if ((type == 'playBgm_s' || type == 'loadBgm_s' || type == 'freeBgm_s') && name == 'EvalString_0') { + return filter(allBgms, content); + } + + // 对音效进行补全 + if (type == 'playSound_s' && name == 'EvalString_0') { + return filter(allSounds, content); + } + + // 对全局商店进行补全 + if ((type == 'openShop_s' || type == 'disableShop_s') && name == 'IdString_0') { + return filter(allShops, content); + } + + // 对\f进行自动补全 + index = Math.max(content.lastIndexOf("\f["), content.lastIndexOf("\\f[")); + if (index >= 0) { + if (content.charAt(index) == '\\') index++; + var after = content.substring(index + 2); + if (after.indexOf(",") < 0 && after.indexOf("]") < 0) { + return filter(allImages, after); + } + } + + // 对\\i进行补全 + index = content.lastIndexOf("\\i["); + if (index >= 0) { + var after = content.substring(index + 3); + if (after.indexOf("]") < 0) { + return filter(allIconIds, after); + } + } + + // 对\r进行补全 + index = Math.max(content.lastIndexOf("\r["), content.lastIndexOf("\\r[")); + if (index >= 0) { + if (content.charAt(index) == '\\') index++; + var after = content.substring(index + 2); + if (after.indexOf("]") < 0) { + return filter(allColors, after); + } + } + + // 对\进行补全! + if (content.charAt(content.length - 1) == '\\') { + return ["n(换行)", "f(立绘)", "r(变色)", "i(图标)", "z(暂停打字)", "t(标题图标)", "b(对话框)", "c(字体大小)", "d(粗体)", "e(斜体)"]; + } + return []; } @@ -1087,11 +1178,13 @@ Blockly.FieldTextInput.prototype.showInlineEditor_ = function(quietInput) { // --- awesomplete var awesomplete = new Awesomplete(htmlInput, { - minChars: pb.type == "idString_3_e" ? 1 : 2, + minChars: 1, maxItems: 12, autoFirst: true, replace: function (text) { text = text.toString(); + var index = text.indexOf("("); + if (index >= 0) text = text.substring(0, index); var value = this.input.value, index = this.input.selectionEnd; if (index == null) index = value.length; if (index < awesomplete.prefix.length) index = awesomplete.prefix.length; @@ -1132,7 +1225,7 @@ Blockly.FieldTextInput.prototype.showInlineEditor_ = function(quietInput) { if (index == null) index = value.length; value = value.substring(0, index); // cal prefix - awesomplete.prefix = ""; + awesomplete.prefix = value; for (var i = index - 1; i>=0; i--) { var c = value.charAt(i); if (!/^[a-zA-Z0-9_\u4E00-\u9FCC]$/.test(c)) { @@ -1141,13 +1234,7 @@ Blockly.FieldTextInput.prototype.showInlineEditor_ = function(quietInput) { } } - var list = editor_blockly.getAutoCompletions(value); - if (pb.type == "idString_3_e") { - list = list.concat(Object.keys(core.material.enemys).filter(function (one) { - return one != value && one.startsWith(value); - })); - list.sort(); - } + var list = editor_blockly.getAutoCompletions(value, pb.type, self.name); awesomplete.list = list; awesomplete.ul.style.marginLeft = getCaretCoordinates(htmlInput, htmlInput.selectionStart).left - diff --git a/_server/editor_datapanel.js b/_server/editor_datapanel.js index 948ce9c0..e93cf7cd 100644 --- a/_server/editor_datapanel.js +++ b/_server/editor_datapanel.js @@ -6,6 +6,197 @@ editor_datapanel_wrapper = function (editor) { //////////////////// 地图编辑 ////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// + // 由于历史遗留原因, 以下变量作为全局变量使用 + // pout exportMap mapEditArea mapEditArea copyMap clearMapButton deleteMap + window.pout = document.getElementById('pout') + window.exportMap = document.getElementById('exportMap') + exportMap.isExport=false + exportMap.onclick=function(){ + editor.updateMap(); + var sx=editor.map.length-1,sy=editor.map[0].length-1; + + var filestr = ''; + for (var yy = 0; yy <= sy; yy++) { + filestr += '[' + for (var xx = 0; xx <= sx; xx++) { + var mapxy = editor.map[yy][xx]; + if (typeof(mapxy) == typeof({})) { + if ('idnum' in mapxy) mapxy = mapxy.idnum; + else { + // mapxy='!!?'; + tip.whichShow(3); + return; + } + } else if (typeof(mapxy) == 'undefined') { + tip.whichShow(3); + return; + } + mapxy = String(mapxy); + mapxy = Array(Math.max(4 - mapxy.length, 0)).join(' ') + mapxy; + filestr += mapxy + (xx == sx ? '' : ',') + } + + filestr += ']' + (yy == sy ? '' : ',\n'); + } + pout.value = filestr; + mapEditArea.mapArr(filestr); + exportMap.isExport = true; + mapEditArea.error(0); + tip.whichShow(2); + } + window.mapEditArea = document.getElementById('mapEditArea') + mapEditArea.errors=[ // 编号1,2 + "格式错误!请使用正确格式(请使用地图生成器进行生成,且需要和本地图宽高完全一致)", + "当前有未定义ID(在地图区域显示红块),请修改ID或者到icons.js和maps.js中进行定义!" + ] + mapEditArea.formatTimer=null + mapEditArea._mapArr='' + mapEditArea.mapArr=function(value){ + if(value!=null){ + var val=value + var oldval=mapEditArea._mapArr + if (val==oldval) return; + + if (exportMap.isExport) { + exportMap.isExport = false; + return; + } + if (mapEditArea.formatArr()) { + mapEditArea.error(0); + + setTimeout(function () { + if (mapEditArea.formatArr())mapEditArea.mapArr(mapEditArea.formatArr()); + mapEditArea.drawMap(); + tip.whichShow(8) + }, 1000); + clearTimeout(mapEditArea.formatTimer); + mapEditArea.formatTimer = setTimeout(function () { + pout.value = mapEditArea.formatArr(); + }, 5000); //5s后再格式化,不然光标跳到最后很烦 + } else { + mapEditArea.error(1); + } + + mapEditArea._mapArr=value + } + return mapEditArea._mapArr + } + pout.oninput=function(){ + mapEditArea.mapArr(pout.value) + } + mapEditArea._error=0 + mapEditArea.error=function(value){ + if(value!=null){ + mapEditArea._error=value + if (value>0) + printe(mapEditArea.errors[value-1]) + } + return mapEditArea._error + } + mapEditArea.drawMap= function () { + // var mapArray = mapEditArea.mapArr().split(/\D+/).join(' ').trim().split(' '); + var mapArray = JSON.parse('[' + mapEditArea.mapArr() + ']'); + var sy=editor.map.length,sx=editor.map[0].length; + for (var y = 0; y < sy; y++) + for (var x = 0; x < sx; x++) { + var num = mapArray[y][x]; + if (num == 0) + editor.map[y][x] = 0; + else if (typeof(editor.indexs[num][0]) == 'undefined') { + mapEditArea.error(2); + editor.map[y][x] = undefined; + } else editor.map[y][x] = editor.ids[[editor.indexs[num][0]]]; + } + + editor.updateMap(); + + } + mapEditArea.formatArr= function () { + var formatArrStr = ''; + console.log(1) + + var si=editor.map.length,sk=editor.map[0].length; + if (mapEditArea.mapArr().split(/\D+/).join(' ').trim().split(' ').length != si*sk) return false; + var arr = mapEditArea.mapArr().replace(/\s+/g, '').split('],['); + + if (arr.length != si) return; + for (var i = 0; i < si; i++) { + var a = []; + formatArrStr += '['; + if (i == 0 || i == si-1) a = arr[i].split(/\D+/).join(' ').trim().split(' '); + else a = arr[i].split(/\D+/); + if (a.length != sk) { + formatArrStr = ''; + return; + } + + for (var k = 0; k < sk; k++) { + var num = parseInt(a[k]); + formatArrStr += Array(Math.max(4 - String(num).length, 0)).join(' ') + num + (k == sk-1 ? '' : ','); + } + formatArrStr += ']' + (i == si-1 ? '' : ',\n'); + } + return formatArrStr; + } + window.copyMap=document.getElementById('copyMap') + copyMap.err='' + copyMap.onclick=function(){ + tip.whichShow(0); + if (pout.value.trim() != '') { + if (mapEditArea.error()) { + copyMap.err = mapEditArea.errors[mapEditArea.error() - 1]; + tip.whichShow(5) + return; + } + try { + pout.focus(); + pout.setSelectionRange(0, pout.value.length); + document.execCommand("Copy"); + tip.whichShow(6); + } catch (e) { + copyMap.err = e; + tip.whichShow(5); + } + } else { + tip.whichShow(7); + } + } + window.clearMapButton=document.getElementById('clearMapButton') + clearMapButton.onclick=function () { + editor.mapInit(); + editor_mode.onmode(''); + editor.file.saveFloorFile(function (err) { + if (err) { + printe(err); + throw(err) + } + ;printf('地图清除成功'); + }); + editor.updateMap(); + clearTimeout(mapEditArea.formatTimer); + clearTimeout(tip.timer); + pout.value = ''; + mapEditArea.mapArr(''); + tip.whichShow(4); + mapEditArea.error(0); + } + window.deleteMap=document.getElementById('deleteMap') + deleteMap.onclick=function () { + editor_mode.onmode(''); + var index = core.floorIds.indexOf(editor.currentFloorId); + if (index>=0) { + core.floorIds.splice(index,1); + editor.file.editTower([['change', "['main']['floorIds']", core.floorIds]], function (objs_) {//console.log(objs_); + if (objs_.slice(-1)[0] != null) { + printe(objs_.slice(-1)[0]); + throw(objs_.slice(-1)[0]) + } + ;printe('删除成功,请F5刷新编辑器生效'); + }); + } + else printe('删除成功,请F5刷新编辑器生效'); + } + editor.uifunctions.newMap_func = function () { @@ -162,8 +353,8 @@ editor_datapanel_wrapper = function (editor) { printe('不合法的idnum'); return; } - if (!/^[0-9a-zA-Z_]+$/.test(id)) { - printe('不合法的id,请使用字母、数字或下划线') + if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(id)) { + printe('不合法的id,请使用字母、数字或下划线,且不能以数字开头'); return; } editor.file.changeIdAndIdnum(id, idnum, editor_mode.info, function (err) { @@ -193,8 +384,8 @@ editor_datapanel_wrapper = function (editor) { changeId.children[1].onclick = function () { var id = changeId.children[0].value; if (id) { - if (!/^[0-9a-zA-Z_]+$/.test(id)) { - printe('不合法的id,请使用字母、数字或下划线') + if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(id)) { + printe('不合法的id,请使用字母、数字或下划线,且不能以数字开头') return; } editor.file.changeIdAndIdnum(id, null, editor_mode.info, function (err) { diff --git a/_server/editor_file.js b/_server/editor_file.js index f737f910..edf8ae27 100644 --- a/_server/editor_file.js +++ b/_server/editor_file.js @@ -8,6 +8,8 @@ editor_file_wrapper = function (editor) { * } * 的形式记录所有更改过的文件,save时写入 * 的内容暂时还没想好 + * + * Mark相关的思路搁置 */ this.fileMark = {} } @@ -136,6 +138,7 @@ editor_file_wrapper = function (editor) { // 给追加素材使用 } + // Mark相关的思路搁置 editor_file_proto.prototype.addMark = function (name) { // 把name对应的文件在editor.file.fileMark添加标记 } @@ -143,6 +146,905 @@ editor_file_wrapper = function (editor) { editor_file_proto.prototype.save = function (callback) { // 根据 editor.file.fileMark 把游戏对象格式化写入文件 } +} + +///////////////////////////////////////////////////////////////////////// -} \ No newline at end of file +editor_file = function (editor, callback) { + + var editor_file = new editor_file_proto(); + editor.file=editor_file; + + editor.file.loadCommentjs(callback); + + editor.file.saveFloorFile = function (callback) { + //callback(err:String) + checkCallback(callback); + /* if (!isset(editor.currentFloorId) || !isset(editor.currentFloorData)) { + callback('未选中文件或无数据'); + } */ + var filename = 'project/floors/' + editor.currentFloorId + '.js'; + var datastr = ['main.floors.', editor.currentFloorId, '=\n']; + + if (core.floorIds.indexOf(editor.currentFloorId) >= 0) { + for(var ii=0,name;name=['map','bgmap','fgmap'][ii];ii++){ + var mapArray=editor[name].map(function (v) { + return v.map(function (v) { + return v.idnum || v || 0 + }) + }); + editor.currentFloorData[name]=mapArray; + } + } + editor.file.saveFloor(editor.currentFloorData, callback) + } + + /////////////////////////////////////////////////////////////////////////// + + editor.file.saveNewFile = function (saveFilename, callback) { + //saveAsFilename不含'/'不含'.js' + checkCallback(callback); + var currData=editor.currentFloorData; + var saveStatus = document.getElementById('newMapStatus').checked; + + var title = saveStatus?currData.title:"新建楼层"; + var name = saveStatus?currData.name:"0"; + if (/^mt\d+$/i.test(saveFilename)) { + name = saveFilename.substring(2); + title = "主塔 "+name+" 层"; + } + + var width = parseInt(document.getElementById('newMapWidth').value); + var height = parseInt(document.getElementById('newMapHeight').value); + var row = [], map = []; + for (var i=0;i0) + saveSetting('icons', iconActions, tempcallback); + else tempcallback(null); + + saveSetting('maps', mapActions, tempcallback); + + if (image=='items') + saveSetting('items', templateActions, tempcallback); + else if (image.indexOf('enemy')==0) + saveSetting('enemys', templateActions, tempcallback); + else tempcallback(null); + } + + editor.file.registerAutotile = function (filename, callback) { + var idnum = 140; + while (editor.core.maps.blocksInfo[idnum]) idnum++; + + var iconActions = []; + var mapActions = []; + + iconActions.push(["add", "['autotile']['" + filename + "']", 0]); + mapActions.push(["add", "['" + idnum + "']", {'cls': 'autotile', 'id': filename, 'noPass': true}]); + + var templist = []; + var tempcallback = function (err) { + templist.push(err); + if (templist.length == 2) { + if (templist[0] != null || templist[1] != null) + callback((templist[0] || '') + '\n' + (templist[1] || '')); + //这里如果一个成功一个失败会出严重bug + else + callback(null); + } + } + + saveSetting('icons', iconActions, tempcallback); + saveSetting('maps', mapActions, tempcallback); + } + + editor.file.changeIdAndIdnum = function (id, idnum, info, callback) { + checkCallback(callback); + + var changeOrNew=core.isset(editor_mode.info.id)?'change':'new' + if(changeOrNew=='new'){ + //检查maps中是否有重复的idnum或id + for (var ii in editor.core.maps.blocksInfo) { + if (ii == idnum) { + callback('idnum重复了'); + return; + } + if (editor.core.maps.blocksInfo[ii].id == id) { + callback('id重复了'); + return; + } + } + var templist = []; + var tempcallback = function (err) { + templist.push(err); + if (templist.length == 2) { + if (templist[0] != null || templist[1] != null) + callback((templist[0] || '') + '\n' + (templist[1] || '')); + //这里如果一个成功一个失败会出严重bug + else + callback(null); + } + } + saveSetting('maps', [["add", "['" + idnum + "']", {'cls': info.images, 'id': id}]], tempcallback); + saveSetting('icons', [["add", "['" + info.images + "']['" + id + "']", info.y]], tempcallback); + if (info.images === 'items') { + saveSetting('items', [["add", "['items']['" + id + "']", editor.file.comment._data.items_template]], function (err) { + if (err) { + printe(err); + throw(err) + } + }); + } + if (info.images === 'enemys' || info.images === 'enemy48') { + saveSetting('enemys', [["add", "['" + id + "']", editor.file.comment._data.enemys_template]], function (err) { + if (err) { + printe(err); + throw(err) + } + }); + } + + callback(null); + + }else{ + //检查maps中是否有重复的idnum或id + for (var ii in editor.core.maps.blocksInfo) { + if (editor.core.maps.blocksInfo[ii].id == id) { + callback('id重复了'); + return; + } + } + idnum = info.idnum; + + maps_90f36752_8815_4be8_b32b_d7fad1d0542e[idnum].id = id; + + var arr=[icons_4665ee12_3a1f_44a4_bea3_0fccba634dc1,items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a,{enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80:enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80}] + arr.forEach(function (obj) { + for(var jj in obj){ + var ii=obj[jj] + if (ii.hasOwnProperty(info.id)){ + ii[id]=ii[info.id]; + delete(ii[info.id]); + } + } + }); + + editor.file.save_icons_maps_items_enemys(callback) + + } + } + //callback(err:String) + editor.file.editItem = function (id, actionList, callback) { + /*actionList:[ + ["change","['items']['name']","红宝石的新名字"], + ["add","['items']['新的和name同级的属性']",123], + ["change","['itemEffectTip']","',攻击力+'+editor.core.values.redJewel"], + ] + 为[]时只查询不修改 + */ + checkCallback(callback); + if (isset(actionList) && actionList.length > 0) { + actionList.forEach(function (value) { + var tempindex = value[1].indexOf(']') + 1; + value[1] = [value[1].slice(0, tempindex), "['" + id + "']", value[1].slice(tempindex)].join(''); + }); + saveSetting('items', actionList, function (err) { + callback([err]); + }); + } else { + callback([ + (function () { + var locObj_ = {}; + Object.keys(editor.file.comment._data.items._data).forEach(function (v) { + if (isset(editor.core.items[v][id]) && v !== 'items') + locObj_[v] = editor.core.items[v][id]; + else + locObj_[v] = null; + }); + locObj_['items'] = (function () { + var locObj = Object.assign({}, editor.core.items.items[id]); + Object.keys(editor.file.comment._data.items._data.items._data).forEach(function (v) { + if (!isset(editor.core.items.items[id][v])) + locObj[v] = null; + }); + return locObj; + })(); + return locObj_; + })(), + editor.file.comment._data.items, + null]); + } + //只有items.cls是items的才有itemEffect和itemEffectTip,keys和constants和tools只有items + } + //callback([obj,commentObj,err:String]) + editor.file.editEnemy = function (id, actionList, callback) { + /*actionList:[ + ["change","['name']","初级巫师的新名字"], + ["add","['新的和name同级的属性']",123], + ["change","['bomb']",null], + ] + 为[]时只查询不修改 + */ + checkCallback(callback); + if (isset(actionList) && actionList.length > 0) { + actionList.forEach(function (value) { + value[1] = "['" + id + "']" + value[1]; + }); + saveSetting('enemys', actionList, function (err) { + callback([err]); + }); + } else { + callback([ + (function () { + var locObj = Object.assign({}, editor.core.enemys.enemys[id]); + Object.keys(editor.file.comment._data.enemys._data).forEach(function (v) { + if (!isset(editor.core.enemys.enemys[id][v])) + /* locObj[v]=editor.core.enemys.enemys[id][v]; + else */ + locObj[v] = null; + }); + return locObj; + })(), + editor.file.comment._data.enemys, + null]); + } + } + //callback([obj,commentObj,err:String]) + + editor.file.editMapBlocksInfo = function (idnum, actionList, callback) { + /*actionList:[ + ["change","['events']",["\t[老人,magician]领域、夹击。\n请注意领域怪需要设置value为伤害数值,可参见样板中初级巫师的写法。"]], + ["change","['afterBattle']",null], + ] + 为[]时只查询不修改 + */ + checkCallback(callback); + if (isset(actionList) && actionList.length > 0) { + var tempmap=[]; + for(var ii=0;ii=editor.core.icons.tilesetStartOffset && !isset(editor.core.maps.blocksInfo[idnum]) && tempmap.indexOf(idnum)===-1){ + actionList.splice(ii,0,["add","['" + idnum + "']",{"cls": "tileset", "id": "X"+idnum, "noPass": true}]); + tempmap.push(idnum); + ii++; + } + value[1] = "['" + idnum + "']" + value[1]; + } + saveSetting('maps', actionList, function (err) { + callback([err]); + }); + } else { + callback([ + (function () { + var sourceobj=editor.core.maps.blocksInfo[idnum]; + if(!isset(sourceobj) && idnum>=editor.core.icons.tilesetStartOffset)sourceobj={"cls": "tileset", "id": "X"+idnum, "noPass": true} + var locObj = Object.assign({}, sourceobj); + Object.keys(editor.file.comment._data.maps._data).forEach(function (v) { + if (!isset(sourceobj[v])) + locObj[v] = null; + }); + locObj.idnum = idnum; + return locObj; + })(), + editor.file.comment._data.maps, + null]); + } + } + //callback([obj,commentObj,err:String]) + + //////////////////////////////////////////////////////////////////// + + editor.file.editLoc = function (x, y, actionList, callback) { + /*actionList:[ + ["change","['events']",["\t[老人,magician]领域、夹击。\n请注意领域怪需要设置value为伤害数值,可参见样板中初级巫师的写法。"]], + ["change","['afterBattle']",null], + ] + 为[]时只查询不修改 + */ + checkCallback(callback); + if (isset(actionList) && actionList.length > 0) { + actionList.forEach(function (value) { + if(/\['autoEvent'\]\['\d+'\]$/.test(value[1]))value[1]=value[1].replace(/\['\d+'\]$/,function(v){return "['" + x + "," + y + "']"+v}) + else value[1] = value[1] + "['" + x + "," + y + "']"; + }); + saveSetting('floorloc', actionList, function (err) { + callback([err]); + }); + } else { + callback([ + (function () { + var locObj = {}; + Object.keys(editor.file.comment._data.floors._data.loc._data).forEach(function (v) { + if (isset(editor.currentFloorData[v][x + ',' + y])) + locObj[v] = editor.currentFloorData[v][x + ',' + y]; + else + locObj[v] = null; + }); + return locObj; + })(), + editor.file.comment._data.floors._data.loc, + null]); + } + + } + //callback([obj,commentObj,err:String]) + + //////////////////////////////////////////////////////////////////// + + editor.file.editFloor = function (actionList, callback) { + /*actionList:[ + ["change","['title']",'样板 3 层'], + ["change","['color']",null], + ] + 为[]时只查询不修改 + */ + checkCallback(callback); + if (isset(actionList) && actionList.length > 0) { + saveSetting('floors', actionList, function (err) { + callback([err]); + }); + } else { + callback([ + (function () { + var locObj = Object.assign({}, editor.currentFloorData); + Object.keys(editor.file.comment._data.floors._data.floor._data).forEach(function (v) { + if (!isset(editor.currentFloorData[v])) + /* locObj[v]=editor.currentFloorData[v]; + else */ + locObj[v] = null; + }); + Object.keys(editor.file.comment._data.floors._data.loc._data).forEach(function (v) { + delete(locObj[v]); + }); + delete(locObj.map); + delete(locObj.bgmap); + delete(locObj.fgmap); + return locObj; + })(), + editor.file.comment._data.floors._data.floor, + null]); + } + } + //callback([obj,commentObj,err:String]) + + //////////////////////////////////////////////////////////////////// + + editor.file.editTower = function (actionList, callback) { + /*actionList:[ + ["change","['firstData']['version']",'Ver 1.0.1 (Beta)'], + ["change","['values']['lavaDamage']",200], + ] + 为[]时只查询不修改 + */ + var data_obj = data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d; + checkCallback(callback); + if (isset(actionList) && actionList.length > 0) { + saveSetting('data', actionList, function (err) { + callback([err]); + }); + } else { + callback([ + (function () { + //var locObj=Object.assign({'main':{}},editor.core.data); + var locObj = Object.assign({}, data_obj, {'main': {}}); + Object.keys(editor.file.dataComment._data.main._data).forEach(function (v) { + if (isset(editor.main[v])) + locObj.main[v] = data_obj.main[v]; + else + locObj.main[v] = null; + }); + return locObj; + })(), + editor.file.dataComment, + null]); + } + } + //callback([obj,commentObj,err:String]) + + //////////////////////////////////////////////////////////////////// + + var fmap = {}; + var fjson = JSON.stringify(functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a, function (k, v) { + if (v instanceof Function) { + var id_ = editor.util.guid(); + fmap[id_] = v.toString(); + return id_; + } else return v + }, 4); + var fobj = JSON.parse(fjson); + editor.file.functionsMap = fmap; + editor.file.functionsJSON = fjson; + var buildlocobj = function (locObj) { + for (var key in locObj) { + if (typeof(locObj[key]) !== typeof('')) buildlocobj(locObj[key]); + else locObj[key] = fmap[locObj[key]]; + } + }; + + editor.file.editFunctions = function (actionList, callback) { + /*actionList:[ + ["change","['events']['afterChangeLight']","function(x,y){console.log(x,y)}"], + ["change","['ui']['drawAbout']","function(){...}"], + ] + 为[]时只查询不修改 + */ + checkCallback(callback); + if (isset(actionList) && actionList.length > 0) { + saveSetting('functions', actionList, function (err) { + callback([err]); + }); + } else { + callback([ + (function () { + var locObj = JSON.parse(fjson); + buildlocobj(locObj); + return locObj; + })(), + editor.file.functionsComment, + null]); + } + } + //callback([obj,commentObj,err:String]) + + //////////////////////////////////////////////////////////////////// + + editor.file.editCommonEvent = function (actionList, callback) { + /*actionList:[ + ["change","['test']",['123']], + ] + 为[]时只查询不修改 + */ + var data_obj = events_c12a15a8_c380_4b28_8144_256cba95f760.commonEvent; + checkCallback(callback); + if (isset(actionList) && actionList.length > 0) { + actionList.forEach(function (value) { + value[1] = "['commonEvent']" + value[1]; + }); + saveSetting('events', actionList, function (err) { + callback([err]); + }); + } else { + callback([ + Object.assign({},data_obj), + editor.file.eventsComment._data.commonEvent, + null]); + } + } + //callback([obj,commentObj,err:String]) + + //////////////////////////////////////////////////////////////////// + + var plmap = {}; + var pljson = JSON.stringify(plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1, function (k, v) { + if (v instanceof Function) { + var id_ = editor.util.guid(); + plmap[id_] = v.toString(); + return id_; + } else if(v===null){ + var id_ = editor.util.guid(); + plmap[id_] = null; + return id_; + } return v + }, 4); + var plobj = JSON.parse(pljson); + editor.file.pluginsMap = plmap; + editor.file.pluginsObj = plobj; + var buildpllocobj = function (locObj) { + for (var key in locObj) { + if (typeof(locObj[key]) !== typeof('')) buildpllocobj(locObj[key]); + else locObj[key] = plmap[locObj[key]]; + } + }; + + editor.file.editPlugins = function (actionList, callback) { + /*actionList:[ + ["change","['test']","function(x,y){console.log(x,y)}"], + ] + 为[]时只查询不修改 + */ + checkCallback(callback); + if (isset(actionList) && actionList.length > 0) { + saveSetting('plugins', actionList, function (err) { + callback([err]); + }); + } else { + callback([ + (function () { + var locObj = JSON.parse(JSON.stringify(plobj)); + buildpllocobj(locObj); + return locObj; + })(), + editor.file.pluginsComment, + null]); + } + } + //callback([obj,commentObj,err:String]) + + //////////////////////////////////////////////////////////////////// + + var isset = function (val) { + if (val == undefined || val == null) { + return false; + } + return true + } + + var checkCallback=function(callback){ + if (!isset(callback)) { + printe('未设置callback'); + throw('未设置callback') + } + } + + var encode = editor.util.encode64; + + editor.file.save_icons_maps_items_enemys=function(callback){ + var check=[] + saveSetting('icons',[],function(err){ + if(err){callback(err);return;} + check.push('icons') + if(check.length==4)callback(null); + }) + saveSetting('maps',[],function(err){ + if(err){callback(err);return;} + check.push('maps') + if(check.length==4)callback(null); + }) + saveSetting('items',[],function(err){ + if(err){callback(err);return;} + check.push('items') + if(check.length==4)callback(null); + }) + saveSetting('enemys',[],function(err){ + if(err){callback(err);return;} + check.push('enemys') + if(check.length==4)callback(null); + }) + } + + var saveSetting = function (file, actionList, callback) { + //console.log(file); + //console.log(actionList); + editor.file.alertWhenCompress(); + + if (file == 'icons') { + actionList.forEach(function (value) { + eval("icons_4665ee12_3a1f_44a4_bea3_0fccba634dc1" + value[1] + '=' + JSON.stringify(value[2])); + }); + var datastr = 'var icons_4665ee12_3a1f_44a4_bea3_0fccba634dc1 = \n'; + datastr += JSON.stringify(icons_4665ee12_3a1f_44a4_bea3_0fccba634dc1, null, '\t'); + fs.writeFile('project/icons.js', encode(datastr), 'base64', function (err, data) { + callback(err); + }); + return; + } + if (file == 'maps') { + actionList.forEach(function (value) { + eval("maps_90f36752_8815_4be8_b32b_d7fad1d0542e" + value[1] + '=' + JSON.stringify(value[2])); + }); + var datastr = 'var maps_90f36752_8815_4be8_b32b_d7fad1d0542e = \n'; + //datastr+=JSON.stringify(maps_90f36752_8815_4be8_b32b_d7fad1d0542e,null,4); + + var emap = {}; + var estr = JSON.stringify(maps_90f36752_8815_4be8_b32b_d7fad1d0542e, function (k, v) { + if (v.id != null) { + var id_ = editor.util.guid(); + emap[id_] = JSON.stringify(v); + return id_; + } else return v + }, '\t'); + for (var id_ in emap) { + estr = estr.replace('"' + id_ + '"', emap[id_]) + } + datastr += estr; + + fs.writeFile('project/maps.js', encode(datastr), 'base64', function (err, data) { + callback(err); + }); + return; + } + if (file == 'items') { + actionList.forEach(function (value) { + eval("items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a" + value[1] + '=' + JSON.stringify(value[2])); + }); + var datastr = 'var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a = \n'; + datastr += JSON.stringify(items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a, null, '\t'); + fs.writeFile('project/items.js', encode(datastr), 'base64', function (err, data) { + callback(err); + }); + return; + } + if (file == 'enemys') { + actionList.forEach(function (value) { + eval("enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80" + value[1] + '=' + JSON.stringify(value[2])); + }); + var datastr = 'var enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80 = \n'; + var emap = {}; + var estr = JSON.stringify(enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80, function (k, v) { + if (v.hp != null) { + var id_ = editor.util.guid(); + emap[id_] = JSON.stringify(v); + return id_; + } else return v + }, '\t'); + for (var id_ in emap) { + estr = estr.replace('"' + id_ + '"', emap[id_]) + } + datastr += estr; + fs.writeFile('project/enemys.js', encode(datastr), 'base64', function (err, data) { + callback(err); + }); + return; + } + if (file == 'data') { + actionList.forEach(function (value) { + eval("data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d" + value[1] + '=' + JSON.stringify(value[2])); + }); + if (data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.main.floorIds.indexOf(data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.firstData.floorId) < 0) + data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.firstData.floorId = data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.main.floorIds[0]; + var datastr = 'var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = \n'; + datastr += JSON.stringify(data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d, null, '\t'); + fs.writeFile('project/data.js', encode(datastr), 'base64', function (err, data) { + callback(err); + }); + return; + } + if (file == 'functions') { + actionList.forEach(function (value) { + eval("fmap[fobj" + value[1] + ']=' + JSON.stringify(value[2])); + }); + var fraw = fjson; + for (var id_ in fmap) { + fraw = fraw.replace('"' + id_ + '"', fmap[id_]) + } + var datastr = 'var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = \n'; + datastr += fraw; + fs.writeFile('project/functions.js', encode(datastr), 'base64', function (err, data) { + callback(err); + }); + return; + } + if (file == 'floorloc') { + actionList.forEach(function (value) { + // 检测null/undefined + if(/\['autoEvent'\]\['\d+,\d+'\]\['\d+'\]$/.test(value[1])){ + var tempvalue=value[1].replace(/\['\d+'\]$/,'') + tempvalue="editor.currentFloorData" +tempvalue + tempvalue=tempvalue+'='+tempvalue+'||{}' + eval(tempvalue) + } + if (value[2]==null && value[0]!=='add') + eval("delete editor.currentFloorData" + value[1]); + else + eval("editor.currentFloorData" + value[1] + '=' + JSON.stringify(value[2])); + }); + editor.file.saveFloorFile(callback); + return; + } + if (file == 'floors') { + actionList.forEach(function (value) { + eval("editor.currentFloorData" + value[1] + '=' + JSON.stringify(value[2])); + }); + editor.file.saveFloorFile(callback); + return; + } + if (file == 'events') { + actionList.forEach(function (value) { + eval("events_c12a15a8_c380_4b28_8144_256cba95f760" + value[1] + '=' + JSON.stringify(value[2])); + }); + var datastr = 'var events_c12a15a8_c380_4b28_8144_256cba95f760 = \n'; + datastr += JSON.stringify(events_c12a15a8_c380_4b28_8144_256cba95f760, null, '\t'); + fs.writeFile('project/events.js', encode(datastr), 'base64', function (err, data) { + callback(err); + }); + return; + } + if (file == 'plugins') { + actionList.forEach(function (value) { + if(value[0]==='add'){ + eval("plobj" + value[1] + '=' + JSON.stringify(value[2])); + } else { + eval("plmap[plobj" + value[1] + ']=' + JSON.stringify(value[2])); + } + }); + var plraw = JSON.stringify(plobj,null,4); + for (var id_ in plmap) { + plraw = plraw.replace('"' + id_ + '"', plmap[id_]) + } + var datastr = 'var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = \n'; + datastr += plraw; + fs.writeFile('project/plugins.js', encode(datastr), 'base64', function (err, data) { + callback(err); + }); + return; + } + callback('出错了,要设置的文件名不识别'); + } + + editor.file.saveSetting = saveSetting; + + return editor_file; +} +//editor_file = editor_file(editor); \ No newline at end of file diff --git a/_server/editor_file_unsorted.js b/_server/editor_file_unsorted.js deleted file mode 100644 index 7ee709c8..00000000 --- a/_server/editor_file_unsorted.js +++ /dev/null @@ -1,904 +0,0 @@ -editor_file = function (editor, callback) { - - var editor_file = new editor_file_proto(); - editor.file=editor_file; - - editor.file.loadCommentjs(callback); - - editor.file.saveFloorFile = function (callback) { - //callback(err:String) - checkCallback(callback); - /* if (!isset(editor.currentFloorId) || !isset(editor.currentFloorData)) { - callback('未选中文件或无数据'); - } */ - var filename = 'project/floors/' + editor.currentFloorId + '.js'; - var datastr = ['main.floors.', editor.currentFloorId, '=\n']; - - if (core.floorIds.indexOf(editor.currentFloorId) >= 0) { - for(var ii=0,name;name=['map','bgmap','fgmap'][ii];ii++){ - var mapArray=editor[name].map(function (v) { - return v.map(function (v) { - return v.idnum || v || 0 - }) - }); - editor.currentFloorData[name]=mapArray; - } - } - editor.file.saveFloor(editor.currentFloorData, callback) - } - - /////////////////////////////////////////////////////////////////////////// - - editor.file.saveNewFile = function (saveFilename, callback) { - //saveAsFilename不含'/'不含'.js' - checkCallback(callback); - var currData=editor.currentFloorData; - var saveStatus = document.getElementById('newMapStatus').checked; - - var title = saveStatus?currData.title:"新建楼层"; - var name = saveStatus?currData.name:"0"; - if (/^mt\d+$/i.test(saveFilename)) { - name = saveFilename.substring(2); - title = "主塔 "+name+" 层"; - } - - var width = parseInt(document.getElementById('newMapWidth').value); - var height = parseInt(document.getElementById('newMapHeight').value); - var row = [], map = []; - for (var i=0;i0) - saveSetting('icons', iconActions, tempcallback); - else tempcallback(null); - - saveSetting('maps', mapActions, tempcallback); - - if (image=='items') - saveSetting('items', templateActions, tempcallback); - else if (image.indexOf('enemy')==0) - saveSetting('enemys', templateActions, tempcallback); - else tempcallback(null); - } - - editor.file.registerAutotile = function (filename, callback) { - var idnum = 140; - while (editor.core.maps.blocksInfo[idnum]) idnum++; - - var iconActions = []; - var mapActions = []; - - iconActions.push(["add", "['autotile']['" + filename + "']", 0]); - mapActions.push(["add", "['" + idnum + "']", {'cls': 'autotile', 'id': filename, 'noPass': true}]); - - var templist = []; - var tempcallback = function (err) { - templist.push(err); - if (templist.length == 2) { - if (templist[0] != null || templist[1] != null) - callback((templist[0] || '') + '\n' + (templist[1] || '')); - //这里如果一个成功一个失败会出严重bug - else - callback(null); - } - } - - saveSetting('icons', iconActions, tempcallback); - saveSetting('maps', mapActions, tempcallback); - } - - editor.file.changeIdAndIdnum = function (id, idnum, info, callback) { - checkCallback(callback); - - var changeOrNew=core.isset(editor_mode.info.id)?'change':'new' - if(changeOrNew=='new'){ - //检查maps中是否有重复的idnum或id - for (var ii in editor.core.maps.blocksInfo) { - if (ii == idnum) { - callback('idnum重复了'); - return; - } - if (editor.core.maps.blocksInfo[ii].id == id) { - callback('id重复了'); - return; - } - } - var templist = []; - var tempcallback = function (err) { - templist.push(err); - if (templist.length == 2) { - if (templist[0] != null || templist[1] != null) - callback((templist[0] || '') + '\n' + (templist[1] || '')); - //这里如果一个成功一个失败会出严重bug - else - callback(null); - } - } - saveSetting('maps', [["add", "['" + idnum + "']", {'cls': info.images, 'id': id}]], tempcallback); - saveSetting('icons', [["add", "['" + info.images + "']['" + id + "']", info.y]], tempcallback); - if (info.images === 'items') { - saveSetting('items', [["add", "['items']['" + id + "']", editor.file.comment._data.items_template]], function (err) { - if (err) { - printe(err); - throw(err) - } - }); - } - if (info.images === 'enemys' || info.images === 'enemy48') { - saveSetting('enemys', [["add", "['" + id + "']", editor.file.comment._data.enemys_template]], function (err) { - if (err) { - printe(err); - throw(err) - } - }); - } - - callback(null); - - }else{ - //检查maps中是否有重复的idnum或id - for (var ii in editor.core.maps.blocksInfo) { - if (editor.core.maps.blocksInfo[ii].id == id) { - callback('id重复了'); - return; - } - } - idnum = info.idnum; - - maps_90f36752_8815_4be8_b32b_d7fad1d0542e[idnum].id = id; - - var arr=[icons_4665ee12_3a1f_44a4_bea3_0fccba634dc1,items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a,{enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80:enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80}] - arr.forEach(function (obj) { - for(var jj in obj){ - var ii=obj[jj] - if (ii.hasOwnProperty(info.id)){ - ii[id]=ii[info.id]; - delete(ii[info.id]); - } - } - }); - - editor.file.save_icons_maps_items_enemys(callback) - - } - } - //callback(err:String) - editor.file.editItem = function (id, actionList, callback) { - /*actionList:[ - ["change","['items']['name']","红宝石的新名字"], - ["add","['items']['新的和name同级的属性']",123], - ["change","['itemEffectTip']","',攻击力+'+editor.core.values.redJewel"], - ] - 为[]时只查询不修改 - */ - checkCallback(callback); - if (isset(actionList) && actionList.length > 0) { - actionList.forEach(function (value) { - var tempindex = value[1].indexOf(']') + 1; - value[1] = [value[1].slice(0, tempindex), "['" + id + "']", value[1].slice(tempindex)].join(''); - }); - saveSetting('items', actionList, function (err) { - callback([err]); - }); - } else { - callback([ - (function () { - var locObj_ = {}; - Object.keys(editor.file.comment._data.items._data).forEach(function (v) { - if (isset(editor.core.items[v][id]) && v !== 'items') - locObj_[v] = editor.core.items[v][id]; - else - locObj_[v] = null; - }); - locObj_['items'] = (function () { - var locObj = Object.assign({}, editor.core.items.items[id]); - Object.keys(editor.file.comment._data.items._data.items._data).forEach(function (v) { - if (!isset(editor.core.items.items[id][v])) - locObj[v] = null; - }); - return locObj; - })(); - return locObj_; - })(), - editor.file.comment._data.items, - null]); - } - //只有items.cls是items的才有itemEffect和itemEffectTip,keys和constants和tools只有items - } - //callback([obj,commentObj,err:String]) - editor.file.editEnemy = function (id, actionList, callback) { - /*actionList:[ - ["change","['name']","初级巫师的新名字"], - ["add","['新的和name同级的属性']",123], - ["change","['bomb']",null], - ] - 为[]时只查询不修改 - */ - checkCallback(callback); - if (isset(actionList) && actionList.length > 0) { - actionList.forEach(function (value) { - value[1] = "['" + id + "']" + value[1]; - }); - saveSetting('enemys', actionList, function (err) { - callback([err]); - }); - } else { - callback([ - (function () { - var locObj = Object.assign({}, editor.core.enemys.enemys[id]); - Object.keys(editor.file.comment._data.enemys._data).forEach(function (v) { - if (!isset(editor.core.enemys.enemys[id][v])) - /* locObj[v]=editor.core.enemys.enemys[id][v]; - else */ - locObj[v] = null; - }); - return locObj; - })(), - editor.file.comment._data.enemys, - null]); - } - } - //callback([obj,commentObj,err:String]) - - editor.file.editMapBlocksInfo = function (idnum, actionList, callback) { - /*actionList:[ - ["change","['events']",["\t[老人,magician]领域、夹击。\n请注意领域怪需要设置value为伤害数值,可参见样板中初级巫师的写法。"]], - ["change","['afterBattle']",null], - ] - 为[]时只查询不修改 - */ - checkCallback(callback); - if (isset(actionList) && actionList.length > 0) { - var tempmap=[]; - for(var ii=0;ii=editor.core.icons.tilesetStartOffset && !isset(editor.core.maps.blocksInfo[idnum]) && tempmap.indexOf(idnum)===-1){ - actionList.splice(ii,0,["add","['" + idnum + "']",{"cls": "tileset", "id": "X"+idnum, "noPass": true}]); - tempmap.push(idnum); - ii++; - } - value[1] = "['" + idnum + "']" + value[1]; - } - saveSetting('maps', actionList, function (err) { - callback([err]); - }); - } else { - callback([ - (function () { - var sourceobj=editor.core.maps.blocksInfo[idnum]; - if(!isset(sourceobj) && idnum>=editor.core.icons.tilesetStartOffset)sourceobj={"cls": "tileset", "id": "X"+idnum, "noPass": true} - var locObj = Object.assign({}, sourceobj); - Object.keys(editor.file.comment._data.maps._data).forEach(function (v) { - if (!isset(sourceobj[v])) - locObj[v] = null; - }); - locObj.idnum = idnum; - return locObj; - })(), - editor.file.comment._data.maps, - null]); - } - } - //callback([obj,commentObj,err:String]) - - //////////////////////////////////////////////////////////////////// - - editor.file.editLoc = function (x, y, actionList, callback) { - /*actionList:[ - ["change","['events']",["\t[老人,magician]领域、夹击。\n请注意领域怪需要设置value为伤害数值,可参见样板中初级巫师的写法。"]], - ["change","['afterBattle']",null], - ] - 为[]时只查询不修改 - */ - checkCallback(callback); - if (isset(actionList) && actionList.length > 0) { - actionList.forEach(function (value) { - if(/\['autoEvent'\]\['\d+'\]$/.test(value[1]))value[1]=value[1].replace(/\['\d+'\]$/,function(v){return "['" + x + "," + y + "']"+v}) - else value[1] = value[1] + "['" + x + "," + y + "']"; - }); - saveSetting('floorloc', actionList, function (err) { - callback([err]); - }); - } else { - callback([ - (function () { - var locObj = {}; - Object.keys(editor.file.comment._data.floors._data.loc._data).forEach(function (v) { - if (isset(editor.currentFloorData[v][x + ',' + y])) - locObj[v] = editor.currentFloorData[v][x + ',' + y]; - else - locObj[v] = null; - }); - return locObj; - })(), - editor.file.comment._data.floors._data.loc, - null]); - } - - } - //callback([obj,commentObj,err:String]) - - //////////////////////////////////////////////////////////////////// - - editor.file.editFloor = function (actionList, callback) { - /*actionList:[ - ["change","['title']",'样板 3 层'], - ["change","['color']",null], - ] - 为[]时只查询不修改 - */ - checkCallback(callback); - if (isset(actionList) && actionList.length > 0) { - saveSetting('floors', actionList, function (err) { - callback([err]); - }); - } else { - callback([ - (function () { - var locObj = Object.assign({}, editor.currentFloorData); - Object.keys(editor.file.comment._data.floors._data.floor._data).forEach(function (v) { - if (!isset(editor.currentFloorData[v])) - /* locObj[v]=editor.currentFloorData[v]; - else */ - locObj[v] = null; - }); - Object.keys(editor.file.comment._data.floors._data.loc._data).forEach(function (v) { - delete(locObj[v]); - }); - delete(locObj.map); - delete(locObj.bgmap); - delete(locObj.fgmap); - return locObj; - })(), - editor.file.comment._data.floors._data.floor, - null]); - } - } - //callback([obj,commentObj,err:String]) - - //////////////////////////////////////////////////////////////////// - - editor.file.editTower = function (actionList, callback) { - /*actionList:[ - ["change","['firstData']['version']",'Ver 1.0.1 (Beta)'], - ["change","['values']['lavaDamage']",200], - ] - 为[]时只查询不修改 - */ - var data_obj = data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d; - checkCallback(callback); - if (isset(actionList) && actionList.length > 0) { - saveSetting('data', actionList, function (err) { - callback([err]); - }); - } else { - callback([ - (function () { - //var locObj=Object.assign({'main':{}},editor.core.data); - var locObj = Object.assign({}, data_obj, {'main': {}}); - Object.keys(editor.file.dataComment._data.main._data).forEach(function (v) { - if (isset(editor.main[v])) - locObj.main[v] = data_obj.main[v]; - else - locObj.main[v] = null; - }); - return locObj; - })(), - editor.file.dataComment, - null]); - } - } - //callback([obj,commentObj,err:String]) - - //////////////////////////////////////////////////////////////////// - - var fmap = {}; - var fjson = JSON.stringify(functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a, function (k, v) { - if (v instanceof Function) { - var id_ = editor.util.guid(); - fmap[id_] = v.toString(); - return id_; - } else return v - }, 4); - var fobj = JSON.parse(fjson); - editor.file.functionsMap = fmap; - editor.file.functionsJSON = fjson; - var buildlocobj = function (locObj) { - for (var key in locObj) { - if (typeof(locObj[key]) !== typeof('')) buildlocobj(locObj[key]); - else locObj[key] = fmap[locObj[key]]; - } - }; - - editor.file.editFunctions = function (actionList, callback) { - /*actionList:[ - ["change","['events']['afterChangeLight']","function(x,y){console.log(x,y)}"], - ["change","['ui']['drawAbout']","function(){...}"], - ] - 为[]时只查询不修改 - */ - checkCallback(callback); - if (isset(actionList) && actionList.length > 0) { - saveSetting('functions', actionList, function (err) { - callback([err]); - }); - } else { - callback([ - (function () { - var locObj = JSON.parse(fjson); - buildlocobj(locObj); - return locObj; - })(), - editor.file.functionsComment, - null]); - } - } - //callback([obj,commentObj,err:String]) - - //////////////////////////////////////////////////////////////////// - - editor.file.editCommonEvent = function (actionList, callback) { - /*actionList:[ - ["change","['test']",['123']], - ] - 为[]时只查询不修改 - */ - var data_obj = events_c12a15a8_c380_4b28_8144_256cba95f760.commonEvent; - checkCallback(callback); - if (isset(actionList) && actionList.length > 0) { - actionList.forEach(function (value) { - value[1] = "['commonEvent']" + value[1]; - }); - saveSetting('events', actionList, function (err) { - callback([err]); - }); - } else { - callback([ - Object.assign({},data_obj), - editor.file.eventsComment._data.commonEvent, - null]); - } - } - //callback([obj,commentObj,err:String]) - - //////////////////////////////////////////////////////////////////// - - var plmap = {}; - var pljson = JSON.stringify(plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1, function (k, v) { - if (v instanceof Function) { - var id_ = editor.util.guid(); - plmap[id_] = v.toString(); - return id_; - } else if(v===null){ - var id_ = editor.util.guid(); - plmap[id_] = null; - return id_; - } return v - }, 4); - var plobj = JSON.parse(pljson); - editor.file.pluginsMap = plmap; - editor.file.pluginsObj = plobj; - var buildpllocobj = function (locObj) { - for (var key in locObj) { - if (typeof(locObj[key]) !== typeof('')) buildpllocobj(locObj[key]); - else locObj[key] = plmap[locObj[key]]; - } - }; - - editor.file.editPlugins = function (actionList, callback) { - /*actionList:[ - ["change","['test']","function(x,y){console.log(x,y)}"], - ] - 为[]时只查询不修改 - */ - checkCallback(callback); - if (isset(actionList) && actionList.length > 0) { - saveSetting('plugins', actionList, function (err) { - callback([err]); - }); - } else { - callback([ - (function () { - var locObj = JSON.parse(JSON.stringify(plobj)); - buildpllocobj(locObj); - return locObj; - })(), - editor.file.pluginsComment, - null]); - } - } - //callback([obj,commentObj,err:String]) - - //////////////////////////////////////////////////////////////////// - - var isset = function (val) { - if (val == undefined || val == null) { - return false; - } - return true - } - - var checkCallback=function(callback){ - if (!isset(callback)) { - printe('未设置callback'); - throw('未设置callback') - } - } - - var encode = editor.util.encode64; - - var alertWhenCompress = function(){ - if(editor.useCompress===true){ - editor.useCompress='alerted'; - setTimeout("alert('当前游戏使用的是压缩文件,修改完成后请使用启动服务.exe->Js代码压缩工具重新压缩,或者把main.js的useCompress改成false来使用原始文件')",1000) - } - } - - editor.file.save_icons_maps_items_enemys=function(callback){ - var check=[] - saveSetting('icons',[],function(err){ - if(err){callback(err);return;} - check.push('icons') - if(check.length==4)callback(null); - }) - saveSetting('maps',[],function(err){ - if(err){callback(err);return;} - check.push('maps') - if(check.length==4)callback(null); - }) - saveSetting('items',[],function(err){ - if(err){callback(err);return;} - check.push('items') - if(check.length==4)callback(null); - }) - saveSetting('enemys',[],function(err){ - if(err){callback(err);return;} - check.push('enemys') - if(check.length==4)callback(null); - }) - } - - var saveSetting = function (file, actionList, callback) { - //console.log(file); - //console.log(actionList); - editor.file.alertWhenCompress(); - - if (file == 'icons') { - actionList.forEach(function (value) { - eval("icons_4665ee12_3a1f_44a4_bea3_0fccba634dc1" + value[1] + '=' + JSON.stringify(value[2])); - }); - var datastr = 'var icons_4665ee12_3a1f_44a4_bea3_0fccba634dc1 = \n'; - datastr += JSON.stringify(icons_4665ee12_3a1f_44a4_bea3_0fccba634dc1, null, '\t'); - fs.writeFile('project/icons.js', encode(datastr), 'base64', function (err, data) { - callback(err); - }); - return; - } - if (file == 'maps') { - actionList.forEach(function (value) { - eval("maps_90f36752_8815_4be8_b32b_d7fad1d0542e" + value[1] + '=' + JSON.stringify(value[2])); - }); - var datastr = 'var maps_90f36752_8815_4be8_b32b_d7fad1d0542e = \n'; - //datastr+=JSON.stringify(maps_90f36752_8815_4be8_b32b_d7fad1d0542e,null,4); - - var emap = {}; - var estr = JSON.stringify(maps_90f36752_8815_4be8_b32b_d7fad1d0542e, function (k, v) { - if (v.id != null) { - var id_ = editor.util.guid(); - emap[id_] = JSON.stringify(v); - return id_; - } else return v - }, '\t'); - for (var id_ in emap) { - estr = estr.replace('"' + id_ + '"', emap[id_]) - } - datastr += estr; - - fs.writeFile('project/maps.js', encode(datastr), 'base64', function (err, data) { - callback(err); - }); - return; - } - if (file == 'items') { - actionList.forEach(function (value) { - eval("items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a" + value[1] + '=' + JSON.stringify(value[2])); - }); - var datastr = 'var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a = \n'; - datastr += JSON.stringify(items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a, null, '\t'); - fs.writeFile('project/items.js', encode(datastr), 'base64', function (err, data) { - callback(err); - }); - return; - } - if (file == 'enemys') { - actionList.forEach(function (value) { - eval("enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80" + value[1] + '=' + JSON.stringify(value[2])); - }); - var datastr = 'var enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80 = \n'; - var emap = {}; - var estr = JSON.stringify(enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80, function (k, v) { - if (v.hp != null) { - var id_ = editor.util.guid(); - emap[id_] = JSON.stringify(v); - return id_; - } else return v - }, '\t'); - for (var id_ in emap) { - estr = estr.replace('"' + id_ + '"', emap[id_]) - } - datastr += estr; - fs.writeFile('project/enemys.js', encode(datastr), 'base64', function (err, data) { - callback(err); - }); - return; - } - if (file == 'data') { - actionList.forEach(function (value) { - eval("data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d" + value[1] + '=' + JSON.stringify(value[2])); - }); - if (data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.main.floorIds.indexOf(data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.firstData.floorId) < 0) - data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.firstData.floorId = data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.main.floorIds[0]; - var datastr = 'var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = \n'; - datastr += JSON.stringify(data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d, null, '\t'); - fs.writeFile('project/data.js', encode(datastr), 'base64', function (err, data) { - callback(err); - }); - return; - } - if (file == 'functions') { - actionList.forEach(function (value) { - eval("fmap[fobj" + value[1] + ']=' + JSON.stringify(value[2])); - }); - var fraw = fjson; - for (var id_ in fmap) { - fraw = fraw.replace('"' + id_ + '"', fmap[id_]) - } - var datastr = 'var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = \n'; - datastr += fraw; - fs.writeFile('project/functions.js', encode(datastr), 'base64', function (err, data) { - callback(err); - }); - return; - } - if (file == 'floorloc') { - actionList.forEach(function (value) { - // 检测null/undefined - if(/\['autoEvent'\]\['\d+,\d+'\]\['\d+'\]$/.test(value[1])){ - var tempvalue=value[1].replace(/\['\d+'\]$/,'') - tempvalue="editor.currentFloorData" +tempvalue - tempvalue=tempvalue+'='+tempvalue+'||{}' - eval(tempvalue) - } - if (value[2]==null && value[0]!=='add') - eval("delete editor.currentFloorData" + value[1]); - else - eval("editor.currentFloorData" + value[1] + '=' + JSON.stringify(value[2])); - }); - editor.file.saveFloorFile(callback); - return; - } - if (file == 'floors') { - actionList.forEach(function (value) { - eval("editor.currentFloorData" + value[1] + '=' + JSON.stringify(value[2])); - }); - editor.file.saveFloorFile(callback); - return; - } - if (file == 'events') { - actionList.forEach(function (value) { - eval("events_c12a15a8_c380_4b28_8144_256cba95f760" + value[1] + '=' + JSON.stringify(value[2])); - }); - var datastr = 'var events_c12a15a8_c380_4b28_8144_256cba95f760 = \n'; - datastr += JSON.stringify(events_c12a15a8_c380_4b28_8144_256cba95f760, null, '\t'); - fs.writeFile('project/events.js', encode(datastr), 'base64', function (err, data) { - callback(err); - }); - return; - } - if (file == 'plugins') { - actionList.forEach(function (value) { - if(value[0]==='add'){ - eval("plobj" + value[1] + '=' + JSON.stringify(value[2])); - } else { - eval("plmap[plobj" + value[1] + ']=' + JSON.stringify(value[2])); - } - }); - var plraw = JSON.stringify(plobj,null,4); - for (var id_ in plmap) { - plraw = plraw.replace('"' + id_ + '"', plmap[id_]) - } - var datastr = 'var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = \n'; - datastr += plraw; - fs.writeFile('project/plugins.js', encode(datastr), 'base64', function (err, data) { - callback(err); - }); - return; - } - callback('出错了,要设置的文件名不识别'); - } - - editor.file.saveSetting = saveSetting; - - return editor_file; -} -//editor_file = editor_file(editor); \ No newline at end of file diff --git a/_server/editor_legacy.js b/_server/editor_legacy.js deleted file mode 100644 index 35e5518d..00000000 --- a/_server/editor_legacy.js +++ /dev/null @@ -1,379 +0,0 @@ -// 由于历史遗留原因, 以下变量作为全局变量使用 -// exportMap mapEditArea pout mapEditArea copyMap clearMapButton deleteMap printf printe tip selectBox -// 除对这些量的功能修改外, 误在此文件中增加新变量或函数 -exportMap = document.getElementById('exportMap') -exportMap.isExport=false -exportMap.onclick=function(){ - editor.updateMap(); - var sx=editor.map.length-1,sy=editor.map[0].length-1; - - var filestr = ''; - for (var yy = 0; yy <= sy; yy++) { - filestr += '[' - for (var xx = 0; xx <= sx; xx++) { - var mapxy = editor.map[yy][xx]; - if (typeof(mapxy) == typeof({})) { - if ('idnum' in mapxy) mapxy = mapxy.idnum; - else { - // mapxy='!!?'; - tip.whichShow(3); - return; - } - } else if (typeof(mapxy) == 'undefined') { - tip.whichShow(3); - return; - } - mapxy = String(mapxy); - mapxy = Array(Math.max(4 - mapxy.length, 0)).join(' ') + mapxy; - filestr += mapxy + (xx == sx ? '' : ',') - } - - filestr += ']' + (yy == sy ? '' : ',\n'); - } - pout.value = filestr; - mapEditArea.mapArr(filestr); - exportMap.isExport = true; - mapEditArea.error(0); - tip.whichShow(2); -} -mapEditArea = document.getElementById('mapEditArea') -mapEditArea.errors=[ // 编号1,2 - "格式错误!请使用正确格式(请使用地图生成器进行生成,且需要和本地图宽高完全一致)", - "当前有未定义ID(在地图区域显示红块),请修改ID或者到icons.js和maps.js中进行定义!" -] -mapEditArea.formatTimer=null -mapEditArea._mapArr='' -mapEditArea.mapArr=function(value){ - if(value!=null){ - var val=value - var oldval=mapEditArea._mapArr - if (val==oldval) return; - - if (exportMap.isExport) { - exportMap.isExport = false; - return; - } - if (mapEditArea.formatArr()) { - mapEditArea.error(0); - - setTimeout(function () { - if (mapEditArea.formatArr())mapEditArea.mapArr(mapEditArea.formatArr()); - mapEditArea.drawMap(); - tip.whichShow(8) - }, 1000); - clearTimeout(mapEditArea.formatTimer); - mapEditArea.formatTimer = setTimeout(function () { - pout.value = mapEditArea.formatArr(); - }, 5000); //5s后再格式化,不然光标跳到最后很烦 - } else { - mapEditArea.error(1); - } - - mapEditArea._mapArr=value - } - return mapEditArea._mapArr -} -pout.oninput=function(){ - mapEditArea.mapArr(pout.value) -} -mapEditArea._error=0 -mapEditArea.error=function(value){ - if(value!=null){ - mapEditArea._error=value - if (value>0) - printe(mapEditArea.errors[value-1]) - } - return mapEditArea._error -} -mapEditArea.drawMap= function () { - // var mapArray = mapEditArea.mapArr().split(/\D+/).join(' ').trim().split(' '); - var mapArray = JSON.parse('[' + mapEditArea.mapArr() + ']'); - var sy=editor.map.length,sx=editor.map[0].length; - for (var y = 0; y < sy; y++) - for (var x = 0; x < sx; x++) { - var num = mapArray[y][x]; - if (num == 0) - editor.map[y][x] = 0; - else if (typeof(editor.indexs[num][0]) == 'undefined') { - mapEditArea.error(2); - editor.map[y][x] = undefined; - } else editor.map[y][x] = editor.ids[[editor.indexs[num][0]]]; - } - - editor.updateMap(); - -} -mapEditArea.formatArr= function () { - var formatArrStr = ''; - console.log(1) - - var si=editor.map.length,sk=editor.map[0].length; - if (mapEditArea.mapArr().split(/\D+/).join(' ').trim().split(' ').length != si*sk) return false; - var arr = mapEditArea.mapArr().replace(/\s+/g, '').split('],['); - - if (arr.length != si) return; - for (var i = 0; i < si; i++) { - var a = []; - formatArrStr += '['; - if (i == 0 || i == si-1) a = arr[i].split(/\D+/).join(' ').trim().split(' '); - else a = arr[i].split(/\D+/); - if (a.length != sk) { - formatArrStr = ''; - return; - } - - for (var k = 0; k < sk; k++) { - var num = parseInt(a[k]); - formatArrStr += Array(Math.max(4 - String(num).length, 0)).join(' ') + num + (k == sk-1 ? '' : ','); - } - formatArrStr += ']' + (i == si-1 ? '' : ',\n'); - } - return formatArrStr; -} -copyMap=document.getElementById('copyMap') -copyMap.err='' -copyMap.onclick=function(){ - tip.whichShow(0); - if (pout.value.trim() != '') { - if (mapEditArea.error()) { - copyMap.err = mapEditArea.errors[mapEditArea.error() - 1]; - tip.whichShow(5) - return; - } - try { - pout.focus(); - pout.setSelectionRange(0, pout.value.length); - document.execCommand("Copy"); - tip.whichShow(6); - } catch (e) { - copyMap.err = e; - tip.whichShow(5); - } - } else { - tip.whichShow(7); - } -} -clearMapButton=document.getElementById('clearMapButton') -clearMapButton.onclick=function () { - editor.mapInit(); - editor_mode.onmode(''); - editor.file.saveFloorFile(function (err) { - if (err) { - printe(err); - throw(err) - } - ;printf('地图清除成功'); - }); - editor.updateMap(); - clearTimeout(mapEditArea.formatTimer); - clearTimeout(tip.timer); - pout.value = ''; - mapEditArea.mapArr(''); - tip.whichShow(4); - mapEditArea.error(0); -} -deleteMap=document.getElementById('deleteMap') -deleteMap.onclick=function () { - editor_mode.onmode(''); - var index = core.floorIds.indexOf(editor.currentFloorId); - if (index>=0) { - core.floorIds.splice(index,1); - editor.file.editTower([['change', "['main']['floorIds']", core.floorIds]], function (objs_) {//console.log(objs_); - if (objs_.slice(-1)[0] != null) { - printe(objs_.slice(-1)[0]); - throw(objs_.slice(-1)[0]) - } - ;printe('删除成功,请F5刷新编辑器生效'); - }); - } - else printe('删除成功,请F5刷新编辑器生效'); -} -printf = function (str_, type) { - selectBox.isSelected(false); - if (!type) { - tip.whichShow(11); - } else { - tip.whichShow(12); - } - setTimeout(function () { - if (!type) { - tip.msgs[11] = String(str_); - tip.whichShow(12); - } else { - tip.msgs[10] = String(str_); - tip.whichShow(11); - } - }, 1); -} -printe = function (str_) { - printf(str_, 'error') -} -tip=document.getElementById('tip') -tip.showHelp = function(value) { - var tips = [ - '表格的文本域可以双击进行编辑', - '双击地图可以选中素材,右键可以弹出菜单', - '双击事件编辑器的图块可以进行长文本编辑/脚本编辑/地图选点/UI绘制预览等操作', - 'ESC或点击空白处可以自动保存当前修改', - 'H键可以打开操作帮助哦', - 'tileset贴图模式可以在地图上拖动来一次绘制一个区域;右键额外素材也可以绑定宽高', - '可以拖动地图上的图块和事件,或按Ctrl+C, Ctrl+X和Ctrl+V进行复制,剪切和粘贴,Delete删除', - 'Alt+数字键保存图块,数字键读取保存的图块', - ]; - if (value == null) value = Math.floor(Math.random() * tips.length); - printf('tips: ' + tips[value]) -} -tip._infos= {} -tip.infos=function(value){ - if(value!=null){ - var val=value - var oldval=tip._infos - - tip.isClearBlock(false); - tip.isAirwall(false); - if (typeof(val) != 'undefined') { - if (val == 0) { - tip.isClearBlock(true); - return; - } - if ('id' in val) { - if (val.idnum == 17) { - tip.isAirwall(true); - return; - } - tip.hasId = true; - } else { - tip.hasId = false; - } - tip.isAutotile = false; - if (val.images == "autotile" && tip.hasId) tip.isAutotile = true; - document.getElementById('isAirwall-else').innerHTML=(tip.hasId?`

图块编号:${ value['idnum'] }

-

图块ID:${ value['id'] }

`:` -

该图块无对应的数字或ID存在,请先前往icons.js和maps.js中进行定义!

`)+` -

图块所在素材:${ value['images'] + (tip.isAutotile ? '( '+value['id']+' )' : '') } -

-

图块索引:${ value['y'] }

` - } - - tip._infos=value - } - return tip._infos -} -tip.hasId= true -tip.isAutotile= false -tip._isSelectedBlock= false -tip.isSelectedBlock=function(value){ - if(value!=null){ - var dshow=document.getElementById('isSelectedBlock-if') - var dhide=document.getElementById('isSelectedBlock-else') - if(!value){ - var dtemp=dshow - dshow=dhide - dhide=dtemp - } - dshow.style.display='' - dhide.style.display='none' - tip._isSelectedBlock=value - } - return tip._isSelectedBlock -} -tip._isClearBlock= false -tip.isClearBlock=function(value){ - if(value!=null){ - var dshow=document.getElementById('isClearBlock-if') - var dhide=document.getElementById('isClearBlock-else') - if(!value){ - var dtemp=dshow - dshow=dhide - dhide=dtemp - } - dshow.style.display='' - dhide.style.display='none' - tip._isClearBlock=value - } - return tip._isClearBlock -} -tip._isAirwall= false -tip.isAirwall=function(value){ - if(value!=null){ - var dshow=document.getElementById('isAirwall-if') - var dhide=document.getElementById('isAirwall-else') - if(!value){ - var dtemp=dshow - dshow=dhide - dhide=dtemp - } - dshow.style.display='' - dhide.style.display='none' - tip._isAirwall=value - } - return tip._isAirwall -} -tip.geneMapSuccess= false -tip.timer= null -tip.msgs= [ //分别编号1,2,3,4,5,6,7,8,9,10;奇数警告,偶数成功 - "当前未选择任何图块,请先在右边选择要画的图块!", - "生成地图成功!可点击复制按钮复制地图数组到剪切板", - "生成失败! 地图中有未定义的图块,建议先用其他有效图块覆盖或点击清除地图!", - "地图清除成功!", - "复制失败!", - "复制成功!可直接粘贴到楼层文件的地图数组中。", - "复制失败!当前还没有数据", - "修改成功!可点击复制按钮复制地图数组到剪切板", - "选择背景图片失败!文件名格式错误或图片不存在!", - "更新背景图片成功!", - "11:警告", - "12:成功" -] -tip._mapMsg= '' -tip.mapMsg=function(value){ - if(value!=null){ - document.getElementById('whichShow-if').innerText=value - tip._mapMsg=value - } - return tip._mapMsg -} -tip._whichShow= 0 -tip.whichShow=function(value){ - if(value!=null){ - - var dshow=document.getElementById('whichShow-if') - var dhide=null - if(!value){ - var dtemp=dshow - dshow=dhide - dhide=dtemp - } - if(dshow)dshow.style.display='' - if(dhide)dhide.style.display='none' - - if(dshow)dshow.setAttribute('class',(value%2) ? 'warnText' : 'successText') - - tip.mapMsg(''); - tip.msgs[4] = "复制失败!" + editTip.err; - clearTimeout(tip.timer); - if (value) { - tip.mapMsg(tip.msgs[value - 1]); - tip.timer = setTimeout(function () { - if (!(value % 2)) - value = 0; - }, 5000); //5秒后自动清除success,warn不清除 - } - tip._whichShow=value - } - return tip._whichShow -} -selectBox=document.getElementById('selectBox') -selectBox._isSelected=false -selectBox.isSelected=function(value){ - if(value!=null){ - selectBox._isSelected=value; - tip.isSelectedBlock(value); - tip.whichShow(0); - clearTimeout(tip.timer); - editor.dom.dataSelection.style.display=value?'':'none' - } - return selectBox._isSelected -} - -// 修改此文件前先看文件开头的说明 \ No newline at end of file diff --git a/_server/editor_listen.js b/_server/editor_listen.js index 31825aa5..8c80ecf0 100644 --- a/_server/editor_listen.js +++ b/_server/editor_listen.js @@ -35,6 +35,7 @@ editor_listen_wrapper = function (editor) { editor.dom.clearLoc.onmousedown = editor.uifunctions.clearLoc_click editor.dom.lastUsed.onmousedown = editor.uifunctions.lastUsed_click; + editor.dom.clearLastUsedBtn.onclick = editor.uifunctions.clearLastUsedBtn_click; editor.dom.lockMode.onchange = editor.uifunctions.lockMode_onchange; editor.dom.brushMod.onchange = editor.uifunctions.brushMod_onchange diff --git a/_server/editor_mappanel.js b/_server/editor_mappanel.js index 9068eff9..996a66ea 100644 --- a/_server/editor_mappanel.js +++ b/_server/editor_mappanel.js @@ -48,7 +48,7 @@ editor_mappanel_wrapper = function (editor) { if (editor.uivalues.bindSpecialDoor.loc != null) return; var loc = editor.uifunctions.eToLoc(e); var pos = editor.uifunctions.locToPos(loc, true); - editor.setSelectBoxFromInfo(editor[editor.layerMod][pos.y][pos.x]); + editor.setSelectBoxFromInfo(editor[editor.layerMod][pos.y][pos.x], true); return; } @@ -472,7 +472,7 @@ editor_mappanel_wrapper = function (editor) { }; bindSpecialDoor.enemys.forEach(function (loc) { editor.currentFloorData.afterBattle[loc] = [ - {"type": "addValue", "name": doorFlag, "value": "1"} + {"type": "setValue", "name": doorFlag, "operator": "+=", "value": "1"} ] }); editor.file.saveFloorFile(function (err) { @@ -514,7 +514,7 @@ editor_mappanel_wrapper = function (editor) { editor.uifunctions.hideMidMenu(); e.stopPropagation(); var thisevent = editor[editor.layerMod][editor.pos.y][editor.pos.x]; - editor.setSelectBoxFromInfo(thisevent); + editor.setSelectBoxFromInfo(thisevent, true); } /** @@ -742,7 +742,13 @@ editor_mappanel_wrapper = function (editor) { return; } + editor.uifunctions.clearLastUsedBtn_click = function () { + if (editor.isMobile) return; + editor.uivalues.lastUsed = []; + editor.config.set('lastUsed', []); + editor.updateLastUsedMap(); + } ///////////////////////////////////////////////////////////////////////////// diff --git a/_server/editor_materialpanel.js b/_server/editor_materialpanel.js index ca3713fb..51752b9c 100644 --- a/_server/editor_materialpanel.js +++ b/_server/editor_materialpanel.js @@ -1,5 +1,21 @@ editor_materialpanel_wrapper = function (editor) { + // 由于历史遗留原因, 以下变量作为全局变量使用 + // selectBox + + window.selectBox=document.getElementById('selectBox') + selectBox._isSelected=false + selectBox.isSelected=function(value){ + if(value!=null){ + selectBox._isSelected=value; + tip.isSelectedBlock(value); + tip.whichShow(0); + clearTimeout(tip.timer); + editor.dom.dataSelection.style.display=value?'':'none' + } + return selectBox._isSelected + } + editor.uifunctions.getScrollBarHeight = function () { var outer = document.createElement("div"); outer.style.visibility = "hidden"; diff --git a/_server/editor_mode.js b/_server/editor_mode.js index 8e42b7e0..7cd86e40 100644 --- a/_server/editor_mode.js +++ b/_server/editor_mode.js @@ -97,12 +97,14 @@ editor_mode = function (editor) { } editor_mode.prototype.onmode = function (mode, callback) { - if (editor_mode.mode != mode) { - if (mode === 'save') editor_mode.doActionList(editor_mode.mode, editor_mode.actionList, callback); - if (editor_mode.mode === 'nextChange' && mode) editor_mode.showMode(mode); - if (mode !== 'save') editor_mode.mode = mode; - editor_mode.actionList = []; - } + setTimeout(function(){ + if (editor_mode.mode != mode) { + if (mode === 'save') editor_mode.doActionList(editor_mode.mode, editor_mode.actionList, callback); + if (editor_mode.mode === 'nextChange' && mode) editor_mode.showMode(mode); + if (mode !== 'save') editor_mode.mode = mode; + editor_mode.actionList = []; + } + }) } editor_mode.prototype.showMode = function (mode) { @@ -167,6 +169,25 @@ editor_mode = function (editor) { return true } + editor_mode.prototype.checkImages = function (thiseval) { + if (!editor_mode.checkUnique(thiseval)) return false; + fs.readdir('project/images', function (err, data) { + if (err) { + printe(err); + throw Error(err); + } + thiseval.map(function (v) { + var name = v.indexOf('.') < 0 ? (v+'.png') : v; + if (data.indexOf(name) < 0) notExist = name; + return name; + }); + if (notExist) { + alert('警告!图片' + notExist + '不存在!保存可能导致工程无法打开,请及时修改!'); + } + }); + return true; + } + editor_mode.prototype.changeDoubleClickModeByButton = function (mode) { ({ delete: function () { diff --git a/_server/editor_table.js b/_server/editor_table.js index c21220fd..c01e3512 100644 --- a/_server/editor_table.js +++ b/_server/editor_table.js @@ -8,7 +8,7 @@ editor_table_wrapper = function (editor) { // HTML模板 editor_table.prototype.select = function (value, values) { - let content = editor.table.option(value) + + var content = editor.table.option(value) + values.map(function (v) { return editor.table.option(v) }).join('') @@ -21,16 +21,35 @@ editor_table_wrapper = function (editor) { return /* html */`\n` } editor_table.prototype.checkbox = function (value) { - return /* html */`\n` + return /* html */`\n` } editor_table.prototype.textarea = function (value, indent) { return /* html */`\n` } - editor_table.prototype.editGrid = function (showComment) { - var html = ""; - if (showComment) html += "
"; - html += ""; - return html; + editor_table.prototype.checkboxSet = function (value, keys, prefixStrings) { + if (!(value instanceof Array)) value = []; + keys=Array.from(keys) + prefixStrings=Array.from(prefixStrings) + for (var index = 0; index < value.length; index++) { + if (keys.indexOf(value[index])==-1) { + keys.push(value[index]) + prefixStrings.push('
'+value[index]+': ') + } + } + var content=[] + for (var index = 0; index < keys.length; index++) { + content.push(editor.table.checkboxSetMember(value.indexOf(keys[index])!=-1,keys[index],prefixStrings[index])) + } + return /* html */`
${content.join('')}
\n`; + } + editor_table.prototype.checkboxSetMember = function (value,key,prefixString) { + return /* html */`${prefixString}\n`; + } + editor_table.prototype.editGrid = function (showComment, showEdit) { + var list = []; + if (showComment) list.push(""); + if (showEdit) list.push(""); + return list.join(' '); } editor_table.prototype.title = function () { @@ -41,16 +60,39 @@ editor_table_wrapper = function (editor) { return /* html */`--------${field}----\n` } - editor_table.prototype.tr = function (guid, field, shortField, commentHTMLescape, cobjstr, shortCommentHTMLescape, tdstr) { + editor_table.prototype.tr = function (guid, field, shortField, commentHTMLescape, cobjstr, shortComment, tdstr, type) { return /* html */` ${shortField} - ${shortCommentHTMLescape} -
${tdstr}
- ${editor.table.editGrid(commentHTMLescape != shortCommentHTMLescape)} + ${shortComment || commentHTMLescape} +
${tdstr}
+ ${editor.table.editGrid(shortComment, type != 'select' && type != 'checkbox' && type != 'checkboxSet')} \n` } + /** + * checkboxset中checkbox的onchange + */ + editor_table.prototype.checkboxSetMemberOnchange = function (onemember) { + var thisset=onemember.parentNode + var inputs=thisset.children + var value=[] + for (var i in inputs) { + if (inputs[i].nodeName == 'INPUT') { + if (inputs[i].checked) { + var one = inputs[i].getAttribute('key'); + if (inputs[i].getAttribute('ctype') == 'number') one = parseFloat(one); + value.push(one); + } + } + } + thiseval = value; + // if (value.length == 0) thiseval = null; + thisset.value=JSON.stringify(thiseval) + thisset.onchange() + } + + ///////////////////////////////////////////////////////////////////////////// // 表格生成的控制 @@ -197,16 +239,16 @@ editor_table_wrapper = function (editor) { var thiseval = vobj; var comment = String(cobj._data); - var charlength = 10; + var charlength = 15; // "['a']['b']" => "b" var shortField = field.split("']").slice(-2)[0].split("['").slice(-1)[0]; // 把长度超过 charlength 的字符改成 固定长度+...的形式 - // shortField = (shortField.length < charlength ? shortField : shortField.slice(0, charlength) + '...'); + shortField = (shortField.length < charlength ? shortField : shortField.slice(0, charlength) + '...'); // 完整的内容转义后供悬停查看 var commentHTMLescape = editor.util.HTMLescape(comment); // 把长度超过 charlength 的字符改成 固定长度+...的形式 - var shortCommentHTMLescape = (comment.length < charlength ? commentHTMLescape : editor.util.HTMLescape(comment.slice(0, charlength)) + '...'); + // var shortCommentHTMLescape = (comment.length < charlength ? commentHTMLescape : editor.util.HTMLescape(comment.slice(0, charlength)) + '...'); var cobjstr = Object.assign({}, cobj); delete cobjstr._data; @@ -214,22 +256,21 @@ editor_table_wrapper = function (editor) { cobjstr = editor.util.HTMLescape(JSON.stringify(cobjstr)); var tdstr = editor.table.objToTd(obj, commentObj, field, cfield, vobj, cobj) - var outstr = editor.table.tr(guid, field, shortField, commentHTMLescape, cobjstr, shortCommentHTMLescape, tdstr) + var outstr = editor.table.tr(guid, field, shortField, commentHTMLescape, cobjstr, cobj._docs, tdstr, cobj._type) return [outstr, guid]; } editor_table.prototype.objToTd = function (obj, commentObj, field, cfield, vobj, cobj) { var thiseval = vobj; - if (cobj._select) { - var values = cobj._select.values; - return editor.table.select(thiseval, values); - } else if (cobj._input) { - return editor.table.text(thiseval); - } else if (cobj._bool) { - return editor.table.checkbox(thiseval); - } else { - var indent = 0; - return editor.table.textarea(thiseval, indent); + switch (cobj._type) { + case 'select': + return editor.table.select(thiseval, cobj._select.values); + case 'checkbox': + return editor.table.checkbox(thiseval); + case 'checkboxSet': + return editor.table.checkboxSet(thiseval, cobj._checkboxSet.key, cobj._checkboxSet.prefix); + default: + return editor.table.textarea(thiseval, cobj.indent || 0); } } diff --git a/_server/editor_ui.js b/_server/editor_ui.js index 4a5e4386..9e5d3256 100644 --- a/_server/editor_ui.js +++ b/_server/editor_ui.js @@ -1,5 +1,183 @@ editor_ui_wrapper = function (editor) { + // 由于历史遗留原因, 以下变量作为全局变量使用 + // printf printe tip + window.printf = function (str_, type) { + selectBox.isSelected(false); + if (!type) { + tip.whichShow(11); + } else { + tip.whichShow(12); + } + setTimeout(function () { + if (!type) { + tip.msgs[11] = String(str_); + tip.whichShow(12); + } else { + tip.msgs[10] = String(str_); + tip.whichShow(11); + } + }, 1); + } + window.printe = function (str_) { + printf(str_, 'error') + } + window.tip=document.getElementById('tip') + tip.showHelp = function(value) { + var tips = [ + '表格的文本域可以双击进行编辑', + '双击地图可以选中素材,右键可以弹出菜单', + '双击事件编辑器的图块可以进行长文本编辑/脚本编辑/地图选点/UI绘制预览等操作', + 'ESC或点击空白处可以自动保存当前修改', + 'H键可以打开操作帮助哦', + 'tileset贴图模式可以在地图上拖动来一次绘制一个区域;右键额外素材也可以绑定宽高', + '可以拖动地图上的图块和事件,或按Ctrl+C, Ctrl+X和Ctrl+V进行复制,剪切和粘贴,Delete删除', + 'Alt+数字键保存图块,数字键读取保存的图块', + ]; + if (value == null) value = Math.floor(Math.random() * tips.length); + printf('tips: ' + tips[value]) + } + tip._infos= {} + tip.infos=function(value){ + if(value!=null){ + var val=value + var oldval=tip._infos + + tip.isClearBlock(false); + tip.isAirwall(false); + if (typeof(val) != 'undefined') { + if (val == 0) { + tip.isClearBlock(true); + return; + } + if ('id' in val) { + if (val.idnum == 17) { + tip.isAirwall(true); + return; + } + tip.hasId = true; + } else { + tip.hasId = false; + } + tip.isAutotile = false; + if (val.images == "autotile" && tip.hasId) tip.isAutotile = true; + document.getElementById('isAirwall-else').innerHTML=(tip.hasId?`

图块编号:${ value['idnum'] }

+

图块ID:${ value['id'] }

`:` +

该图块无对应的数字或ID存在,请先前往icons.js和maps.js中进行定义!

`)+` +

图块所在素材:${ value['images'] + (tip.isAutotile ? '( '+value['id']+' )' : '') } +

+

图块索引:${ value['y'] }

` + } + + tip._infos=value + } + return tip._infos + } + tip.hasId= true + tip.isAutotile= false + tip._isSelectedBlock= false + tip.isSelectedBlock=function(value){ + if(value!=null){ + var dshow=document.getElementById('isSelectedBlock-if') + var dhide=document.getElementById('isSelectedBlock-else') + if(!value){ + var dtemp=dshow + dshow=dhide + dhide=dtemp + } + dshow.style.display='' + dhide.style.display='none' + tip._isSelectedBlock=value + } + return tip._isSelectedBlock + } + tip._isClearBlock= false + tip.isClearBlock=function(value){ + if(value!=null){ + var dshow=document.getElementById('isClearBlock-if') + var dhide=document.getElementById('isClearBlock-else') + if(!value){ + var dtemp=dshow + dshow=dhide + dhide=dtemp + } + dshow.style.display='' + dhide.style.display='none' + tip._isClearBlock=value + } + return tip._isClearBlock + } + tip._isAirwall= false + tip.isAirwall=function(value){ + if(value!=null){ + var dshow=document.getElementById('isAirwall-if') + var dhide=document.getElementById('isAirwall-else') + if(!value){ + var dtemp=dshow + dshow=dhide + dhide=dtemp + } + dshow.style.display='' + dhide.style.display='none' + tip._isAirwall=value + } + return tip._isAirwall + } + tip.geneMapSuccess= false + tip.timer= null + tip.msgs= [ //分别编号1,2,3,4,5,6,7,8,9,10;奇数警告,偶数成功 + "当前未选择任何图块,请先在右边选择要画的图块!", + "生成地图成功!可点击复制按钮复制地图数组到剪切板", + "生成失败! 地图中有未定义的图块,建议先用其他有效图块覆盖或点击清除地图!", + "地图清除成功!", + "复制失败!", + "复制成功!可直接粘贴到楼层文件的地图数组中。", + "复制失败!当前还没有数据", + "修改成功!可点击复制按钮复制地图数组到剪切板", + "选择背景图片失败!文件名格式错误或图片不存在!", + "更新背景图片成功!", + "11:警告", + "12:成功" + ] + tip._mapMsg= '' + tip.mapMsg=function(value){ + if(value!=null){ + document.getElementById('whichShow-if').innerText=value + tip._mapMsg=value + } + return tip._mapMsg + } + tip._whichShow= 0 + tip.whichShow=function(value){ + if(value!=null){ + + var dshow=document.getElementById('whichShow-if') + var dhide=null + if(!value){ + var dtemp=dshow + dshow=dhide + dhide=dtemp + } + if(dshow)dshow.style.display='' + if(dhide)dhide.style.display='none' + + if(dshow)dshow.setAttribute('class',(value%2) ? 'warnText' : 'successText') + + tip.mapMsg(''); + tip.msgs[4] = "复制失败!" + editTip.err; + clearTimeout(tip.timer); + if (value) { + tip.mapMsg(tip.msgs[value - 1]); + tip.timer = setTimeout(function () { + if (!(value % 2)) + value = 0; + }, 5000); //5秒后自动清除success,warn不清除 + } + tip._whichShow=value + } + return tip._whichShow + } + /** * 根据鼠标点击, 得到从元素向上到body的所有id @@ -367,7 +545,8 @@ editor_ui_wrapper = function (editor) { uievent.elements.selectPoint.style.display = 'block'; uievent.elements.yes.style.display = 'inline'; uievent.elements.selectBackground.style.display = 'none'; - uievent.elements.selectFloor.style.display = hideFloor ? 'none' : 'inline'; + // uievent.elements.selectFloor.style.display = hideFloor ? 'none' : 'inline'; + uievent.elements.selectFloor.style.display = 'inline'; uievent.elements.selectPointBox.style.display = 'block'; uievent.elements.canvas.style.display = 'block'; uievent.elements.usedFlags.style.display = 'none'; @@ -468,7 +647,8 @@ editor_ui_wrapper = function (editor) { })(); uievent.elements.div.onmousewheel = function (e) { - if (uievent.mode != 'selectPoint' || uievent.values.hideFloor) return; + // if (uievent.mode != 'selectPoint' || uievent.values.hideFloor) return; + if (uievent.mode != 'selectPoint') return; var index = core.floorIds.indexOf(uievent.values.floorId); try { if (e.wheelDelta) diff --git a/_server/refactoring.md b/_server/refactoring.md index fbd0fff0..f6b6c07f 100644 --- a/_server/refactoring.md +++ b/_server/refactoring.md @@ -1,6 +1,6 @@ # 重构 -> 目前状态: 按功能分类已基本完成, 未完成file/game的重写 +> 目前状态: 按功能分类, 维持稳定状态, 在3.0中重写 总体思路 + 按功能拆分文件 diff --git a/_server/table/comment.js b/_server/table/comment.js index 5bac4a9b..c55edea4 100644 --- a/_server/table/comment.js +++ b/_server/table/comment.js @@ -19,37 +19,45 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_type": "select", "_select": { "values": [ - "keys", "items", "constants", "tools", "equips" ] }, - "_data": "只能取keys(钥匙) items(宝石、血瓶) constants(永久物品) tools(消耗道具) equips(装备)" + "_docs": "道具类别", + "_data": "只能取items(宝石、血瓶) constants(永久物品) tools(消耗道具) equips(装备)" }, "name": { "_leaf": true, "_type": "textarea", "_string": true, - "_data": "名称" + "_data": "道具名称" }, "text": { "_leaf": true, "_type": "textarea", "_string": true, + "_docs": "道具描述", "_data": "道具在道具栏中显示的描述" }, + "hideInToolbox": { + "_leaf": true, + "_type": "checkbox", + "_docs": "道具栏中隐藏", + "_data": "是否不显示在道具栏中" + }, "equip": { "_leaf": true, "_type": "textarea", - "_data": "装备属性设置,仅对cls为equips有效。\n如果此项不为null,需要是一个对象,里面可含\"type\",\"atk\",\"def\",\"mdef\",\"animate\"五项,分别对应装备部位、攻防魔防和动画。\n具体详见文档(元件说明-装备)和已有的几个装备的写法。" + "_docs": "道具的装备属性", + "_data": "装备属性设置,仅对cls为equips有效。\n如果此项不为null,需要是一个对象,里面可含\"type\",\"atk\",\"def\",\"mdef\",\"animate\"五项,分别对应装备部位、攻防护盾和动画。\n具体详见文档(元件说明-装备)和已有的几个装备的写法。" }, "hideInReplay": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", - "_data": "是否回放时绘制道具栏。\n如果此项为true,则在回放录像时使用本道具将不会绘制道具栏页面,而是直接使用。\n此项建议在会频繁连续多次使用的道具开启(如开启技能,或者《镜子》那样的镜像切换等等)" + "_docs": "回放不绘制道具栏", + "_data": "是否回放时不绘制道具栏。\n如果此项为true,则在回放录像时使用本道具将不会绘制道具栏页面,而是直接使用。\n此项建议在会频繁连续多次使用的道具开启(如开启技能,或者《镜子》那样的镜像切换等等)" } } }, @@ -58,6 +66,7 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_type": "textarea", "_string": true, "_lint": true, + "_docs": "即捡即用效果", "_data": "即捡即用类物品的效果,仅对cls为items有效。" }, "itemEffectTip": { @@ -65,12 +74,14 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_type": "textarea", "_string": true, "_lint": true, + "_docs": "即捡即用提示", "_data": "即捡即用类物品在获得时提示的文字,仅对cls为items有效。" }, "useItemEvent": { "_leaf": true, "_type": "event", "_event": "item", + "_docs": "碰触或使用事件", "_data": "碰触或使用本道具所执行的事件" }, "useItemEffect": { @@ -78,6 +89,7 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_type": "textarea", "_string": true, "_lint": true, + "_docs": "使用效果", "_data": "道具效果,仅对cls为tools或constants有效。" }, "canUseItemEffect": { @@ -85,6 +97,7 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_type": "textarea", "_string": true, "_lint": true, + "_docs": "能否使用条件", "_data": "当前能否使用该道具,仅对cls为tools或constants有效。" }, "equipCondition": { @@ -92,11 +105,12 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_type": "textarea", "_string": true, "_lint": true, + "_docs": "能否装备条件", "_data": "能装备某个装备的条件,仅对cls为equips有效。\n与canUseItemEffect不同,这里null代表可以装备。" } } }, - "items_template": { 'cls': 'items', 'name': '新物品' }, + "items_template": { 'cls': 'items', 'name': '新物品', 'canPass': true }, // --------------------------- 【怪物】相关的表格配置 --------------------------- // @@ -113,6 +127,7 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_leaf": true, "_type": "textarea", "_string": true, + "_docs": "手册映射ID", "_data": "在怪物手册中映射到的怪物ID。如果此项不为null,则在怪物手册中,将用目标ID来替换该怪物原本的ID。\n此项应被运用在同一个怪物的多朝向上。\n例如,如果想定义同一个怪物的向下和向左的行走图,则需要建立两个属性完全相同的怪物。\n但是这样会导致在怪物手册中同时存在向下和向左的两种怪物的显示。\n可以将朝向左的怪物的displayIdInBook项指定为朝向下的怪物ID,这样在怪物手册中则会归一化,只显示一个。" }, "hp": { @@ -135,7 +150,7 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_type": "textarea", "_data": "金币" }, - "experience": { + "exp": { "_leaf": true, "_type": "textarea", "_data": "经验" @@ -147,66 +162,85 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { }, "special": { "_leaf": true, - "_type": "textarea", - "_range": "thiseval==null || thiseval instanceof Array || (thiseval==~~thiseval && thiseval>=0)", - "_data": "特殊属性\n\n0:无,1:先攻,2:魔攻,3:坚固,4:2连击,\n5:3连击,6:n连击,7:破甲,8:反击,9:净化,\n10:模仿,11:吸血,12:中毒,13:衰弱,14:诅咒,\n15:领域,16:夹击,17:仇恨,18:阻击,19:自爆,\n20:无敌,21:退化,22:固伤,23:重生,24:激光,25:光环\n26:支援,27:捕捉\n多个属性例如用[1,4,11]表示先攻2连击吸血" + "_type": "checkboxSet", + "_checkboxSet":function(){ + var array=functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a.enemys.getSpecials() + var b=[],c=[]; + for (var index = 0; index < array.length; index++) { + b.push(array[index][0]) + var name = array[index][1]; + if (name instanceof Function) name = name({}); + c.push((index%2==0&&index>0?'
':'')+name+'') + } + return { + "prefix":c, + "key":b + } + }, + "_data": "特殊属性" }, "value": { "_leaf": true, "_type": "textarea", + "_docs": "特殊属性值", "_data": "特殊属性的数值\n如:领域/阻激/激光怪的伤害值;吸血怪的吸血比例;光环怪增加生命的比例" }, "zoneSquare": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", + "_docs": "九宫格领域", "_data": "领域怪是否九宫格伤害" }, "range": { "_leaf": true, "_type": "textarea", "_range": "(thiseval==~~thiseval && thiseval>0)||thiseval==null", + "_docs": "领域范围", "_data": "领域伤害的范围;不加默认为1" }, "notBomb": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", + "_docs": "是否不可炸", "_data": "该怪物不可被炸" }, "n": { "_leaf": true, "_type": "textarea", "_range": "(thiseval==~~thiseval && thiseval>0)||thiseval==null", + "_docs": "连击数", "_data": "多连击的连击数" }, "add": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", + "_docs": "吸血加自身", "_data": "吸血后是否加到自身;光环是否叠加" }, "atkValue": { "_leaf": true, "_type": "textarea", "_range": "thiseval==~~thiseval||thiseval==null", + "_docs": "退化扣攻击", "_data": "退化时勇士下降的攻击力点数;光环怪增加攻击的比例" }, "defValue": { "_leaf": true, "_type": "textarea", "_range": "thiseval==~~thiseval||thiseval==null", + "_docs": "退化扣防御", "_data": "退化时勇士下降的防御力点数;光环怪增加防御的比例" }, "damage": { "_leaf": true, "_type": "textarea", "_range": "thiseval==~~thiseval||thiseval==null", + "_docs": "固伤", "_data": "战前扣血的点数" } } }, - "enemys_template": { 'name': '新敌人', 'hp': 0, 'atk': 0, 'def': 0, 'money': 0, 'experience': 0, 'point': 0, 'special': 0 }, + "enemys_template": { 'name': '新敌人', 'hp': 0, 'atk': 0, 'def': 0, 'money': 0, 'exp': 0, 'point': 0, 'special': [] }, // --------------------------- 【图块属性】相关的表格配置 --------------------------- // @@ -244,60 +278,71 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "values": [ "null", "openDoor", - "passNet", - "changeLight", "pushBox", + "ski", "custom" ] }, + "_docs": "触发器", "_data": "该图块的默认触发器" }, - "noPass": { + "canPass": { "_leaf": true, - "_type": "select", - "_select": { - "values": [ - "null", - "true", - "false" - ] - }, - "_data": "该图块是否不可通行;true代表不可通行,false代表可通行,null代表使用系统缺省值" + "_type": "checkbox", + "_docs": "可通行性", + "_data": "该图块是否可以通行;true代表可以通行,false代表不可通行" }, "script": { "_leaf": true, "_type": "textarea", "_string": true, "_lint": true, + "_docs": "碰触脚本", "_data": "触碰到该图块时自动执行的脚本内容;此脚本会在该点的触发器执行前执行" }, "cannotOut": { "_leaf": true, - "_type": "textarea", - "_range": "thiseval==null||(thiseval instanceof Array)", + "_type": "checkboxSet", + "_checkboxSet": { + "prefix":["上: ","下: ","
左: ","右: "], + "key":["up","down","left","right"] + }, + "_docs": "不可出方向", "_data": "该图块的不可出方向\n可以在这里定义在该图块时不能前往哪个方向,可以达到悬崖之类的效果\n例如 [\"up\", \"left\"] 代表在该图块时不能往上和左走\n此值对背景层、事件层、前景层上的图块均有效" }, "cannotIn": { "_leaf": true, - "_type": "textarea", - "_range": "thiseval==null||(thiseval instanceof Array)", + "_type": "checkboxSet", + "_checkboxSet": { + "prefix":["上: ","下: ","
左: ","右: "], + "key":["up","down","left","right"] + }, + "_docs": "不可入方向", "_data": "该图块的不可入方向\n可以在这里定义不能朝哪个方向进入该图块,可以达到悬崖之类的效果\n例如 [\"down\"] 代表不能从该图块的上方点朝向下进入此图块\n此值对背景层、事件层、前景层上的图块均有效" }, "canBreak": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", + "_docs": "可破震", "_data": "该图块是否可被破墙或地震" }, "animate": { "_leaf": true, "_type": "textarea", "_range": "thiseval==~~thiseval||thiseval==null", + "_docs": "动画帧数", "_data": "该图块的全局动画帧数。\n如果此项为null,则对于除了npc48外,使用素材默认帧数;npc48默认是1帧(即静止)。" }, + "doorInfo": { + "_leaf": true, + "_type": "textarea", + "_docs": "门信息", + "_data": "该图块的门信息,是一个三元数组。\n第一项为所需要的钥匙信息,第二项为开此门时的音效,第三项为关此门时的音效。仅对animates生效。" + }, "faceIds": { "_leaf": true, "_type": "textarea", + "_docs": "行走图朝向", "_data": "行走图朝向,仅对NPC有效。可以在这里定义同一个NPC的多个朝向行走图。\n比如 {\"up\":\"N333\",\"down\":\"N334\",\"left\":\"N335\",\"right\":\"N336\"} 就将该素材的上下左右朝向分别绑定到N333,N334,N335和N336四个图块。\n在勇士撞上NPC时,或NPC在移动时,会自动选择最合适的朝向图块(如果存在定义)来进行绘制。" } } @@ -315,64 +360,71 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_leaf": true, "_type": "textarea", "_range": "false", + "_docs": "楼层ID", "_data": "文件名和floorId需要保持完全一致 \n楼层唯一标识符仅能由字母、数字、下划线组成,且不能由数字开头 \n推荐用法:第20层就用MT20,第38层就用MT38,地下6层就用MT_6(用下划线代替负号),隐藏3层用MT3h(h表示隐藏),等等 \n楼层唯一标识符,需要和名字完全一致 \n这里不能更改floorId,请通过另存为来实现" }, "title": { "_leaf": true, "_type": "textarea", + "_docs": "楼层中文名", "_data": "楼层中文名,将在切换楼层和浏览地图时显示" }, "name": { "_leaf": true, "_type": "textarea", + "_docs": "状态栏显示", "_data": "显示在状态栏中的层数" }, "width": { "_leaf": true, "_type": "textarea", "_range": "false", + "_docs": "宽度", "_data": "地图x方向大小,这里不能更改,仅能在新建地图时设置,null视为13" }, "height": { "_leaf": true, "_type": "textarea", "_range": "false", + "_docs": "高度", "_data": "地图y方向大小,这里不能更改,仅能在新建地图时设置,null视为13" }, "canFlyTo": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", + "_docs": "可飞", "_data": "该楼能否被楼传器飞到(不能的话在该楼也不允许使用楼传器)" }, "canUseQuickShop": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", + "_docs": "可快捷商店", "_data": "该层是否允许使用快捷商店" }, "cannotViewMap": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", + "_docs": "不可浏览", "_data": "该层是否不允许被浏览地图看到;如果勾上则浏览地图会跳过该层" }, "cannotMoveDirectly": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", + "_docs": "不可瞬移", "_data": "该层是否不允许瞬间移动;如果勾上则不可在此层进行瞬移" }, "firstArrive": { "_leaf": true, "_type": "event", "_event": "firstArrive", + "_docs": "首次到达事件", "_data": "第一次到该楼层触发的事件,可以双击进入事件编辑器。" }, "eachArrive": { "_leaf": true, "_type": "event", "_event": "eachArrive", + "_docs": "每次到达事件", "_data": "每次到该楼层触发的事件,可以双击进入事件编辑器;该事件会在firstArrive执行后再执行。" }, "parallelDo": { @@ -380,41 +432,45 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_type": "textarea", "_string": true, "_lint": true, - "_data": "在该层楼时执行的并行事件处理。\n可以在这里写上任意需要自动执行的脚本,比如打怪自动开门等。\n详见文档-事件-并行事件处理。" + "_docs": "并行处理脚本", + "_data": "在该层楼时执行的并行脚本处理。\n可以在这里写上任意需要自动执行的脚本,比如打怪自动开门等。\n详见文档-事件-并行事件处理。" }, "upFloor": { "_leaf": true, "_type": "textarea", "_range": "thiseval==null||((thiseval instanceof Array) && thiseval.length==2)", + "_docs": "上楼点", "_data": "该层上楼点,如[2,3]。\n如果此项不为null,则楼层转换时的stair:upFloor,以及楼传器的落点会被替换成该点而不是该层的上楼梯。" }, "downFloor": { "_leaf": true, "_type": "textarea", "_range": "thiseval==null||((thiseval instanceof Array) && thiseval.length==2)", + "_docs": "下楼点", "_data": "该层下楼点,如[2,3]。\n如果此项不为null,则楼层转换时的stair:downFloor,以及楼传器的落点会被替换成该点而不是该层的下楼梯。" }, "defaultGround": { "_leaf": true, - "_type": "select", - "_select": { - "values": Object.keys(editor.core.icons.icons.terrains) - }, - "_data": "默认地面的图块ID,此项修改后需要刷新才能看到效果。" + "_type": "textarea", + "_docs": "地面图块", + "_data": "默认地面的图块ID,此项修改后需要刷新才能看到效果。不填则默认是ground" }, "images": { "_leaf": true, "_type": "textarea", + "_docs": "楼层贴图", "_data": "背景/前景图;你可以选择若干张图片来作为背景/前景素材。详细用法请参见文档“自定义素材”中的说明。" }, "color": { "_leaf": true, "_type": "textarea", + "_docs": "色调", "_data": "该层的默认画面色调。本项可不写(代表无色调),如果写需要是一个RGBA数组如[255,0,0,0.3]" }, "weather": { "_leaf": true, "_type": "textarea", + "_docs": "天气", "_data": "该层的默认天气。本项可忽略表示晴天,如果写则第一项为\"rain\",\"snow\"或\"fog\"代表雨雪雾,第二项为1-10之间的数代表强度。\n如[\"rain\", 8]代表8级雨天。" }, "bgm": { @@ -423,18 +479,20 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_select": { "values": [null].concat(Object.keys(editor.core.material.bgms)) }, + "_docs": "背景音乐", "_data": "到达该层后默认播放的BGM。本项可忽略,或者为一个定义过的背景音乐如\"bgm.mp3\"。" }, "item_ratio": { "_leaf": true, "_type": "textarea", "_range": "(thiseval==~~thiseval && thiseval>=0)||thiseval==null", + "_docs": "宝石血瓶效果", "_data": "每一层的宝石/血瓶效果,即获得宝石和血瓶时框内\"ratio\"的值。" }, "underGround": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", + "_docs": "是否是地下层", "_data": "是否是地下层;如果该项为true则同层传送将传送至上楼梯" } } @@ -446,15 +504,16 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_leaf": true, "_type": "event", "_event": "event", + "_docs": "普通事件", "_data": "该点的可能事件列表,可以双击进入事件编辑器。" }, "autoEvent": { "_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) { @@ -462,7 +521,7 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_leaf": true, "_type": "event", "_event": "autoEvent", - "_data": "自动事件页" + "_data": "自动事件" } } }, @@ -470,30 +529,38 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_leaf": true, "_type": "event", "_event": "changeFloor", + "_docs": "楼层转换", "_data": "该点楼层转换事件;该事件不能和上面的events同时出现,否则会被覆盖" }, "afterBattle": { "_leaf": true, "_type": "event", "_event": "afterBattle", + "_docs": "战后事件", "_data": "该点战斗后可能触发的事件列表,可以双击进入事件编辑器。" }, "afterGetItem": { "_leaf": true, "_type": "event", "_event": "afterGetItem", + "_docs": "道具后事件", "_data": "该点获得道具后可能触发的事件列表,可以双击进入事件编辑器。" }, "afterOpenDoor": { "_leaf": true, "_type": "event", "_event": "afterOpenDoor", + "_docs": "开门后事件", "_data": "该点开完门后可能触发的事件列表,可以双击进入事件编辑器。" }, "cannotMove": { "_leaf": true, - "_type": "textarea", - "_range": "thiseval==null||(thiseval instanceof Array)", + "_type": "checkboxSet", + "_checkboxSet": { + "prefix":["上: ","下: ","
左: ","右: "], + "key":["up","down","left","right"] + }, + "_docs": "不可通行性", "_data": "该点不可通行的方向 \n 可以在这里定义该点不能前往哪个方向,可以达到悬崖之类的效果\n例如 [\"up\", \"left\"] 代表该点不能往上和左走" }, } diff --git a/_server/table/data.comment.js b/_server/table/data.comment.js index 74237a8f..7a1ec51e 100644 --- a/_server/table/data.comment.js +++ b/_server/table/data.comment.js @@ -14,131 +14,153 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_leaf": true, "_type": "textarea", "_range": "editor.mode.checkFloorIds(thiseval)", + "_docs": "楼层列表", "_data": "在这里按顺序放所有的楼层;其顺序直接影响到楼层传送器、浏览地图和上/下楼器的顺序" }, "images": { "_leaf": true, "_type": "textarea", - "_range": "editor.mode.checkUnique(thiseval)", + "_range": "editor.mode.checkImages(thiseval)", + "_docs": "本塔使用图片", "_data": "在此存放所有可能使用的图片(tilesets除外) \n图片可以被作为背景图(的一部分),也可以直接用自定义事件进行显示。 \n 图片名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好 \n 建议对于较大的图片,在网上使用在线的“图片压缩工具(http://compresspng.com/zh/)”来进行压缩,以节省流量 \n 依次向后添加" }, "tilesets": { "_leaf": true, "_type": "textarea", - "_range": "editor.mode.checkUnique(thiseval)", + "_range": "editor.mode.checkImages(thiseval)", + "_docs": "本塔额外素材", "_data": "在此存放额外素材的图片名, \n可以自定导入任意张素材图片,无需PS,无需注册,即可直接在游戏中使用 \n 形式如[\"1.png\", \"2.png\"] ,将需要的素材图片放在images目录下 \n 素材的宽高必须都是32的倍数,且图片上的总图块数不超过1000(即最多有1000个32*32的图块在该图片上)" }, "animates": { "_leaf": true, "_type": "textarea", "_range": "editor.mode.checkUnique(thiseval)", + "_docs": "本塔使用动画", "_data": "在此存放所有可能使用的动画,必须是animate格式,在这里不写后缀名 \n动画必须放在animates目录下;文件名不能使用中文,不能带空格或特殊字符 \n \"jianji\", \"thunder\" 根据需求自行添加" }, "bgms": { "_leaf": true, "_type": "textarea", "_range": "editor.mode.checkUnique(thiseval)", + "_docs": "本塔使用音乐", "_data": "在此存放所有的bgm,和文件名一致。 \n音频名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好" }, "sounds": { "_leaf": true, "_type": "textarea", "_range": "editor.mode.checkUnique(thiseval)", + "_docs": "本塔使用音效", "_data": "在此存放所有的SE,和文件名一致 \n音频名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好" }, "nameMap": { "_leaf": true, "_type": "textarea", + "_docs": "文件名映射", "_data": "文件名映射,目前仅对images, animates, bgms, sounds有效。\n例如定义 {\"精灵石.mp3\":\"jinglingshi.mp3\"} 就可以使用\ncore.playBgm(\"精灵石.mp3\") 或对应的事件来播放该bgm。" }, "startBackground": { "_leaf": true, "_type": "textarea", "_string": true, + "_docs": "标题背景", "_data": "标题界面的背景,建议使用jpg格式以压缩背景图空间" }, "startLogoStyle": { "_leaf": true, "_type": "textarea", "_string": true, + "_docs": "标题样式", "_data": "标题样式:可以改变颜色,也可以写\"display: none\"来隐藏标题" }, "startButtonsStyle": { "_leaf": true, "_type": "textarea", "_string": true, + "_docs": "标题按钮样式", "_data": "标题界面按钮的样式;caret-color指的是当前选中项的边框颜色" }, "levelChoose": { "_leaf": true, "_type": "textarea", "_range": "thiseval instanceof Array && thiseval.length>=1 && thiseval[0] instanceof Array && thiseval[0].length==2", + "_docs": "难度分歧", "_data": "难度选择:每个数组的第一个是其在标题界面显示的难度,第二个是在游戏内部传输的字符串,会显示在状态栏,修改此处后需要在project/functions中作相应更改。\n如果需直接开始游戏将下面的startDirectly开关打开即可。" }, "equipName": { "_leaf": true, "_type": "textarea", "_range": "(thiseval instanceof Array && thiseval.length<=6)||thiseval==null", + "_docs": "装备孔", "_data": "装备位名称,为不超过6个的数组,此项的顺序与equiptype数值关联;例如可写[\"武器\",\"防具\",\"首饰\"]等等。" }, "startBgm": { "_leaf": true, "_type": "textarea", "_string": true, + "_docs": "标题音乐", "_data": "在标题界面应该播放的bgm内容" }, "statusLeftBackground": { "_leaf": true, "_type": "textarea", "_string": true, + "_docs": "横屏状态栏", "_data": "横屏时左侧状态栏的背景样式,可以定义背景图、平铺方式等。\n具体请网上搜索\"css background\"了解写法。\n如果弄一张图片作为背景图,推荐写法:\n\"url(project/images/XXX.png) 0 0/100% 100% no-repeat\"\n图片最好进行一些压缩等操作节省流量。" }, "statusTopBackground": { "_leaf": true, "_type": "textarea", "_string": true, + "_docs": "竖屏状态栏", "_data": "竖屏时上方状态栏的背景样式,可以定义背景图、平铺方式等。\n具体请网上搜索\"css background\"了解写法。\n如果弄一张图片作为背景图,推荐写法:\n\"url(project/images/XXX.png) 0 0/100% 100% no-repeat\"\n图片最好进行一些压缩等操作节省流量。" }, "toolsBackground": { "_leaf": true, "_type": "textarea", "_string": true, - "_data": "竖屏时下方道具栏的背景样式,可以定义背景图、平铺方式等。\n具体请网上搜索\"css background\"了解写法。\n如果弄一张图片作为背景图,推荐写法:\n\"url(project/images/XXX.png) 0 0/100% 100% no-repeat\"\n图片最好进行一些压缩等操作节省流量。" + "_docs": "竖屏工具栏", + "_data": "竖屏时下方工具栏的背景样式,可以定义背景图、平铺方式等。\n具体请网上搜索\"css background\"了解写法。\n如果弄一张图片作为背景图,推荐写法:\n\"url(project/images/XXX.png) 0 0/100% 100% no-repeat\"\n图片最好进行一些压缩等操作节省流量。" }, "borderColor": { "_leaf": true, "_type": "textarea", "_string": true, + "_docs": "边框色", "_data": "边框颜色,包括游戏边界的边框和对话框边框等。" }, "statusBarColor": { "_leaf": true, "_type": "textarea", "_string": true, + "_docs": "状态栏文字色", "_data": "状态栏的文字颜色,默认是白色" }, "hardLabelColor": { "_leaf": true, "_type": "textarea", "_string": true, + "_docs": "难度标签色", "_data": "难度显示的颜色,默认是红色" }, "floorChangingBackground": { "_leaf": true, "_type": "textarea", "_string": true, + "_docs": "转场背景色", "_data": "楼层转换界面的背景样式;可以使用纯色(默认值black),也可以使用图片(参见状态栏的图片写法)" }, "floorChangingTextColor": { "_leaf": true, "_type": "textarea", "_string": true, + "_docs": "转场文字色", "_data": "楼层转换界面的文字颜色,默认是白色" }, "font": { "_leaf": true, "_type": "textarea", "_string": true, + "_docs": "全局字体", "_data": "游戏中使用的字体,默认是Verdana" } } @@ -150,6 +172,7 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_leaf": true, "_type": "textarea", "_string": true, + "_docs": "游戏名", "_data": "游戏名,将显示在标题页面以及切换楼层的界面中" }, "name": { @@ -157,12 +180,14 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_type": "textarea", "_string": true, "_range": "/^[a-zA-Z0-9_]{1,30}$/.test(thiseval)", + "_docs": "唯一英文标识符", "_data": "游戏的唯一英文标识符。由英文、数字、下划线组成,不能超过30个字符。\n此项必须修改,其将直接影响到存档的定位!" }, "version": { "_leaf": true, "_type": "textarea", "_string": true, + "_docs": "游戏版本", "_data": "当前游戏版本;版本不一致的存档不能通用。" }, "floorId": { @@ -172,6 +197,7 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "values": data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.main.floorIds }, "_range": "data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.main.floorIds.indexOf(thiseval)!==-1", + "_docs": "初始楼层", "_data": "初始楼层的ID" }, "hero": { @@ -181,33 +207,34 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_leaf": true, "_type": "textarea", "_string": true, - "_data": "勇士名;可以改成喜欢的" + "_data": "勇士名" }, "lv": { "_leaf": true, "_type": "textarea", "_range": "thiseval==~~thiseval &&thiseval>0", - "_data": "初始等级,该项必须为正整数" + "_data": "初始等级" }, "hpmax": { "_leaf": true, "_type": "textarea", - "_data": "初始生命上限,只有在enableHPMax开启时才有效" + "_data": "初始上限" }, "hp": { "_leaf": true, "_type": "textarea", - "_data": "初始生命值" + "_data": "初始生命" }, "manamax": { "_leaf": true, "_type": "textarea", + "_docs": "魔力上限", "_data": "魔力上限;此项非负才会生效(null或小于0都不会生效)" }, "mana": { "_leaf": true, "_type": "textarea", - "_data": "初始魔力值,只在enableMana开启时才有效" + "_data": "初始魔力" }, "atk": { "_leaf": true, @@ -222,14 +249,14 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "mdef": { "_leaf": true, "_type": "textarea", - "_data": "初始魔防" + "_data": "初始护盾" }, "money": { "_leaf": true, "_type": "textarea", "_data": "初始金币" }, - "experience": { + "exp": { "_leaf": true, "_type": "textarea", "_data": "初始经验" @@ -238,33 +265,30 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_leaf": true, "_type": "textarea", "_range": "thiseval instanceof Array", - "_data": "初始装上的装备,此处建议请直接留空数组" + "_data": "初始装备" }, "items": { "_type": "object", "_data": { - "keys": { - "_leaf": true, - "_type": "textarea", - "_range": "thiseval instanceof Object && !(thiseval instanceof Array)", - "_data": "初始三种钥匙个数" - }, "constants": { "_leaf": true, "_type": "textarea", "_range": "thiseval instanceof Object && !(thiseval instanceof Array)", + "_docs": "永久道具", "_data": "初始永久道具个数,例如初始送手册可以写 {\"book\": 1}" }, "tools": { "_leaf": true, "_type": "textarea", "_range": "thiseval instanceof Object && !(thiseval instanceof Array)", + "_docs": "消耗道具", "_data": "初始消耗道具个数,例如初始有两破可以写 {\"pickaxe\": 2}" }, "equips": { "_leaf": true, "_type": "textarea", "_range": "thiseval instanceof Object && !(thiseval instanceof Array)", + "_docs": "初始装备个数", "_data": "初始装备个数,例如初始送铁剑可以写 {\"sword1\": 1}" } } @@ -275,7 +299,7 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "direction": { "_leaf": true, "_type": "select", - "_data": "勇士初始方向", + "_data": "初始朝向", "_select": { "values": [ "up", @@ -288,12 +312,12 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "x": { "_leaf": true, "_type": "textarea", - "_data": "勇士初始x坐标" + "_data": "初始x坐标" }, "y": { "_leaf": true, "_type": "textarea", - "_data": "勇士初始y坐标" + "_data": "初始y坐标" } } }, @@ -301,12 +325,18 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_leaf": true, "_type": "textarea", "_range": "thiseval instanceof Object && !(thiseval instanceof Array)", - "_data": "游戏过程中的变量或flags" + "_data": "游戏变量" + }, + "followers": { + "_leaf": true, + "_type": "textarea", + "_range": "thiseval instanceof Array", + "_data": "跟随者列表" }, "steps": { "_leaf": true, "_type": "textarea", - "_data": "行走步数统计" + "_data": "行走步数" } } }, @@ -315,6 +345,7 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_type": "event", "_event": "firstArrive", "_range": "thiseval==null || thiseval instanceof Array", + "_docs": "标题事件化", "_data": "标题界面事件化,可以使用事件流的形式来绘制开始界面等。\n需要开启startUsingCanvas这个开关。\n详见文档-个性化-标题界面事件化。" }, "startText": { @@ -322,6 +353,7 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_type": "event", "_event": "firstArrive", "_range": "thiseval==null || thiseval instanceof Array", + "_docs": "开场剧情", "_data": "游戏开始前剧情,可以执行任意自定义事件。\n双击进入事件编辑器。\n如果无剧情直接留一个空数组即可。" }, "shops": { @@ -329,6 +361,7 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_type": "event", "_event": "shop", "_range": "thiseval instanceof Array", + "_docs": "全局商店", "_data": "全局商店,是一个数组,可以双击进入事件编辑器。" }, "levelUp": { @@ -336,6 +369,7 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_type": "event", "_event": "level", "_range": "thiseval==null || thiseval instanceof Array", + "_docs": "等级提升", "_data": "经验升级所需要的数值,是一个数组,可以双击进行编辑。 \n 第一项为初始等级,仅title生效 \n 每一个里面可以含有三个参数 need, title, action \n need为所需要的经验数值,可以是个表达式。请确保need依次递增 \n title为该等级的名称,也可以省略代表使用系统默认值;本项将显示在状态栏中 \n action为本次升级所执行的事件,可由若干项组成" } } @@ -346,374 +380,275 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "lavaDamage": { "_leaf": true, "_type": "textarea", - "_data": "经过血网受到的伤害" + "_data": "血网伤害" }, "poisonDamage": { "_leaf": true, "_type": "textarea", - "_data": "中毒后每步受到的伤害" + "_data": "中毒伤害" }, "weakValue": { "_leaf": true, "_type": "textarea", + "_docs": "衰弱效果", "_data": "衰弱状态下攻防减少的数值\n如果此项不小于1,则作为实际下降的数值(比如10就是攻防各下降10)\n如果在0到1之间则为下降的比例(比如0.3就是下降30%的攻防)" }, "redJewel": { "_leaf": true, "_type": "textarea", + "_docs": "红宝石效果", "_data": "红宝石加攻击的数值" }, "blueJewel": { "_leaf": true, "_type": "textarea", + "_docs": "蓝宝石效果", "_data": "蓝宝石加防御的数值" }, "greenJewel": { "_leaf": true, "_type": "textarea", - "_data": "绿宝石加魔防的数值" + "_docs": "绿宝石效果", + "_data": "绿宝石加护盾的数值" }, "redPotion": { "_leaf": true, "_type": "textarea", + "_docs": "红血瓶效果", "_data": "红血瓶加血数值" }, "bluePotion": { "_leaf": true, "_type": "textarea", + "_docs": "蓝血瓶效果", "_data": "蓝血瓶加血数值" }, "yellowPotion": { "_leaf": true, "_type": "textarea", + "_docs": "黄血瓶效果", "_data": "黄血瓶加血数值" }, "greenPotion": { "_leaf": true, "_type": "textarea", + "_docs": "绿血瓶效果", "_data": "绿血瓶加血数值" }, "breakArmor": { "_leaf": true, "_type": "textarea", + "_docs": "破甲比例", "_data": "破甲的比例(战斗前,怪物附加角色防御的x倍作为伤害)" }, "counterAttack": { "_leaf": true, "_type": "textarea", + "_docs": "反击比例", "_data": "反击的比例(战斗时,怪物每回合附加角色攻击的x倍作为伤害,无视角色防御)" }, "purify": { "_leaf": true, "_type": "textarea", - "_data": "净化的比例(战斗前,怪物附加勇士魔防的x倍作为伤害)" + "_docs": "净化比例", + "_data": "净化的比例(战斗前,怪物附加勇士护盾的x倍作为伤害)" }, "hatred": { "_leaf": true, "_type": "textarea", + "_docs": "仇恨增值", "_data": "仇恨属性中,每杀死一个怪物获得的仇恨值" }, - "moveSpeed": { - "_leaf": true, - "_type": "textarea", - "_data": "行走速度,即勇士每走一格的时间,一般100比较合适" - }, "animateSpeed": { "_leaf": true, "_type": "textarea", + "_docs": "全局动画时间", "_data": "全局动画时间,即怪物振动频率,一般300比较合适" - }, - "floorChangeTime": { - "_leaf": true, - "_type": "textarea", - "_data": "默认楼层切换时间" } } }, "flags": { "_type": "object", "_data": { - "enableFloor": { + "statusBarItems": { "_leaf": true, - "_type": "checkbox", - "_bool": "bool", - "_data": "是否在状态栏显示当前楼层" - }, - "enableName": { - "_leaf": true, - "_type": "checkbox", - "_bool": "bool", - "_data": "是否在状态栏显示勇士名字" - }, - "enableLv": { - "_leaf": true, - "_type": "checkbox", - "_bool": "bool", - "_data": "是否在状态栏显示当前等级" - }, - "enableHPMax": { - "_leaf": true, - "_type": "checkbox", - "_bool": "bool", - "_data": "是否是否启用生命上限" - }, - "enableMana": { - "_leaf": true, - "_type": "checkbox", - "_bool": "bool", - "_data": "是否开启魔力值" - }, - "enableMDef": { - "_leaf": true, - "_type": "checkbox", - "_bool": "bool", - "_data": "是否在状态栏及战斗界面显示魔防(护盾)" - }, - "enableMoney": { - "_leaf": true, - "_type": "checkbox", - "_bool": "bool", - "_data": "是否在状态栏、怪物手册及战斗界面显示金币" - }, - "enableExperience": { - "_leaf": true, - "_type": "checkbox", - "_bool": "bool", - "_data": "是否在状态栏、怪物手册及战斗界面显示经验" - }, - "enableLevelUp": { - "_leaf": true, - "_type": "checkbox", - "_bool": "bool", - "_data": "是否允许等级提升(进阶);如果上面enableExperience为false,则此项恒视为false" - }, - "levelUpLeftMode": { - "_leaf": true, - "_type": "checkbox", - "_bool": "bool", - "_data": "进阶使用扣除模式,即在状态栏显示距离下个等级所需要的经验值;只有enableExperience和enableLevelUp均开启时才有效。" - }, - "enableKeys": { - "_leaf": true, - "_type": "checkbox", - "_bool": "bool", - "_data": "是否在状态栏显示三色钥匙数量" - }, - "enablePZF": { - "_leaf": true, - "_type": "checkbox", - "_bool": "bool", - "_data": "是否在状态栏显示破炸飞数量" - }, - "enableDebuff": { - "_leaf": true, - "_type": "checkbox", - "_bool": "bool", - "_data": "是否在状态栏显示毒衰咒" - }, - "enableSkill": { - "_leaf": true, - "_type": "checkbox", - "_bool": "bool", - "_data": "是否启用技能栏" + "_type": "checkboxSet", + "_checkboxSet": { + "prefix": [ + "楼层", + "名字", + "
等级", + "血限", + "
生命", + "魔力", + "
攻击", + "防御", + "
护盾", + "金币", + "
经验", + "升级", + "
升级扣除模式", + "
钥匙", + "绿钥", + "
破炸", + "负面", + "
技能" + ], + "key": [ + "enableFloor", + "enableName", + "enableLv", + "enableHPMax", + "enableHP", + "enableMana", + "enableAtk", + "enableDef", + "enableMDef", + "enableMoney", + "enableExp", + "enableLevelUp", + "levelUpLeftMode", + "enableKeys", + "enableGreenKey", + "enablePZF", + "enableDebuff", + "enableSkill" + ] + }, + "_data": "状态栏显示" }, "flyNearStair": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", + "_docs": "楼传楼梯边", "_data": "传送器是否需要在楼梯边使用;如果flyRecordPosition开启,则此项对箭头也有效。" }, "flyRecordPosition": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", + "_docs": "楼传平面模式", "_data": "传送器平面塔模式;此模式下楼层传送器将飞到上次离开该楼层的位置。" }, - "pickaxeFourDirections": { - "_leaf": true, - "_type": "checkbox", - "_bool": "bool", - "_data": "使用破墙镐是否四个方向都破坏;如果false则只破坏面前的墙壁" - }, - "bombFourDirections": { - "_leaf": true, - "_type": "checkbox", - "_bool": "bool", - "_data": "使用炸弹是否四个方向都会炸;如果false则只炸面前的怪物(即和圣锤等价)" - }, - "snowFourDirections": { - "_leaf": true, - "_type": "checkbox", - "_bool": "bool", - "_data": "使用冰冻徽章是否四个方向都会消除熔岩;如果false则只消除面前的熔岩" - }, - "bigKeyIsBox": { - "_leaf": true, - "_type": "checkbox", - "_bool": "bool", - "_data": "如果此项为true,则视为钥匙盒,红黄蓝钥匙+1;若为false,则视为大黄门钥匙" - }, "steelDoorWithoutKey": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", + "_docs": "铁门不消耗", "_data": "铁门是否不需要钥匙开启。如果此项为true,则无需钥匙也可以开铁门。" }, "itemFirstText": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", + "_docs": "首次道具提示", "_data": "首次获得道具是否提示" }, - "equipment": { - "_leaf": true, - "_type": "checkbox", - "_bool": "bool", - "_data": "剑和盾是否作为装备。如果此项为true,则作为装备,需要在装备栏使用,否则将直接加属性。" - }, "equipboxButton": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", + "_docs": "状态栏装备", "_data": "状态栏的装备按钮。若此项为true则将状态栏中的楼层转换器按钮换为装备栏按钮" }, - "iconInEquipbox": { - "_leaf": true, - "_type": "checkbox", - "_bool": "bool", - "_data": "在装备栏中的属性变化,是否绘制图标;如果此项开启,则会绘制图标而不是文字" - }, "enableAddPoint": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", + "_docs": "加点", "_data": "是否支持加点" }, "enableNegativeDamage": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", + "_docs": "负伤", "_data": "是否支持负伤害(回血)" }, - "hatredDecrease": { - "_leaf": true, - "_type": "checkbox", - "_bool": "bool", - "_data": "是否在和仇恨怪战斗后减一半的仇恨值,此项为false则和仇恨怪不会扣减仇恨值。" - }, - "betweenAttackCeil": { - "_leaf": true, - "_type": "checkbox", - "_bool": "bool", - "_data": "夹击上整还是下整。如果此项为true则夹击伤害值向上取整,为false则为向下取整" - }, "betweenAttackMax": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", + "_docs": "夹击不超伤害", "_data": "夹击伤害是否不超过怪物伤害值。" }, "useLoop": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", + "_docs": "二分临界", "_data": "是否循环计算临界;如果此项为true则使用循环法(而不是回合数计算法)来算临界\n从V2.5.3开始,对于大数据的循环法将改为使用二分法进行计算" }, "startUsingCanvas": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", + "_docs": "标题事件化", "_data": "是否开始菜单canvas化;如果此项为true,则将使用canvas来绘制开始菜单" }, "startDirectly": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", + "_docs": "不选择难度", "_data": "点击“开始游戏”后是否立刻开始游戏而不显示难度选择界面" }, "statusCanvas": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", + "_docs": "自绘状态栏", "_data": "是否状态栏canvas化,即手动自定义绘制状态栏。\n如果此项开启,则可在脚本编辑的drawStatusBar中自定义绘制菜单栏。" }, "statusCanvasRowsOnMobile": { "_leaf": true, "_type": "textarea", "_range": "thiseval==null || (thiseval>0 && thiseval<=4)", + "_docs": "竖屏自绘行数", "_data": "竖屏模式下,顶端状态栏canvas化后的行数。\n此项将决定竖屏的状态栏高度,如果设置则不小于1且不大于4。\n仅在statusCanvas开启时才有效" }, "displayEnemyDamage": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", + "_docs": "怪物显伤", "_data": "是否地图怪物显伤;用户可以手动在菜单栏中开关" }, "displayCritical": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", + "_docs": "临界显伤", "_data": "是否地图显示临界;用户可以手动在菜单栏中开关" }, "displayExtraDamage": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", + "_docs": "高级显伤", "_data": "是否地图高级显伤(领域、夹击等);用户可以手动在菜单栏中开关" }, "enableGentleClick": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", + "_docs": "允许轻按", "_data": "是否允许轻触(获得面前物品)" }, - "potionWhileRouting": { - "_leaf": true, - "_type": "checkbox", - "_bool": "bool", - "_data": "寻路算法是否经过血瓶;如果该项为false,则寻路算法会自动尽量绕过血瓶" - }, "ignoreChangeFloor": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", + "_docs": "允许穿透楼梯", "_data": "经过楼梯、传送门时是否能“穿透”。\n穿透的意思是,自动寻路得到的的路径中间经过了楼梯,行走时是否触发楼层转换事件" }, "canGoDeadZone": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", + "_docs": "允许将死领域", "_data": "是否允许走到将死的领域上。如果此项为true,则可以走到将死的领域上" }, "enableMoveDirectly": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", + "_docs": "允许瞬移", "_data": "是否允许瞬间移动" }, - "enableDisabledShop": { - "_leaf": true, - "_type": "checkbox", - "_bool": "bool", - "_data": "是否允许查看未开启状态的快捷商店内容;如果此项为真,则对于未开启状态的商店允许查看其内容(但不能购买)" - }, "disableShopOnDamage": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", + "_docs": "伤害禁用商店", "_data": "是否在经过领域/夹击/路障等伤害后禁用快捷商店。" }, "blurFg": { "_leaf": true, "_type": "checkbox", - "_bool": "bool", + "_docs": "虚化前景层", "_data": "是否虚化前景层;如果此项开启,则在游戏中事件层有东西(如宝石等)时虚化前景层。" - }, - "checkConsole": { - "_leaf": true, - "_type": "checkbox", - "_bool": "bool", - "_data": "是否检查控制台的开启情况。" } } } diff --git a/_server/table/events.comment.js b/_server/table/events.comment.js index 4432901f..65f81cea 100644 --- a/_server/table/events.comment.js +++ b/_server/table/events.comment.js @@ -16,14 +16,14 @@ var events_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_type": "event", "_range": "thiseval instanceof Array", "_event": "commonEvent", - "_data": "打败怪物后加点" + "_data": "加点事件" }, "毒衰咒处理": { "_leaf": true, "_type": "event", "_range": "thiseval instanceof Array", "_event": "commonEvent", - "_data": "毒衰咒效果处理" + "_data": "毒衰咒处理" }, "滑冰事件": { "_leaf": true, @@ -38,7 +38,7 @@ var events_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_leaf": true, "_type": "event", "_event": "commonEvent", - "_data": "自定义公共事件,可以双击进入事件编辑器" + "_data": "公共事件" } } } diff --git a/_server/table/functions.comment.js b/_server/table/functions.comment.js index 81e18e7c..b0ab8a39 100644 --- a/_server/table/functions.comment.js +++ b/_server/table/functions.comment.js @@ -14,25 +14,19 @@ var functions_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_leaf": true, "_type": "textarea", "_lint": true, - "_data": "重置整个游戏" - }, - "setInitData": { - "_leaf": true, - "_type": "textarea", - "_lint": true, - "_data": "设置初始属性" + "_data": "重置游戏" }, "win": { "_leaf": true, "_type": "textarea", "_lint": true, - "_data": "游戏获胜事件" + "_data": "游戏获胜" }, "lose": { "_leaf": true, "_type": "textarea", "_lint": true, - "_data": "游戏失败事件" + "_data": "游戏失败" }, "changingFloor": { "_leaf": true, @@ -56,55 +50,31 @@ var functions_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_leaf": true, "_type": "textarea", "_lint": true, - "_data": "战前事件" + "_data": "战前判定" }, "afterBattle": { "_leaf": true, "_type": "textarea", "_lint": true, - "_data": "战后事件" + "_data": "战后脚本" }, "afterOpenDoor": { "_leaf": true, "_type": "textarea", "_lint": true, - "_data": "开门后事件" + "_data": "开门后脚本" }, "afterGetItem": { "_leaf": true, "_type": "textarea", "_lint": true, - "_data": "获得道具后事件" - }, - "afterChangeLight": { - "_leaf": true, - "_type": "textarea", - "_lint": true, - "_data": "改变亮灯事件" + "_data": "道具后脚本" }, "afterPushBox": { "_leaf": true, "_type": "textarea", "_lint": true, - "_data": "推箱子事件" - }, - "afterUseBomb": { - "_leaf": true, - "_type": "textarea", - "_lint": true, - "_data": "炸弹事件" - }, - "afterPassNet": { - "_leaf": true, - "_type": "textarea", - "_lint": true, - "_data": "经过特殊地形后的事件" - }, - "canUseQuickShop": { - "_leaf": true, - "_type": "textarea", - "_lint": true, - "_data": "能否用快捷商店" + "_data": "推箱子后" } } }, @@ -115,19 +85,19 @@ var functions_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_leaf": true, "_type": "textarea", "_lint": true, - "_data": "怪物特殊属性定义" + "_data": "怪物特殊属性" }, "getEnemyInfo": { "_leaf": true, "_type": "textarea", "_lint": true, - "_data": "获得怪物真实属性" + "_data": "怪物真实属性" }, "getDamageInfo": { "_leaf": true, "_type": "textarea", "_lint": true, - "_data": "获得战斗伤害信息" + "_data": "战斗伤害信息" } } }, @@ -144,6 +114,7 @@ var functions_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_leaf": true, "_type": "textarea", "_lint": true, + "_docs": "点击状态栏", "_data": "状态栏点击事件,仅在开启自绘状态栏时生效" } } @@ -179,19 +150,19 @@ var functions_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_leaf": true, "_type": "textarea", "_lint": true, - "_data": "每一步后的操作" + "_data": "每步后操作" }, "moveDirectly": { "_leaf": true, "_type": "textarea", "_lint": true, - "_data": "瞬间移动处理" + "_data": "瞬间移动" }, "parallelDo": { "_leaf": true, "_type": "textarea", "_lint": true, - "_data": "并行事件处理" + "_data": "并行脚本" } } }, @@ -208,13 +179,13 @@ var functions_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_leaf": true, "_type": "textarea", "_lint": true, - "_data": "地图数据统计" + "_data": "数据统计" }, "drawAbout": { "_leaf": true, "_type": "textarea", "_lint": true, - "_data": "绘制关于界面" + "_data": "关于界面" } } } diff --git a/_server/table/maps.comment.js b/_server/table/maps.comment.js deleted file mode 100644 index 187119a9..00000000 --- a/_server/table/maps.comment.js +++ /dev/null @@ -1,197 +0,0 @@ -var maps_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = -{ - ////////////////////////// 地形部分 ////////////////////////// - - // 0-20 地形 - '1':' 黄墙', - '2':' 白墙', - '3':' 蓝墙', - '4':' 星空', - '5':' 岩浆', - '6':' 冰面', - '7':' 蓝色商店左', - '8':' 蓝色商店右', - '9':' 粉色商店左', - '10':' 粉色商店左', - '11':' 血网', - '12':' 毒网', - '13':' 衰网', - '14':' 咒网', - '15':' 水', - // 在这里添加更多地形 - // 如果空位不足,可以从180以后开始继续放,只要不和现有的数字冲突即可 - - // Autotile - '20':' autotile', - // 更多的autotile从151到160等,只要不和现有的数字冲突即可 - '151':'', - '152':'', - '153':'', - - ////////////////////////// 物品部分 ////////////////////////// - - // 21-80 物品 - '21':' 黄钥匙', - '22':' 蓝钥匙', - '23':' 红钥匙', - '24':' 绿钥匙', - '25':' 铁门钥匙', - '26':' 大黄门钥匙(钥匙盒)', - '27':' 红宝石', - '28':' 蓝宝石', - '29':' 绿宝石', - '30':' 黄宝石', - '31':' 红血瓶', - '32':' 蓝血瓶', - '33':' 绿血瓶', - '34':' 黄血瓶', - '35':' 铁剑', - '36':' 铁盾', - '37':' 银剑', - '38':' 银盾', - '39':' 骑士剑', - '40':' 骑士盾', - '41':' 圣剑', - '42':' 圣盾', - '43':' 神圣剑', - '44':' 神圣盾', - '45':' 怪物手册', - '46':' 楼层传送器', - '47':' 破墙镐', - '48':' 破冰镐', - '49':' 炸弹', - '50':' 中心对称', - '51':' 上楼器', - '52':' 下楼器', - '53':' 幸运金币', - '54':' 冰冻徽章', - '55':' 十字架', - '56':' 圣水', - '57':' 地震卷轴', - '58':' 解毒药水', - '59':' 解衰药水', - '60':' 解咒药水', - '61':' 万能药水', - '62':' 屠龙匕首', - '63':' 金钱袋', - '64':' 绿鞋', - '65':' 圣锤', - - - ////////////////////////// 门、楼梯、传送点部分 ////////////////////////// - - // 81-100 门 - '81':' 黄门', - '82':' 蓝门', - '83':' 红门', - '84':' 绿门', - '85':' 机关门左', - '86':' 铁门', - '87':' 上楼梯', - '88':' 下楼梯', - '89':' 传送门', - '90':' 星空传送门', - '91':' 上箭头', - '92':' 左箭头', - '93':' 下箭头', - '94':' 右箭头', - - - ////////////////////////// NPC部分 ////////////////////////// - - // 121-150 NPC - '121':'', - '122':'', - '123':'', - '124':'', - '125':'', - '126':'', - '127':'', - '128':'', - '129':'', - '130':'', - '131':'', - '132':'', - - ////////////////////////// 其他部分 ////////////////////////// - - // 161-200 其他(单向箭头、灯、箱子等等) - '161':' 单向上箭头', - '162':' 单向下箭头', - '163':' 单向左箭头', - '164':' 单向右箭头', - '165':' 灯', - '166':' 暗灯', - '167':' 滑冰', - '168':' 花', - '169':' 箱子', - '170':' 完成的箱子', - - - ////////////////////////// 怪物部分 ////////////////////////// - - // 201-300 怪物 - '201':'', - '202':'', - '203':'', - '204':'', - '205':'', - '206':'', - '207':'', - '208':'', - '209':'', - '210':'', - '211':'', - '212':'', - '213':'', - '214':'', - '215':'', - '216':'', - '217':'', - '218':'', - '219':'', - '220':'', - '221':'', - '222':'', - '223':'', - '224':'', - '225':'', - '226':'', - '227':'', - '228':'', - '229':'', - '230':'', - '231':'', - '232':'', - '233':'', - '234':'', - '235':'', - '236':'', - '237':'', - '238':'', - '239':'', - '240':'', - '241':'', - '242':'', - '243':'', - '244':'', - '245':'', - '246':'', - '247':'', - '248':'', - '249':'', - '250':'', - '251':'', - '252':'', - '253':'', - '254':'', - '255':'', - '256':'', - '257':'', - '258':'', - '259':'', - '260':'', - - ////////////////////////// 待定... ////////////////////////// - // 目前ID暂时不要超过400 -} \ No newline at end of file diff --git a/_server/table/plugins.comment.js b/_server/table/plugins.comment.js index 3d436a06..f012cdc1 100644 --- a/_server/table/plugins.comment.js +++ b/_server/table/plugins.comment.js @@ -14,23 +14,29 @@ var plugins_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_range": "typeof(thiseval)=='string'", "_data": "自定义插件" }, + "shop": { + "_leaf": true, + "_type": "textarea", + "_range": "typeof(thiseval)=='string'", + "_data": "全局商店" + }, "drawLight": { "_leaf": true, "_type": "textarea", "_range": "typeof(thiseval)=='string' || thiseval==null", - "_data": "绘制灯光效果" + "_data": "灯光效果" }, - "drawItemShop": { + "itemShop": { "_leaf": true, "_type": "textarea", "_range": "typeof(thiseval)=='string' || thiseval==null", - "_data": "道具商店插件" + "_data": "道具商店" }, "smoothCamera": { "_leaf": true, "_type": "textarea", "_range": "typeof(thiseval)=='string' || thiseval==null", - "_data": "平滑移动镜头效果" + "_data": "平滑移动镜头" }, } if (obj[key]) return obj[key]; diff --git a/editor-mobile.html b/editor-mobile.html index 45fe1dce..784302b5 100644 --- a/editor-mobile.html +++ b/editor-mobile.html @@ -315,7 +315,7 @@ -
- -

+
+ +

@@ -487,6 +487,7 @@ +
@@ -588,7 +589,6 @@ - @@ -596,7 +596,6 @@ - diff --git a/editor.html b/editor.html index 0e26d46f..d82f8236 100644 --- a/editor.html +++ b/editor.html @@ -359,7 +359,7 @@
-

最近使用的图块列表:

+

最近使用的图块列表(Ctrl+滚轮放缩)

@@ -453,9 +453,9 @@

-
- -

+
+ +

@@ -469,6 +469,7 @@ +
@@ -572,7 +573,6 @@ - @@ -580,7 +580,6 @@ - diff --git a/extensions/dynamicMapEditor.js b/extensions/dynamicMapEditor.js index a06e7f70..83690a51 100644 --- a/extensions/dynamicMapEditor.js +++ b/extensions/dynamicMapEditor.js @@ -359,7 +359,7 @@ dynamicMapEditor.prototype.refreshToolBox = function() { core.formatBigNumber(core.getRealStatus("mdef"), true); core.fillText(this.canvas, text1, this.offsetX + 60, 380, '#FF7F00', 120); var text2 = core.formatBigNumber(core.getRealStatus('money', true)) + "/" + - core.formatBigNumber(core.getRealStatus('experience'), true) + "/" + + core.formatBigNumber(core.getRealStatus('exp'), true) + "/" + core.itemCount('yellowKey') + '/' + core.itemCount('blueKey') + '/' + core.itemCount('redKey'); core.fillText(this.canvas, text2, this.offsetX + 60, 395, '#FF7F00', 120); @@ -396,7 +396,7 @@ dynamicMapEditor.prototype.showHelp = function (fromButton) { text += " - [ 键将开关此模式;\n - ] 键将会把改动保存到文件;\n - \\ 键将撤销上步操作。\n"; text += " - Alt+0~9 保存当前图块 \n - 0~9 读取当前图块\n"; text += "最下面三行数据分别是:\n" - text += "血攻防魔防;金经黄蓝红;破炸飞和debuff。"; + text += "血攻防护盾;金经黄蓝红;破炸飞和debuff。"; if (!fromButton) text += "\n\n点取消将不再提示本页面。"; core.myconfirm(text, null, function () { if (!fromButton) core.setLocalStorage("_dynamicMapEditor_help", true); diff --git a/index.html b/index.html index e68366cd..a8128fc7 100644 --- a/index.html +++ b/index.html @@ -111,9 +111,9 @@

-
- -

+
+ +

@@ -127,6 +127,7 @@ +
diff --git a/libs/actions.js b/libs/actions.js index 0eb7ba2c..0a9ed824 100644 --- a/libs/actions.js +++ b/libs/actions.js @@ -1,3 +1,5 @@ +/// + /* actions.js:用户交互的事件的处理 键盘、鼠标、触摸屏事件相关 @@ -36,17 +38,14 @@ actions.prototype._init = function () { this.registerAction('keyUp', '_sys_keyUp', this._sys_keyUp, 0); // --- ondown注册 this.registerAction('ondown', '_sys_checkReplay', this._sys_checkReplay, 100); - this.registerAction('ondown', '_sys_ondown_paint', this._sys_ondown_paint, 60); this.registerAction('ondown', '_sys_ondown_lockControl', this._sys_ondown_lockControl, 30); this.registerAction('ondown', '_sys_ondown', this._sys_ondown, 0); // --- onmove注册 this.registerAction('onmove', '_sys_checkReplay', this._sys_checkReplay, 100); - this.registerAction('onmove', '_sys_onmove_paint', this._sys_onmove_paint, 50); this.registerAction('onmove', '_sys_onmove_choices', this._sys_onmove_choices, 30); this.registerAction('onmove', '_sys_onmove', this._sys_onmove, 0); // --- onup注册 this.registerAction('onup', '_sys_checkReplay', this._sys_checkReplay, 100); - this.registerAction('onup', '_sys_onup_paint', this._sys_onup_paint, 50); this.registerAction('onup', '_sys_onup', this._sys_onup, 0); // --- onclick注册 this.registerAction('onclick', '_sys_checkReplay', this._sys_checkReplay, 100); @@ -261,9 +260,6 @@ actions.prototype._sys_keyDown_lockControl = function (keyCode) { case 'replayRemain': this._keyDownSL(keyCode); break; - case 'shop': - this._keyDownShop(keyCode); - break; case 'selectShop': case 'switchs': case 'settings': @@ -347,9 +343,6 @@ actions.prototype._sys_keyUp_lockControl = function (keyCode, altKey) { case 'viewMaps': this._keyUpViewMaps(keyCode); break; - case 'shop': - this._keyUpShop(keyCode); - break; case 'selectShop': this._keyUpQuickShop(keyCode); break; @@ -398,9 +391,6 @@ actions.prototype._sys_keyUp_lockControl = function (keyCode, altKey) { case 'centerFly': this._keyUpCenterFly(keyCode); break; - case 'paint': - this._keyUpPaint(keyCode); - break; } return true; } @@ -423,19 +413,12 @@ actions.prototype.ondown = function (loc) { this.doRegisteredAction('ondown', x, y, px, py); } -actions.prototype._sys_ondown_paint = function (x, y, px, py) { - // 画板 - if (core.status.played && (core.status.event || {}).id == 'paint') { - this._ondownPaint(px, py); - return true; - } -} - actions.prototype._sys_ondown_lockControl = function (x, y, px, py) { if (core.status.played && !core.status.lockControl) return false; // --- wait事件也要提供px和py if (core.status.event.id == 'action' && core.status.event.data.type == 'wait') { + clearTimeout(core.status.event.interval); core.setFlag('type', 1); core.setFlag('x', x); core.setFlag('y', y); @@ -481,21 +464,12 @@ actions.prototype.onmove = function (loc) { this.doRegisteredAction('onmove', x, y, px, py); } -actions.prototype._sys_onmove_paint = function (x, y, px, py) { - // 画板 - if (core.status.played && (core.status.event || {}).id == 'paint') { - core.actions._onmovePaint(px, py); - return true; - } -} - actions.prototype._sys_onmove_choices = function (x, y) { if (!core.status.lockControl) return false; switch (core.status.event.id) { case 'action': if (core.status.event.data.type != 'choices') break; - case 'shop': case 'selectShop': case 'switchs': case 'settings': @@ -507,6 +481,9 @@ actions.prototype._sys_onmove_choices = function (x, y) { case 'gameInfo': this._onMoveChoices(x, y); return true; + case 'confirmBox': + this._onMoveConfirmBox(x, y); + return true; default: break; } @@ -543,14 +520,6 @@ actions.prototype.onup = function (loc) { this.doRegisteredAction('onup', x, y, px, py); } -actions.prototype._sys_onup_paint = function () { - // 画板 - if (core.status.played && (core.status.event || {}).id == 'paint') { - this._onupPaint(); - return true; - } -} - actions.prototype._sys_onup = function () { clearTimeout(core.timeout.onDownTimeout); core.timeout.onDownTimeout = null; @@ -641,9 +610,6 @@ actions.prototype._sys_onclick_lockControl = function (x, y) { case 'settings': this._clickSettings(x, y); break; - case 'shop': - this._clickShop(x, y); - break; case 'selectShop': this._clickQuickShop(x, y); break; @@ -752,6 +718,7 @@ actions.prototype._sys_onmousewheel = function (direct) { // wait事件 if (core.status.lockControl && core.status.event.id == 'action' && core.status.event.data.type == 'wait') { + clearTimeout(core.status.event.interval); core.setFlag('type', 0); var keycode = direct == 1 ? 33 : 34; core.setFlag('keycode', keycode); @@ -818,10 +785,6 @@ actions.prototype._sys_longClick_lockControl = function (x, y) { return true; } } - // 长按商店连续购买 - if (core.status.event.id == 'shop' && x >= this.CHOICES_LEFT && x <= this.CHOICES_RIGHT) { - return this._clickShop(x, y); - } // 长按可以跳过等待事件 if (core.status.event.id == 'action' && core.status.event.data.type == 'sleep' && !core.status.event.data.current.noSkip) { @@ -867,12 +830,6 @@ actions.prototype._selectChoices = function (length, keycode, callback) { if (keycode == 13 || keycode == 32 || keycode == 67) { callback.apply(this, [this.HSIZE, topIndex + core.status.event.selection]); } - //左右方向键调整 音量 行走速度 - if(core.status.event.id == "switchs" && (core.status.event.selection == 2 || core.status.event.selection == 3)) - { - if (keycode == 37) callback.apply(this, [this.HSIZE - 2, topIndex + core.status.event.selection]); - if (keycode == 39) callback.apply(this, [this.HSIZE + 2, topIndex + core.status.event.selection]); - } if (keycode >= 49 && keycode <= 57) { var index = keycode - 49; @@ -918,7 +875,7 @@ actions.prototype._clickCenterFly = function (x, y) { core.useItem('centerFly'); } else { - core.drawTip('当前不能使用中心对称飞行器'); + core.drawTip('当前不能使用' + core.material.items['centerFly'].name); } } } @@ -930,7 +887,7 @@ actions.prototype._keyUpCenterFly = function (keycode) { core.useItem('centerFly'); } else { - core.drawTip('当前不能使用中心对称飞行器'); + core.drawTip('当前不能使用' + core.material.items['centerFly'].name); } } } @@ -971,6 +928,22 @@ actions.prototype._keyUpConfirmBox = function (keycode) { } } +////// 鼠标在确认框上移动时 ////// +actions.prototype._onMoveConfirmBox = function (x, y) { + if (y == this.HSIZE + 1) { + if (x == this.HSIZE - 2 || x == this.HSIZE - 1) { + core.status.event.selection = 0; + core.ui.drawConfirmBox(core.status.event.ui, core.status.event.data.yes, core.status.event.data.no); + return; + } + if (x == this.HSIZE + 2 || x == this.HSIZE + 1) { + core.status.event.selection = 1; + core.ui.drawConfirmBox(core.status.event.ui, core.status.event.data.yes, core.status.event.data.no); + return; + } + } +} + ////// 自定义事件时的点击操作 ////// actions.prototype._clickAction = function (x, y) { if (core.status.event.data.type == 'text') { @@ -993,6 +966,7 @@ actions.prototype._clickAction = function (x, y) { if (x >= this.CHOICES_LEFT && x <= this.CHOICES_RIGHT) { var topIndex = this.HSIZE - parseInt((choices.length - 1) / 2) + (core.status.event.ui.offset || 0); if (y >= topIndex && y < topIndex + choices.length) { + clearTimeout(core.status.event.interval); // 选择 core.status.route.push("choices:" + (y - topIndex)); core.insertAction(choices[y - topIndex].action); @@ -1004,11 +978,13 @@ actions.prototype._clickAction = function (x, y) { if (core.status.event.data.type == 'confirm') { if ((x == this.HSIZE-2 || x == this.HSIZE-1) && y == this.HSIZE+1) { + clearTimeout(core.status.event.interval); core.status.route.push("choices:0"); core.insertAction(core.status.event.ui.yes); core.doAction(); } else if ((x == this.HSIZE+2 || x == this.HSIZE+1) && y == this.HSIZE+1) { + clearTimeout(core.status.event.interval); core.status.route.push("choices:1"); core.insertAction(core.status.event.ui.no); core.doAction(); @@ -1041,6 +1017,7 @@ actions.prototype._keyUpAction = function (keycode) { return; } if (core.status.event.data.type == 'wait') { + clearTimeout(core.status.event.interval); core.setFlag('type', 0); core.setFlag('keycode', keycode); core.status.route.push("input:" + keycode); @@ -1214,11 +1191,6 @@ actions.prototype._clickViewMaps = function (x, y) { core.ui.drawMaps(index, cx, cy); return; } - if (x <= per - 2 && y >= this.SIZE + 1 - per) { - core.status.event.data.paint = !core.status.event.data.paint; - core.ui.drawMaps(index, cx, cy); - return; - } if (x >= this.SIZE + 1 - per && y <= per - 2) { core.status.event.data.all = !core.status.event.data.all; core.ui.drawMaps(index, cx, cy); @@ -1302,11 +1274,6 @@ actions.prototype._keyUpViewMaps = function (keycode) { core.ui.drawMaps(core.status.event.data); return; } - if (keycode == 77) { - core.status.event.data.paint = !core.status.event.data.paint; - core.ui.drawMaps(core.status.event.data); - return; - } if (keycode == 88 || (core.isReplaying() && keycode == 67)) { if (core.isReplaying()) { core.bookReplay(); @@ -1318,66 +1285,28 @@ actions.prototype._keyUpViewMaps = function (keycode) { return; } -////// 商店界面时的点击操作 ////// -actions.prototype._clickShop = function (x, y) { - var shop = core.status.event.data.shop; - var choices = shop.choices; - if (x >= this.CHOICES_LEFT && x <= this.CHOICES_RIGHT) { - var topIndex = this.HSIZE - parseInt(choices.length / 2) + (core.status.event.ui.offset || 0); - if (y >= topIndex && y < topIndex + choices.length) { - return core.events._useShop(shop, y - topIndex); - } - // 离开 - else if (y == topIndex + choices.length) { - core.events._exitShop(); - } - else return false; - } - return true; -} - -actions.prototype._keyDownShop = function (keycode) { - // 商店界面长按空格连续购买 - if (keycode == 32 && core.status.event.selection != core.status.event.data.shop.choices.length) { - this._selectChoices(core.status.event.data.shop.choices.length + 1, keycode, this._clickShop); - return; - } - this._keyDownChoices(keycode); -} - -////// 商店界面时,放开某个键的操作 ////// -actions.prototype._keyUpShop = function (keycode) { - if (keycode == 27 || keycode == 88) { - core.events._exitShop(); - return; - } - if (keycode != 32 || core.status.event.selection == core.status.event.data.shop.choices.length) { - this._selectChoices(core.status.event.data.shop.choices.length + 1, keycode, this._clickShop); - return; - } - return; -} - ////// 快捷商店界面时的点击操作 ////// actions.prototype._clickQuickShop = function (x, y) { - var keys = Object.keys(core.status.shops).filter(function (shopId) { - return core.status.shops[shopId].visited || !core.status.shops[shopId].mustEnable - }); + var shopIds = core.listShopIds(); if (x >= this.CHOICES_LEFT && x <= this.CHOICES_RIGHT) { - var topIndex = this.HSIZE - parseInt(keys.length / 2) + (core.status.event.ui.offset || 0); - if (y >= topIndex && y < topIndex + keys.length) { - var reason = core.events.canUseQuickShop(keys[y - topIndex]); - if (!core.flags.enableDisabledShop && reason) { - core.drawText(reason); + var topIndex = this.HSIZE - parseInt(shopIds.length / 2) + (core.status.event.ui.offset || 0); + if (y >= topIndex && y < topIndex + shopIds.length) { + var shopId = shopIds[y - topIndex]; + if (!core.canOpenShop(shopId)) { + core.drawTip('当前项尚未开启'); return; } - core.events.openShop(keys[y - topIndex], true); - if (core.status.event.id == 'shop') - core.status.event.data.fromList = true; + var message = core.canUseQuickShop(shopId); + if (message == null) { + // core.ui.closePanel(); + core.openShop(shopIds[y - topIndex], false); + } else { + core.drawTip(message); + } } // 离开 - else if (y == topIndex + keys.length) + else if (y == topIndex + shopIds.length) core.ui.closePanel(); return; } @@ -1390,15 +1319,17 @@ actions.prototype._keyUpQuickShop = function (keycode) { core.ui.closePanel(); return; } - 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); + this._selectChoices(core.listShopIds().length + 1, keycode, this._clickQuickShop); return; } ////// 工具栏界面时的点击操作 ////// actions.prototype._clickToolbox = function (x, y) { + var tools = Object.keys(core.status.hero.items.tools) + .filter(function (id) { return !core.material.items[id].hideInToolbox; }).sort(); + var constants = Object.keys(core.status.hero.items.constants) + .filter(function (id) { return !core.material.items[id].hideInToolbox; }).sort(); + // 装备栏 if (x >= this.LAST - 2 && y == 0) { core.ui.closePanel(); @@ -1428,11 +1359,11 @@ actions.prototype._clickToolbox = function (x, y) { } // 下一页 if (x == this.HSIZE+2 || x == this.HSIZE+3) { - if (y == this.LAST - 5 && toolsPage < Math.ceil(Object.keys(core.status.hero.items.tools).length / this.LAST)) { + if (y == this.LAST - 5 && toolsPage < Math.ceil(tools.length / this.LAST)) { core.status.event.data.toolsPage++; core.ui.drawToolbox(core.status.event.selection); } - if (y == this.LAST && constantsPage < Math.ceil(Object.keys(core.status.hero.items.constants).length / this.LAST)) { + if (y == this.LAST && constantsPage < Math.ceil(constants.length / this.LAST)) { core.status.event.data.constantsPage++; core.ui.drawToolbox(core.status.event.selection); } @@ -1450,15 +1381,20 @@ actions.prototype._clickToolbox = function (x, y) { ////// 选择工具栏界面中某个Index后的操作 ////// actions.prototype._clickToolboxIndex = function (index) { + var tools = Object.keys(core.status.hero.items.tools) + .filter(function (id) { return !core.material.items[id].hideInToolbox; }).sort(); + var constants = Object.keys(core.status.hero.items.constants) + .filter(function (id) { return !core.material.items[id].hideInToolbox; }).sort(); + var items = null; var select; if (index < this.LAST) { select = index + this.LAST * (core.status.event.data.toolsPage - 1); - items = Object.keys(core.status.hero.items.tools).sort(); + items = tools; } else { select = index % this.LAST + this.LAST * (core.status.event.data.constantsPage - 1); - items = Object.keys(core.status.hero.items.constants).sort(); + items = constants; } if (items == null) return; if (select >= items.length) return; @@ -1478,8 +1414,10 @@ actions.prototype._keyDownToolbox = function (keycode) { var last_index = this.LAST - 1; - var tools = Object.keys(core.status.hero.items.tools).sort(); - var constants = Object.keys(core.status.hero.items.constants).sort(); + var tools = Object.keys(core.status.hero.items.tools) + .filter(function (id) { return !core.material.items[id].hideInToolbox; }).sort(); + var constants = Object.keys(core.status.hero.items.constants) + .filter(function (id) { return !core.material.items[id].hideInToolbox; }).sort(); var index = core.status.event.selection; var toolsPage = core.status.event.data.toolsPage; var constantsPage = core.status.event.data.constantsPage; @@ -1981,9 +1919,11 @@ actions.prototype._clickSwitchs = function (x, y) { var topIndex = this.HSIZE - parseInt((choices.length - 1) / 2) + (core.status.event.ui.offset || 0); var selection = y - topIndex; if (x < this.CHOICES_LEFT || x > this.CHOICES_RIGHT) { - if (selection != 2 && selection != 3) return; - if (x != this.HSIZE - 2 && x != this.HSIZE + 2) return; + if (selection != 2 && selection != 3 && selection != 4) return; } + var width = choices[selection].width; + var leftPos = (core.__PIXELS__ - width) / 2, rightPos = (core.__PIXELS__ + width) / 2; + var leftGrid = parseInt(leftPos / 32), rightGrid = parseInt(rightPos / 32) - 1; if (selection >= 0 && selection < choices.length) { core.status.event.selection = selection; switch (selection) { @@ -1992,24 +1932,28 @@ actions.prototype._clickSwitchs = function (x, y) { case 1: return this._clickSwitchs_sound(); case 2: - if (x == this.HSIZE - 2) return this._clickSwitchs_userVolume(-1); - if (x == this.HSIZE + 2) return this._clickSwitchs_userVolume(1); + if (x == leftGrid || x == leftGrid + 1) return this._clickSwitchs_userVolume(-1); + if (x == rightGrid || x == rightGrid + 1) return this._clickSwitchs_userVolume(1); return; case 3: - if (x == this.HSIZE - 2) return this._clickSwitchs_moveSpeed(-10); - if (x == this.HSIZE + 2) return this._clickSwitchs_moveSpeed(10); + if (x == leftGrid || x == leftGrid + 1) return this._clickSwitchs_moveSpeed(-10); + if (x == rightGrid || x == rightGrid + 1) return this._clickSwitchs_moveSpeed(10); return; case 4: - return this._clickSwitchs_displayEnemyDamage(); + if (x == leftGrid || x == leftGrid + 1) return this._clickSwitchs_floorChangeTime(-100); + if (x == rightGrid || x == rightGrid + 1) return this._clickSwitchs_floorChangeTime(100); + return; case 5: - return this._clickSwitchs_displayCritical(); + return this._clickSwitchs_displayEnemyDamage(); case 6: - return this._clickSwitchs_displayExtraDamage(); + return this._clickSwitchs_displayCritical(); case 7: - return this._clickSwitchs_localForage(); + return this._clickSwitchs_displayExtraDamage(); case 8: - return this._clickSwitchs_clickMove(); + return this._clickSwitchs_potionNoRouting(); case 9: + return this._clickSwitchs_clickMove(); + case 10: core.status.event.selection = 0; core.ui.drawSettings(); break; @@ -2030,6 +1974,7 @@ actions.prototype._clickSwitchs_sound = function () { actions.prototype._clickSwitchs_userVolume = function (delta) { var value = Math.round(Math.sqrt(100 * core.musicStatus.userVolume)); + if (value == 0 && delta < 0) return; core.musicStatus.userVolume = core.clamp(Math.pow(value + delta, 2) / 100, 0, 1); //audioContext 音效 不受designVolume 影响 if (core.musicStatus.gainNode != null) core.musicStatus.gainNode.gain.value = core.musicStatus.userVolume; @@ -2044,6 +1989,12 @@ actions.prototype._clickSwitchs_moveSpeed = function (delta) { core.ui.drawSwitchs(); } +actions.prototype._clickSwitchs_floorChangeTime = function (delta) { + core.values.floorChangeTime = core.clamp(core.values.floorChangeTime + delta, 0, 2000); + core.setLocalStorage("floorChangeTime", core.values.floorChangeTime); + core.ui.drawSwitchs(); +} + actions.prototype._clickSwitchs_displayEnemyDamage = function () { core.flags.displayEnemyDamage = !core.flags.displayEnemyDamage; core.updateDamage(); @@ -2065,12 +2016,9 @@ actions.prototype._clickSwitchs_displayExtraDamage = function () { core.ui.drawSwitchs(); } -actions.prototype._clickSwitchs_localForage = function () { - core.platform.useLocalForage = !core.platform.useLocalForage; - core.setLocalStorage('useLocalForage', core.platform.useLocalForage); - core.control.getSaveIndexes(function (indexes) { - core.saves.ids = indexes; - }); +actions.prototype._clickSwitchs_potionNoRouting = function () { + if (core.hasFlag('__potionNoRouting__')) core.removeFlag('__potionNoRouting__'); + else core.setFlag('__potionNoRouting__', true); core.ui.drawSwitchs(); } @@ -2087,6 +2035,19 @@ actions.prototype._keyUpSwitchs = function (keycode) { core.ui.drawSettings(); return; } + if (keycode == 37) { + switch (core.status.event.selection) { + case 2: return this._clickSwitchs_userVolume(-1); + case 3: return this._clickSwitchs_moveSpeed(-10); + case 4: this._clickSwitchs_floorChangeTime(-100); + } + } else if (keycode == 39) { + switch (core.status.event.selection) { + case 2: return this._clickSwitchs_userVolume(1); + case 3: return this._clickSwitchs_moveSpeed(10); + case 4: this._clickSwitchs_floorChangeTime(100); + } + } this._selectChoices(core.status.event.ui.choices.length, keycode, this._clickSwitchs); } @@ -2111,20 +2072,16 @@ actions.prototype._clickSettings = function (x, y) { core.ui.drawMaps(); break; case 3: - core.clearUI(); - core.ui.drawPaint(); - break; - case 4: core.status.event.selection = 0; core.ui.drawSyncSave(); break; - case 5: + case 4: core.status.event.selection = 0; core.ui.drawGameInfo(); break; - case 6: + case 5: return core.confirmRestart(); - case 7: + case 6: core.ui.closePanel(); break; } @@ -2617,107 +2574,3 @@ actions.prototype._keyUpCursor = function (keycode) { return; } } - -////// 绘图相关 ////// - -actions.prototype._ondownPaint = function (x, y) { - x += core.bigmap.offsetX; - y += core.bigmap.offsetY; - if (!core.status.event.data.erase) { - core.dymCanvas.paint.beginPath(); - core.dymCanvas.paint.moveTo(x, y); - } - core.status.event.data.x = x; - core.status.event.data.y = y; -} - -actions.prototype._onmovePaint = function (x, y) { - if (core.status.event.data.x == null) return; - x += core.bigmap.offsetX; - y += core.bigmap.offsetY; - if (core.status.event.data.erase) { - core.clearMap('paint', x - 10, y - 10, 20, 20); - return; - } - var midx = (core.status.event.data.x + x) / 2, midy = (core.status.event.data.y + y) / 2; - core.dymCanvas.paint.quadraticCurveTo(midx, midy, x, y); - core.dymCanvas.paint.stroke(); - core.status.event.data.x = x; - core.status.event.data.y = y; -} - -actions.prototype._onupPaint = function () { - core.status.event.data.x = null; - core.status.event.data.y = null; - // 保存 - core.paint[core.status.floorId] = lzw_encode(core.utils._encodeCanvas(core.dymCanvas.paint).join(",")); -} - -actions.prototype.setPaintMode = function (mode) { - if (mode == 'paint') core.status.event.data.erase = false; - else if (mode == 'erase') core.status.event.data.erase = true; - else return; - - core.drawTip("进入" + (core.status.event.data.erase ? "擦除" : "绘图") + "模式"); -} - -actions.prototype.clearPaint = function () { - core.clearMap('paint'); - delete core.paint[core.status.floorId]; - core.drawTip("已清空绘图内容"); -} - -actions.prototype.savePaint = function () { - var data = {}; - for (var floorId in core.paint) { - if (core.paint[floorId]) - data[floorId] = lzw_decode(core.paint[floorId]); - } - core.download(core.firstData.name + ".h5paint", JSON.stringify({ - 'name': core.firstData.name, - 'paint': data - })); -} - -actions.prototype.loadPaint = function () { - core.readFile(function (obj) { - if (obj.name != core.firstData.name) { - alert("绘图文件和游戏不一致!"); - return; - } - if (!obj.paint) { - alert("无效的绘图文件!"); - return; - } - core.paint = {}; - for (var floorId in obj.paint) { - if (obj.paint[floorId]) - core.paint[floorId] = lzw_encode(obj.paint[floorId]); - } - - core.clearMap('paint'); - var value = core.paint[core.status.floorId]; - if (value) value = lzw_decode(value).split(","); - core.utils._decodeCanvas(value, 32 * core.bigmap.width, 32 * core.bigmap.height); - core.drawImage('paint', core.bigmap.tempCanvas.canvas, 0, 0); - - core.drawTip("读取绘图文件成功"); - }) -} - -actions.prototype.exitPaint = function () { - core.deleteCanvas('paint'); - core.ui.closePanel(); - core.statusBar.image.keyboard.style.opacity = 1; - core.statusBar.image.shop.style.opacity = 1; - core.drawTip("退出绘图模式"); -} - -actions.prototype._keyUpPaint = function (keycode) { - if (keycode == 27 || keycode == 88 || keycode == 77 || keycode == 13 || keycode == 32 || keycode == 67) { - this.exitPaint(); - return; - } -} - -////// 绘图相关 END ////// diff --git a/libs/control.js b/libs/control.js index 0753d913..923b5833 100644 --- a/libs/control.js +++ b/libs/control.js @@ -1,3 +1,5 @@ +/// + /* control.js:游戏主要逻辑控制 主要负责status相关内容,以及各种变量获取/存储 @@ -22,9 +24,8 @@ control.prototype._init = function () { this.registerAnimationFrame("animate", true, this._animationFrame_animate); this.registerAnimationFrame("heroMoving", true, this._animationFrame_heroMoving); this.registerAnimationFrame("weather", true, this._animationFrame_weather); - this.registerAnimationFrame("tips", true, this._animateFrame_tips); + this.registerAnimationFrame("tip", true, this._animateFrame_tip); this.registerAnimationFrame("parallelDo", false, this._animationFrame_parallelDo); - this.registerAnimationFrame("checkConsoleOpened", true, this._animationFrame_checkConsoleOpened); // --- 注册系统的replay this.registerReplayAction("move", this._replayAction_move); this.registerReplayAction("item", this._replayAction_item); @@ -181,7 +182,7 @@ control.prototype._animationFrame_animate = function (timestamp) { control.prototype._animationFrame_heroMoving = function (timestamp) { if (core.status.heroMoving <= 0) return; // 换腿 - if (timestamp - core.animateFrame.moveTime > (core.values.moveSpeed||100)) { + if (timestamp - core.animateFrame.moveTime > core.values.moveSpeed) { core.animateFrame.leftLeg = !core.animateFrame.leftLeg; core.animateFrame.moveTime = timestamp; } @@ -283,48 +284,37 @@ control.prototype._animationFrame_weather_fog = function () { } } -control.prototype._animateFrame_tips = function (timestamp) { - var tips = core.animateFrame.tips; - if (timestamp - tips.time <= 30) return; - var delta = timestamp - tips.time; - tips.time = timestamp; - if (tips.list.length == 0) return; +control.prototype._animateFrame_tip = function (timestamp) { + if (core.animateFrame.tip == null) return; + var tip = core.animateFrame.tip; + if (timestamp - tip.time <= 30) return; + var delta = timestamp - tip.time; + tip.time = timestamp; - var currentOffset = Math.max(tips.offset - 5, 0), firstOffset = null; - var currList = []; core.setFont('data', "16px Arial"); core.setTextAlign('data', 'left'); - core.clearMap('data', 0, 0, this.PIXEL, tips.lastSize * 50); - tips.lastLength = tips.list.length; - - while (tips.list.length > 0) { - var one = tips.list.shift(); - core.ui._drawTip_drawOne(one, currentOffset); - if (one.stage == 1) { - one.opacity += 0.05; - if (one.opacity >= 0.7) one.stage = 2; - } else if (one.stage == 2) { - one.time += delta; - if (one.time >= 2000) one.stage = 3; - } else one.opacity -= 0.05; - if (one.opacity > 0) { - currList.push(one); - if (firstOffset == null) firstOffset = currentOffset; + core.clearMap('data', 0, 0, core.__PIXELS__, 50); + core.ui._drawTip_drawOne(tip); + if (tip.stage == 1) { + tip.opacity += 0.05; + if (tip.opacity >= 0.6) { + tip.stage = 2; + tip.displayTime = 0; } - currentOffset += 50; + } else if (tip.stage == 2) { + tip.displayTime += delta; + if (tip.displayTime >= 1000) tip.stage = 3; + } else tip.opacity -= 0.05; + + if (tip.opacity <= 0) { + core.animateFrame.tip = null; } - tips.list = currList; - tips.offset = firstOffset || 0; } control.prototype._animationFrame_parallelDo = function (timestamp) { core.control.controldata.parallelDo(timestamp); } -control.prototype._animationFrame_checkConsoleOpened = function (timestamp) { - if (core.consoleOpened()) core.setFlag('__consoleOpened__', true); -} - // ------ 标题界面的处理 ------ // ////// 显示游戏开始界面 ////// @@ -399,7 +389,7 @@ control.prototype._initStatistics = function (totalTime) { 'hp': 0, "battle": 0, 'money': 0, - 'experience': 0, + 'exp': 0, 'battleDamage': 0, 'poisonDamage': 0, 'extraDamage': 0, @@ -498,7 +488,7 @@ control.prototype._setAutomaticRoute_isMoving = function (destX, destY) { core.control.tryMoveDirectly(destX, destY); } core.status.automaticRoute.moveDirectly = false; - }, core.values.moveSpeed || 100); + }, core.values.moveSpeed); } return true; } @@ -614,7 +604,7 @@ control.prototype.setHeroMoveInterval = function (callback) { core.moveOneStep(core.nextX(), core.nextY()); if (callback) callback(); } - }, (core.values.moveSpeed||100) / 8 * toAdd / core.status.replay.speed); + }, core.values.moveSpeed / 8 * toAdd / core.status.replay.speed); } ////// 每移动一格后执行的事件 ////// @@ -666,10 +656,9 @@ control.prototype._moveAction_moving = function (callback) { // 执行该点事件 if (!hasTrigger) core.events._trigger(nowx, nowy); - core.updateStatusBar(); // 检查该点是否是滑冰 - if (core.getBgNumber() == 167) { + if (core.onSki()) { core.insertAction("滑冰事件", null, null, null, true); } @@ -755,7 +744,7 @@ control.prototype.waitHeroToStop = function(callback) { core.setHeroLoc('direction', lastDirection); core.drawHero(); callback(); - }, 30); + }, core.status.replay.speed == 24 ? 0 : 30); } } @@ -837,14 +826,14 @@ control.prototype._drawHero_getDrawObjs = function (direction, x, y, status, off "status": status, "index": index++, }); - (core.status.hero.followers||[]).forEach(function (t) { + core.status.hero.followers.forEach(function (t) { drawObjs.push({ "img": core.material.images.images[t.name], "width": core.material.images.images[t.name].width/4, "height": core.material.images.images[t.name].height/4, "heroIcon": heroIconArr[t.direction], - "posx": 32*t.x - core.bigmap.offsetX + (t.stop?0:core.utils.scan[t.direction].x*offset), - "posy": 32*t.y - core.bigmap.offsetY + (t.stop?0:core.utils.scan[t.direction].y*offset), + "posx": 32*t.x - core.bigmap.offsetX + (t.stop?0:core.utils.scan[t.direction].x*Math.abs(offset)), + "posy": 32*t.y - core.bigmap.offsetY + (t.stop?0:core.utils.scan[t.direction].y*Math.abs(offset)), "status": t.stop?"stop":status, "index": index++ }); @@ -909,7 +898,7 @@ control.prototype.setViewport = function (x, y) { ////// 移动视野范围 ////// control.prototype.moveViewport = function (steps, time, callback) { - time = time || core.values.moveSpeed || 300; + time = time || core.values.moveSpeed; var step = 0, moveSteps = (steps||[]).filter(function (t) { return ['up','down','left','right'].indexOf(t)>=0; }); @@ -959,7 +948,7 @@ control.prototype.nearHero = function (x, y, n) { ////// 聚集跟随者 ////// control.prototype.gatherFollowers = function () { var x=core.getHeroLoc('x'), y=core.getHeroLoc('y'), dir=core.getHeroLoc('direction'); - (core.status.hero.followers||[]).forEach(function (t) { + core.status.hero.followers.forEach(function (t) { t.x = x; t.y = y; t.stop = true; @@ -969,7 +958,7 @@ control.prototype.gatherFollowers = function () { ////// 更新跟随者坐标 ////// control.prototype.updateFollowers = function () { - (core.status.hero.followers||[]).forEach(function (t) { + core.status.hero.followers.forEach(function (t) { if (!t.stop) { t.x += core.utils.scan[t.direction].x; t.y += core.utils.scan[t.direction].y; @@ -977,7 +966,7 @@ control.prototype.updateFollowers = function () { }) var nowx = core.getHeroLoc('x'), nowy = core.getHeroLoc('y'); - (core.status.hero.followers||[]).forEach(function (t) { + core.status.hero.followers.forEach(function (t) { t.stop = true; var dx = nowx - t.x, dy = nowy - t.y; for (var dir in core.utils.scan) { @@ -1001,7 +990,8 @@ control.prototype.checkBlock = function () { var damage = core.status.checkBlock.damage[loc]; if (damage) { core.status.hero.hp -= damage; - core.drawTip("受到"+(core.status.checkBlock.type[loc]||"伤害")+damage+"点"); + var text = (Object.keys(core.status.checkBlock.type[loc] || {}).join(",")) || "伤害"; + core.drawTip("受到"+text+damage+"点"); core.drawHeroAnimate("zone"); this._checkBlock_disableQuickShop(); core.status.hero.statistics.extraDamage += damage; @@ -1010,6 +1000,8 @@ control.prototype.checkBlock = function () { core.updateStatusBar(); core.events.lose(); return; + } else { + core.updateStatusBar(); } } this._checkBlock_snipe(core.status.checkBlock.snipe[loc]); @@ -1019,9 +1011,9 @@ control.prototype.checkBlock = function () { control.prototype._checkBlock_disableQuickShop = function () { // 禁用快捷商店 if (core.flags.disableShopOnDamage) { - for (var shopId in core.status.shops) { - core.status.shops[shopId].visited = false; - } + Object.keys(core.status.shops).forEach(function (shopId) { + core.setShopVisited(shopId, false); + }); } } @@ -1030,7 +1022,7 @@ control.prototype._checkBlock_snipe = function (snipe) { if (!snipe || snipe.length == 0) return; var actions = []; snipe.forEach(function (t) { - actions.push({"type": "move", "loc": [t[0],t[1]], "steps": [t[3]], "time": 500, "keep": true, "async": true}); + actions.push({"type": "move", "loc": [t[0],t[1]], "steps": [t[3]], "time": 250, "keep": true, "async": true}); }); actions.push({"type": "waitAsync"}); core.insertAction(actions); @@ -1042,12 +1034,14 @@ control.prototype._checkBlock_ambush = function (ambush) { // 捕捉效果 var actions = []; ambush.forEach(function (t) { - actions.push({"type": "move", "loc": [t[0],t[1]], "steps": [t[3]], "time": 500, "keep": false, "async":true}); + actions.push({"type": "move", "loc": [t[0],t[1]], "steps": [t[3]], "time": 250, "keep": false, "async":true}); }); actions.push({"type": "waitAsync"}); // 强制战斗 ambush.forEach(function (t) { - actions.push({"type": "battle", "id": t[2]}); + actions.push({"type": "function", "function": "function() { "+ + "core.battle('" + t[2] + "', " + t[0]+ "," + t[1] + ", true, core.doAction); "+ + "}", "async": true}); }); core.insertAction(actions); } @@ -1275,7 +1269,7 @@ control.prototype.bookReplay = function () { if (core.isMoving() || core.status.replay.animate || (core.status.event.id && core.status.event.id != 'viewMaps')) return core.drawTip("请等待当前事件的处理结束"); - if (!core.hasItem('book')) return core.drawTip('你没有怪物手册'); + if (!core.hasItem('book')) return core.drawTip('你没有'+core.material.items['book'].name); // 从“浏览地图”页面打开 if (core.status.event.id=='viewMaps') @@ -1440,12 +1434,14 @@ control.prototype._replayAction_item = function (action) { if (action.indexOf("item:")!=0) return false; var itemId = action.substring(5); if (!core.canUseItem(itemId)) return false; - if (core.material.items[itemId].hideInReplay) { + if (core.material.items[itemId].hideInReplay || core.status.replay.speed == 24) { core.useItem(itemId, false, core.replay); return true; } - var tools = Object.keys(core.status.hero.items.tools).sort(); - var constants = Object.keys(core.status.hero.items.constants).sort(); + var tools = Object.keys(core.status.hero.items.tools) + .filter(function (id) { return !core.material.items[id].hideInToolbox; }).sort(); + var constants = Object.keys(core.status.hero.items.constants) + .filter(function (id) { return !core.material.items[id].hideInToolbox; }).sort(); var index, per = core.__SIZE__-1; if ((index=tools.indexOf(itemId))>=0) { core.status.event.data = {"toolsPage": Math.floor(index/per)+1, "constantsPage":1}; @@ -1471,7 +1467,7 @@ control.prototype._replayAction_equip = function (action) { var index = ownEquipment.indexOf(equipId), per = core.__SIZE__-1; if (index<0) return false; core.status.route.push(action); - if (core.material.items[equipId].hideInReplay) { + if (core.material.items[equipId].hideInReplay || core.status.replay.speed == 24) { core.loadEquip(equipId, core.replay); return true; } @@ -1491,6 +1487,10 @@ control.prototype._replayAction_unEquip = function (action) { if (!core.isset(equipType)) return false; core.ui.drawEquipbox(equipType); core.status.route.push(action); + if (core.status.replay.speed == 24) { + core.unloadEquip(equipType, core.replay); + return true; + } setTimeout(function () { core.ui.closePanel(); core.unloadEquip(equipType, core.replay); @@ -1504,6 +1504,11 @@ control.prototype._replayAction_fly = function (action) { var toIndex=core.floorIds.indexOf(floorId); if (!core.canUseItem('fly')) return false; core.ui.drawFly(toIndex); + if (core.status.replay.speed == 24) { + if (!core.flyTo(floorId, core.replay)) + core.control._replay_error(action); + return true; + } setTimeout(function () { if (!core.flyTo(floorId, core.replay)) core.control._replay_error(action); @@ -1513,36 +1518,13 @@ control.prototype._replayAction_fly = function (action) { control.prototype._replayAction_shop = function (action) { if (action.indexOf("shop:")!=0) return false; - var sps=action.substring(5).split(":"); - var shopId=sps[0], selections=sps[1].split(""); - if (selections.length == 0) return false; - var shop=core.status.shops[shopId]; - if (!shop || !shop.visited) return false; - // --- 判定commonEvent或item - if (shop.commonEvent || shop.item) { - core.openShop(shopId, false); - setTimeout(core.replay); + var shopId = action.substring(5); + if (core.canUseQuickShop(shopId) != null || !core.canOpenShop(shopId)) { + this._replay_error(shopId); return true; } - var choices = shop.choices; - core.status.event.selection = parseInt(selections.shift()); - core.events.openShop(shopId, false); - var topIndex = core.__HALF_SIZE__ - parseInt(choices.length / 2) + (core.status.event.ui.offset || 0); - var shopInterval = setInterval(function () { - if (!core.actions._clickShop(core.__HALF_SIZE__, topIndex+core.status.event.selection)) { - clearInterval(shopInterval); - core.control._replay_error(action); - return; - } - if (selections.length==0) { - clearInterval(shopInterval); - core.actions._clickShop(core.__HALF_SIZE__, topIndex+choices.length); - core.replay(); - return; - } - core.status.event.selection = parseInt(selections.shift()); - core.events.openShop(shopId, false); - }, core.control.__replay_getTimeout()); + core.openShop(shopId, false); + core.replay(); return true; } @@ -1550,14 +1532,14 @@ control.prototype._replayAction_turn = function (action) { if (action != 'turn' && action.indexOf('turn:') != 0) return false; if (action == 'turn') core.turnHero(); else core.turnHero(action.substring(5)); - setTimeout(core.replay); + core.replay(); return true; } control.prototype._replayAction_getNext = function (action) { if (action != "getNext") return false; if (!core.getNextItem()) return false; - setTimeout(core.replay); + core.replay(); return true; } @@ -1574,6 +1556,11 @@ control.prototype._replayAction_moveDirectly = function (action) { var x=parseInt(pos[0]), y=parseInt(pos[1]); var nowx=core.getHeroLoc('x'), nowy=core.getHeroLoc('y'); if (!core.moveDirectly(x, y)) return false; + if (core.status.replay.speed == 24) { + core.replay(); + return true; + } + core.ui.drawArrow('ui', 32*nowx+16-core.bigmap.offsetX, 32*nowy+16-core.bigmap.offsetY, 32*x+16-core.bigmap.offsetX, 32*y+16-core.bigmap.offsetY, '#FF0000', 3); setTimeout(function () { @@ -1586,7 +1573,7 @@ control.prototype._replayAction_moveDirectly = function (action) { control.prototype._replayAction_key = function (action) { if (action.indexOf("key:") != 0) return false; core.actions.keyUp(parseInt(action.substring(4)), false, true); - setTimeout(core.replay); + core.replay(); return true; } @@ -1718,16 +1705,13 @@ control.prototype._doSL_load_afterGet = function (id, data) { var _replay = function () { core.startGame(data.hard, data.hero.flags.__seed__, core.decodeRoute(data.route)); }; - if (core.flags.checkConsole && data.hashCode != null && data.hashCode != core.hashCode(data.hero)) { - core.myconfirm("存档校验失败,请勿修改存档文件!\n你想回放此存档的录像吗?\n可以随时停止录像播放以继续游戏。", _replay); - return; - } if (data.version != core.firstData.version) { core.myconfirm("存档版本不匹配!\n你想回放此存档的录像吗?\n可以随时停止录像播放以继续游戏。", _replay); return; } core.ui.closePanel(); core.loadData(data, function() { + core.removeFlag('__fromLoad__'); core.drawTip("读档成功"); if (id!="autoSave") { core.saves.saveIndex=id; @@ -2006,7 +1990,6 @@ control.prototype._updateFavoriteSaves = function () { ////// 设置勇士属性 ////// control.prototype.setStatus = function (name, value) { if (!core.status.hero) return; - if (name == 'exp') name = 'experience'; if (name == 'x' || name == 'y' || name == 'direction') this.setHeroLoc(name, value); else @@ -2023,7 +2006,6 @@ control.prototype.getStatus = function (name) { if (!core.status.hero) return null; if (name == 'x' || name == 'y' || name == 'direction') return this.getHeroLoc(name); - if (name == 'exp') name = 'experience'; return core.status.hero[name]; } @@ -2075,14 +2057,7 @@ control.prototype.getHeroLoc = function (name) { return core.status.hero.loc[name]; } -////// 获得某个属性的中文名 ////// -control.prototype.getStatusName = function (name) { - var map = { - name: "名称", lv: "等级", hpmax: "生命上限", hp: "生命", manamax: "魔力上限", mana: "魔力", - atk: "攻击", def: "防御", mdef: "魔防", money: "金币", exp: "经验", experience: "经验", steps: "步数" - }; - return map[name] || name; -} + ////// 获得某个等级的名称 ////// control.prototype.getLvName = function (lv) { @@ -2318,6 +2293,7 @@ control.prototype.pauseBgm = function () { if (main.mode!='play')return; try { if (core.musicStatus.playingBgm) { + core.musicStatus.pauseTime = core.material.bgms[core.musicStatus.playingBgm].currentTime; core.material.bgms[core.musicStatus.playingBgm].pause(); core.musicStatus.playingBgm = null; } @@ -2330,10 +2306,11 @@ control.prototype.pauseBgm = function () { } ////// 恢复背景音乐的播放 ////// -control.prototype.resumeBgm = function () { +control.prototype.resumeBgm = function (resumeTime) { if (main.mode!='play')return; try { - core.playBgm(core.musicStatus.playingBgm || core.musicStatus.lastBgm || main.startBgm); + core.playBgm(core.musicStatus.playingBgm || core.musicStatus.lastBgm || main.startBgm, + resumeTime ? core.musicStatus.pauseTime : 0); } catch (e) { console.log("无法恢复BGM"); @@ -2628,20 +2605,25 @@ control.prototype._shouldDisplayStatus = function(id) { } return toDraw; } + var obj = {}; + core.flags.statusBarItems.forEach(function (v) { obj[v] = true; }) switch (id) { - case 'floor': return core.flags.enableFloor; - case 'name': return core.flags.enableName; - case 'lv': return core.flags.enableLv; - case 'hpmax': return core.flags.enableHPMax; - case 'mana': return core.flags.enableMana; - case 'mdef': return core.flags.enableMDef; - case 'money': return core.flags.enableMoney; - case 'experience': return core.flags.enableExperience && !core.flags.levelUpLeftMode; - case 'up': return core.flags.enableLevelUp; - case 'skill': return core.flags.enableSkill; - case 'key': return core.flags.enableKeys; - case 'pzf': return core.flags.enablePZF; - case 'debuff': return core.flags.enableDebuff; + case 'floor': return obj.enableFloor; + case 'name': return obj.enableName; + case 'lv': return obj.enableLv; + case 'hp': return obj.enableHP; + case 'hpmax': return obj.enableHPMax; + case 'mana': return obj.enableMana; + case 'atk': return obj.enableAtk; + case 'def': return obj.enableDef; + case 'mdef': return obj.enableMDef; + case 'money': return obj.enableMoney; + case 'exp': return obj.enableExp && !obj.levelUpLeftMode; + case 'up': return obj.enableLevelUp; + case 'skill': return obj.enableSkill; + case 'key': return obj.enableKeys; + case 'pzf': return obj.enablePZF; + case 'debuff': return obj.enableDebuff; default: return true; } } @@ -2837,6 +2819,14 @@ control.prototype._resize_status = function (obj) { for (var i = 0; i < core.dom.statusTexts.length; ++i) { core.dom.statusTexts[i].style.color = obj.globalAttribute.statusBarColor; } + // keys + if (core.flags.statusBarItems.indexOf('enableGreenKey')>=0) { + core.dom.keyCol.style.fontSize = '0.75em'; + core.statusBar.greenKey.style.display = ''; + } else { + core.dom.keyCol.style.fontSize = ''; + core.statusBar.greenKey.style.display = 'none'; + } } control.prototype._resize_toolBar = function (obj) { diff --git a/libs/core.js b/libs/core.js index f3097a12..cc6c3c9e 100644 --- a/libs/core.js +++ b/libs/core.js @@ -1,3 +1,5 @@ +/// + /** * 初始化 start */ @@ -45,12 +47,7 @@ function core() { 'data': null, 'fog': null, }, - "tips": { - 'time': 0, - 'offset': 0, - 'list': [], - 'lastSize': 0, - }, + "tip": null, "asyncId": {} } this.musicStatus = { @@ -58,6 +55,7 @@ function core() { 'bgmStatus': false, // 是否播放BGM 'soundStatus': true, // 是否播放SE 'playingBgm': null, // 正在播放的BGM + 'pauseTime': 0, // 上次暂停的时间 'lastBgm': null, // 上次播放的bgm 'gainNode': null, 'playingSounds': {}, // 正在播放的SE @@ -98,7 +96,6 @@ function core() { height: this.__SIZE__, tempCanvas: null, // A temp canvas for drawing } - this.paint = {}; this.saves = { "saveIndex": null, "ids": {}, @@ -280,19 +277,17 @@ core.prototype._init_flags = function () { // 初始化怪物、道具等 core.material.enemys = core.enemys.getEnemys(); core.material.items = core.items.getItems(); - core.items._resetItems(); core.material.icons = core.icons.getIcons(); } core.prototype._init_sys_flags = function () { - if (!core.flags.enableExperience) core.flags.enableLevelUp = false; - if (!core.flags.enableLevelUp) core.flags.levelUpLeftMode = false; if (core.flags.equipboxButton) core.flags.equipment = true; core.flags.displayEnemyDamage = core.getLocalStorage('enemyDamage', core.flags.displayEnemyDamage); core.flags.displayCritical = core.getLocalStorage('critical', core.flags.displayCritical); core.flags.displayExtraDamage = core.getLocalStorage('extraDamage', core.flags.displayExtraDamage); // 行走速度 - core.values.moveSpeed = core.getLocalStorage('moveSpeed', core.values.moveSpeed); + core.values.moveSpeed = core.getLocalStorage('moveSpeed', 100); + core.values.floorChangeTime = core.getLocalStorage('floorChangeTime', 500); } core.prototype._init_platform = function () { diff --git a/libs/data.js b/libs/data.js index 684e71cb..5ec17f8c 100644 --- a/libs/data.js +++ b/libs/data.js @@ -1,3 +1,5 @@ +/// + "use strict"; function data() { diff --git a/libs/enemys.js b/libs/enemys.js index e9aaab26..4c82a6fa 100644 --- a/libs/enemys.js +++ b/libs/enemys.js @@ -1,3 +1,5 @@ +/// + "use strict"; function enemys() { @@ -113,27 +115,6 @@ enemys.prototype.canBattle = function (enemy, x, y, floorId) { return damage != null && damage < core.status.hero.hp; } -////// 获得某个怪物的伤害 ////// -enemys.prototype.getDamage = function (enemy, x, y, floorId) { - if (typeof enemy == 'string') enemy = core.material.enemys[enemy]; - var damage = this._calDamage(enemy, null, x, y, floorId); - if (damage == null) return null; - return damage + this.getExtraDamage(enemy, x, y, floorId); -} - -////// 获得某个怪物的额外伤害 ////// -enemys.prototype.getExtraDamage = function (enemy, x, y, floorId) { - if (typeof enemy == 'string') enemy = core.material.enemys[enemy]; - var extra_damage = 0; - if (this.hasSpecial(enemy.special, 17)) { // 仇恨 - extra_damage += core.getFlag('hatred', 0); - } - if (this.hasSpecial(enemy.special, 22)) { // 固伤 - extra_damage += enemy.damage || 0; - } - return extra_damage; -} - enemys.prototype.getDamageString = function (enemy, x, y, floorId) { if (typeof enemy == 'string') enemy = core.material.enemys[enemy]; var damage = this.getDamage(enemy, x, y, floorId); @@ -279,26 +260,33 @@ enemys.prototype._nextCriticals_useTurn = function (enemy, info, number, x, y, f enemys.prototype.getDefDamage = function (enemy, k, x, y, floorId) { if (typeof enemy == 'string') enemy = core.material.enemys[enemy]; k = k || 1; - var nowDamage = this._calDamage(enemy, null, x, y, floorId); - var nextDamage = this._calDamage(enemy, {"def": core.status.hero.def + k}, x, y, floorId); + var nowDamage = this._getDamage(enemy, null, x, y, floorId); + var nextDamage = this._getDamage(enemy, {"def": core.status.hero.def + k}, x, y, floorId); if (nowDamage == null || nextDamage == null) return "???"; return nowDamage - nextDamage; } enemys.prototype.getEnemyInfo = function (enemy, hero, x, y, floorId) { + if (enemy == null) return null; if (typeof enemy == 'string') enemy = core.material.enemys[enemy]; return this.enemydata.getEnemyInfo(enemy, hero, x, y, floorId) } ////// 获得战斗伤害信息(实际伤害计算函数) ////// enemys.prototype.getDamageInfo = function (enemy, hero, x, y, floorId) { + if (enemy == null) return null; // 移动到了脚本编辑 - getDamageInfo中 if (typeof enemy == 'string') enemy = core.material.enemys[enemy]; return this.enemydata.getDamageInfo(enemy, hero, x, y, floorId); } ////// 获得在某个勇士属性下怪物伤害 ////// -enemys.prototype._calDamage = function (enemy, hero, x, y, floorId) { +enemys.prototype.getDamage = function (enemy, x, y, floorId) { + return this._getDamage(enemy, null, x, y, floorId); +} + +enemys.prototype._getDamage = function (enemy, hero, x, y, floorId) { + if (enemy == null) return null; if (typeof enemy == 'string') enemy = core.material.enemys[enemy]; var info = this.getDamageInfo(enemy, hero, x, y, floorId); @@ -307,9 +295,6 @@ enemys.prototype._calDamage = function (enemy, hero, x, y, floorId) { return info.damage; } -////// 更新怪物数据。已经不再使用,这里留空进行兼容。 ////// -enemys.prototype.updateEnemys = function () {} - ////// 获得当前楼层的怪物列表 ////// enemys.prototype.getCurrentEnemys = function (floorId) { floorId = floorId || core.status.floorId; @@ -373,14 +358,18 @@ enemys.prototype._getCurrentEnemys_sort = function (enemys) { enemys.prototype.hasEnemyLeft = function (enemyId, floorId) { if (floorId == null) floorId = core.status.floorId; - if (floorId instanceof Array) { - for (var i = 0; i < floorId.length; ++i) { - if (core.hasEnemyLeft(enemyId, floorId[i])) - return true; + if (!(floorId instanceof Array)) floorId = [floorId]; + var enemyMap = {}; + if (enemyId instanceof Array) enemyId.forEach(function(v) { enemyMap[v] = true;}); + else if (enemyId) enemyMap[enemyId] = true; + else enemyMap = null; + for (var i = 0; i < floorId.length; i++) { + var mapBlocks = core.status.maps[floorId[i]].blocks; + for (var b = 0; b < mapBlocks.length; b++) { + if (!mapBlocks[b].disable && mapBlocks[b].event.cls.indexOf('enemy') === 0) { + if (enemyMap === null || enemyMap[mapBlocks[b].event.id]) return true; + } } - return false; } - return core.getCurrentEnemys(floorId).filter(function (enemy) { - return enemyId == null || enemy.id == enemyId; - }).length > 0; -} \ No newline at end of file + return false; +} diff --git a/libs/events.js b/libs/events.js index 80c92ccf..ea9a45b4 100644 --- a/libs/events.js +++ b/libs/events.js @@ -1,3 +1,5 @@ +/// + "use strict"; function events() { @@ -51,7 +53,6 @@ events.prototype._startGame_start = function (hard, seed, route, callback) { core.setFlag('__rand__', seed); } else core.utils.__init_seed(); - this.setInitData(); core.clearStatusBar(); var todo = []; @@ -102,11 +103,6 @@ events.prototype._startGame_upload = function () { core.utils.http("POST", "/games/upload.php", formData); } -////// 不同难度分别设置初始属性 ////// -events.prototype.setInitData = function () { - return this.eventdata.setInitData(); -} - ////// 游戏获胜事件 ////// events.prototype.win = function (reason, norank, noexit) { if (!noexit) core.status.gameOver = true; @@ -137,7 +133,6 @@ events.prototype.gameOver = function (ending, fromReplay, norank) { var reason = null; if (fromReplay) reason = "录像回放完毕!"; else if (core.hasFlag("debug")) reason = "\t[系统提示]调试模式下无法上传成绩"; - else if (core.hasFlag("__consoleOpened__")) reason = "\t[系统提示]本存档开启过控制台,无法上传成绩"; if (reason != null) core.drawText(reason, core.restart); @@ -188,7 +183,7 @@ events.prototype._gameOver_doUpload = function (username, ending, norank) { formData.append('def', core.status.hero.def); formData.append('mdef', core.status.hero.mdef); formData.append('money', core.status.hero.money); - formData.append('experience', core.status.hero.experience); + formData.append('experience', core.status.hero.exp); formData.append('steps', core.status.hero.steps); formData.append('norank', norank ? 1 : 0); formData.append('seed', core.getFlag('__seed__')); @@ -322,7 +317,7 @@ events.prototype._trigger = function (x, y) { eval(block.event.script); } catch (e) { main.log(e); } - if (block.event.trigger) { + if (block.event.trigger && block.event.trigger != 'null') { var noPass = block.event.noPass, trigger = block.event.trigger; if (noPass) core.clearAutomaticRouteNode(x, y); @@ -366,7 +361,7 @@ events.prototype.battle = function (id, x, y, force, callback) { if (!id) return core.clearContinueAutomaticRoute(callback); // 非强制战斗 if (!core.enemys.canBattle(id, x, y) && !force && !core.status.event.id) { - core.drawTip("你打不过此怪物!", null, true); + core.drawTip("你打不过此怪物!"); return core.clearContinueAutomaticRoute(callback); } // 自动存档 @@ -407,39 +402,61 @@ events.prototype.openDoor = function (x, y, needKey, callback) { }); return; } - core.playSound("door.mp3"); - this._openDoor_animate(id, x, y, callback); + if (core.status.replay.speed == 24) { + core.status.replay.animate = true; + core.removeBlock(x, y); + setTimeout(function () { + core.status.replay.animate = false; + core.events.afterOpenDoor(id, x, y, callback); + }); + } else { + 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("无法开启此门"); + 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(); @@ -469,16 +486,16 @@ events.prototype.afterOpenDoor = function (doorId, x, y, callback) { } events.prototype._sys_getItem = function (data, callback) { - this.getItem(data.event.id, 1, data.x, data.y, callback); + this.getItem(data.event.id, 1, data.x, data.y, false, callback); } ////// 获得某个物品 ////// -events.prototype.getItem = function (id, num, x, y, callback) { +events.prototype.getItem = function (id, num, x, y, isGentleClick, callback) { if (num == null) num = 1; num = num || 1; var itemCls = core.material.items[id].cls; - core.items.getItemEffect(id, num); core.removeBlock(x, y); + core.items.getItemEffect(id, num); var text = '获得 ' + core.material.items[id].name; if (num > 1) text += "x" + num; if (itemCls === 'items' && num == 1) text += core.items.getItemEffectTip(id); @@ -494,7 +511,7 @@ events.prototype.getItem = function (id, num, x, y, callback) { } catch (e) {} if (!core.status.event.id || core.status.event.id=='action') { core.insertAction("\t["+core.material.items[id].name+","+id+"]" + hint + "\n" - + (itemCls == 'keys' || id == 'greenKey' || id == 'steelKey' ? "(钥匙类道具,遇到对应的门时自动打开)" + + (id.endsWith('Key') ? "(钥匙类道具,遇到对应的门时自动打开)" : itemCls == 'tools' ? "(消耗类道具,请按T在道具栏使用)" : itemCls == 'constants' ? "(永久类道具,请按T在道具栏使用)" : itemCls == 'equips' ? "(装备类道具,请按Q在装备栏进行装备)" : "")); @@ -502,14 +519,11 @@ events.prototype.getItem = function (id, num, x, y, callback) { itemHint.push(id); } - - core.updateStatusBar(); - - this.afterGetItem(id, x, y, callback); + this.afterGetItem(id, x, y, isGentleClick, callback); } -events.prototype.afterGetItem = function (id, x, y, callback) { - this.eventdata.afterGetItem(id, x, y, callback); +events.prototype.afterGetItem = function (id, x, y, isGentleClick, callback) { + this.eventdata.afterGetItem(id, x, y, isGentleClick, callback); } ////// 获得面前的物品(轻按) ////// @@ -537,7 +551,7 @@ events.prototype._getNextItem = function (direction, noRoute) { var nx = core.getHeroLoc('x') + core.utils.scan[direction].x; var ny = core.getHeroLoc('y') + core.utils.scan[direction].y; if (!noRoute) core.status.route.push("getNext"); - this.getItem(core.getBlockId(nx, ny), 1, nx, ny); + this.getItem(core.getBlockId(nx, ny), 1, nx, ny, true); return true; } @@ -554,13 +568,12 @@ events.prototype._sys_changeFloor = function (data, callback) { } ////// 楼层切换 ////// -events.prototype.changeFloor = function (floorId, stair, heroLoc, time, callback, fromLoad) { +events.prototype.changeFloor = function (floorId, stair, heroLoc, time, callback) { var info = this._changeFloor_getInfo(floorId, stair, heroLoc, time); if (info == null) { if (callback) callback(); return; } - info.fromLoad = fromLoad; floorId = info.floorId; info.locked = core.status.lockControl; @@ -594,8 +607,6 @@ events.prototype._changeFloor_getInfo = function (floorId, stair, heroLoc, time) if (main.mode != 'play' || core.isReplaying()) time = 0; if (time == null) time = core.values.floorChangeTime; - if (time == null) time = 800; - if (time < 100) time = 0; time /= 20; return { @@ -657,7 +668,7 @@ events.prototype._changeFloor_beforeChange = function (info, callback) { } events.prototype._changeFloor_changing = function (info, callback) { - this.changingFloor(info.floorId, info.heroLoc, info.fromLoad); + this.changingFloor(info.floorId, info.heroLoc); if (info.time == 0) this._changeFloor_afterChange(info, callback); @@ -670,58 +681,33 @@ events.prototype._changeFloor_changing = function (info, callback) { events.prototype._changeFloor_afterChange = function (info, callback) { if (!info.locked) core.unLockControl(); core.status.replay.animate = false; - core.events.afterChangeFloor(info.floorId, info.fromLoad); + core.events.afterChangeFloor(info.floorId); if (callback) callback(); } -events.prototype.changingFloor = function (floorId, heroLoc, fromLoad) { - this.eventdata.changingFloor(floorId, heroLoc, fromLoad); +events.prototype.changingFloor = function (floorId, heroLoc) { + this.eventdata.changingFloor(floorId, heroLoc); } ////// 转换楼层结束的事件 ////// -events.prototype.afterChangeFloor = function (floorId, fromLoad) { +events.prototype.afterChangeFloor = function (floorId) { if (main.mode != 'play') return; - return this.eventdata.afterChangeFloor(floorId, fromLoad); + return this.eventdata.afterChangeFloor(floorId); } ////// 是否到达过某个楼层 ////// events.prototype.hasVisitedFloor = function (floorId) { + if (!core.hasFlag("__visited__")) core.setFlag("__visited__", {}); return core.getFlag("__visited__")[floorId] || false; } ////// 到达某楼层 ////// events.prototype.visitFloor = function (floorId) { + if (!core.hasFlag("__visited__")) core.setFlag("__visited__", {}); core.getFlag("__visited__")[floorId] = true; } -events.prototype._sys_passNet = function (data, callback) { - this.passNet(data); - if (callback) callback(); -} - -////// 经过一个路障 ////// -events.prototype.passNet = function (data) { - if (!core.hasItem('shoes')) { - // 血网 lavaNet 移动到 checkBlock 中处理 - if (data.event.id == 'poisonNet') { // 毒网 - core.insertAction({"type":"insert","name":"毒衰咒处理","args":[0]}); - } - else if (data.event.id == 'weakNet') { // 衰网 - core.insertAction({"type":"insert","name":"毒衰咒处理","args":[1]}); - } - else if (data.event.id == 'curseNet') { // 咒网 - core.insertAction({"type":"insert","name":"毒衰咒处理","args":[2]}); - } - } - this.afterPassNet(data.x, data.y, data.event.id); - core.updateStatusBar(); -} - -events.prototype.afterPassNet = function (x, y, id) { - if (this.eventdata.afterPassNet) this.eventdata.afterPassNet(x, y, id); -} - events.prototype._sys_pushBox = function (data, callback) { this.pushBox(data); if (callback) callback(); @@ -736,7 +722,15 @@ events.prototype.pushBox = function (data) { nx = data.x + core.utils.scan[direction].x, ny = data.y + core.utils.scan[direction].y; // 检测能否推上去 - if (!core.canMoveHero() || !core.canMoveHero(data.x, data.y, direction)) return; + if (!core.canMoveHero()) return; + var canGoDeadZone = core.flags.canGoDeadZone; + core.flags.canGoDeadZone = false; + if (!core.canMoveHero(data.x, data.y, direction)) { + core.flags.canGoDeadZone = canGoDeadZone; + return; + } + core.flags.canGoDeadZone = canGoDeadZone; + var nextId = core.getBlockId(nx, ny); if (nextId != null && nextId != 'flower') return; @@ -746,8 +740,6 @@ events.prototype.pushBox = function (data) { core.removeBlock(data.x, data.y); else core.setBlock(168, data.x, data.y); - - core.updateStatusBar(); this._pushBox_moveHero(direction); } @@ -773,22 +765,17 @@ events.prototype.afterPushBox = function () { return this.eventdata.afterPushBox(); } -events.prototype._sys_changeLight = function (data, callback) { - core.events.changeLight(data.event.id, data.x, data.y); - if (callback) callback(); -} - -////// 改变亮灯(感叹号)的事件 ////// -events.prototype.changeLight = function (id, x, y) { - if (id != null && id != 'light') return; - core.setBlock(core.getNumberById('darkLight'), x, y); - return this.eventdata.afterChangeLight(x, y); -} - events.prototype._sys_ski = function (data, callback) { core.insertAction(["V2.6后,请将滑冰放在背景层!"], data.x, data.y, callback); } +/// 当前是否在冰上 +events.prototype.onSki = function (number) { + if (number == null) number = core.getBgNumber(); + var block = core.getBlockByNumber(number); + return block && block.event && block.event.trigger == 'ski'; +} + events.prototype._sys_action = function (data, callback) { var ev = core.clone(data.event.data), ex = data.x, ey = data.y; // 检查是否需要改变朝向 @@ -880,6 +867,7 @@ events.prototype.doAction = function (keepUI) { // 清空boxAnimate和UI层 core.clearUI(); clearInterval(core.status.event.interval); + clearTimeout(core.status.event.interval); core.status.event.interval = null; } // 判定是否执行完毕 @@ -1115,7 +1103,7 @@ events.prototype.__precompile_getArray = function () { "closeDoor", "battle", "trigger", "insert" ]; var values = [ - "setValue", "setValue2", "addValue", "setEnemy", "setFloor", "setGlobalValue", + "setValue", "setEnemy", "setFloor", "setGlobalValue", ]; var uievents = [ "clearMap", "fillText", "fillBoldText", "fillRect", "strokeRect", "strokeCircle", @@ -1198,17 +1186,20 @@ events.prototype.__action_doAsyncFunc = function (isAsync, func) { events.prototype._action_text = function (data, x, y, prefix) { if (this.__action_checkReplaying()) return; + data.text = core.replaceText(data.text, prefix); core.ui.drawTextBox(data.text, data.showAll); } events.prototype._action_autoText = function (data, x, y, prefix) { if (this.__action_checkReplaying()) return; + data.text = core.replaceText(data.text, prefix); core.ui.drawTextBox(data.text); setTimeout(core.doAction, data.time || 3000); } events.prototype._action_scrollText = function (data, x, y, prefix) { if (this.__action_checkReplaying()) return; + data.text = core.replaceText(data.text, prefix); this.__action_doAsyncFunc(data.async, core.drawScrollText, data.text, data.time || 5000, data.lineHeight || 1.4); } @@ -1217,7 +1208,7 @@ events.prototype._action_comment = function (data, x, y, prefix) { } events.prototype._action_setText = function (data, x, y, prefix) { - ["position", "offset", "align", "bold", "titlefont", "textfont", "time", "interval"].forEach(function (t) { + ["position", "offset", "align", "bold", "titlefont", "textfont", "lineHeight", "time", "interval"].forEach(function (t) { if (data[t] != null) core.status.textAttribute[t] = data[t]; }); ["background", "title", "text"].forEach(function (t) { @@ -1238,7 +1229,7 @@ events.prototype._action_setText = function (data, x, y, prefix) { } events.prototype._action_tip = function (data, x, y, prefix) { - core.drawTip(core.replaceText(data.text), data.icon); + core.drawTip(core.replaceText(data.text, prefix), data.icon); core.doAction(); } @@ -1318,7 +1309,7 @@ events.prototype._action_animate = function (data, x, y, prefix) { this.__action_doAsyncFunc(data.async, core.drawHeroAnimate, data.name); } else { data.loc = this.__action_getLoc(data.loc, x, y, prefix); - this.__action_doAsyncFunc(data.async, core.drawAnimate, data.name, data.loc[0], data.loc[1]); + this.__action_doAsyncFunc(data.async, core.drawAnimate, data.name, data.loc[0], data.loc[1], data.alignWindow); } } @@ -1371,6 +1362,12 @@ events.prototype._action_changeFloor = function (data, x, y, prefix) { events.prototype._action_changePos = function (data, x, y, prefix) { core.clearMap('hero'); + if (data.x == null && data.y == null && data.direction) { + core.setHeroLoc('direction', data.direction, true); + core.drawHero(); + return core.doAction(); + } + var loc = this.__action_getHeroLoc(data.loc, prefix); core.setHeroLoc('x', loc[0]); core.setHeroLoc('y', loc[1]); @@ -1394,6 +1391,7 @@ events.prototype._precompile_showImage = function (data) { events.prototype._action_showTextImage = function (data, x, y, prefix) { var loc = this.__action_getLoc(data.loc, 0, 0, prefix); if (core.isReplaying()) data.time = 0; + data.text = core.replaceText(data.text, prefix); this.__action_doAsyncFunc(data.async || data.time == 0, core.showImage, data.code, core.ui.textImage(data.text), null, loc, data.opacity, data.time); } @@ -1419,19 +1417,15 @@ events.prototype._precompile_moveImage = function (data) { return data; } -events.prototype._action_setFg = function (data, x, y, prefix) { - return this._action_setCurtain(data, x, y, prefix); -} - events.prototype._action_setCurtain = function (data, x, y, prefix) { if (data.async) { core.setCurtain(data.color, data.time); - core.setFlag('__color__', data.color || null); + if (data.color == null || data.keep) core.setFlag('__color__', data.color || null); core.doAction(); } else { core.setCurtain(data.color, data.time, function () { - core.setFlag('__color__', data.color || null); + if (data.color == null || data.keep) core.setFlag('__color__', data.color || null); core.doAction(); }); } @@ -1443,7 +1437,7 @@ events.prototype._action_screenFlash = function (data, x, y, prefix) { events.prototype._action_setWeather = function (data, x, y, prefix) { core.setWeather(data.name, data.level); - if (data.name == 'rain' || data.name == 'snow' || data.name == 'fog') + if ((data.name == 'rain' || data.name == 'snow' || data.name == 'fog') && data.keep) core.setFlag('__weather__', [data.name, data.level]); else core.removeFlag('__weather__'); core.doAction(); @@ -1488,16 +1482,13 @@ events.prototype._action_unloadEquip = function (data, x, y, prefix) { } events.prototype._action_openShop = function (data, x, y, prefix) { - core.status.shops[data.id].visited = true; - this.setEvents([]); - if (!core.isReplaying()) - this.openShop(data.id); - if (core.status.event.id == 'action') - core.doAction(); + core.setShopVisited(data.id, true); + if (data.open) core.openShop(data.id, true); + core.doAction(); } events.prototype._action_disableShop = function (data, x, y, prefix) { - this.disableQuickShop(data.id); + core.setShopVisited(data.id, false); core.doAction(); } @@ -1557,7 +1548,7 @@ events.prototype._action_insert = function (data, x, y, prefix) { } events.prototype._action_playBgm = function (data, x, y, prefix) { - core.playBgm(data.name); + core.playBgm(data.name, data.startTime || 0); core.setFlag("__bgm__", data.keep ? data.name : null); core.doAction(); } @@ -1568,7 +1559,7 @@ events.prototype._action_pauseBgm = function (data, x, y, prefix) { } events.prototype._action_resumeBgm = function (data, x, y, prefix) { - core.resumeBgm(); + core.resumeBgm(data.resume); core.doAction(); } @@ -1600,25 +1591,7 @@ events.prototype._action_setVolume = function (data, x, y, prefix) { } events.prototype._action_setValue = function (data, x, y, prefix) { - this.setValue(data.name, data.value, prefix); - if (!data.norefresh) { - if (core.status.hero.hp <= 0) { - core.status.hero.hp = 0; - core.updateStatusBar(); - core.events.lose(); - } else { - core.updateStatusBar(); - } - } - core.doAction(); -} - -events.prototype._action_setValue2 = function (data, x, y, prefix) { - this._action_addValue(data, x, y, prefix); -} - -events.prototype._action_addValue = function (data, x, y, prefix) { - this.addValue(data.name, data.value, prefix); + this.setValue(data.name, data.operator, data.value, prefix); if (!data.norefresh) { if (core.status.hero.hp <= 0) { core.status.hero.hp = 0; @@ -1662,7 +1635,7 @@ events.prototype._action_setHeroIcon = function (data, x, y, prefix) { } events.prototype._action_input = function (data, x, y, prefix) { - this.__action_getInput(data.text, false, function (value) { + this.__action_getInput(core.replaceText(data.text, prefix), false, function (value) { value = Math.abs(parseInt(value) || 0); core.status.route.push("input:" + value); core.setFlag("input", value); @@ -1671,7 +1644,7 @@ events.prototype._action_input = function (data, x, y, prefix) { } events.prototype._action_input2 = function (data, x, y, prefix) { - this.__action_getInput(data.text, true, function (value) { + this.__action_getInput(core.replaceText(data.text, prefix), true, function (value) { value = value || ""; core.status.route.push("input2:" + core.encodeBase64(value)); core.setFlag("input", value); @@ -1746,23 +1719,29 @@ events.prototype._action_choices = function (data, x, y, prefix) { }) if (data.choices.length == 0) return this.doAction(); if (core.isReplaying()) { - var action = core.status.replay.toReplay.shift(), index; + var action = core.status.replay.toReplay.shift(); // --- 忽略可能的turn事件 if (action == 'turn') action = core.status.replay.toReplay.shift(); - if (action.indexOf("choices:") == 0 && ((index = parseInt(action.substring(8))) >= 0) && index < data.choices.length) { - core.status.event.selection = index; - setTimeout(function () { - core.status.route.push("choices:" + index); - core.insertAction(data.choices[index].action); - core.doAction(); - }, core.status.replay.speed == 24 ? 1 : 750 / Math.max(1, core.status.replay.speed)) - } - else { - core.control._replay_error(action); - return; + if (action.indexOf('choices:') == 0) { + var index = action.substring(8); + if (index == 'none' || ((index = parseInt(index)) >= 0) && index < data.choices.length) { + core.status.event.selection = index; + setTimeout(function () { + core.status.route.push("choices:"+index); + if (index != 'none') { + core.insertAction(data.choices[index].action); + } + core.doAction(); + }, core.status.replay.speed == 24 ? 1 : 750 / Math.max(1, core.status.replay.speed)); + } } + } else if (data.timeout) { + core.status.event.interval = setTimeout(function () { + core.status.route.push("choices:none"); + core.doAction(); + }, data.timeout); } - core.ui.drawChoices(data.text, data.choices); + core.ui.drawChoices(core.replaceText(data.text, prefix), data.choices); } events.prototype._precompile_choices = function (data) { @@ -1776,27 +1755,37 @@ events.prototype._precompile_choices = function (data) { } events.prototype._action_confirm = function (data, x, y, prefix) { - core.status.event.ui = {"text": data.text, "yes": data.yes, "no": data.no}; + core.status.event.ui = {"text": core.replaceText(data.text, prefix), "yes": data.yes, "no": data.no}; if (core.isReplaying()) { - var action = core.status.replay.toReplay.shift(), index; + var action = core.status.replay.toReplay.shift(); // --- 忽略可能的turn事件 if (action == 'turn') action = core.status.replay.toReplay.shift(); - if (action.indexOf("choices:") == 0 && ((index = parseInt(action.substring(8))) >= 0) && index < 2) { - core.status.event.selection = index; - setTimeout(function () { - core.status.route.push("choices:" + index); - if (index == 0) core.insertAction(data.yes); - else core.insertAction(data.no); - core.doAction(); - }, core.status.replay.speed == 24 ? 1 : 750 / Math.max(1, core.status.replay.speed)) - } - else { + if (action.indexOf('choices:') == 0) { + var index = action.substring(8); + if (index == 'none' || ((index = parseInt(index)) >= 0) && index < 2) { + core.status.event.selection = index; + setTimeout(function () { + core.status.route.push("choices:"+index); + if (index != 'none') { + if (index == 0) core.insertAction(data.yes); + else core.insertAction(data.no); + } + core.doAction(); + }, core.status.replay.speed == 24 ? 1 : 750 / Math.max(1, core.status.replay.speed)); + } + } else { core.control._replay_error(action); return; } } else { core.status.event.selection = data["default"] ? 0 : 1; + if (data.timeout) { + core.status.event.interval = setTimeout(function () { + core.status.route.push("choices:none"); + core.doAction(); + }, data.timeout); + } } core.ui.drawConfirmBox(data.text); } @@ -1807,6 +1796,67 @@ events.prototype._precompile_confirm = function (data) { return data; } +events.prototype._action_for = function (data, x, y, prefix) { + // Only support temp:A + if (!/^temp:[A-Z]$/.test(data.name)) { + core.insertAction('循环遍历事件只支持临时变量!'); + return core.doAction(); + } + var from = core.calValue(data.from); + if (typeof from != 'number') { + core.insertAction('循环遍历事件要求【起始点】仅能是数字!'); + return core.doAction(); + } + var letter = data.name.substring(5); + core.setFlag('@temp@' + letter, from); + var toName = '@temp@for-to@' + letter; + var stepName = '@temp@for-step@' + letter; + core.setFlag(toName, data.to); + core.setFlag(stepName, data.step); + var condition = "(function () {"+ + "var to = core.calValue(core.getFlag('" + toName + "'));"+ + "var step = core.calValue(core.getFlag('" + stepName + "'));"+ + "if (typeof step != 'number' || typeof to != 'number') return false;"+ + "if (step == 0) return true;"+ + "var currentValue = core.getFlag('@temp@" + letter + "');"+ + "currentValue += step;"+ + "core.setFlag('@temp@" + letter + "', currentValue);"+ + "if (step > 0) { return currentValue <= to; }"+ + "else { return currentValue >= to; }"+ + "})()"; + return this._action_dowhile({"condition": condition, "data": data.data}, x, y, prefix); +} + +events.prototype._precompile_for = function (data) { + data.from = core.replaceValue(data.from); + data.to = core.replaceValue(data.to); + data.step = core.replaceValue(data.step); + data.data = this.precompile(data.data); + return data; +} + +events.prototype._action_forEach = function (data, x, y, prefix) { + // Only support temp:A + if (!/^temp:[A-Z]$/.test(data.name)) { + core.insertAction(['循环遍历事件只支持临时变量!']); + return core.doAction(); + } + var listName = '@temp@forEach@' + data.name.substring(5); + core.setFlag(listName, core.clone(data.list)); + var condition = "(function () {" + + "var list = core.getFlag('"+listName+"', []);"+ + "if (list.length == 0) return false;"+ + "core.setFlag('@temp@'+'" + data.name.substring(5) + "', list.shift());"+ + "return true;"+ + "})()"; + return this._action_while({"condition": condition, "data": data.data}, x, y, prefix); +} + +events.prototype._precompile_forEach = function (data) { + data.data = this.precompile(data.data); + return data; +} + events.prototype._action_while = function (data, x, y, prefix) { if (core.calValue(data.condition, prefix)) { core.unshift(core.status.event.data.list, @@ -1851,11 +1901,11 @@ events.prototype._action_continue = function (data, x, y, prefix) { } events.prototype._action_win = function (data, x, y, prefix) { - this.win(core.replaceText(data.reason), data.norank, data.noexit); + this.win(core.replaceText(data.reason, prefix), data.norank, data.noexit); } events.prototype._action_lose = function (data, x, y, prefix) { - this.lose(core.replaceText(data.reason)); + this.lose(core.replaceText(data.reason, prefix)); } events.prototype._action_restart = function (data, x, y, prefix) { @@ -1876,7 +1926,7 @@ events.prototype._action_function = function (data, x, y, prefix) { } events.prototype._action_update = function (data, x, y, prefix) { - core.updateStatusBar(); + core.updateStatusBar(data.doNotCheckAutoEvents); core.doAction(); } @@ -1917,10 +1967,15 @@ events.prototype._action_wait = function (data, x, y, prefix) { if (core.isReplaying()) { var code = core.status.replay.toReplay.shift(); if (code.indexOf("input:") == 0) { - var value = parseInt(code.substring(6)); - core.status.route.push("input:" + value); - this.__action_wait_getValue(value); - this.__action_wait_afterGet(data); + if (code == "input:none") { + core.status.route.push("input:none"); + core.removeFlag("type"); + } else { + var value = parseInt(code.substring(6)); + core.status.route.push("input:" + value); + this.__action_wait_getValue(value); + this.__action_wait_afterGet(data); + } } else { main.log("录像文件出错!当前需要一个 input: 项,实际为 " + code); @@ -1929,6 +1984,12 @@ events.prototype._action_wait = function (data, x, y, prefix) { } core.doAction(); return; + } else if (data.timeout) { + core.status.event.interval = setTimeout(function() { + core.status.route.push("input:none"); + core.removeFlag("type"); + core.doAction(); + }, data.timeout); } } @@ -1960,9 +2021,11 @@ events.prototype.__action_wait_afterGet = function (data) { var todo = []; data.data.forEach(function (one) { if (one["case"] == "keyboard" && core.getFlag("type") == 0) { - if (one["keycode"] == core.getFlag("keycode", 0)) { - core.push(todo, one.action); - } + (one.keycode + "").split(",").forEach(function (keycode) { + if (core.getFlag("keycode", 0) == keycode) { + core.push(todo, one.action); + } + }); } if (one["case"] == "mouse" && one.px instanceof Array && one.py instanceof Array && core.getFlag("type") == 1) { @@ -2000,13 +2063,6 @@ events.prototype._action_waitAsync = function (data, x, y, prefix) { }, 50); } -events.prototype._action_revisit = function (data, x, y, prefix) { - var block = core.getBlock(x, y); - if (block != null && block.block.event.trigger == 'action') - this.setEvents(block.block.event.data); - core.doAction(); -} - events.prototype._action_callBook = function (data, x, y, prefix) { if (core.isReplaying() || !core.hasItem('book')) { core.doAction(); @@ -2086,10 +2142,12 @@ events.prototype._action_clearMap = function (data, x, y, prefix) { } events.prototype._action_fillText = function (data, x, y, prefix) { + data.text = core.replaceText(data.text, prefix); this.__action_doUIEvent(data); } events.prototype._action_fillBoldText = function (data, x, y, prefix) { + data.text = core.replaceText(data.text, prefix); this.__action_doUIEvent(data); } @@ -2156,6 +2214,7 @@ events.prototype._action_drawBackground = function (data, x, y, prefix) { } events.prototype._action_drawTextContent = function (data, x, y, prefix) { + data.text = core.replaceText(data.text, prefix); this.__action_doUIEvent(data); } @@ -2207,14 +2266,14 @@ events.prototype.useFly = function (fromUserAction) { if (core.isReplaying()) return; if (!this._checkStatus('fly', fromUserAction, true)) return; if (core.flags.flyNearStair && !core.nearStair()) { - core.drawTip("只有在楼梯边才能使用传送器"); + core.drawTip("只有在楼梯边才能使用" + core.material.items['fly'].name); core.unLockControl(); core.status.event.data = null; core.status.event.id = null; return; } if (!core.canUseItem('fly')) { - core.drawTip("楼层传送器好像失效了"); + core.drawTip(core.material.items['fly'].name + "好像失效了"); core.unLockControl(); core.status.event.data = null; core.status.event.id = null; @@ -2254,13 +2313,17 @@ events.prototype.openQuickShop = function (fromUserAction) { // --- 如果只有一个商店,则直接打开之 if (Object.keys(core.status.shops).length == 1) { var shopId = Object.keys(core.status.shops)[0]; - if (core.status.event.id != null || !this._checkStatus('shop', false)) return; - var reason = core.events.canUseQuickShop(shopId); - if (!core.flags.enableDisabledShop && reason) { - core.drawText(reason); + if (core.status.event.id != null) return; + if (!core.canOpenShop(shopId)) { + core.drawTip("当前无法打开快捷商店!"); return; } - core.events.openShop(shopId, true); + var message = core.canUseQuickShop(shopId); + if (message != null) { + core.drawTip(message); + return; + } + core.openShop(shopId, false); return; } @@ -2322,7 +2385,6 @@ events.prototype.hasAsync = function () { ////// 跟随 ////// events.prototype.follow = function (name) { - core.status.hero.followers = core.status.hero.followers || []; name = core.getMappedName(name); if (core.material.images.images[name]) { core.status.hero.followers.push({"name": name}); @@ -2334,7 +2396,6 @@ events.prototype.follow = function (name) { ////// 取消跟随 ////// events.prototype.unfollow = function (name) { - core.status.hero.followers = core.status.hero.followers || []; if (!name) { core.status.hero.followers = []; } @@ -2353,13 +2414,24 @@ events.prototype.unfollow = function (name) { } ////// 数值操作 ////// -events.prototype.setValue = function (name, value, prefix, add) { - var value = core.calValue(value, prefix); - if (add) value += core.calValue(name, prefix); +events.prototype.setValue = function (name, operator, value, prefix) { + value = core.calValue(value, prefix); + var originValue = core.calValue(name, prefix); + switch (operator) { + case '+=': value = originValue + value; break; + case '-=': value = originValue - value; break; + case '*=': value = originValue * value; break; + case '/=': value = originValue / value; break; + case '**=': value = Math.pow(originValue, value); break; + case '//=': value = Math.trunc(originValue / value); break; + case '%=': value = originValue % value; break; + default: break; + } this._setValue_setStatus(name, value); this._setValue_setItem(name, value); this._setValue_setFlag(name, value); this._setValue_setSwitch(name, value, prefix); + this._setValue_setTemp(name, value, prefix); this._setValue_setGlobal(name, value); } @@ -2385,6 +2457,11 @@ events.prototype._setValue_setSwitch = function (name, value, prefix) { core.setFlag((prefix || ":f@x@y") + "@" + name.substring(7), value); } +events.prototype._setValue_setTemp = function (name, value) { + if (name.indexOf("temp:") !== 0) return; + core.setFlag("@temp@" + name.substring(5), value); +} + events.prototype._setValue_setGlobal = function (name, value) { if (name.indexOf("global:") !== 0) return; core.setGlobal(name.substring(7), value); @@ -2392,17 +2469,7 @@ events.prototype._setValue_setGlobal = function (name, value) { ////// 数值增减 ////// events.prototype.addValue = function (name, value, prefix) { - this.setValue(name, value, prefix, true); -} - -////// 执行一个表达式的effect操作 ////// -events.prototype.doEffect = function (effect, need, times) { - effect.split(";").forEach(function (expression) { - var arr = expression.split("+="); - if (arr.length != 2) return; - var name=arr[0], value=core.calValue(arr[1], null, need, times); - core.addValue(name, value); - }); + this.setValue(name, '+=', value, prefix); } ////// 设置一个怪物属性 ////// @@ -2443,8 +2510,15 @@ events.prototype.setGlobalAttribute = function (name, value) { ////// 设置全局开关 ////// events.prototype.setGlobalFlag = function (name, value) { var flags = core.getFlag("globalFlags", {}); - flags[name] = value; - core.flags[name] = value; + if (name.startsWith('s:')) { + name = name.substring(2); + var statusBarItems = core.flags.statusBarItems.filter(function (v) {return v!=name;}); + if (value) statusBarItems.push(name); + core.flags.statusBarItems = statusBarItems; + flags.statusBarItems = core.clone(statusBarItems); + } else { + flags[name] = core.flags.name = value; + } core.setFlag("globalFlags", flags); core.resize(); if (name == 'blurFg') @@ -2453,15 +2527,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) { @@ -2668,7 +2747,7 @@ events.prototype._vibrate_update = function (shakeInfo) { /////// 使用事件让勇士移动。这个函数将不会触发任何事件 ////// events.prototype.eventMoveHero = function(steps, time, callback) { - time = time || core.values.moveSpeed || 100; + time = time || core.values.moveSpeed; var step = 0, moveSteps = (steps||[]).filter(function (t) { return ['up','down','left','right','forward','backward'].indexOf(t)>=0; }); @@ -2760,86 +2839,6 @@ events.prototype._jumpHero_finished = function (animate, ex, ey, callback) { if (callback) callback(); } -////// 打开一个全局商店 ////// -events.prototype.openShop = function (shopId, needVisited) { - var shop = core.status.shops[shopId]; - shop.times = shop.times || 0; - if (shop.commonTimes) shop.times = core.getFlag('commonTimes', 0); - if (needVisited && !shop.visited) { - if (!core.flags.enableDisabledShop || shop.commonEvent || shop.item) { - if (shop.times == 0) core.drawTip("该项尚未开启"); - else core.drawTip("该项已失效"); - core.ui.closePanel(); - return; - } - else { - core.drawTip("该商店尚未开启,只能浏览不可使用"); - } - } - else shop.visited = true; - - if (shop.item) { - core.status.route.push("shop:" + shopId + ":0"); - if (core.openItemShop) { - core.openItemShop(shopId); - } else { - core.insertAction("道具商店插件不存在!请检查是否存在该插件!"); - } - return; - } else 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); -} - -events.prototype._useShop = function (shop, index) { - var reason = core.events.canUseQuickShop(shop.id); - if (!reason && !shop.visited) reason = shop.times ? "该商店已失效" : "该商店尚未开启"; - if (reason) { - core.drawTip(reason); - return false; - } - var use = shop.use, choice = shop.choices[index]; - var times = shop.times, need = core.calValue(choice.need || shop.need, null, null, times); - if (need > core.getStatus(use)) { - core.drawTip("你的" + (use == 'money' ? "金币" : "经验") + "不足"); - return false; - } - core.status.event.selection = index; - core.status.event.data.actions.push(index); - core.setStatus(use, core.getStatus(use) - need); - core.doEffect(choice.effect, need, times); - core.updateStatusBar(); - shop.times++; - if (shop.commonTimes) core.setFlag('commonTimes', shop.times); - this.openShop(shop.id); - return true; -} - -events.prototype._exitShop = function () { - if (core.status.event.data.actions.length > 0) { - core.status.route.push("shop:" + core.status.event.data.id + ":" + core.status.event.data.actions.join("")); - } - core.status.event.data.actions = []; - core.status.boxAnimateObjs = []; - if (core.status.event.data.fromList) - core.ui.drawQuickShop(); - else - core.ui.closePanel(); -} - -////// 禁用一个全局商店 ////// -events.prototype.disableQuickShop = function (shopId) { - core.status.shops[shopId].visited = false; -} - -////// 能否使用快捷商店 ////// -events.prototype.canUseQuickShop = function (shopId) { - return this.eventdata.canUseQuickShop(shopId); -} - ////// 设置角色行走图 ////// events.prototype.setHeroIcon = function (name, noDraw) { name = core.getMappedName(name); @@ -2865,16 +2864,16 @@ events.prototype.checkLvUp = function () { } events.prototype._checkLvUp_check = function () { - if (!core.flags.enableLevelUp || !core.firstData.levelUp + if (core.flags.statusBarItems.indexOf('enableLevelUp')>=0 || !core.firstData.levelUp || core.status.hero.lv >= core.firstData.levelUp.length) return null; // 计算下一个所需要的数值 var next = (core.firstData.levelUp[core.status.hero.lv] || {}); var need = core.calValue(next.need); if (need == null) return null; - if (core.status.hero.experience >= need) { + if (core.status.hero.exp >= need) { // 升级 core.status.hero.lv++; - if (next.clear) core.status.hero.experience -= need; + if (next.clear) core.status.hero.exp -= need; return next.action || []; } return null; @@ -2891,35 +2890,3 @@ events.prototype.tryUseItem = function (itemId) { if (core.canUseItem(itemId)) core.useItem(itemId); else core.drawTip("当前无法使用" + core.material.items[itemId].name); } - -////// 使用炸弹/圣锤后的事件 ////// -events.prototype.afterUseBomb = function () { - return this.eventdata.afterUseBomb(); -} - -////// 上传当前数据 ////// -events.prototype._uploadCurrent = function (username) { - var formData = new FormData(); - - formData.append('type', 'score'); - formData.append('name', core.firstData.name); - formData.append('version', core.firstData.version); - formData.append('platform', core.platform.string); - formData.append('hard', core.encodeBase64(core.status.hard)); - formData.append('username', core.encodeBase64(username || "current")); - formData.append('lv', core.status.hero.lv); - formData.append('hp', Math.min(core.status.hero.hp, Math.pow(2, 63))); - formData.append('atk', core.status.hero.atk); - formData.append('def', core.status.hero.def); - formData.append('mdef', core.status.hero.mdef); - formData.append('money', core.status.hero.money); - formData.append('experience', core.status.hero.experience); - formData.append('steps', core.status.hero.steps); - formData.append('seed', core.getFlag('__seed__')); - formData.append('totalTime', Math.floor(core.status.hero.statistics.totalTime / 1000)); - formData.append('route', core.encodeRoute(core.status.route)); - formData.append('deler', 'current'); - formData.append('base64', 1); - - core.http("POST", "/games/upload.php", formData); -} diff --git a/libs/extensions.js b/libs/extensions.js index d7e6fba5..f3450523 100644 --- a/libs/extensions.js +++ b/libs/extensions.js @@ -1,3 +1,5 @@ +/// + /* extensions.js:负责拓展插件 */ diff --git a/libs/icons.js b/libs/icons.js index 12b78828..a21780f3 100644 --- a/libs/icons.js +++ b/libs/icons.js @@ -1,3 +1,5 @@ +/// + "use strict"; function icons() { @@ -25,6 +27,15 @@ icons.prototype.getClsFromId = function (id) { return null; } +icons.prototype.getAllIconIds = function () { + if (this.allIconIds) return this.allIconIds; + this.allIconIds = []; + for (var type in this.icons) { + this.allIconIds = this.allIconIds.concat(Object.keys(this.icons[type])); + } + return this.allIconIds; +} + icons.prototype._getAnimateFrames = function (cls, useOriginValue) { if (cls == 'enemys' || cls == 'npcs') { return 2; diff --git a/libs/items.js b/libs/items.js index 4f0fa179..41c9d61c 100644 --- a/libs/items.js +++ b/libs/items.js @@ -1,3 +1,5 @@ +/// + "use strict"; function items() { @@ -24,35 +26,6 @@ items.prototype.getItems = function () { return core.clone(this.items); } -items.prototype._resetItems = function () { - // 只有运行时才能执行此函数! - if (main.mode != 'play') return; - - // 根据flag来对道具进行修改 - if (core.flags.bigKeyIsBox) { - core.material.items.bigKey.cls = 'items'; - core.material.items.bigKey.name = '钥匙盒'; - } - if (core.flags.pickaxeFourDirections) - core.material.items.pickaxe.text = "可以破坏勇士四周的墙"; - if (core.flags.bombFourDirections) - core.material.items.bomb.text = "可以炸掉勇士四周的怪物"; - if (core.flags.snowFourDirections) - core.material.items.snow.text = "可以将四周的熔岩变成平地"; - if (core.flags.equipment) { - core.material.items.sword1.cls = 'equips'; - core.material.items.sword2.cls = 'equips'; - core.material.items.sword3.cls = 'equips'; - core.material.items.sword4.cls = 'equips'; - core.material.items.sword5.cls = 'equips'; - core.material.items.shield1.cls = 'equips'; - core.material.items.shield2.cls = 'equips'; - core.material.items.shield3.cls = 'equips'; - core.material.items.shield4.cls = 'equips'; - core.material.items.shield5.cls = 'equips'; - } -} - ////// “即捡即用类”道具的使用效果 ////// items.prototype.getItemEffect = function (itemId, itemNum) { var itemCls = core.material.items[itemId].cls; @@ -79,6 +52,7 @@ items.prototype.getItemEffect = function (itemId, itemNum) { main.log(e); } } + core.updateStatusBar(); } else { core.addItem(itemId, itemNum); @@ -145,9 +119,6 @@ items.prototype._afterUseItem = function (itemId) { core.status.hero.items[itemCls][itemId]--; if (core.status.hero.items[itemCls][itemId] <= 0) delete core.status.hero.items[itemCls][itemId]; - - if (!core.status.event.id) - core.status.event.ui = null; core.updateStatusBar(); } @@ -156,21 +127,15 @@ items.prototype.canUseItem = function (itemId) { // 没有道具 if (!core.hasItem(itemId)) return false; - var able = false; if (itemId in this.canUseItemEffect) { try { - able = eval(this.canUseItemEffect[itemId]); + return eval(this.canUseItemEffect[itemId]); } catch (e) { main.log(e); + return false; } } - if (!able) { - core.status.event.data = null; - core.status.event.ui = null; - } - - return able; } ////// 获得某个物品的个数 ////// @@ -209,8 +174,7 @@ items.prototype.setItem = function (itemId, itemNum) { core.status.hero.items[itemCls][itemId] = itemNum; if (core.status.hero.items[itemCls][itemId] <= 0) { - if (itemCls != 'keys') delete core.status.hero.items[itemCls][itemId]; - else core.status.hero.items[itemCls][itemId] = 0; + delete core.status.hero.items[itemCls][itemId]; } core.updateStatusBar(); } @@ -226,8 +190,7 @@ items.prototype.addItem = function (itemId, itemNum) { } core.status.hero.items[itemCls][itemId] += itemNum; if (core.status.hero.items[itemCls][itemId] <= 0) { - if (itemCls != 'keys') delete core.status.hero.items[itemCls][itemId]; - else core.status.hero.items[itemCls][itemId] = 0; + delete core.status.hero.items[itemCls][itemId]; } // 永久道具只能有一个 if (itemCls == 'constants' && core.status.hero.items[itemCls][itemId] > 1) @@ -242,8 +205,7 @@ items.prototype.removeItem = function (itemId, itemNum) { var itemCls = core.material.items[itemId].cls; core.status.hero.items[itemCls][itemId] -= itemNum; if (core.status.hero.items[itemCls][itemId] <= 0) { - if (itemCls != 'keys') delete core.status.hero.items[itemCls][itemId]; - else core.status.hero.items[itemCls][itemId] = 0; + delete core.status.hero.items[itemCls][itemId]; } core.updateStatusBar(); return true; diff --git a/libs/loader.js b/libs/loader.js index 563df8a5..88b92b02 100644 --- a/libs/loader.js +++ b/libs/loader.js @@ -1,3 +1,5 @@ +/// + /* loader.js:负责对资源的加载 diff --git a/libs/maps.js b/libs/maps.js index a5cb4ada..0ff7ba5d 100644 --- a/libs/maps.js +++ b/libs/maps.js @@ -1,3 +1,5 @@ +/// + "use strict"; function maps() { @@ -88,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; @@ -103,8 +109,14 @@ maps.prototype.initBlock = function (x, y, id, addInfo, eventFloor) { else if (core.icons.getTilesetOffset(id)) block.event = {"cls": "tileset", "id": "X" + id, "noPass": true}; else block.event = {'cls': 'terrains', 'id': 'none', 'noPass': false}; - if (typeof block.event.noPass === 'string') - block.event.noPass = JSON.parse(block.event.noPass); + if (block.event.noPass == null) { + if (block.event.canPass == null) { + block.event.noPass = block.event.cls != 'items'; + } else { + block.event.noPass = !block.event.canPass; + } + } + delete block.event.canPass; if (addInfo) this._addInfo(block); if (eventFloor) { @@ -124,11 +136,6 @@ maps.prototype._addInfo = function (block) { if (block.event.cls == 'items' && !block.event.trigger) { block.event.trigger = 'getItem'; } - if (block.event.noPass == null) { - if (block.event.cls != 'items') { - block.event.noPass = true; - } - } if (block.event.animate == null) { block.event.animate = core.icons._getAnimateFrames(block.event.cls, false); } @@ -509,6 +516,7 @@ maps.prototype._canMoveHero_checkCannotInOut = function (number, name, direction } return false; } + if (name == 'cannotIn') direction = core.reverseDirection(direction); return core.inArray((this.getBlockByNumber(number).event || {})[name], direction); } @@ -588,7 +596,7 @@ maps.prototype._canMoveDirectly_bfs = function (sx, sy, locs, number, ans) { if (!core.inArray(canMoveArray[x][y], direction)) continue; var nx = x + core.utils.scan[direction].x, ny = y + core.utils.scan[direction].y, nindex = nx + "," + ny; if (visited[nindex]) continue; - if (bgMap[ny][nx] == 167) continue; + if (core.onSki(bgMap[ny][nx])) continue; if (!this._canMoveDirectly_checkNextPoint(blocksObj, nx, ny)) continue; visited[nindex] = visited[now] + 1; // if (nx == ex && ny == ey) return visited[nindex]; @@ -612,7 +620,8 @@ maps.prototype._canMoveDirectly_bfs = function (sx, sy, locs, number, ans) { maps.prototype._canMoveDirectly_checkNextPoint = function (blocksObj, x, y) { var index = x + "," + y; // 该点是否有事件 - if (blocksObj[index] && (blocksObj[index].event.trigger || blocksObj[index].event.noPass)) return false; + if (blocksObj[index] && (blocksObj[index].event.trigger || blocksObj[index].event.noPass + || blocksObj[index].event.script)) return false; // 是否存在阻激夹域伤害 if (core.status.checkBlock.damage[index]) return false; // 是否存在捕捉 @@ -678,8 +687,8 @@ maps.prototype._automaticRoute_deepAdd = function (x, y) { if (id == "light") deepAdd += 100; // 绕过路障 if (id.endsWith("Net")) deepAdd += 100; - // 绕过血瓶 - if (!core.flags.potionWhileRouting && id.endsWith("Potion")) deepAdd += 100; + // 绕过血瓶和绿宝石 + if (core.hasFlag('__potionNoRouting__') && (id.endsWith("Potion") || id == 'greenJewel')) deepAdd += 100; // 绕过传送点 // if (block.block.event.trigger == 'changeFloor') deepAdd+=10; } @@ -743,8 +752,10 @@ maps.prototype._drawBlockInfo_bgfg = function (blockInfo, name, x, y) { maps.prototype.generateGroundPattern = function (floorId) { // 生成floorId层的groundPattern(盒子内的怪物动画) var groundId = ((core.status.maps || core.floors)[floorId || core.status.floorId] || {}).defaultGround || "ground"; + var groundInfo = core.getBlockInfo(groundId); + if (groundInfo == null) return; core.material.groundCanvas.clearRect(0, 0, 32, 32); - core.material.groundCanvas.drawImage(core.material.images.terrains, 0, 32 * core.material.icons.terrains[groundId], 32, 32, 0, 0, 32, 32); + core.material.groundCanvas.drawImage(groundInfo.image, 32 * groundInfo.posX, groundInfo.height * groundInfo.posY, 32, 32, 0, 0, 32, 32); core.material.groundPattern = core.material.groundCanvas.createPattern(core.material.groundCanvas.canvas, 'repeat'); // 如果需要用纯色可以直接将下面代码改成改成 // core.material.groundPattern = '#000000'; @@ -813,11 +824,11 @@ maps.prototype.drawBg = function (floorId, ctx) { maps.prototype._drawBg_drawBackground = function (floorId, ctx) { var width = core.floors[floorId].width, height = core.floors[floorId].height; var groundId = (core.status.maps || core.floors)[floorId].defaultGround || "ground"; - var yOffset = core.material.icons.terrains[groundId]; - if (yOffset != null) { + var groundInfo = core.getBlockInfo(groundId); + if (groundInfo != null) { for (var i = 0; i < width; i++) { for (var j = 0; j < height; j++) { - ctx.drawImage(core.material.images.terrains, 0, yOffset * 32, 32, 32, i * 32, j * 32, 32, 32); + ctx.drawImage(groundInfo.image, 32 * groundInfo.posX, groundInfo.height * groundInfo.posY, 32, 32, i * 32, j * 32, 32, 32); } } } @@ -1408,7 +1419,7 @@ maps.prototype.searchBlock = function (id, floorId, showDisable) { } for (var i = 0; i < core.status.maps[floorId].blocks.length; ++i) { var block = core.status.maps[floorId].blocks[i]; - if ((showDisable || !block.disable) && core.matchWildcard(id, block.event.id)) { + if ((showDisable || !block.disable) && (core.matchWildcard(id, block.event.id) || core.matchRegex(id, block.event.id))) { result.push({floorId: floorId, index: i, block: block, x: block.x, y: block.y}); } } @@ -1460,10 +1471,10 @@ maps.prototype.hideBlock = function (x, y, floorId) { ////// 将某个块从启用变成禁用状态 ////// maps.prototype.removeBlock = function (x, y, floorId) { floorId = floorId || core.status.floorId; - if (!floorId) return; + if (!floorId) return false; var block = core.getBlock(x, y, floorId, true); - if (block == null) return; // 不存在 + if (block == null) return false; // 不存在 var index = block.index; @@ -1477,12 +1488,13 @@ maps.prototype.removeBlock = function (x, y, floorId) { } // 删除Index - core.removeBlockById(index, floorId); + core.removeBlockByIndex(index, floorId); core.updateStatusBar(); + return true; } ////// 根据block的索引(尽可能)删除该块 ////// -maps.prototype.removeBlockById = function (index, floorId) { +maps.prototype.removeBlockByIndex = function (index, floorId) { floorId = floorId || core.status.floorId; if (!floorId) return; @@ -1497,13 +1509,11 @@ maps.prototype.removeBlockById = function (index, floorId) { } ////// 一次性删除多个block ////// -maps.prototype.removeBlockByIds = function (floorId, ids) { - floorId = floorId || core.status.floorId; - if (!floorId) return; - ids.sort(function (a, b) { - return b - a - }).forEach(function (id) { - core.removeBlockById(id, floorId); +maps.prototype.removeBlockByIndexes = function (indexes, floorId) { + indexes.sort(function (a, b) { + return b - a; + }).forEach(function (index) { + core.removeBlockByIndex(index, floorId); }); } @@ -1769,6 +1779,7 @@ maps.prototype._getAndRemoveBlock = function (x, y) { ////// 显示移动某块的动画,达到{“type”:”move”}的效果 ////// maps.prototype.moveBlock = function (x, y, steps, time, keep, callback) { + if (core.status.replay.speed == 24) time = 1; time = time || 500; var blockArr = this._getAndRemoveBlock(x, y); if (blockArr == null) { @@ -1930,6 +1941,7 @@ maps.prototype._moveJumpBlock_finished = function (blockInfo, canvases, info, an ////// 显示/隐藏某个块时的动画效果 ////// maps.prototype.animateBlock = function (loc, type, time, callback) { + if (core.status.replay.speed == 24) time = 1; var isHide = type == 'hide'; if (typeof loc[0] == 'number' && typeof loc[1] == 'number') loc = [loc]; @@ -2048,7 +2060,7 @@ maps.prototype.drawBoxAnimate = function () { } ////// 绘制动画 ////// -maps.prototype.drawAnimate = function (name, x, y, callback) { +maps.prototype.drawAnimate = function (name, x, y, alignWindow, callback) { name = core.getMappedName(name); // 正在播放录像:不显示动画 @@ -2059,6 +2071,10 @@ maps.prototype.drawAnimate = function (name, x, y, callback) { // 开始绘制 var animate = core.material.animates[name], centerX = 32 * x + 16, centerY = 32 * y + 16; + if (alignWindow) { + centerX += core.bigmap.offsetX; + centerY += core.bigmap.offsetY; + } // 播放音效 core.playSound(animate.se); diff --git a/libs/ui.js b/libs/ui.js index 8c11dd0b..b1ca9d0e 100644 --- a/libs/ui.js +++ b/libs/ui.js @@ -1,3 +1,5 @@ +/// + /** * ui.js:负责所有和UI界面相关的绘制 * 包括: @@ -101,13 +103,15 @@ ui.prototype._fillTextWithMaxWidth = function (ctx, text, x, y, maxWidth) { } ////// 在某个canvas上绘制粗体 ////// -ui.prototype.fillBoldText = function (name, text, x, y, style, font) { +ui.prototype.fillBoldText = function (name, text, x, y, style, strokeStyle, font) { var ctx = this.getContextByName(name); if (!ctx) return; if (font) ctx.font = font; if (!style) style = ctx.fillStyle; if (style instanceof Array) style = core.arrayToRGBA(style); - ctx.fillStyle = '#000000'; + if (!strokeStyle) strokeStyle = '#000000'; + if (strokeStyle instanceof Array) strokeStyle = core.arrayToRGBA(strokeStyle); + ctx.fillStyle = strokeStyle; ctx.fillText(text, x-1, y-1); ctx.fillText(text, x-1, y+1); ctx.fillText(text, x+1, y-1); @@ -118,7 +122,7 @@ ui.prototype.fillBoldText = function (name, text, x, y, style, font) { ui.prototype._uievent_fillBoldText = function (data) { this._createUIEvent(); - this.fillBoldText('uievent', core.replaceText(data.text), core.calValue(data.x), core.calValue(data.y), data.style, data.font); + this.fillBoldText('uievent', core.replaceText(data.text), core.calValue(data.x), core.calValue(data.y), data.style, data.strokeStyle, data.font); } ////// 在某个canvas上绘制一个矩形 ////// @@ -356,23 +360,56 @@ ui.prototype.splitLines = function (name, text, maxWidth, font) { if (!ctx) return [text]; if (font) core.setFont(name, font); + // 不能在行首的标点 + var forbidStart = "))】》>﹞>)]»›〕〉}]」}〗』" + ",。?!:;·…,.?!:;、……~&@#~&@#"; + // 不能在行尾的标点 + var forbidEnd = "((【《<﹝<([«‹〔〈{[「{〖『"; + var contents = []; var last = 0; + var forceChangeLine = false; // 是否强制换行,避免多个连续forbidStart存在 for (var i = 0; i < text.length; i++) { if (text.charAt(i) == '\n') { contents.push(text.substring(last, i)); last = i + 1; + forceChangeLine = false; } else if (text.charAt(i) == '\\' && text.charAt(i + 1) == 'n') { contents.push(text.substring(last, i)); last = i + 2; + forceChangeLine = false; } else { + var curr = text.charAt(i); var toAdd = text.substring(last, i + 1); var width = core.calWidth(name, toAdd); if (maxWidth && width > maxWidth) { + // --- 当前应当换行,然而还是检查一下是否是forbidStart + if (!forceChangeLine && forbidStart.indexOf(curr) >= 0) { + forceChangeLine = true; + continue; + } contents.push(text.substring(last, i)); last = i; + forceChangeLine = false; + } else { + // --- 当前不应该换行;但是提前检查一下是否是行尾标点 + var curr = text.charAt(i); + if (forbidEnd.indexOf(curr) >= 0 && i < text.length -1) { + // 检查是否是行尾 + var nextcurr = text.charAt(i+1); + // 确认不是手动换行 + if (nextcurr != '\n' && !(nextcurr == '\\' && text.charAt(i+2) == 'n')) { + var toAdd = text.substring(last, i+2); + var width = core.calWidth(name, toAdd); + if (maxWidth && width > maxWidth) { + // 下一项会换行,因此在此处换行 + contents.push(text.substring(last, i)); + last = i; + forceChangeLine = false; + } + } + } } } } @@ -411,7 +448,8 @@ ui.prototype._uievent_drawImage = function (data) { core.calValue(data.x1), core.calValue(data.y1), core.calValue(data.w1), core.calValue(data.h1)); } -ui.prototype.drawIcon = function (name, id, x, y, w, h) { +ui.prototype.drawIcon = function (name, id, x, y, w, h, frame) { + frame = frame || 0; var ctx = this.getContextByName(name); if (!ctx) return; var info = core.getBlockInfo(id); @@ -421,7 +459,7 @@ ui.prototype.drawIcon = function (name, id, x, y, w, h) { info = {image: core.statusBar.icons[id], posX: 0, posY: 0, height: 32}; else return; } - ctx.drawImage(info.image, 32 * info.posX, info.height * info.posY, 32, info.height, x, y, w || 32, h || info.height); + ctx.drawImage(info.image, 32 * (info.posX + frame), info.height * info.posY, 32, info.height, x, y, w || 32, h || info.height); } ui.prototype._uievent_drawIcon = function (data) { @@ -431,13 +469,21 @@ ui.prototype._uievent_drawIcon = function (data) { id = core.calValue(data.id); if (typeof id !== 'string') id = data.id; } catch (e) { id = data.id; } - this.drawIcon('uievent', id, core.calValue(data.x), core.calValue(data.y), core.calValue(data.width), core.calValue(data.height)); + this.drawIcon('uievent', id, core.calValue(data.x), core.calValue(data.y), core.calValue(data.width), core.calValue(data.height), data.frame||0); } ///////////////// UI绘制 ////// 结束一切事件和绘制,关闭UI窗口,返回游戏进程 ////// ui.prototype.closePanel = function () { + if (core.status.hero && core.status.hero.flags) { + // 清除全部临时变量 + Object.keys(core.status.hero.flags).forEach(function (name) { + if (name.startsWith("@temp@")) { + delete core.status.hero.flags[name]; + } + }); + } this.clearUI(); core.maps.generateGroundPattern(); core.updateStatusBar(true); @@ -458,14 +504,14 @@ ui.prototype.clearUI = function () { } ////// 左上角绘制一段提示 ////// -ui.prototype.drawTip = function (text, id, clear) { - this.clearTip(); +ui.prototype.drawTip = function (text, id, frame) { var one = { text: text, textX: 21, width: 26 + core.calWidth('data', text, "16px Arial"), opacity: 0.1, stage: 1, + frame: frame || 0, time: 0 }; if (id != null) { @@ -473,7 +519,7 @@ ui.prototype.drawTip = function (text, id, clear) { if (info == null || !info.image) { // 检查状态栏图标 if (core.statusBar.icons[id] instanceof Image) { - id = {image: core.statusBar.icons[id], posX: 0, posY: 0, height: 32}; + info = {image: core.statusBar.icons[id], posX: 0, posY: 0, height: 32}; } else info = null; } @@ -486,25 +532,21 @@ ui.prototype.drawTip = function (text, id, clear) { one.width += 24; } } - core.animateFrame.tips.list.push(one); - if (core.animateFrame.tips.list.length > 3) { - core.animateFrame.tips.list.shift(); - } + core.animateFrame.tip = one; } -ui.prototype._drawTip_drawOne = function (one, offset) { - core.setAlpha('data', one.opacity); - core.fillRect('data', 5, offset+ 5, one.width, 42, '#000000'); - if (one.image) - core.drawImage('data', one.image, one.posX * 32, one.posY * one.height, 32, 32, 10, offset + 10, 32, 32); - core.fillText('data', one.text, one.textX, offset + 33, '#FFFFFF'); +ui.prototype._drawTip_drawOne = function (tip) { + core.setAlpha('data', tip.opacity); + core.fillRect('data', 5, 5, tip.width, 42, '#000000'); + if (tip.image) + core.drawImage('data', tip.image, (tip.posX + tip.frame) * 32, tip.posY * tip.height, 32, 32, 10, 10, 32, 32); + core.fillText('data', tip.text, tip.textX, 33, '#FFFFFF'); core.setAlpha('data', 1); } ui.prototype.clearTip = function () { - core.animateFrame.tips.list = []; - core.animateFrame.tips.offset = 0; - core.animateFrame.tips.lastSize = 0; + core.clearMap('data', 0, 0, this.PIXEL, 50); + core.animateFrame.tip = null; } ////// 地图中间绘制一段文字 ////// @@ -606,7 +648,7 @@ ui.prototype._getPosition = function (content) { var str = s3.split(','); px = py = null; if (str.length == 1) { - var follower = (core.status.hero.followers||[])[parseInt(str[0])-1]; + var follower = core.status.hero.followers[parseInt(str[0])-1]; if (follower) { px = follower.x; py = follower.y; @@ -651,6 +693,14 @@ ui.prototype._uievent_drawSelector = function (data) { this._drawSelector(ctx, background, w, h); } +ui.prototype._clearUIEventSelector = function (codes) { + if (codes instanceof Array) { + codes.forEach(function (code) { core.ui._clearUIEventSelector(code); }); + return; + } + core.deleteCanvas('_uievent_selector_' + (codes || 0)); +} + ui.prototype._drawSelector = function (ctx, background, w, h, left, top) { left = left || 0; top = top || 0; @@ -866,7 +916,7 @@ ui.prototype.drawTextContent = function (ctx, content, config) { config.index = 0; config.currcolor = config.color; config.currfont = config.fontSize; - config.lineMargin = Math.max(0, config.lineHeight - config.fontSize); + config.lineMargin = Math.max(Math.round(config.fontSize / 4), config.lineHeight - config.fontSize); config.topMargin = parseInt(config.lineMargin / 2); config.lineMaxHeight = config.lineMargin + config.fontSize; config.offsetX = 0; @@ -906,9 +956,11 @@ ui.prototype._drawTextContent_draw = function (ctx, tempCtx, content, config) { var _drawNext = function () { if (config.index >= config.blocks.length) return false; var block = config.blocks[config.index++]; - ctx.drawImage(tempCtx.canvas, block.left, block.top, block.width, block.height, - config.left + block.left + block.marginLeft, config.top + block.top + block.marginTop, - block.width, block.height); + if (block != null) { + ctx.drawImage(tempCtx.canvas, block.left, block.top, block.width, block.height, + config.left + block.left + block.marginLeft, config.top + block.top + block.marginTop, + block.width, block.height); + } return true; } if (config.time == 0) { @@ -960,6 +1012,7 @@ ui.prototype._drawTextContent_drawChar = function (tempCtx, content, config, ch) tempCtx.font = this._buildFont(config.currfont, config.bold, config.italic); return true; } + if (c == 'z') return this._drawTextContent_emptyChar(tempCtx, content, config); } // \\e 斜体切换 if (ch == '\\' && content.charAt(config.index)=='e') { @@ -993,6 +1046,7 @@ ui.prototype._drawTextContent_newLine = function (tempCtx, config) { marginLeft = totalWidth - width; config.blocks.forEach(function (b) { + if (b == null) return; if (b.line == config.line) { b.marginLeft = marginLeft; // b.marginTop = 0; // 上对齐 @@ -1037,6 +1091,23 @@ ui.prototype._drawTextContent_changeFont = function (tempCtx, content, config) { return this._drawTextContent_next(tempCtx, content, config); } +ui.prototype._drawTextContent_emptyChar = function (tempCtx, content, config) { + config.index++; + var index = config.index, index2; + if (content.charAt(index) == '[' && ((index2=content.indexOf(']', index))>=0)) { + var str = content.substring(index+1, index2); + if (/^\d+$/.test(str)) { + var value = parseInt(str); + for (var i = 0; i < value; ++i) { + config.blocks.push(null); // Empty char + } + } else config.blocks.push(null); + config.index = index2 + 1; + } + else config.blocks.push(null); + return this._drawTextContent_next(tempCtx, content, config); +} + ui.prototype._drawTextContent_drawIcon = function (tempCtx, content, config) { // 绘制一个 \i 效果 var index = config.index, index2; @@ -1071,7 +1142,7 @@ ui.prototype.getTextContentHeight = function (content, config) { } ui.prototype._getRealContent = function (content) { - return content.replace(/(\r|\\(r|c|d|e))(\[.*?])?/g, "").replace(/(\\i)(\[.*?])?/g, "占1"); + return content.replace(/(\r|\\(r|c|d|e|z))(\[.*?])?/g, "").replace(/(\\i)(\[.*?])?/g, "占1"); } ////// 绘制一个对话框 ////// @@ -1165,7 +1236,7 @@ ui.prototype._drawTextBox_getHorizontalPosition = function (content, titleInfo, ui.prototype._drawTextBox_getVerticalPosition = function (content, titleInfo, posInfo, validWidth) { var textAttribute = core.status.textAttribute || core.initStatus.textAttribute; - var lineHeight = textAttribute.textfont + 6; + var lineHeight = textAttribute.lineHeight || (textAttribute.textfont + 6); var height = 45 + this.getTextContentHeight(content, { lineHeight: lineHeight, maxWidth: validWidth }); @@ -1416,7 +1487,7 @@ ui.prototype._drawChoices_drawChoices = function (choices, isWindowSkin, hPos, v core.fillText('ui', choices[i].text, offset, vPos.choice_top + 32 * i, color); } - if (choices.length>0) { + if (choices.length>0 && core.status.event.selection != 'none') { core.status.event.selection = core.status.event.selection || 0; while (core.status.event.selection < 0) core.status.event.selection += choices.length; while (core.status.event.selection >= choices.length) core.status.event.selection -= choices.length; @@ -1442,7 +1513,7 @@ ui.prototype.drawConfirmBox = function (text, yesCallback, noCallback) { core.status.event.data = {'yes': yesCallback, 'no': noCallback}; } - if (core.status.event.selection != 0) core.status.event.selection = 1; + if (core.status.event.selection != 0 && core.status.event.selection != 'none') core.status.event.selection = 1; this.clearUI(); core.setFont('ui', this._buildFont(19, true)); @@ -1458,14 +1529,15 @@ ui.prototype.drawConfirmBox = function (text, yesCallback, noCallback) { core.fillText('ui', "确定", this.HPIXEL - 38, rect.bottom - 35, null, this._buildFont(17, true)); core.fillText('ui', "取消", this.HPIXEL + 38, rect.bottom - 35); - var len=core.calWidth('ui', "确定"); - var strokeLeft = this.HPIXEL + (76*core.status.event.selection-38) - parseInt(len/2) - 5; - - if (isWindowSkin) - this.drawWindowSelector(core.status.textAttribute.background, strokeLeft, rect.bottom-35-20, len+10, 28); - else - core.strokeRect('ui', strokeLeft, rect.bottom-35-20, len+10, 28, "#FFD700", 2); - + if (core.status.event.selection != 'none') { + var len=core.calWidth('ui', "确定"); + var strokeLeft = this.HPIXEL + (76*core.status.event.selection-38) - parseInt(len/2) - 5; + + if (isWindowSkin) + this.drawWindowSelector(core.status.textAttribute.background, strokeLeft, rect.bottom-35-20, len+10, 28); + else + core.strokeRect('ui', strokeLeft, rect.bottom-35-20, len+10, 28, "#FFD700", 2); + } } ui.prototype._drawConfirmBox_getRect = function (contents) { @@ -1501,10 +1573,11 @@ ui.prototype.drawSwitchs = function() { " < 音量:" + Math.round(Math.sqrt(100 * core.musicStatus.userVolume)) + " > ", //数值越大耗时越长 " < 步时:" + core.values.moveSpeed + " > ", + " < 转场:" + core.values.floorChangeTime + " > ", "怪物显伤: "+(core.flags.displayEnemyDamage ? "[ON]" : "[OFF]"), "临界显伤: "+(core.flags.displayCritical ? "[ON]" : "[OFF]"), "领域显伤: "+(core.flags.displayExtraDamage ? "[ON]" : "[OFF]"), - "新版存档: "+(core.platform.useLocalForage ? "[ON]":"[OFF]"), + "血瓶绕路: "+(core.hasFlag('__potionNoRouting__') ? "[ON]":"[OFF]"), "单击瞬移: "+(!core.hasFlag("__noClickMove__") ? "[ON]":"[OFF]"), "返回主菜单" ]; @@ -1515,18 +1588,16 @@ ui.prototype.drawSwitchs = function() { ui.prototype.drawSettings = function () { core.status.event.id = 'settings'; this.drawChoices(null, [ - "系统设置", "虚拟键盘", "浏览地图", "绘图模式", "同步存档", "游戏信息", "返回标题", "返回游戏" + "系统设置", "虚拟键盘", "浏览地图", "同步存档", "游戏信息", "返回标题", "返回游戏" ]); } ////// 绘制快捷商店选择栏 ////// ui.prototype.drawQuickShop = function () { core.status.event.id = 'selectShop'; - var shopList = core.status.shops, keys = Object.keys(shopList).filter(function (shopId) { - return shopList[shopId].visited || !shopList[shopId].mustEnable - }); + var shopList = core.status.shops, keys = core.listShopIds(); var choices = keys.map(function (shopId) { - return {"text": shopList[shopId].textInList, "color": shopList[shopId].visited?null:"#999999"}; + return {"text": shopList[shopId].textInList, "color": core.isShopVisited(shopId) ? null : "#999999"}; }); choices.push("返回游戏"); this.drawChoices(null, choices); @@ -1738,9 +1809,9 @@ ui.prototype._drawBook_drawRow2 = function (index, enemy, top, left, width, posi var col1 = left, col2 = left + width * 9 / 25, col3 = left + width * 17 / 25; // 获得第二行绘制的内容 var second_line = []; - if (core.flags.enableMoney) second_line.push(["金币", core.formatBigNumber(enemy.money || 0)]); + if (core.flags.statusBarItems.indexOf('enableMoney')>=0) second_line.push(["金币", core.formatBigNumber(enemy.money || 0)]); if (core.flags.enableAddPoint) second_line.push(["加点", core.formatBigNumber(enemy.point || 0)]); - if (core.flags.enableExperience) second_line.push(["经验", core.formatBigNumber(enemy.experience || 0)]); + if (core.flags.statusBarItems.indexOf('enableExp')>=0) second_line.push(["经验", core.formatBigNumber(enemy.exp || 0)]); var damage_offset = col1 + (this.PIXEL - col1) / 2 - 12; // 第一列 @@ -2004,37 +2075,10 @@ ui.prototype.drawCenterFly = function () { offsetY = core.clamp(toY - core.__HALF_SIZE__, 0, core.bigmap.height - core.__SIZE__); core.fillRect('ui', (toX - offsetX) * 32, (toY - offsetY) * 32, 32, 32, fillstyle); core.status.event.data = {"x": toX, "y": toY, "posX": toX - offsetX, "posY": toY - offsetY}; - core.drawTip("请确认当前中心对称飞行器的位置"); + core.drawTip("请确认当前"+core.material.items['centerFly'].name+"的位置"); return; } -////// 绘制全局商店 -ui.prototype.drawShop = function (shopId) { - var shop = core.status.shops[shopId]; - var actions = [], fromList = (core.status.event.data||{}).fromList, selection = core.status.event.selection; - if (core.status.event.data && core.status.event.data.actions) actions=core.status.event.data.actions; - - core.ui.closePanel(); - core.lockControl(); - core.status.event.id = 'shop'; - core.status.event.data = {'id': shopId, 'shop': shop, 'actions': actions, 'fromList': fromList}; - core.status.event.selection = selection; - - var times = shop.times, need=core.calValue(shop.need, null, null, times); - var content = "\t["+shop.name+","+shop.icon+"]" + core.replaceText(shop.text, need, times); - var use = shop.use=='experience'?'经验':'金币'; - var choices = []; - for (var i=0;i= core.__PIXELS__) { // 换行 @@ -2531,7 +2566,7 @@ ui.prototype._drawSLPanel_drawRecord = function(title, data, x, y, size, cho, hi var v2 = "/"+core.formatBigNumber(data.hero.mdef,true); if (core.calWidth('ui', v + v2, this._buildFont(10, false)) <= size) v += v2; core.fillText('ui', v, x, y+30+size, '#FFD700'); - core.fillText('ui', core.formatDate(new Date(data.time)), x, y+43+size, data.hero.flags.__consoleOpened__||data.hero.flags.debug?'#FF6A6A':'#FFFFFF'); + core.fillText('ui', core.formatDate(new Date(data.time)), x, y+43+size, data.hero.flags.debug?'#FF6A6A':'#FFFFFF'); } else { core.fillRect('ui', x-size/2, y+15, size, size, '#333333', 2); @@ -2632,10 +2667,10 @@ ui.prototype.drawStatistics = function (floorIds) { +",总游戏时长"+core.formatTime(statistics.totalTime) +"。\n瞬间移动次数:"+statistics.moveDirectly+",共计少走"+statistics.ignoreSteps+"步。" +"\n\n总计通过血瓶恢复生命值为"+core.formatBigNumber(statistics.hp)+"点。\n\n" - +"总计打死了"+statistics.battle+"个怪物,得到了"+core.formatBigNumber(statistics.money)+"金币,"+core.formatBigNumber(statistics.experience)+"点经验。\n\n" + +"总计打死了"+statistics.battle+"个怪物,得到了"+core.formatBigNumber(statistics.money)+"金币,"+core.formatBigNumber(statistics.exp)+"点经验。\n\n" +"受到的总伤害为"+core.formatBigNumber(statistics.battleDamage+statistics.poisonDamage+statistics.extraDamage) +",其中战斗伤害"+core.formatBigNumber(statistics.battleDamage)+"点" - +(core.flags.enableDebuff?(",中毒伤害"+core.formatBigNumber(statistics.poisonDamage)+"点"):"") + +(core.flags.statusBarItems.indexOf('enableDebuff')>=0?(",中毒伤害"+core.formatBigNumber(statistics.poisonDamage)+"点"):"") +",领域/夹击/阻击/血网伤害"+core.formatBigNumber(statistics.extraDamage)+"点。", "\t[说明]1. 地图数据统计的效果仅模拟当前立刻获得该道具的效果。\n2. 不会计算“不可被浏览地图”的隐藏层的数据。\n" + "3. 不会计算任何通过事件得到的道具(显示事件、改变图块、或直接增加道具等)。\n"+ @@ -2663,7 +2698,7 @@ ui.prototype._drawStatistics_buildObj = function () { else cls[e] = core.material.items[e].cls; cnt[e] = 0; }) - var order = ["doors", "keys", "items", "tools", "constants", "equips"]; + var order = ["doors", "items", "tools", "constants", "equips"]; ids.sort(function (a, b) { var c1 = order.indexOf(cls[a]), c2 = order.indexOf(cls[b]); if (c1==c2) return ori.indexOf(a)-ori.indexOf(b); @@ -2671,7 +2706,7 @@ ui.prototype._drawStatistics_buildObj = function () { }); var obj = { 'monster': { - 'count': 0, 'money': 0, 'experience': 0, 'point': 0, + 'count': 0, 'money': 0, 'exp': 0, 'point': 0, }, 'count': cnt, 'add': { @@ -2708,7 +2743,7 @@ ui.prototype._drawStatistics_floorId = function (floorId, obj) { ui.prototype._drawStatistics_enemy = function (floorId, id, obj) { var enemy = core.material.enemys[id]; this._drawStatistics_add(floorId, obj, 'monster', 'money', enemy.money); - this._drawStatistics_add(floorId, obj, 'monster', 'experience', enemy.experience); + this._drawStatistics_add(floorId, obj, 'monster', 'exp', enemy.exp); this._drawStatistics_add(floorId, obj, 'monster', 'point', enemy.point); this._drawStatistics_add(floorId, obj, 'monster', 'count', 1); } @@ -2737,7 +2772,7 @@ ui.prototype._drawStatistics_items = function (floorId, floor, id, obj) { var t = ""; if (atk > 0) t += atk + "攻"; if (def > 0) t += def + "防"; - if (mdef > 0) t += mdef + "魔防"; + if (mdef > 0) t += mdef + "护盾"; if (t != "") obj.ext[id] = t; } this._drawStatistics_add(floorId, obj, 'count', id, 1); @@ -2750,8 +2785,8 @@ ui.prototype._drawStatistics_items = function (floorId, floor, id, obj) { ui.prototype._drawStatistics_generateText = function (obj, type, data) { var text = type+"地图中:\n"; text += "共有怪物"+data.monster.count+"个"; - if (core.flags.enableMoney) text+=",总金币数"+data.monster.money; - if (core.flags.enableExperience) text+=",总经验数"+data.monster.experience; + if (core.flags.statusBarItems.indexOf('enableMoney')>=0) text+=",总金币数"+data.monster.money; + if (core.flags.statusBarItems.indexOf('enableExp')>=0) text+=",总经验数"+data.monster.exp; if (core.flags.enableAddPoint) text+=",总加点数"+data.monster.point; text+="。\n"; @@ -2765,71 +2800,26 @@ ui.prototype._drawStatistics_generateText = function (obj, type, data) { } else text += ","; prev = obj.cls[key]; - text+=core.ui._drawStatistics_getName(key)+value+"个"; + var name = ((core.material.items[key] || (core.getBlockById(key) || {}).event)||{}).name || key; + text+=name+value+"个"; if (obj.ext[key]) text+="("+obj.ext[key]+")"; }) if (prev!="") text+="。"; - text+="\n\n"; + text+="\n"; text+="共加生命值"+core.formatBigNumber(data.add.hp)+"点,攻击" +core.formatBigNumber(data.add.atk)+"点,防御" - +core.formatBigNumber(data.add.def)+"点,魔防" + +core.formatBigNumber(data.add.def)+"点,护盾" +core.formatBigNumber(data.add.mdef)+"点。"; return text; } -ui.prototype._drawStatistics_getName = function (key) { - return {"yellowDoor": "黄门", "blueDoor": "蓝门", "redDoor": "红门", "greenDoor": "绿门", - "steelDoor": "铁门"}[key] || core.material.items[key].name; -} - ////// 绘制“关于”界面 ////// ui.prototype.drawAbout = function () { return this.uidata.drawAbout(); } -////// 绘制“画图”界面 ////// -ui.prototype.drawPaint = function () { - core.drawText( - "\t[进入绘图模式]你可以在此页面上任意进行绘图和标记操作。\nM键可以进入或退出此模式。\n\n"+ - "绘图的内容会自动保存,且以页面为生命周期,和存读档无关,重新开始游戏或读档后绘制的内容仍有效,但刷新页面就会消失。\n"+ - "你可以将绘制内容保存到文件,也可以从文件读取保存的绘制内容。\n"+ - "浏览地图页面可以按楼传按钮或M键来开启/关闭该层的绘图显示。\n\n更多功能请详见文档-元件-绘图模式。", - this._drawPaint_draw - ); -} - -ui.prototype._drawPaint_draw = function () { - core.drawTip("打开绘图模式,现在可以任意在界面上绘图标记"); - - core.lockControl(); - core.status.event.id = 'paint'; - core.status.event.data = {"x": null, "y": null, "erase": false}; - - core.clearUI(); - core.createCanvas('paint', -core.bigmap.offsetX, -core.bigmap.offsetY, 32*core.bigmap.width, 32*core.bigmap.height, 95); - - // 将已有的内容绘制到route上 - var value = core.paint[core.status.floorId]; - if (value) value = lzw_decode(value).split(","); - core.utils._decodeCanvas(value, 32*core.bigmap.width, 32*core.bigmap.height); - core.drawImage('paint', core.bigmap.tempCanvas.canvas, 0, 0); - - core.setLineWidth('paint', 3); - core.setStrokeStyle('paint', '#FF0000'); - - core.statusBar.image.keyboard.style.opacity = 0; - core.statusBar.image.shop.style.opacity = 0; - - core.statusBar.image.book.src = core.statusBar.icons.paint.src; - core.statusBar.image.fly.src = core.statusBar.icons.erase.src; - core.statusBar.image.toolbox.src = core.statusBar.icons.empty.src; - core.statusBar.image.settings.src = core.statusBar.icons.exit.src; - core.statusBar.image.book.style.opacity = 1; - core.statusBar.image.fly.style.opacity = 1; -} - ////// 绘制帮助页面 ////// ui.prototype.drawHelp = function () { core.clearUI(); @@ -2844,13 +2834,13 @@ ui.prototype.drawHelp = function () { core.drawText([ "\t[键盘快捷键列表]"+ "[CTRL] 跳过对话 [Z] 转向\n" + - "[X] 怪物手册 [G] 楼层传送\n" + - "[A] 读取自动存档 [S/D] 存读档页面\n" + + "[X] "+core.material.items['book'].name + " [G] "+core.material.items['fly'].name+"\n" + + "[A] 读取自动存档 [W] 撤销读取自动存档\n" + + "[S/D] 存读档页面 [SPACE] 轻按\n" + "[V] 快捷商店 [ESC] 系统菜单\n" + "[T] 道具页面 [Q] 装备页面\n" + "[B] 数据统计 [H] 帮助页面\n" + "[R] 回放录像 [E] 显示光标\n" + - "[SPACE] 轻按 [M] 绘图模式\n" + "[N] 返回标题页面 [P] 游戏主页\n" + "[O] 查看工程 [F7] 打开debug穿墙模式\n" + "[PgUp/PgDn] 浏览地图\n"+ diff --git a/libs/utils.js b/libs/utils.js index 009625ff..9f3df032 100644 --- a/libs/utils.js +++ b/libs/utils.js @@ -1,3 +1,5 @@ +/// + /* utils.js 工具类 @@ -60,9 +62,10 @@ utils.prototype._init = function () { } ////// 将文字中的${和}(表达式)进行替换 ////// -utils.prototype.replaceText = function (text, need, times) { +utils.prototype.replaceText = function (text, prefix) { + if (typeof text != 'string') return text; return text.replace(/\${(.*?)}/g, function (word, value) { - return core.calValue(value, null, need, times); + return core.calValue(value, prefix); }); } @@ -79,19 +82,21 @@ utils.prototype.replaceValue = function (value) { if (value.indexOf('global:') >= 0) value = value.replace(/global:([a-zA-Z0-9_\u4E00-\u9FCC]+)/g, "core.getGlobal('$1', 0)"); if (value.indexOf('enemy:')>=0) - value = value.replace(/enemy:([a-zA-Z0-9_]+)\.([a-zA-Z0-9_]+)/g, "core.material.enemys['$1'].$2"); + value = value.replace(/enemy:([a-zA-Z0-9_]+)[\.:]([a-zA-Z0-9_]+)/g, "core.material.enemys['$1'].$2"); if (value.indexOf('blockId:')>=0) value = value.replace(/blockId:(\d+),(\d+)/g, "core.getBlockId($1, $2)"); if (value.indexOf('blockCls:')>=0) value = value.replace(/blockCls:(\d+),(\d+)/g, "core.getBlockCls($1, $2)"); if (value.indexOf('equip:')>=0) value = value.replace(/equip:(\d)/g, "core.getEquip($1)"); + if (value.indexOf('temp:')>=0) + value = value.replace(/temp:([a-zA-Z0-9_]+)/g, "core.getFlag('@temp@$1', 0)"); } return value; } ////// 计算表达式的值 ////// -utils.prototype.calValue = function (value, prefix, need, times) { +utils.prototype.calValue = function (value, prefix) { if (!core.isset(value)) return null; if (typeof value === 'string') { if (value.indexOf(':') >= 0) { @@ -591,7 +596,7 @@ utils.prototype._decodeRoute_decodeOne = function (decodeObj, c) { decodeObj.ans.push("choices:" + nxt); break; case "S": - decodeObj.ans.push("shop:" + nxt + ":" + this._decodeRoute_getNumber(decodeObj, true)); + decodeObj.ans.push("shop:" + nxt); break; case "T": decodeObj.ans.push("turn"); @@ -692,9 +697,23 @@ utils.prototype.reverseDirection = function (direction) { } utils.prototype.matchWildcard = function (pattern, string) { - return new RegExp('^' + pattern.split(/\*+/).map(function (s) { - return s.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&'); - }).join('.*') + '$').test(string); + try { + return new RegExp('^' + pattern.split(/\*+/).map(function (s) { + return s.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&'); + }).join('.*') + '$').test(string); + } catch (e) { + return false; + } +} + +utils.prototype.matchRegex = function (pattern, string) { + try { + if (pattern.startsWith("^")) pattern = pattern.substring(1); + if (pattern.endsWith("$")) pattern = pattern.substring(0, pattern.length - 1); + return new RegExp("^" + pattern + "$").test(string); + } catch (e) { + return false; + } } ////// Base64加密 ////// @@ -711,26 +730,6 @@ utils.prototype.decodeBase64 = function (str) { }).join('')); } -////// 任意进制转换 ////// -utils.prototype.convertBase = function (str, fromBase, toBase) { - var map = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~`!@#$%^&*()_-+={}[]\\|:;<>,.?/"; - if (fromBase == toBase) return str; - var len = str.length, ans = ""; - var t = []; - for (var i = 0; i < len; i++) t[i] = map.indexOf(str.charAt(i)); - t[len] = 0; - while (len > 0) { - for (var i = len; i >= 1; i--) { - t[i - 1] += t[i] % toBase * fromBase; - t[i] = parseInt(t[i] / toBase); - } - ans += map.charAt(t[0] % toBase); - t[0] = parseInt(t[0] / toBase); - while (len > 0 && t[len - 1] == 0) len--; - } - return ans; -} - utils.prototype.rand = function (num) { var rand = core.getFlag('__rand__'); rand = this.__next_rand(rand); @@ -1073,17 +1072,6 @@ utils.prototype._decodeCanvas = function (arr, width, height) { tempCanvas.putImageData(imgData, 0, 0); } -utils.prototype.consoleOpened = function () { - if (!core.flags.checkConsole) return false; - if (window.Firebug && window.Firebug.chrome && window.Firebug.chrome.isInitialized) - return true; - if (!core.platform.isPC) return false; - var threshold = 160; - var zoom = Math.min(window.outerWidth / window.innerWidth, window.outerHeight / window.innerHeight); - return window.outerWidth - zoom * window.innerWidth > threshold - || window.outerHeight - zoom * window.innerHeight > threshold; -} - utils.prototype.hashCode = function (obj) { if (typeof obj == 'string') { var hash = 0, i, chr; diff --git a/main.js b/main.js index d9e3534a..e6206b82 100644 --- a/main.js +++ b/main.js @@ -61,7 +61,7 @@ function main() { 'defCol': document.getElementById('defCol'), 'mdefCol': document.getElementById('mdefCol'), 'moneyCol': document.getElementById('moneyCol'), - 'experienceCol': document.getElementById('experienceCol'), + 'expCol': document.getElementById('expCol'), 'upCol': document.getElementById('upCol'), 'keyCol': document.getElementById('keyCol'), 'pzfCol': document.getElementById('pzfCol'), @@ -100,7 +100,7 @@ function main() { 'def': document.getElementById("img-def"), 'mdef': document.getElementById("img-mdef"), 'money': document.getElementById("img-money"), - 'experience': document.getElementById("img-experience"), + 'exp': document.getElementById("img-exp"), 'up': document.getElementById("img-up"), 'skill': document.getElementById('img-skill'), 'book': document.getElementById("img-book"), @@ -130,7 +130,7 @@ function main() { 'def': 5, 'mdef': 6, 'money': 7, - 'experience': 8, + 'exp': 8, 'up': 9, 'book': 10, 'fly': 11, @@ -149,18 +149,14 @@ function main() { 'equipbox': 24, 'mana': 25, 'skill': 26, - 'paint': 27, - 'erase': 28, - 'empty': 29, - 'exit': 30, - 'btn1': 31, - 'btn2': 32, - 'btn3': 33, - 'btn4': 34, - 'btn5': 35, - 'btn6': 36, - 'btn7': 37, - 'btn8': 38 + 'btn1': 27, + 'btn2': 28, + 'btn3': 29, + 'btn4': 30, + 'btn5': 31, + 'btn6': 32, + 'btn7': 33, + 'btn8': 34 }, 'floor': document.getElementById('floor'), 'name': document.getElementById('name'), @@ -172,12 +168,13 @@ function main() { 'def': document.getElementById("def"), 'mdef': document.getElementById('mdef'), 'money': document.getElementById("money"), - 'experience': document.getElementById("experience"), + 'exp': document.getElementById("exp"), 'up': document.getElementById('up'), 'skill': document.getElementById('skill'), 'yellowKey': document.getElementById("yellowKey"), 'blueKey': document.getElementById("blueKey"), 'redKey': document.getElementById("redKey"), + 'greenKey': document.getElementById("greenKey"), 'poison': document.getElementById('poison'), 'weak':document.getElementById('weak'), 'curse': document.getElementById('curse'), @@ -536,11 +533,6 @@ main.statusBar.image.book.onclick = function (e) { return; } - if (main.core.isPlaying() && (core.status.event||{}).id=='paint') { - core.actions.setPaintMode('paint'); - return; - } - if (main.core.isPlaying()) main.core.openBook(true); } @@ -555,12 +547,6 @@ main.statusBar.image.fly.onclick = function (e) { return; } - // 绘图模式 - if (main.core.isPlaying() && (core.status.event||{}).id=='paint') { - core.actions.setPaintMode('erase'); - return; - } - if (main.core.isPlaying()) { if (!main.core.flags.equipboxButton) { main.core.useFly(true); @@ -580,11 +566,6 @@ main.statusBar.image.toolbox.onclick = function (e) { return; } - if (main.core.isPlaying() && (core.status.event||{}).id=='paint') { - core.actions.clearPaint(); - return; - } - if (main.core.isPlaying()) { main.core.openToolbox(core.status.event.id != 'equipbox'); } @@ -616,7 +597,7 @@ main.statusBar.image.keyboard.onclick = function (e) { main.core.openKeyBoard(true); } -////// 点击状态栏中的快捷商店键盘时 ////// +////// 点击状态栏中的快捷商店时 ////// main.statusBar.image.shop.onclick = function (e) { e.stopPropagation(); @@ -629,7 +610,7 @@ main.statusBar.image.shop.onclick = function (e) { main.core.openQuickShop(true); } -////// 点击金币时也可以开启虚拟键盘 ////// +////// 点击金币时也可以开启快捷商店 ////// main.statusBar.image.money.onclick = function (e) { e.stopPropagation(); @@ -646,11 +627,6 @@ main.statusBar.image.save.onclick = function (e) { return; } - if (main.core.isPlaying() && (core.status.event||{}).id=='paint') { - core.actions.savePaint(); - return; - } - if (main.core.isPlaying()) main.core.save(true); } @@ -664,11 +640,6 @@ main.statusBar.image.load.onclick = function (e) { return; } - if (main.core.isPlaying() && (core.status.event||{}).id=='paint') { - core.actions.loadPaint(); - return; - } - if (main.core.isPlaying()) main.core.load(true); } @@ -682,11 +653,6 @@ main.statusBar.image.settings.onclick = function (e) { return; } - if (main.core.isPlaying() && (core.status.event||{}).id=='paint') { - core.actions.exitPaint(); - return; - } - if (main.core.isPlaying()) main.core.openSettings(true); } diff --git a/project/data.js b/project/data.js index f5c220f7..49445eab 100644 --- a/project/data.js +++ b/project/data.js @@ -91,14 +91,9 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = "def": 100, "mdef": 0, "money": 0, - "experience": 0, + "exp": 0, "equipment": [], "items": { - "keys": { - "yellowKey": 0, - "blueKey": 0, - "redKey": 0 - }, "constants": {}, "tools": {}, "equips": {} @@ -109,6 +104,7 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = "y": 10 }, "flags": {}, + "followers": [], "steps": 0 }, "startCanvas": [ @@ -128,8 +124,6 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = 0, 0 ], - "dw": 100, - "dh": 100, "opacity": 1, "time": 0 }, @@ -165,11 +159,7 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = "true": [ { "type": "comment", - "text": "直接开始游戏,设置初始化数据" - }, - { - "type": "function", - "function": "function(){\ncore.events.setInitData('')\n}" + "text": "直接开始游戏" } ], "false": [ @@ -179,7 +169,7 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = }, { "type": "function", - "function": "function(){\nvar choices = [];\nmain.levelChoose.forEach(function (one) {\n\tchoices.push({\"text\": one[0], \"action\": [\n\t\t{\"type\": \"function\", \"function\": \"function() { core.status.hard = '\"+one[1]+\"'; core.events.setInitData('\"+one[1]+\"'); }\"}\n\t]});\n})\ncore.insertAction({\"type\": \"choices\", \"choices\": choices});\n}" + "function": "function(){\nvar choices = [];\nmain.levelChoose.forEach(function (one) {\n\tchoices.push({\n\t\t\"text\": one[0],\n\t\t\"action\": [\n\t\t\t{ \"type\": \"function\", \"function\": \"function() { core.status.hard = '\" + one[1] + \"'; }\" }\n\t\t]\n\t});\n})\ncore.insertAction({ \"type\": \"choices\", \"choices\": choices });\n}" } ] }, @@ -232,8 +222,7 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = "type": "function", "function": "function(){\ncore.chooseReplayFile()\n}" } - ], - "false": [] + ] } ] } @@ -247,43 +236,163 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = } ], "startText": [ - "Hi,欢迎来到 HTML5 魔塔样板!\n\n本样板由艾之葵制作,可以让你在不会写任何代码\n的情况下也能做出属于自己的H5魔塔!", - "这里游戏开始时的剧情。\n定义在data.js的startText处。\n\n你可以在这里写上自己的内容。", - "赶快来试一试吧!" - ], - "shops": [ { - "id": "moneyShop1", - "name": "贪婪之神", - "icon": "blueShop", - "textInList": "1F金币商店", - "commonTimes": false, - "mustEnable": false, - "use": "money", - "need": "20+10*times*(times+1)", - "text": "勇敢的武士啊,给我${need}金币就可以:", - "choices": [ + "type": "comment", + "text": "根据难度分歧设置并给其他初始值" + }, + { + "type": "switch", + "condition": "core.status.hard", + "caseList": [ { - "text": "生命+800", - "effect": "status:hp+=800" + "case": "'Easy'", + "action": [ + { + "type": "setValue", + "name": "flag:hard", + "value": "1" + }, + { + "type": "comment", + "text": "可以在这里修改初始道具或属性,比如赠送黄钥匙等" + } + ] + }, + { + "case": "'Normal'", + "action": [ + { + "type": "setValue", + "name": "flag:hard", + "value": "2" + } + ] + }, + { + "case": "'Hard'", + "action": [ + { + "type": "setValue", + "name": "flag:hard", + "value": "3" + } + ] + }, + { + "case": "'Hell'", + "action": [ + { + "type": "setValue", + "name": "flag:hard", + "value": "4" + } + ] } ] }, { - "id": "expShop1", - "name": "经验之神", - "icon": "pinkShop", - "textInList": "1F经验商店", - "commonTimes": false, + "type": "comment", + "text": "初始剧情" + }, + "Hi,欢迎来到 HTML5 魔塔样板!\n\n本样板由艾之葵制作,可以让你在不会写任何代码\n的情况下也能做出属于自己的H5魔塔!", + "这里游戏开始时的剧情。\n\n你可以在这里写上自己的内容。\n赶快来试一试吧!" + ], + "shops": [ + { + "id": "shop1", + "text": "\t[贪婪之神,blueShop]勇敢的武士啊, 给我${20+2*flag:shop1}金币就可以:", + "textInList": "1F金币商店", "mustEnable": false, - "use": "experience", - "need": "-1", - "text": "勇敢的武士啊,给我若干经验就可以:", + "disablePreview": false, "choices": [ { - "text": "等级+1", - "need": "100", - "effect": "status:hp+=1000" + "text": "生命+800", + "need": "status:money>=20+2*flag:shop1", + "action": [ + { + "type": "comment", + "text": "新版商店中需要手动扣减金币和增加访问次数" + }, + { + "type": "setValue", + "name": "status:money", + "operator": "-=", + "value": "20+2*flag:shop1" + }, + { + "type": "setValue", + "name": "flag:shop1", + "operator": "+=", + "value": "1" + }, + { + "type": "setValue", + "name": "status:hp", + "operator": "+=", + "value": "800" + } + ] + }, + { + "text": "攻击+4", + "need": "status:money>=20+2*flag:shop1", + "action": [ + { + "type": "comment", + "text": "新版商店中需要手动扣减金币和增加访问次数" + }, + { + "type": "setValue", + "name": "status:money", + "operator": "-=", + "value": "20+2*flag:shop1" + }, + { + "type": "setValue", + "name": "flag:shop1", + "operator": "+=", + "value": "1" + }, + { + "type": "setValue", + "name": "status:atk", + "operator": "+=", + "value": "4" + } + ] + } + ] + }, + { + "id": "shop2", + "text": "\t[贪婪之神,pinkShop]勇敢的武士啊, 给我一定经验就可以:", + "textInList": "1F经验商店", + "mustEnable": false, + "disablePreview": true, + "choices": [ + { + "text": "等级+1(100经验)", + "need": "status:exp>=100", + "action": [ + { + "type": "setValue", + "name": "status:exp", + "operator": "-=", + "value": "100" + }, + { + "type": "setValue", + "name": "status:lv", + "operator": "+=", + "value": "1" + }, + { + "type": "setValue", + "name": "status:hp", + "operator": "+=", + "value": "1000" + } + ] } ] }, @@ -296,12 +405,13 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = { "id": "yellowKey", "number": 10, - "money": 10 + "money": "10", + "sell": "5" } ] }, { - "id": "keyShop1", + "id": "keyShop", "textInList": "回收钥匙商店", "mustEnable": false, "commonEvent": "回收钥匙商店" @@ -320,17 +430,19 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = }, { "need": "20", - "title": "第二级", + "title": "", "action": [ { "type": "setValue", "name": "status:atk", - "value": "status:atk+10" + "operator": "+=", + "value": "10" }, { "type": "setValue", "name": "status:def", - "value": "status:def+10" + "operator": "+=", + "value": "10" } ] }, @@ -361,40 +473,25 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = "counterAttack": 0.1, "purify": 3, "hatred": 2, - "moveSpeed": 100, - "animateSpeed": 400, - "floorChangeTime": 800 + "animateSpeed": 400 }, "flags": { - "enableFloor": true, - "enableName": false, - "enableLv": false, - "enableHPMax": false, - "enableMana": false, - "enableMDef": true, - "enableMoney": true, - "enableExperience": false, - "enableLevelUp": false, - "levelUpLeftMode": false, - "enableKeys": true, - "enablePZF": false, - "enableDebuff": false, - "enableSkill": false, + "statusBarItems": [ + "enableFloor", + "enableHP", + "enableAtk", + "enableDef", + "enableMDef", + "enableMoney", + "enableKeys" + ], "flyNearStair": true, "flyRecordPosition": false, - "pickaxeFourDirections": false, - "bombFourDirections": false, - "snowFourDirections": false, - "bigKeyIsBox": false, "steelDoorWithoutKey": false, "itemFirstText": false, - "equipment": false, "equipboxButton": false, - "iconInEquipbox": false, "enableAddPoint": false, "enableNegativeDamage": false, - "hatredDecrease": true, - "betweenAttackCeil": false, "betweenAttackMax": false, "useLoop": false, "startUsingCanvas": false, @@ -405,13 +502,10 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = "displayCritical": true, "displayExtraDamage": true, "enableGentleClick": true, - "potionWhileRouting": false, "ignoreChangeFloor": true, "canGoDeadZone": false, "enableMoveDirectly": true, - "enableDisabledShop": true, "disableShopOnDamage": false, - "blurFg": false, - "checkConsole": false + "blurFg": false } } \ No newline at end of file diff --git a/project/enemys.js b/project/enemys.js index 680dc953..29779d70 100644 --- a/project/enemys.js +++ b/project/enemys.js @@ -1,67 +1,67 @@ var enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80 = { - "greenSlime": {"name":"绿头怪","hp":100,"atk":120,"def":0,"money":1,"experience":1,"point":0,"special":[1,5,7,8]}, - "redSlime": {"name":"红头怪","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":[16,18],"value":10}, - "blackSlime": {"name":"青头怪","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "slimelord": {"name":"怪王","hp":100,"atk":120,"def":0,"money":10,"experience":0,"point":0,"special":[1,9]}, - "bat": {"name":"小蝙蝠","hp":100,"atk":120,"def":0,"money":2,"experience":0,"point":0,"special":1}, - "bigBat": {"name":"大蝙蝠","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "redBat": {"name":"红蝙蝠","hp":100,"atk":120,"def":0,"money":5,"experience":0,"point":0,"special":4}, - "vampire": {"name":"冥灵魔王","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "skeleton": {"name":"骷髅人","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "skeletonSoilder": {"name":"骷髅士兵","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "skeletonCaptain": {"name":"骷髅队长","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "ghostSkeleton": {"name":"冥队长","hp":100,"atk":120,"def":0,"money":8,"experience":0,"point":0,"special":7}, - "zombie": {"name":"兽人","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "zombieKnight": {"name":"兽人武士","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "rock": {"name":"石头人","hp":100,"atk":120,"def":0,"money":4,"experience":0,"point":0,"special":3}, - "slimeMan": {"name":"影子战士","hp":100,"atk":0,"def":0,"money":11,"experience":0,"point":0,"special":[10,21],"atkValue":2,"defValue":3}, - "bluePriest": {"name":"初级法师","hp":100,"atk":120,"def":0,"money":3,"experience":0,"point":1,"special":2}, - "redPriest": {"name":"高级法师","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "brownWizard": {"name":"初级巫师","hp":100,"atk":120,"def":0,"money":16,"experience":0,"point":0,"special":15,"value":100,"range":2}, - "redWizard": {"name":"高级巫师","hp":1000,"atk":1200,"def":0,"money":160,"experience":0,"point":0,"special":15,"value":200,"zoneSquare":true}, - "yellowGuard": {"name":"初级卫兵","hp":100,"atk":120,"def":0,"money":10,"experience":0,"point":0,"special":0}, - "blueGuard": {"name":"中级卫兵","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "redGuard": {"name":"高级卫兵","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "swordsman": {"name":"双手剑士","hp":100,"atk":120,"def":0,"money":6,"experience":0,"point":0,"special":[5,23]}, - "soldier": {"name":"冥战士","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "yellowKnight": {"name":"金骑士","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "redKnight": {"name":"红骑士","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "darkKnight": {"name":"黑骑士","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "blackKing": {"name":"黑衣魔王","hp":1000,"atk":500,"def":0,"money":1000,"experience":1000,"point":0,"special":0,"notBomb":true}, - "yellowKing": {"name":"黄衣魔王","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "greenKing": {"name":"青衣武士","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "blueKnight": {"name":"蓝骑士","hp":100,"atk":120,"def":0,"money":9,"experience":0,"point":0,"special":8}, - "goldSlime": {"name":"黄头怪","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "poisonSkeleton": {"name":"紫骷髅","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "poisonBat": {"name":"紫蝙蝠","hp":100,"atk":120,"def":0,"money":14,"experience":0,"point":0,"special":13}, - "steelRock": {"name":"铁面人","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "skeletonPriest": {"name":"骷髅法师","hp":100,"atk":100,"def":0,"money":0,"experience":0,"point":0,"special":18,"value":20}, - "skeletonKing": {"name":"骷髅王","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "skeletonWizard": {"name":"骷髅巫师","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "redSkeletonCaption": {"name":"骷髅武士","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "badHero": {"name":"迷失勇者","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "demon": {"name":"魔神武士","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "demonPriest": {"name":"魔神法师","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "goldHornSlime": {"name":"金角怪","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "redKing": {"name":"红衣魔王","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "whiteKing": {"name":"白衣武士","hp":100,"atk":120,"def":0,"money":17,"experience":0,"point":0,"special":16}, - "blackMagician": {"name":"黑暗大法师","hp":100,"atk":120,"def":0,"money":12,"experience":0,"point":0,"special":11,"value":0.3333333333333333,"add":true,"notBomb":true}, - "silverSlime": {"name":"银头怪","hp":100,"atk":120,"def":0,"money":15,"experience":0,"point":0,"special":14}, - "swordEmperor": {"name":"剑圣","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "whiteHornSlime": {"name":"尖角怪","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "badPrincess": {"name":"痛苦魔女","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "badFairy": {"name":"黑暗仙子","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "grayPriest": {"name":"中级法师","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "redSwordsman": {"name":"剑王","hp":100,"atk":120,"def":0,"money":7,"experience":0,"point":0,"special":6,"n":8}, - "whiteGhost": {"name":"水银战士","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "poisonZombie": {"name":"绿兽人","hp":100,"atk":120,"def":0,"money":13,"experience":0,"point":0,"special":12}, - "magicDragon": {"name":"魔龙","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "octopus": {"name":"血影","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "darkFairy": {"name":"仙子","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "greenKnight": {"name":"强盾骑士","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "angel": {"name":"天使","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "elemental": {"name":"元素生物","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":0}, - "steelGuard": {"name":"铁守卫","hp":0,"atk":0,"def":0,"money":0,"experience":0,"point":0,"special":18,"value":20}, - "evilBat": {"name":"邪恶蝙蝠","hp":1000,"atk":1,"def":0,"money":0,"experience":0,"point":0,"special":[2,3]} + "greenSlime": {"name":"绿头怪","hp":100,"atk":120,"def":0,"money":1,"exp":1,"point":0,"special":[1,5,7,8]}, + "redSlime": {"name":"红头怪","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[16,18],"value":10}, + "blackSlime": {"name":"青头怪","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "slimelord": {"name":"怪王","hp":100,"atk":120,"def":0,"money":10,"exp":0,"point":0,"special":[1,9]}, + "bat": {"name":"小蝙蝠","hp":100,"atk":120,"def":0,"money":2,"exp":0,"point":0,"special":[1]}, + "bigBat": {"name":"大蝙蝠","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "redBat": {"name":"红蝙蝠","hp":100,"atk":120,"def":0,"money":5,"exp":0,"point":0,"special":[4]}, + "vampire": {"name":"冥灵魔王","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "skeleton": {"name":"骷髅人","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "skeletonSoilder": {"name":"骷髅士兵","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "skeletonCaptain": {"name":"骷髅队长","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "ghostSkeleton": {"name":"冥队长","hp":100,"atk":120,"def":0,"money":8,"exp":0,"point":0,"special":[7]}, + "zombie": {"name":"兽人","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "zombieKnight": {"name":"兽人武士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "rock": {"name":"石头人","hp":100,"atk":120,"def":0,"money":4,"exp":0,"point":0,"special":[3]}, + "slimeMan": {"name":"影子战士","hp":100,"atk":0,"def":0,"money":11,"exp":0,"point":0,"special":[10,21],"atkValue":2,"defValue":3}, + "bluePriest": {"name":"初级法师","hp":100,"atk":120,"def":0,"money":3,"exp":0,"point":1,"special":[2]}, + "redPriest": {"name":"高级法师","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "brownWizard": {"name":"初级巫师","hp":100,"atk":120,"def":0,"money":16,"exp":0,"point":0,"special":[15],"value":100,"range":2}, + "redWizard": {"name":"高级巫师","hp":1000,"atk":1200,"def":0,"money":160,"exp":0,"point":0,"special":[15],"value":200,"zoneSquare":true}, + "yellowGuard": {"name":"初级卫兵","hp":100,"atk":120,"def":0,"money":10,"exp":0,"point":0,"special":[]}, + "blueGuard": {"name":"中级卫兵","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "redGuard": {"name":"高级卫兵","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "swordsman": {"name":"双手剑士","hp":100,"atk":120,"def":0,"money":6,"exp":0,"point":0,"special":[5,23]}, + "soldier": {"name":"冥战士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "yellowKnight": {"name":"金骑士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "redKnight": {"name":"红骑士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "darkKnight": {"name":"黑骑士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "blackKing": {"name":"黑衣魔王","hp":1000,"atk":500,"def":0,"money":1000,"exp":1000,"point":0,"special":[],"notBomb":true}, + "yellowKing": {"name":"黄衣魔王","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "greenKing": {"name":"青衣武士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "blueKnight": {"name":"蓝骑士","hp":100,"atk":120,"def":0,"money":9,"exp":0,"point":0,"special":[8]}, + "goldSlime": {"name":"黄头怪","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "poisonSkeleton": {"name":"紫骷髅","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "poisonBat": {"name":"紫蝙蝠","hp":100,"atk":120,"def":0,"money":14,"exp":0,"point":0,"special":[13]}, + "steelRock": {"name":"铁面人","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "skeletonPriest": {"name":"骷髅法师","hp":100,"atk":100,"def":0,"money":0,"exp":0,"point":0,"special":[18],"value":20}, + "skeletonKing": {"name":"骷髅王","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "skeletonWizard": {"name":"骷髅巫师","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "redSkeletonCaption": {"name":"骷髅武士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "badHero": {"name":"迷失勇者","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "demon": {"name":"魔神武士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "demonPriest": {"name":"魔神法师","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "goldHornSlime": {"name":"金角怪","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "redKing": {"name":"红衣魔王","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "whiteKing": {"name":"白衣武士","hp":100,"atk":120,"def":0,"money":17,"exp":0,"point":0,"special":[16]}, + "blackMagician": {"name":"黑暗大法师","hp":100,"atk":120,"def":0,"money":12,"exp":0,"point":0,"special":[11],"value":0.3333333333333333,"add":true,"notBomb":true}, + "silverSlime": {"name":"银头怪","hp":100,"atk":120,"def":0,"money":15,"exp":0,"point":0,"special":[14]}, + "swordEmperor": {"name":"剑圣","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "whiteHornSlime": {"name":"尖角怪","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "badPrincess": {"name":"痛苦魔女","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "badFairy": {"name":"黑暗仙子","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "grayPriest": {"name":"中级法师","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "redSwordsman": {"name":"剑王","hp":100,"atk":120,"def":0,"money":7,"exp":0,"point":0,"special":[6],"n":8}, + "whiteGhost": {"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]}, + "magicDragon": {"name":"魔龙","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "octopus": {"name":"血影","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "darkFairy": {"name":"仙子","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "greenKnight": {"name":"强盾骑士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "angel": {"name":"天使","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "elemental": {"name":"元素生物","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]}, + "steelGuard": {"name":"铁守卫","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[18],"value":20}, + "evilBat": {"name":"邪恶蝙蝠","hp":1000,"atk":1,"def":0,"money":0,"exp":0,"point":0,"special":[2,3]} } \ No newline at end of file diff --git a/project/events.js b/project/events.js index 57aec84c..b6aea258 100644 --- a/project/events.js +++ b/project/events.js @@ -15,7 +15,8 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 = { "type": "setValue", "name": "status:atk", - "value": "status:atk+1*flag:arg1" + "operator": "+=", + "value": "1*flag:arg1" } ] }, @@ -25,7 +26,8 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 = { "type": "setValue", "name": "status:def", - "value": "status:def+2*flag:arg1" + "operator": "+=", + "value": "2*flag:arg1" } ] }, @@ -35,7 +37,8 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 = { "type": "setValue", "name": "status:hp", - "value": "status:hp+200*flag:arg1" + "operator": "+=", + "value": "200*flag:arg1" } ] } @@ -97,14 +100,16 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 = "text": ">=1:直接扣数值" }, { - "type": "addValue", + "type": "setValue", "name": "status:atk", - "value": "-core.values.weakValue" + "operator": "-=", + "value": "core.values.weakValue" }, { - "type": "addValue", + "type": "setValue", "name": "status:def", - "value": "-core.values.weakValue" + "operator": "-=", + "value": "core.values.weakValue" } ], "false": [ @@ -158,90 +163,88 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 = }, { "type": "if", - "condition": "core.canMoveHero()", + "condition": "core.onSki()", "true": [ - { - "type": "comment", - "text": "检测下一个点是否可通行" - }, - { - "type": "setValue", - "name": "flag:nx", - "value": "core.nextX()" - }, - { - "type": "setValue", - "name": "flag:ny", - "value": "core.nextY()" - }, { "type": "if", - "condition": "core.noPass(flag:nx, flag:ny)", + "condition": "core.canMoveHero()", "true": [ { "type": "comment", - "text": "不可通行,触发下一个点的事件" + "text": "检测下一个点是否可通行" }, { - "type": "trigger", - "loc": [ - "flag:nx", - "flag:ny" - ] - } - ], - "false": [ - { - "type": "comment", - "text": "可通行,先移动到下个点,然后检查阻激夹域,并尝试触发该点事件" + "type": "setValue", + "name": "flag:nx", + "value": "core.nextX()" }, { - "type": "moveHero", - "time": 80, - "steps": [ - "forward" - ] - }, - { - "type": "function", - "function": "function(){\ncore.checkBlock();\n}" - }, - { - "type": "comment", - "text": "【触发事件】如果该点存在事件则会立刻结束当前事件" - }, - { - "type": "trigger", - "loc": [ - "flag:nx", - "flag:ny" - ] - }, - { - "type": "comment", - "text": "如果该点不存在事件,则继续检测该点是否是滑冰点" + "type": "setValue", + "name": "flag:ny", + "value": "core.nextY()" }, { "type": "if", - "condition": "core.getBgNumber() == 167", + "condition": "core.noPass(flag:nx, flag:ny)", "true": [ + { + "type": "comment", + "text": "不可通行,触发下一个点的事件" + }, + { + "type": "trigger", + "loc": [ + "flag:nx", + "flag:ny" + ] + } + ], + "false": [ + { + "type": "comment", + "text": "可通行,先移动到下个点,然后检查阻激夹域,并尝试触发该点事件" + }, + { + "type": "moveHero", + "time": 80, + "steps": [ + "forward" + ] + }, + { + "type": "function", + "function": "function(){\ncore.checkBlock();\n}" + }, + { + "type": "comment", + "text": "【触发事件】如果该点存在事件则会立刻结束当前事件" + }, + { + "type": "trigger", + "loc": [ + "flag:nx", + "flag:ny" + ] + }, + { + "type": "comment", + "text": "如果该点不存在事件,则继续检测该点是否是滑冰点" + }, { "type": "function", "function": "function(){\ncore.insertAction(\"滑冰事件\",null,null,null,true)\n}" } - ], - "false": [] + ] } ] } - ], - "false": [] + ] } ], "回收钥匙商店": [ { "type": "comment", - "text": "此事件在全局商店中被引用了(全局商店keyShop1)" + "text": "此事件在全局商店中被引用了(全局商店keyShop)" }, { "type": "comment", @@ -273,13 +276,15 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 = "condition": "item:yellowKey >= 1", "true": [ { - "type": "addValue", + "type": "setValue", "name": "item:yellowKey", - "value": "-1" + "operator": "-=", + "value": "1" }, { - "type": "addValue", + "type": "setValue", "name": "status:money", + "operator": "+=", "value": "10" } ], @@ -303,13 +308,15 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 = "condition": "item:blueKey >= 1", "true": [ { - "type": "addValue", + "type": "setValue", "name": "item:blueKey", - "value": "-1" + "operator": "-=", + "value": "1" }, { - "type": "addValue", + "type": "setValue", "name": "status:money", + "operator": "+=", "value": "50" } ], diff --git a/project/floors/MT0.js b/project/floors/MT0.js index afcc0832..8e98ca33 100644 --- a/project/floors/MT0.js +++ b/project/floors/MT0.js @@ -1,15 +1,15 @@ main.floors.MT0= { -"floorId": "MT0", -"title": "主塔 0 层", -"name": "0", -"canFlyTo": true, -"canUseQuickShop": true, -"cannotViewMap": false, -"defaultGround": "ground", -"images": [], -"item_ratio": 1, -"map": [ + "floorId": "MT0", + "title": "主塔 0 层", + "name": "0", + "canFlyTo": true, + "canUseQuickShop": true, + "cannotViewMap": false, + "defaultGround": "ground", + "images": [], + "item_ratio": 1, + "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], @@ -24,18 +24,21 @@ main.floors.MT0= [ 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] ], -"firstArrive": [], -"parallelDo": "", -"events": {}, -"changeFloor": {}, -"afterBattle": {}, -"afterGetItem": {}, -"afterOpenDoor": {}, -"cannotMove": {}, -"bgmap": [ + "firstArrive": [], + "parallelDo": "", + "events": {}, + "changeFloor": {}, + "afterBattle": {}, + "afterGetItem": {}, + "afterOpenDoor": {}, + "cannotMove": {}, + "bgmap": [ ], -"fgmap": [ + "fgmap": [ ], + "width": 13, + "height": 13, + "autoEvent": {} } \ No newline at end of file diff --git a/project/floors/sample0.js b/project/floors/sample0.js index 8ed705e3..4af03e43 100644 --- a/project/floors/sample0.js +++ b/project/floors/sample0.js @@ -1,15 +1,15 @@ main.floors.sample0= { -"floorId": "sample0", -"title": "样板 0 层", -"name": "0", -"canFlyTo": true, -"canUseQuickShop": true, -"defaultGround": "ground", -"images": [], -"bgm": "bgm.mp3", -"item_ratio": 1, -"map": [ + "floorId": "sample0", + "title": "样板 0 层", + "name": "0", + "canFlyTo": true, + "canUseQuickShop": true, + "defaultGround": "ground", + "images": [], + "bgm": "bgm.mp3", + "item_ratio": 1, + "map": [ [ 0, 0,220, 0, 0, 20, 87, 3, 65, 64, 44, 43, 42], [ 0,246, 0,246, 0, 20, 0, 3, 58, 59, 60, 61, 41], [219, 0, 0, 0,219, 20, 0, 3, 57, 26, 62, 63, 40], @@ -24,199 +24,202 @@ main.floors.sample0= [ 87, 11, 12, 13, 14, 4, 4, 2, 2, 2,122, 2, 2], [ 88, 89, 90, 91, 92, 93, 94, 2, 81, 82, 83, 84, 86] ], -"firstArrive": [ - { - "type": "setText", - "background": "winskin.png", - "time": 0 - }, - "\t[样板提示]首次到达某层可以触发 firstArrive 事件,该事件可类似于RMXP中的“自动执行脚本”。\n\n本事件支持一切的事件类型,常常用来触发对话,例如:", - "\t[hero]\b[up,hero]我是谁?我从哪来?我又要到哪去?", - "\t[仙子,fairy]你问我...?我也不知道啊...", - "本层主要对道具、门、怪物等进行介绍,有关事件的各种信息在下一层会有更为详细的说明。" -], -"events": { - "10,9": [ - "\t[老人,man]这些是本样板支持的所有的道具。\n\n道具分为四类:items, constants, tools,equips。\nitems 为即捡即用类道具,例如宝石、血瓶、剑盾等。\nconstants 为永久道具,例如怪物手册、楼层传送器、幸运金币等。\ntools 为消耗类道具,例如破墙镐、炸弹、中心对称飞行器等。\nequips 为装备,例如剑盾等。", - "\t[老人,man]\b[up]有关道具效果,定义在items.js中。\n目前大多数道具已有默认行为,如有自定义的需求则需在items.js中修改代码。", - "\t[老人,man]\b[up]拾取道具结束后可触发 afterGetItem 事件。\n\n有关事件的各种信息在下一层会有更为详细的说明。", + "firstArrive": [ { - "type": "hide", - "time": 500 - } + "type": "setText", + "background": "winskin.png", + "time": 0 + }, + "\t[样板提示]首次到达某层可以触发 firstArrive 事件,该事件可类似于RMXP中的“自动执行脚本”。\n\n本事件支持一切的事件类型,常常用来触发对话,例如:", + "\t[hero]\b[up,hero]我是谁?我从哪来?我又要到哪去?", + "\t[仙子,fairy]你问我...?我也不知道啊...", + "本层主要对道具、门、怪物等进行介绍,有关事件的各种信息在下一层会有更为详细的说明。" ], - "10,11": [ - "\t[老人,woman]这些是门,需要对应的钥匙打开。\n机关门必须使用特殊的开法。", - "\t[老人,woman]开门后可触发 afterOpenDoor 事件。\n\n有关事件的各种信息在下一层会有更为详细的说明。", - { - "type": "hide", - "time": 500 - } - ], - "2,10": [ - "\t[少女,npc0]这些是路障、楼梯、传送门。", - "\t[少女,npc0]血网的伤害数值、中毒后每步伤害数值、衰弱时攻防下降的数值,都在 data.js 内定义。\n\n路障同样会尽量被自动寻路绕过。", - "\t[少女,npc0]楼梯和传送门需要在changeFloor中定义目标楼层和位置,可参见样板里已有的的写法。", - { - "type": "hide", - "time": 500 - } - ], - "2,8": [ - "\t[老人,magician]这些都是各种各样的怪物,所有怪物的数据都在enemys.js中设置。", - "\t[老人,magician]这批怪物分别为:普通、先攻、魔攻、坚固、2连击、3连击、4连击、破甲、反击、净化。", - "\t[老人,magician]打败怪物后可触发 afterBattle 事件。\n\n有关事件的各种信息在下一层会有更为详细的说明。", - { - "type": "hide", - "time": 500 - } - ], - "2,5": [ - "\t[老人,magician]模仿、吸血、中毒、衰弱、诅咒。\n\n请注意吸血怪需要设置value为吸血数值,可参见样板中黑暗大法师的写法。", - { - "type": "hide", - "time": 500 - } - ], - "2,3": [ - "\t[老人,magician]领域、夹击。\n请注意领域怪需要设置value为伤害数值,可参见样板中初级巫师的写法。", - "\t[老人,magician]夹击和领域同时发生时先计算领域,再夹击。\n自动寻路同样会尽量绕过你设置的这些点。", - { - "type": "hide", - "time": 500 - } - ], - "12,10": { - "enable": false, - "data": [ - "\t[仙子,fairy]只有楼上启用事件后,才能看到我并可以和我对话来触发事件。", + "events": { + "10,9": [ + "\t[老人,man]这些是本样板支持的所有的道具。\n\n道具分为四类:items, constants, tools,equips。\nitems 为即捡即用类道具,例如宝石、血瓶、剑盾等。\nconstants 为永久道具,例如怪物手册、楼层传送器、幸运金币等。\ntools 为消耗类道具,例如破墙镐、炸弹、中心对称飞行器等。\nequips 为装备,例如剑盾等。", + "\t[老人,man]\b[up]有关道具效果,定义在items.js中。\n目前大多数道具已有默认行为,如有自定义的需求则需在items.js中修改代码。", + "\t[老人,man]\b[up]拾取道具结束后可触发 afterGetItem 事件。\n\n有关事件的各种信息在下一层会有更为详细的说明。", { "type": "hide", "time": 500 } - ] - } -}, -"changeFloor": { - "6,0": { - "floorId": "sample1", - "stair": "downFloor" + ], + "10,11": [ + "\t[老人,woman]这些是门,需要对应的钥匙打开。\n机关门必须使用特殊的开法。", + "\t[老人,woman]开门后可触发 afterOpenDoor 事件。\n\n有关事件的各种信息在下一层会有更为详细的说明。", + { + "type": "hide", + "time": 500 + } + ], + "2,10": [ + "\t[少女,npc0]这些是路障、楼梯、传送门。", + "\t[少女,npc0]血网的伤害数值、中毒后每步伤害数值、衰弱时攻防下降的数值,都在 data.js 内定义。\n\n路障同样会尽量被自动寻路绕过。", + "\t[少女,npc0]楼梯和传送门需要在changeFloor中定义目标楼层和位置,可参见样板里已有的的写法。", + { + "type": "hide", + "time": 500 + } + ], + "2,8": [ + "\t[老人,magician]这些都是各种各样的怪物,所有怪物的数据都在enemys.js中设置。", + "\t[老人,magician]这批怪物分别为:普通、先攻、魔攻、坚固、2连击、3连击、4连击、破甲、反击、净化。", + "\t[老人,magician]打败怪物后可触发 afterBattle 事件。\n\n有关事件的各种信息在下一层会有更为详细的说明。", + { + "type": "hide", + "time": 500 + } + ], + "2,5": [ + "\t[老人,magician]模仿、吸血、中毒、衰弱、诅咒。\n\n请注意吸血怪需要设置value为吸血数值,可参见样板中黑暗大法师的写法。", + { + "type": "hide", + "time": 500 + } + ], + "2,3": [ + "\t[老人,magician]领域、夹击。\n请注意领域怪需要设置value为伤害数值,可参见样板中初级巫师的写法。", + "\t[老人,magician]夹击和领域同时发生时先计算领域,再夹击。\n自动寻路同样会尽量绕过你设置的这些点。", + { + "type": "hide", + "time": 500 + } + ], + "12,10": { + "enable": false, + "data": [ + "\t[仙子,fairy]只有楼上启用事件后,才能看到我并可以和我对话来触发事件。", + { + "type": "hide", + "time": 500 + } + ] + } }, - "0,11": { - "floorId": "sample0", - "loc": [ - 0, - 12 + "changeFloor": { + "6,0": { + "floorId": "sample1", + "stair": "downFloor" + }, + "0,11": { + "floorId": "sample0", + "loc": [ + 0, + 12 + ] + }, + "0,12": { + "floorId": "sample0", + "stair": "upFloor" + }, + "1,12": { + "floorId": "sample0", + "loc": [ + 1, + 12 + ] + }, + "2,12": { + "floorId": "sample0", + "loc": [ + 2, + 12 + ] + }, + "3,12": { + "floorId": "sample0", + "loc": [ + 6, + 1 + ], + "direction": "up" + }, + "4,12": { + "floorId": "sample0", + "loc": [ + 0, + 9 + ], + "direction": "left", + "time": 1000 + }, + "5,12": { + "floorId": "sample0", + "loc": [ + 6, + 10 + ], + "time": 0, + "portalWithoutTrigger": false + }, + "6,12": { + "floorId": "sample0", + "loc": [ + 10, + 10 + ], + "direction": "left", + "time": 1000 + } + }, + "afterBattle": { + "2,6": [ + "\t[ghostSkeleton]不可能,你怎么可能打败我!\n(一个打败怪物触发的事件)" ] }, - "0,12": { - "floorId": "sample0", - "stair": "upFloor" - }, - "1,12": { - "floorId": "sample0", - "loc": [ - 1, - 12 + "afterGetItem": { + "11,8": [ + "由于状态栏放不下,绿钥匙和铁门钥匙均视为tools,放入工具栏中。\n碰到绿门和铁门仍然会自动使用开门。" + ], + "8,6": [ + "由于吸血和夹击等的存在,血瓶默认自动被绕路。\n你可以修改data.js中的系统Flag来设置这一项。" + ], + "8,7": [ + "如需修改消耗品的效果,请前往 data.js ,找到并修改values内对应的具体数值即可。\n如果有更高级的需求(如每个区域宝石数值变化),详见doc文档内的做法说明。" + ], + "9,5": [ + "每层楼的 canFlyTo 决定了该楼层能否被飞到。\n\n不能被飞到的楼层也无法使用楼层传送器。", + "飞行的楼层顺序由 main.js 中 floorIds 加载顺序所决定。\n\n是否必须在楼梯边使用楼传器由 data.js 中的系统Flag所决定。" + ], + "10,5": [ + "破墙镐是破面前的墙壁还是四个方向的墙壁,由data.js中的系统Flag所决定。" + ], + "8,4": [ + "炸弹是只能炸面前的怪物还是四个方向的怪物,由data.js中的系统Flag所决定。\n如只能炸前方怪物则和上面的圣锤等价。\n不能被炸的怪物在enemys中可以定义,可参见样板里黑衣魔王和黑暗大法师的写法。" + ], + "10,4": [ + "“上楼”和“下楼”的目标层由 main.js 的 floorIds顺序所决定。" + ], + "9,2": [ + "该道具默认是大黄门钥匙,如需改为钥匙盒直接修改 data.js 中的系统Flag即可。" + ], + "10,2": [ + "屠龙匕首目前未被定义,可能需要自行实现功能。\n有关如何实现一个道具功能参见doc文档。" + ], + "12,7": [ + "在 data.js 的系统Flag中设置是否启用装备栏。\n如果不启用则装备会直接增加属性。" + ], + "12,6": [ + "在 data.js 的系统Flag中设置是否启用装备栏按钮。\n如果启用则装备栏按钮会替代楼传按钮。" + ], + "12,5": [ + "装备的种类由全塔属性中的equipName决定,type的值就是该类型在equipName中的位次,例如默认情况下equiptype为0代表武器,同时只有type为0的装备的animate属性生效" ] }, - "2,12": { - "floorId": "sample0", - "loc": [ - 2, - 12 + "afterOpenDoor": { + "11,12": [ + "你开了一个绿门,触发了一个afterOpenDoor事件" ] }, - "3,12": { - "floorId": "sample0", - "loc": [ - 6, - 1 - ], - "direction": "up" - }, - "4,12": { - "floorId": "sample0", - "loc": [ - 0, - 9 - ], - "direction": "left", - "time": 1000 - }, - "5,12": { - "floorId": "sample0", - "loc": [ - 6, - 10 - ], - "time": 0, - "portalWithoutTrigger": false - }, - "6,12": { - "floorId": "sample0", - "loc": [ - 10, - 10 - ], - "direction": "left", - "time": 1000 - } -}, -"afterBattle": { - "2,6": [ - "\t[ghostSkeleton]不可能,你怎么可能打败我!\n(一个打败怪物触发的事件)" - ] -}, -"afterGetItem": { - "11,8": [ - "由于状态栏放不下,绿钥匙和铁门钥匙均视为tools,放入工具栏中。\n碰到绿门和铁门仍然会自动使用开门。" - ], - "8,6": [ - "由于吸血和夹击等的存在,血瓶默认自动被绕路。\n你可以修改data.js中的系统Flag来设置这一项。" - ], - "8,7": [ - "如需修改消耗品的效果,请前往 data.js ,找到并修改values内对应的具体数值即可。\n如果有更高级的需求(如每个区域宝石数值变化),详见doc文档内的做法说明。" - ], - "9,5": [ - "每层楼的 canFlyTo 决定了该楼层能否被飞到。\n\n不能被飞到的楼层也无法使用楼层传送器。", - "飞行的楼层顺序由 main.js 中 floorIds 加载顺序所决定。\n\n是否必须在楼梯边使用楼传器由 data.js 中的系统Flag所决定。" - ], - "10,5": [ - "破墙镐是破面前的墙壁还是四个方向的墙壁,由data.js中的系统Flag所决定。" - ], - "8,4": [ - "炸弹是只能炸面前的怪物还是四个方向的怪物,由data.js中的系统Flag所决定。\n如只能炸前方怪物则和上面的圣锤等价。\n不能被炸的怪物在enemys中可以定义,可参见样板里黑衣魔王和黑暗大法师的写法。" - ], - "10,4": [ - "“上楼”和“下楼”的目标层由 main.js 的 floorIds顺序所决定。" - ], - "9,2": [ - "该道具默认是大黄门钥匙,如需改为钥匙盒直接修改 data.js 中的系统Flag即可。" - ], - "10,2": [ - "屠龙匕首目前未被定义,可能需要自行实现功能。\n有关如何实现一个道具功能参见doc文档。" - ], - "12,7": [ - "在 data.js 的系统Flag中设置是否启用装备栏。\n如果不启用则装备会直接增加属性。" - ], - "12,6": [ - "在 data.js 的系统Flag中设置是否启用装备栏按钮。\n如果启用则装备栏按钮会替代楼传按钮。" - ], - "12,5": [ - "装备的种类由全塔属性中的equipName决定,type的值就是该类型在equipName中的位次,例如默认情况下equiptype为0代表武器,同时只有type为0的装备的animate属性生效" - ] -}, -"afterOpenDoor": { - "11,12": [ - "你开了一个绿门,触发了一个afterOpenDoor事件" - ] -}, -"cannotMove": {}, -"bgmap": [ + "cannotMove": {}, + "bgmap": [ ], -"fgmap": [ + "fgmap": [ ], + "width": 13, + "height": 13, + "autoEvent": {} } \ No newline at end of file diff --git a/project/floors/sample1.js b/project/floors/sample1.js index 8b5c8646..9c769745 100644 --- a/project/floors/sample1.js +++ b/project/floors/sample1.js @@ -1,25 +1,25 @@ main.floors.sample1= { -"floorId": "sample1", -"title": "样板 1 层", -"name": "1", -"canFlyTo": true, -"canUseQuickShop": true, -"defaultGround": "grass", -"images": [ - [ - 0, - 0, - "bg.jpg", - 0 - ] -], -"weather": [ - "snow", - 6 -], -"item_ratio": 1, -"map": [ + "floorId": "sample1", + "title": "样板 1 层", + "name": "1", + "canFlyTo": true, + "canUseQuickShop": true, + "defaultGround": "grass", + "images": [ + [ + 0, + 0, + "bg.jpg", + 0 + ] + ], + "weather": [ + "snow", + 6 + ], + "item_ratio": 1, + "map": [ [ 7,131, 8,152, 9,130, 10,152,166,165,132,165,166], [ 0, 0, 0, 0, 0, 0, 0,152,165,164, 0,162,165], [152,152,152,152,121,152,152,152, 0, 0,229, 0, 0], @@ -32,736 +32,619 @@ main.floors.sample1= [ 0, 0, 0, 0, 0, 0, 0,164, 0, 0,163, 0, 0], [ 1, 1, 1, 1, 0, 20, 0, 0, 0,162, 0,161, 0], [ 1, 0,123, 1, 0, 20,124, 0,121, 0,122, 0,126], - [ 1, 0, 0, 1, 88, 20, 86, 0, 0, 0, 0, 0,122] + [ 1, 0, 0, 1, 88, 20, 86, 0, 0, 0, 0, 0, 0] ], -"firstArrive": [], -"events": { - "4,10": [ - "\t[样板提示]本层楼将会对各类事件进行介绍。", - "左边是一个仿50层的陷阱做法,上方是商店、快捷商店的使用方法,右上是一个典型的杀怪开门的例子,右下是各类可能的NPC事件。", - "本样板目前支持的事件列表大致有:\ntext: 显示一段文字(比如你现在正在看到的)\ntip: 左上角显示提示\nshow: 使一个事件有效(可见、可被交互)\nhide: 使一个事件失效(不可见、不可被交互)\ntrigger: 触发另一个地点的事件\nanimate: 显示动画\nbattle: 强制和某怪物战斗\nopenDoor: 无需钥匙开门(例如机关门、暗墙)", - "openShop: 打开一个全局商店\ndisableShop: 禁用一个全局商店\nchangeFloor: 传送勇士到某层某位置\nchangePos: 传送勇士到当层某位置;转向\nshowImage: 显示图片\nsetFg: 更改画面色调\nsetWeather: 更改天气\nmove: 移动事件效果\nmoveHero: 移动勇士效果\nplayBgm: 播放某个背景音乐\npauseBgm: 暂停背景音乐\nresumeBgm: 恢复背景音乐的播放\nplaySound: 播放某个音频", - "if: 条件判断\nchoices: 提供选项\nsetValue: 设置勇士属性道具,或某个变量/flag\nupdate: 更新状态栏和地图显伤\nwin: 获得胜利(游戏通关)\nlose: 游戏失败\nsleep: 等待多少毫秒\nexit: 立刻结束当前事件\nrevisit: 立刻结束事件并重新触发\nfunction: 自定义JS脚本\n\n更多支持的事件还在编写中,欢迎您宝贵的意见。", - "有关各事件的样例,可参见本层一些NPC的写法。\n所有事件样例本层都有介绍。\n\n一个自定义事件处理完后,需要调用{\"type\": \"hide\"}该事件才不会再次出现。", - { - "type": "hide" - } - ], - "1,5": { - "enable": false, - "data": [] - }, - "1,6": { - "enable": false, - "data": [] - }, - "0,7": { - "enable": false, - "data": [] - }, - "2,7": { - "enable": false, - "data": [] - }, - "1,8": { - "enable": false, - "data": [] - }, - "1,7": [ - { - "type": "show", - "loc": [ - 1, - 5 - ], - "time": 1500 + "firstArrive": [], + "events": { + "4,10": [ + "\t[样板提示]本层楼将会对各类事件进行介绍。", + "左边是一个仿50层的陷阱做法,上方是商店、快捷商店的使用方法,右上是一个典型的杀怪开门的例子,右下是各类可能的NPC事件。", + "本样板目前支持的事件列表大致有:\ntext: 显示一段文字(比如你现在正在看到的)\ntip: 左上角显示提示\nshow: 使一个事件有效(可见、可被交互)\nhide: 使一个事件失效(不可见、不可被交互)\ntrigger: 触发另一个地点的事件\nanimate: 显示动画\nbattle: 强制和某怪物战斗\nopenDoor: 无需钥匙开门(例如机关门、暗墙)", + "openShop: 打开一个全局商店\ndisableShop: 禁用一个全局商店\nchangeFloor: 传送勇士到某层某位置\nchangePos: 传送勇士到当层某位置;转向\nshowImage: 显示图片\nsetFg: 更改画面色调\nsetWeather: 更改天气\nmove: 移动事件效果\nmoveHero: 移动勇士效果\nplayBgm: 播放某个背景音乐\npauseBgm: 暂停背景音乐\nresumeBgm: 恢复背景音乐的播放\nplaySound: 播放某个音频", + "if: 条件判断\nchoices: 提供选项\nsetValue: 设置勇士属性道具,或某个变量/flag\nupdate: 更新状态栏和地图显伤\nwin: 获得胜利(游戏通关)\nlose: 游戏失败\nsleep: 等待多少毫秒\nexit: 立刻结束当前事件\nfunction: 自定义JS脚本\n\n更多支持的事件还在编写中,欢迎您宝贵的意见。", + "有关各事件的样例,可参见本层一些NPC的写法。\n所有事件样例本层都有介绍。\n\n一个自定义事件处理完后,需要调用{\"type\": \"hide\"}该事件才不会再次出现。", + { + "type": "hide" + } + ], + "1,5": { + "enable": false, + "data": [] }, - { - "type": "sleep", - "time": 500 + "1,6": { + "enable": false, + "data": [] }, - "\t[redKing]欢迎来到魔塔,你是第一百位挑战者。\n若你能打败我所有的手下,我就与你一对一的决斗。\n现在你必须接受我的安排。", - { - "type": "show", - "loc": [ - [ + "0,7": { + "enable": false, + "data": [] + }, + "2,7": { + "enable": false, + "data": [] + }, + "1,8": { + "enable": false, + "data": [] + }, + "1,7": [ + { + "type": "show", + "loc": [ 1, - 6 + 5 ], - [ - 0, - 7 - ], - [ - 1, - 8 - ], - [ - 2, - 7 - ] - ], - "time": 500 - }, - "\t[hero]什么?", - { - "type": "playSound", - "name": "attack.mp3" - }, - { - "type": "setValue", - "name": "status:atk", - "value": "status:atk/10" - }, - { - "type": "setValue", - "name": "status:def", - "value": "status:def/10" - }, - { - "type": "hide", - "loc": [ - [ - 1, - 6 - ], - [ - 0, - 7 - ], - [ - 2, - 7 - ], - [ - 1, - 8 - ] - ] - }, - { - "type": "hide", - "loc": [ - 1, - 5 - ], - "time": 500 - }, - { - "type": "hide" - }, - { - "type": "setCurtain", - "color": [ - 0, - 0, - 0 - ], - "time": 1250 - }, - { - "type": "sleep", - "time": 700 - }, - { - "type": "changeFloor", - "floorId": "sample1", - "loc": [ - 1, - 11 - ], - "direction": "right", - "time": 1000 - }, - { - "type": "trigger", - "loc": [ - 2, - 11 - ] - } - ], - "2,11": [ - "\t[杰克,thief]喂!醒醒!快醒醒!", - { - "type": "setCurtain", - "time": 1500 - }, - "\t[hero]额,我这是在什么地方?", - "\t[杰克,thief]你被魔王抓了起来扔进了监狱,和我关在了一起,但是幸运的是我在昨天刚刚挖好一条越狱的暗道!", - { - "type": "openDoor", - "loc": [ - 3, - 11 - ] - }, - { - "type": "sleep", - "time": 300 - }, - "\t[杰克,thief]我先走了,祝你好运!", - { - "type": "move", - "time": 750, - "steps": [ - "right", - "right", - "down" - ] - }, - "上面是个move事件,可以对NPC等进行移动。\n详见样板中小偷事件的写法。", - "\t[hero]怎么跑的这么快..." - ], - "4,2": [ - "\t[老人,man]本塔的商店有两类,全局商店和非全局商店。\n\n所谓非全局商店,就类似于右下角那个卖钥匙的老人一样,一定要碰到才能触发事件。\n\n而全局商店,则能在快捷商店中直接使用。", - "\t[老人,man]要注册一个全局商店,你需要在 data.js 中,找到 shops,并在内添加你的商店信息。", - "\t[老人,man]商店信息添加后,可以在需要的事件处调用{\"type\": \"openShop\"}来打开你添加的全局商店。", - "\t[老人,man]在上面的例子里,左边是一个仿50层的金币商店,右边是一个仿24层的经验商店。\n\n商店被访问后即可在快捷商店中进行使用。", - "\t[老人,man]如果你需要在某层暂时禁用快捷商店,可以在data.js中设置cannotUseQuickShop。\n如果需要永久禁用商店,请使用{\"type\":\"disableShop\"}", - { - "type": "hide", - "time": 500 - } - ], - "1,0": [ - { - "type": "openShop", - "id": "moneyShop1" - } - ], - "5,0": [ - { - "type": "openShop", - "id": "expShop1" - } - ], - "7,7": [ - "\t[老人,man]这是一个典型的杀怪开门、强制战斗事件。", - { - "type": "hide" - } - ], - "8,7": { - "enable": false, - "data": [] - }, - "9,7": [ - { - "type": "show", - "loc": [ - 8, - 7 - ] - }, - { - "type": "hide" - } - ], - "10,4": [ - "\t[blackKing]你终于还是来了。", - "\t[hero]放开我们的公主!", - "\t[blackKing]如果我不愿意呢?", - "\t[hero]无需多说,拔剑吧!", - { - "type": "battle", - "id": "blackKing" - }, - { - "type": "hide", - "loc": [ - 10, - 2 - ] - }, - { - "type": "openDoor", - "loc": [ - 8, - 7 - ] - }, - "\t[blackKing]没想到你已经变得这么强大了... 算你厉害。\n公主就交给你了,请好好对她。", - { - "type": "hide" - } - ], - "10,0": [ - "\t[hero]公主,我来救你了~", - "\t[公主,princess]快救我出去!我受够这里了!", - "\t[hero]公主别怕,我们走吧~", - { - "type": "win", - "reason": "救出公主" - } - ], - "6,12": { - "enable": false, - "data": [] - }, - "6,11": [ - "\t[仙子,fairy]通过调用 {\"type\": \"show\"} 可以使隐藏的事件显示出来。\n比如我下面这个机关门。", - { - "type": "show", - "loc": [ - 6, - 12 - ] - }, - "\t[仙子,fairy]通过调用 {\"type\": \"openDoor\"} 可以无需钥匙打开一扇门或暗墙。", - { - "type": "openDoor", - "loc": [ - 6, - 12 - ] - }, - "\t[仙子,fairy]同时,也可以对其它层进行操作,比如楼下的机关门,现在已经为你打开了。", - { - "type": "openDoor", - "loc": [ - 11, - 10 - ], - "floorId": "sample0" - }, - "\t[仙子,fairy]如果 show 或 hide 指定了 time 参数,则以动画效果显示,指定的参数作为消失时间(毫秒)来计算。", - "\t[仙子,fairy]现在到楼下来找我吧~", - { - "type": "show", - "loc": [ - 12, - 10 - ], - "floorId": "sample0" - }, - { - "type": "hide", - "time": 500 - } - ], - "8,11": [ - { - "type": "setValue", - "name": "flag:man_times", - "value": "flag:man_times+1" - }, - "\t[老人,man]在文字中使用${' ${ '}和 } 可以计算并显示一个表达式的结果。\n", - "\t[老人,man]例如:\n你的当前攻击力是${status:atk},防御力是${status:def}。\n攻防和的十倍是${10*(status:atk+status:def)},攻防之积是${status:atk*status:def}。\n你有${item:yellowKey}把黄钥匙,${item:blueKey}把蓝钥匙,${item:redKey}把红钥匙。\n你有${item:pickaxe}个破,${item:bomb}个炸,${item:centerFly}个飞。\n这是你第${flag:man_times}次和我对话。", - "\t[老人,man]同时,你也可以通过{\"type\": \"setValue\"}来设置一个勇士的属性、道具,或某个Flag。", - "\t[老人,man]例如:\n现在我将让你的攻防提升50%,再将攻防和的十倍加到生命值上。", - { - "type": "setValue", - "name": "status:atk", - "value": "status:atk*1.5" - }, - { - "type": "setValue", - "name": "status:def", - "value": "status:def*1.5" - }, - { - "type": "setValue", - "name": "status:hp", - "value": "status:hp+10*(status:atk+status:def)" - }, - "\t[老人,man]再送你500金币,1000经验,1破2炸3飞!", - { - "type": "setValue", - "name": "status:money", - "value": "status:money+500" - }, - { - "type": "setValue", - "name": "status:experience", - "value": "status:experience+1000" - }, - { - "type": "setValue", - "name": "item:pickaxe", - "value": "item:pickaxe+1" - }, - { - "type": "setValue", - "name": "item:bomb", - "value": "item:bomb+2" - }, - { - "type": "setValue", - "name": "item:centerFly", - "value": "item:centerFly+3" - }, - "\t[老人,man]status:xxx 代表勇士的某个属性。\n其中xxx可取hp, atk, def, mdef, money,experience这几项。\n\nitem:xxx 代表勇士的某个道具的个数。\nxxx为道具ID,具体可参见items.js中的定义。\n\nflag:xxx 代表某个自定义Flag或变量。\nxxx为Flag/变量名,可以自行定义,由字母、数字和下划线组成。\n未定义过而直接取用的Flag默认值为false。", - "\t[老人,man]你现在可以重新和我进行对话,进一步看到属性值的改变。" - ], - "10,11": [ - { - "type": "if", - "condition": "flag:woman_times==0", - "true": [ - "\t[老人,woman]这是个很复杂的例子,它将教会你如何使用if 语句进行条件判断,以及 choices 提供选项来供用户进行选择。", - "\t[老人,woman]第一次访问我将显示这段文字;从第二次开始将会向你出售钥匙。\n钥匙价格将随着访问次数递增。\n当合计出售了七把钥匙后,将送你一把大黄门钥匙,并消失不再出现。", - "\t[老人,woman]这部分的逻辑比较长,请细心看样板的写法,是很容易看懂并理解的。" - ], - "false": [ - { - "type": "if", - "condition": "flag:woman_times==8", - "true": [ - "\t[老人,woman]你购买的钥匙已经够多了,再继续卖给你的话我会有危险的。", - "\t[老人,woman]看在你贡献给我这么多钱的份上,送你一把大黄门钥匙吧,希望你能好好用它。", - { - "type": "setValue", - "name": "item:bigKey", - "value": "item:bigKey+1" - }, - "\t[老人,woman]我先走了,拜拜~", - { - "type": "hide", - "time": 500 - }, - { - "type": "exit" - } + "time": 1500 + }, + { + "type": "sleep", + "time": 500 + }, + "\t[redKing]欢迎来到魔塔,你是第一百位挑战者。\n若你能打败我所有的手下,我就与你一对一的决斗。\n现在你必须接受我的安排。", + { + "type": "show", + "loc": [ + [ + 1, + 6 ], - "false": [ - { - "type": "choices", - "text": "\t[老人,woman]少年,你需要钥匙吗?\n我这里有大把的!", - "choices": [ - { - "text": "黄钥匙(${9+flag:woman_times}金币)", - "action": [ - { - "type": "if", - "condition": "status:money>=9+flag:woman_times", - "true": [ - { - "type": "setValue", - "name": "status:money", - "value": "status:money-(9+flag:woman_times)" - }, - { - "type": "setValue", - "name": "item:yellowKey", - "value": "item:yellowKey+1" - } - ], - "false": [ - "\t[老人,woman]你的金钱不足!", - { - "type": "revisit" - } - ] - } - ] - }, - { - "text": "蓝钥匙(${18+2*flag:woman_times}金币)", - "action": [ - { - "type": "if", - "condition": "status:money>=18+2*flag:woman_times", - "true": [ - { - "type": "setValue", - "name": "status:money", - "value": "status:money-(18+2*flag:woman_times)" - }, - { - "type": "setValue", - "name": "item:blueKey", - "value": "item:blueKey+1" - } - ], - "false": [ - "\t[老人,woman]你的金钱不足!", - { - "type": "revisit" - } - ] - } - ] - }, - { - "text": "红钥匙(${36+4*flag:woman_times}金币)", - "action": [ - { - "type": "if", - "condition": "status:money>=36+4*flag:woman_times", - "true": [ - { - "type": "setValue", - "name": "status:money", - "value": "status:money-(36+4*flag:woman_times)" - }, - { - "type": "setValue", - "name": "item:redKey", - "value": "item:redKey+1" - } - ], - "false": [ - "\t[老人,woman]你的金钱不足!", - { - "type": "revisit" - } - ] - } - ] - }, - { - "text": "离开", - "action": [ - { - "type": "exit" - } - ] - } - ] - } + [ + 0, + 7 + ], + [ + 1, + 8 + ], + [ + 2, + 7 ] - } - ] - }, - { - "type": "setValue", - "name": "flag:woman_times", - "value": "flag:woman_times+1" - }, - { - "type": "revisit" - } - ], - "12,11": [ - "\t[老人,womanMagician]使用 {\"type\":\"function\"} 可以写自定义的JS脚本。\n本塔支持的所有主要API会在doc文档内给出。", - "\t[老人,womanMagician]例如这个例子:即将弹出一个输入窗口,然后会将你的输入结果直接加到你的攻击力上。", - { - "type": "input", - "text": "请输入你要加攻击力的数值:" - }, - { - "type": "if", - "condition": "flag:input>0", - "true": [ - { - "type": "setValue", - "name": "status:atk", - "value": "status:atk+flag:input" - }, - { - "type": "tip", - "text": "操作成功,攻击+${flag:input}" - }, - "操作成功,攻击+${flag:input}" - ], - "false": [] - }, - "\t[老人,womanMagician]具体可参见样板中本事件的写法。" - ], - "10,12": null, - "12,12": [ - { - "type": "switch", - "condition": "flag:woman_times", - "caseList": [ - { - "case": "0", - "action": [ - "\t[老人,woman]现在使用switch改写这个例子" + ], + "time": 500 + }, + "\t[hero]什么?", + { + "type": "playSound", + "name": "attack.mp3" + }, + { + "type": "setValue", + "name": "status:atk", + "operator": "/=", + "value": "10" + }, + { + "type": "setValue", + "name": "status:def", + "operator": "/=", + "value": "10" + }, + { + "type": "hide", + "loc": [ + [ + 1, + 6 + ], + [ + 0, + 7 + ], + [ + 2, + 7 + ], + [ + 1, + 8 ] - }, - { - "case": "8", - "action": [ - "\t[老人,woman]你购买的钥匙已经够多了,再继续卖给你的话我会有危险的。", - "\t[老人,woman]看在你贡献给我这么多钱的份上,送你一把大黄门钥匙吧,希望你能好好用它。", - { - "type": "setValue", - "name": "item:bigKey", - "value": "item:bigKey+1" - }, - "\t[老人,woman]我先走了,拜拜~", - { - "type": "hide", - "time": 500 - }, - { - "type": "exit" - } - ] - }, - { - "case": "default", - "action": [ - { - "type": "comment", - "text": "当没有符合的值的场合执行此事件" - }, - { - "type": "choices", - "text": "\t[老人,woman]少年,你需要钥匙吗?\n我这里有大把的!", - "choices": [ - { - "text": "黄钥匙(${9+flag:woman_times}金币)", - "action": [ - { - "type": "if", - "condition": "status:money>=9+flag:woman_times", - "true": [ - { - "type": "setValue", - "name": "status:money", - "value": "status:money-(9+flag:woman_times)" - }, - { - "type": "setValue", - "name": "item:yellowKey", - "value": "item:yellowKey+1" - } - ], - "false": [ - "\t[老人,woman]你的金钱不足!", - { - "type": "revisit" - } - ] - } - ] - }, - { - "text": "蓝钥匙(${18+2*flag:woman_times}金币)", - "action": [ - { - "type": "if", - "condition": "status:money>=18+2*flag:woman_times", - "true": [ - { - "type": "setValue", - "name": "status:money", - "value": "status:money-(18+2*flag:woman_times)" - }, - { - "type": "setValue", - "name": "item:blueKey", - "value": "item:blueKey+1" - } - ], - "false": [ - "\t[老人,woman]你的金钱不足!", - { - "type": "revisit" - } - ] - } - ] - }, - { - "text": "红钥匙(${36+4*flag:woman_times}金币)", - "action": [ - { - "type": "if", - "condition": "status:money>=36+4*flag:woman_times", - "true": [ - { - "type": "setValue", - "name": "status:money", - "value": "status:money-(36+4*flag:woman_times)" - }, - { - "type": "setValue", - "name": "item:redKey", - "value": "item:redKey+1" - } - ], - "false": [ - "\t[老人,woman]你的金钱不足!", - { - "type": "revisit" - } - ] - } - ] - }, - { - "text": "离开", - "action": [ - { - "type": "exit" - } - ] - } - ] - } - ] - } - ] + ] + }, + { + "type": "hide", + "loc": [ + 1, + 5 + ], + "time": 500 + }, + { + "type": "hide" + }, + { + "type": "setCurtain", + "color": [ + 0, + 0, + 0 + ], + "time": 1250 + }, + { + "type": "sleep", + "time": 700 + }, + { + "type": "changeFloor", + "floorId": "sample1", + "loc": [ + 1, + 11 + ], + "direction": "right", + "time": 1000 + }, + { + "type": "trigger", + "loc": [ + 2, + 11 + ] + } + ], + "2,11": [ + "\t[杰克,thief]喂!醒醒!快醒醒!", + { + "type": "setCurtain", + "time": 1500 + }, + "\t[hero]额,我这是在什么地方?", + "\t[杰克,thief]你被魔王抓了起来扔进了监狱,和我关在了一起,但是幸运的是我在昨天刚刚挖好一条越狱的暗道!", + { + "type": "openDoor", + "loc": [ + 3, + 11 + ] + }, + { + "type": "sleep", + "time": 300 + }, + "\t[杰克,thief]我先走了,祝你好运!", + { + "type": "move", + "time": 750, + "steps": [ + "right", + "right", + "down" + ] + }, + "上面是个move事件,可以对NPC等进行移动。\n详见样板中小偷事件的写法。", + "\t[hero]怎么跑的这么快..." + ], + "4,2": [ + "\t[老人,man]本塔的商店有两类,全局商店和非全局商店。\n\n所谓非全局商店,就类似于右下角那个卖钥匙的老人一样,一定要碰到才能触发事件。\n\n而全局商店,则能在快捷商店中直接使用。", + "\t[老人,man]要注册一个全局商店,你需要在 data.js 中,找到 shops,并在内添加你的商店信息。", + "\t[老人,man]商店信息添加后,可以在需要的事件处调用{\"type\": \"openShop\"}来打开你添加的全局商店。", + "\t[老人,man]在上面的例子里,左边是一个仿50层的金币商店,右边是一个仿24层的经验商店。\n\n商店被访问后即可在快捷商店中进行使用。", + "\t[老人,man]如果你需要在某层暂时禁用快捷商店,可以在data.js中设置cannotUseQuickShop。\n如果需要永久禁用商店,请使用{\"type\":\"disableShop\"}", + { + "type": "hide", + "time": 500 + } + ], + "1,0": [ + { + "type": "openShop", + "id": "shop1", + "open": true + } + ], + "5,0": [ + { + "type": "openShop", + "id": "shop2", + "open": true + } + ], + "7,7": [ + "\t[老人,man]这是一个典型的杀怪开门、强制战斗事件。", + { + "type": "hide" + } + ], + "8,7": { + "enable": false, + "data": [] }, - { - "type": "setValue", - "name": "flag:woman_times", - "value": "flag:woman_times+1" + "9,7": [ + { + "type": "show", + "loc": [ + 8, + 7 + ] + }, + { + "type": "hide" + } + ], + "10,4": [ + "\t[blackKing]你终于还是来了。", + "\t[hero]放开我们的公主!", + "\t[blackKing]如果我不愿意呢?", + "\t[hero]无需多说,拔剑吧!", + { + "type": "battle", + "id": "blackKing" + }, + { + "type": "hide", + "loc": [ + 10, + 2 + ] + }, + { + "type": "openDoor", + "loc": [ + 8, + 7 + ] + }, + "\t[blackKing]没想到你已经变得这么强大了... 算你厉害。\n公主就交给你了,请好好对她。", + { + "type": "hide" + } + ], + "10,0": [ + "\t[hero]公主,我来救你了~", + "\t[公主,princess]快救我出去!我受够这里了!", + "\t[hero]公主别怕,我们走吧~", + { + "type": "win", + "reason": "救出公主" + } + ], + "6,12": { + "enable": false, + "data": [] }, - { - "type": "revisit" - } - ] -}, -"changeFloor": { - "4,12": { - "floorId": "sample0", - "loc": [ - 6, - 0 + "6,11": [ + "\t[仙子,fairy]通过调用 {\"type\": \"show\"} 可以使隐藏的事件显示出来。\n比如我下面这个机关门。", + { + "type": "show", + "loc": [ + 6, + 12 + ] + }, + "\t[仙子,fairy]通过调用 {\"type\": \"openDoor\"} 可以无需钥匙打开一扇门或暗墙。", + { + "type": "openDoor", + "loc": [ + 6, + 12 + ] + }, + "\t[仙子,fairy]同时,也可以对其它层进行操作,比如楼下的机关门,现在已经为你打开了。", + { + "type": "openDoor", + "loc": [ + 11, + 10 + ], + "floorId": "sample0" + }, + "\t[仙子,fairy]如果 show 或 hide 指定了 time 参数,则以动画效果显示,指定的参数作为消失时间(毫秒)来计算。", + "\t[仙子,fairy]现在到楼下来找我吧~", + { + "type": "show", + "loc": [ + 12, + 10 + ], + "floorId": "sample0" + }, + { + "type": "hide", + "time": 500 + } + ], + "8,11": [ + { + "type": "setValue", + "name": "flag:man_times", + "operator": "+=", + "value": "1" + }, + "\t[老人,man]在文字中使用$+{}可以计算并显示一个表达式的结果。\n", + "\t[老人,man]例如:\n你的当前攻击力是${status:atk},防御力是${status:def}。\n攻防和的十倍是${10*(status:atk+status:def)},攻防之积是${status:atk*status:def}。\n你有${item:yellowKey}把黄钥匙,${item:blueKey}把蓝钥匙,${item:redKey}把红钥匙。\n你有${item:pickaxe}个破,${item:bomb}个炸,${item:centerFly}个飞。\n这是你第${flag:man_times}次和我对话。", + "\t[老人,man]同时,你也可以通过{\"type\": \"setValue\"}来设置一个勇士的属性、道具,或某个Flag。", + "\t[老人,man]例如:\n现在我将让你的攻防提升50%,再将攻防和的十倍加到生命值上。", + { + "type": "setValue", + "name": "status:atk", + "operator": "*=", + "value": "1.5" + }, + { + "type": "setValue", + "name": "status:def", + "operator": "*=", + "value": "1.5" + }, + { + "type": "setValue", + "name": "status:hp", + "operator": "+=", + "value": "10*(status:atk+status:def)" + }, + "\t[老人,man]再送你500金币,1000经验,1破2炸3飞!", + { + "type": "setValue", + "name": "status:money", + "operator": "+=", + "value": "500" + }, + { + "type": "setValue", + "name": "status:exp", + "operator": "+=", + "value": "1000" + }, + { + "type": "setValue", + "name": "item:pickaxe", + "operator": "+=", + "value": "1" + }, + { + "type": "setValue", + "name": "item:bomb", + "operator": "+=", + "value": "2" + }, + { + "type": "setValue", + "name": "item:centerFly", + "operator": "+=", + "value": "3" + }, + "\t[老人,man]status:xxx 代表勇士的某个属性。\n其中xxx可取hp, atk, def, mdef, money,exp这几项。\n\nitem:xxx 代表勇士的某个道具的个数。\nxxx为道具ID,具体可参见items.js中的定义。\n\nflag:xxx 代表某个自定义Flag或变量。\nxxx为Flag/变量名,可以自行定义,由字母、数字和下划线组成。\n未定义过而直接取用的Flag默认值为false。", + "\t[老人,man]你现在可以重新和我进行对话,进一步看到属性值的改变。" + ], + "10,11": [ + { + "type": "while", + "condition": "true", + "data": [ + { + "type": "switch", + "condition": "flag:woman_times", + "caseList": [ + { + "case": "0", + "action": [ + "\t[老人,woman]这是个很复杂的例子,它将教会你如何使用if 语句进行条件判断,以及 choices 提供选项来供用户进行选择。", + "\t[老人,woman]第一次访问我将显示这段文字;从第二次开始将会向你出售钥匙。\n钥匙价格将随着访问次数递增。\n当合计出售了七把钥匙后,将送你一把大黄门钥匙,并消失不再出现。", + "\t[老人,woman]这部分的逻辑比较长,请细心看样板的写法,是很容易看懂并理解的。" + ] + }, + { + "case": "8", + "action": [ + "\t[老人,woman]你购买的钥匙已经够多了,再继续卖给你的话我会有危险的。", + "\t[老人,woman]看在你贡献给我这么多钱的份上,送你一把大黄门钥匙吧,希望你能好好用它。", + { + "type": "setValue", + "name": "item:bigKey", + "operator": "+=", + "value": "1" + }, + "\t[老人,woman]我先走了,拜拜~", + { + "type": "hide", + "time": 500 + }, + { + "type": "exit" + } + ] + }, + { + "case": "default", + "action": [ + { + "type": "choices", + "text": "\t[老人,woman]少年,你需要钥匙吗?\n我这里有大把的!", + "choices": [ + { + "text": "黄钥匙(${9+flag:woman_times}金币)", + "action": [ + { + "type": "if", + "condition": "status:money>=9+flag:woman_times", + "true": [ + { + "type": "setValue", + "name": "status:money", + "operator": "-=", + "value": "9+flag:woman_times" + }, + { + "type": "setValue", + "name": "item:yellowKey", + "operator": "+=", + "value": "1" + } + ], + "false": [ + "\t[老人,woman]你的金钱不足!" + ] + } + ] + }, + { + "text": "蓝钥匙(${18+2*flag:woman_times}金币)", + "action": [ + { + "type": "if", + "condition": "status:money>=18+2*flag:woman_times", + "true": [ + { + "type": "setValue", + "name": "status:money", + "operator": "-=", + "value": "18+2*flag:woman_times" + }, + { + "type": "setValue", + "name": "item:blueKey", + "operator": "+=", + "value": "1" + }, + { + "type": "continue" + } + ], + "false": [ + "\t[老人,woman]你的金钱不足!" + ] + } + ] + }, + { + "text": "红钥匙(${36+4*flag:woman_times}金币)", + "action": [ + { + "type": "if", + "condition": "status:money>=36+4*flag:woman_times", + "true": [ + { + "type": "setValue", + "name": "status:money", + "operator": "-=", + "value": "36+4*flag:woman_times" + }, + { + "type": "setValue", + "name": "item:redKey", + "operator": "+=", + "value": "1" + } + ], + "false": [ + "\t[老人,woman]你的金钱不足!", + { + "type": "continue" + } + ] + } + ] + }, + { + "text": "离开", + "action": [ + { + "type": "exit" + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "setValue", + "name": "flag:woman_times", + "operator": "+=", + "value": "1" + } + ] + } + ], + "12,11": [ + "\t[老人,womanMagician]使用 {\"type\":\"function\"} 可以写自定义的JS脚本。\n本塔支持的所有主要API会在doc文档内给出。", + "\t[老人,womanMagician]例如这个例子:即将弹出一个输入窗口,然后会将你的输入结果直接加到你的攻击力上。", + { + "type": "input", + "text": "请输入你要加攻击力的数值:" + }, + { + "type": "if", + "condition": "flag:input>0", + "true": [ + { + "type": "setValue", + "name": "status:atk", + "operator": "+=", + "value": "flag:input" + }, + { + "type": "tip", + "text": "操作成功,攻击+${flag:input}" + }, + "操作成功,攻击+${flag:input}" + ], + "false": [] + }, + "\t[老人,womanMagician]具体可参见样板中本事件的写法。" ] }, - "5,5": { - "floorId": "sample2", - "stair": "downFloor", - "direction": "up" - }, - "10,12": null -}, -"afterBattle": { - "9,6": [ - { - "type": "setValue", - "name": "flag:door", - "value": "flag:door+1" - } - ], - "11,6": [ - { - "type": "setValue", - "name": "flag:door", - "value": "flag:door+1" - } - ] -}, -"afterGetItem": {}, -"afterOpenDoor": {}, -"cannotMove": {}, -"bgmap": [ - -], -"fgmap": [ - -], -"autoEvent": { - "10,5": { - "0": { - "condition": "flag:door==2", - "currentFloor": true, - "priority": 0, - "delayExecute": false, - "multiExecute": false, - "data": [ - { - "type": "openDoor" - } - + "changeFloor": { + "4,12": { + "floorId": "sample0", + "loc": [ + 6, + 0 ] + }, + "5,5": { + "floorId": "sample2", + "stair": "downFloor", + "direction": "up" + }, + "10,12": null + }, + "afterBattle": { + "9,6": [ + { + "type": "setValue", + "name": "flag:door", + "operator": "+=", + "value": "1" + } + ], + "11,6": [ + { + "type": "setValue", + "name": "flag:door", + "operator": "+=", + "value": "1" + } + ] + }, + "afterGetItem": {}, + "afterOpenDoor": {}, + "cannotMove": {}, + "bgmap": [ + +], + "fgmap": [ + +], + "autoEvent": { + "10,5": { + "0": { + "condition": "flag:door==2", + "currentFloor": true, + "priority": 0, + "delayExecute": false, + "multiExecute": false, + "data": [ + { + "type": "openDoor" + } + ] + } } - } -} + }, + "width": 13, + "height": 13 } \ No newline at end of file diff --git a/project/floors/sample2.js b/project/floors/sample2.js index 7ae07530..a118ee6d 100644 --- a/project/floors/sample2.js +++ b/project/floors/sample2.js @@ -1,15 +1,15 @@ main.floors.sample2= { -"floorId": "sample2", -"title": "样板 2 层", -"name": "2", -"canFlyTo": true, -"canUseQuickShop": true, -"cannotViewMap": false, -"defaultGround": "ground", -"images": [], -"item_ratio": 1, -"map": [ + "floorId": "sample2", + "title": "样板 2 层", + "name": "2", + "canFlyTo": true, + "canUseQuickShop": true, + "cannotViewMap": false, + "defaultGround": "ground", + "images": [], + "item_ratio": 1, + "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], @@ -37,36 +37,37 @@ main.floors.sample2= [ 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], [ 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] ], -"width": 26, -"height": 26, -"firstArrive": [], -"events": { - "3,2": [ - "123" - ], - "12,12": [ - "234" - ] -}, -"changeFloor": { - "6,10": { - "floorId": "sample1", - "stair": "upFloor" + "width": 26, + "height": 26, + "firstArrive": [], + "events": { + "3,2": [ + "123" + ], + "12,12": [ + "234" + ] }, - "7,12": { - "floorId": "sample3", - "stair": "downFloor" - } -}, -"afterBattle": {}, -"afterGetItem": {}, -"afterOpenDoor": {}, -"cannotMove": {}, -"upFloor": null, -"bgmap": [ + "changeFloor": { + "6,10": { + "floorId": "sample1", + "stair": "upFloor" + }, + "7,12": { + "floorId": "sample3", + "stair": "downFloor" + } + }, + "afterBattle": {}, + "afterGetItem": {}, + "afterOpenDoor": {}, + "cannotMove": {}, + "upFloor": null, + "bgmap": [ ], -"fgmap": [ + "fgmap": [ ], + "autoEvent": {} } \ No newline at end of file diff --git a/project/floors/sample3.js b/project/floors/sample3.js index e115ba5f..e0c28451 100644 --- a/project/floors/sample3.js +++ b/project/floors/sample3.js @@ -1,25 +1,25 @@ main.floors.sample3= { -"floorId": "sample3", -"title": "主塔 40 层", -"name": "40", -"canFlyTo": false, -"canUseQuickShop": true, -"defaultGround": "snowGround", -"images": [], -"color": [ - 255, - 0, - 0, - 0.3 -], -"weather": [ - "rain", - 10 -], -"bgm": "bgm.mp3", -"item_ratio": 1, -"map": [ + "floorId": "sample3", + "title": "主塔 40 层", + "name": "40", + "canFlyTo": false, + "canUseQuickShop": true, + "defaultGround": "snowGround", + "images": [], + "color": [ + 255, + 0, + 0, + 0.3 + ], + "weather": [ + "rain", + 10 + ], + "bgm": "bgm.mp3", + "item_ratio": 1, + "map": [ [ 5, 5, 5, 5, 5, 5, 87, 5, 5, 5, 5, 5, 5], [ 5, 4, 4, 4, 4, 1, 0, 1, 4, 4, 4, 4, 5], [ 5, 4, 4, 4, 4, 1, 85, 1, 4, 4, 4, 4, 5], @@ -34,972 +34,975 @@ main.floors.sample3= [ 5, 4, 4, 4, 4, 4, 85, 4, 4, 4, 4, 4, 5], [ 5, 5, 5, 5, 5, 5, 88, 5, 5, 5, 5, 5, 5] ], -"firstArrive": [ - "\t[实战!]本楼将尝试复刻《宿命的旋律》40F剧情。" -], -"events": { - "6,11": { - "enable": false, - "data": [] - }, - "6,10": [ - { - "type": "playSound", - "name": "door.mp3" - }, - { - "type": "show", - "loc": [ - 6, - 11 - ] - }, - { - "type": "hide" - }, - { - "type": "trigger", - "loc": [ - 6, - 7 - ] - } + "firstArrive": [ + "\t[实战!]本楼将尝试复刻《宿命的旋律》40F剧情。" ], - "6,7": [ - { - "type": "playSound", - "name": "item.mp3" + "events": { + "6,11": { + "enable": false, + "data": [] }, - "\t[hero]杰克,你究竟是什么人?", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[杰克,thief]……", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[hero]我们……是朋友对吧?\n是朋友就应该相互信任对吧?", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[杰克,thief]……事到如今也没有什么好隐瞒的了。", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[杰克,thief]没错,我就是这一切的背后主谋。", - { - "type": "move", - "steps": [ - { - "direction": "up", - "value": 3 - } - ], - "time": 1000 - }, - { - "type": "show", - "loc": [ - 6, - 4 - ], - "time": 1000 - }, - { - "type": "sleep", - "time": 500 - }, - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]我的真名为——黑暗大法师,第四区域的头目。", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[hero]呵呵,不知道为什么,我竟然对事情走到现在这一步毫不感觉意外。", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]以杰克的名义利用了你这么久,真是抱歉啊。", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[hero]真正的杰克现在在哪里?", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]盗贼杰克这个人类从未存在过,他只是我用来接近你的一副皮囊而已。", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[hero]……这样啊,呵呵。", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]为什么你看上去丝毫不生气?", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[hero]多亏了鬼帝,我现在的脾气好得连我自己都害怕。", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[hero]说起来我还得好好感谢你呢,如果没有杰克……你的帮助,我早就死在第一区域了。", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[hero]不论你的目的如何,你的所作所为都是对我有利的。不是吗?", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]能够如此淡定的面对背叛,看来跟五年前相比,你确实成长了很多啊。", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[hero]五年前?……黑暗大法师,在这之前,我们好像素未谋面吧?", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]五年前那场屠城你应该这一生都不会忘记吧。", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]很不巧,那场屠城的主谋,也是我。", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[hero]……", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[hero]这么说,击中我双亲的那道紫色闪电,也就是你释放的吧……", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]你的双亲?这种事情我怎么可能会记得?\n你难道在踩死蚂蚁的时候还会一只只记下他们的样子吗?", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[hero]老 子 要 你 的 命", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]你应该对我心怀感激才对,如果不是那时的我看出了你隐藏的稀有勇者体质,你绝对不可能活到今天。", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]在暗中动手脚让你通过勇者选拔的人也是我,我一直一直在暗中引导你走到今天这一步。", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]是我救赎了一无是处的你。", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[hero]为什么只有我一个人活了下来!!!!", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[hero]为什么偏偏是我!!!!", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]我刚才不是说过了吗?因为我看出了你有稀有勇者体质啊。", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]你刚刚跟鬼帝交过手,应该已经很清楚这稀有勇者体质意味着什么了吧?", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[hero]……就因为我有这种体质,就不得不背负如此残酷的宿命吗?", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]愚蠢!这意味着只要我对你加以引导跟培养,你就能成为这世间实力最强的存在!", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[hero]……所以,你究竟想利用我干什么?", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]我利用你干的事情,你不是已经完成了吗?", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[hero]……你说什么?", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]不知不觉间,你已经在我的指引下跟鬼帝正面交手并且杀掉了他啊。", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[hero]就连我跟鬼帝的对决……也是被你安排好了的?", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]你们两个一个是人类勇者,一个是魔物勇者,迟早会有交手的一天。", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]我只不过是操纵了一系列的连锁事件让这一天提早了数十年到来而已。", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[hero]……你这样做对谁有好处?他可是你们魔物世界的救世主啊。", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]一个惧怕征战,爱好和平的懦夫,也配叫救世主?", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]获得了力量,却只会被动挨打而不主动向人类世界出击,龟缩在第二区域惶惶度日,他根本就不配拥有稀有勇者体质。", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]为了不让这种人霸占着积累多年的庞大灵魂能量无作为,我设计让你杀掉了他。", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]你没有辜负我的期待,成功战胜了那个废物,现在你体内累积的灵魂能量……也就是魔力,已经达到了能跟魔王匹敌的地步。", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[hero]……是吗?现在的我能与魔王匹敌?", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]不止如此,你现在的力量之强就算是统治世界也是绰绰有余!", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]怎么样?要不要加入我的麾下,跟随我去征战人类世界?", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[hero]能与魔王匹敌的话,也就是说。", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[hero]我 现 在 对 付 你 这 种 杂 碎 也 绰 绰 有 余 吧 ?", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]……什么?!", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]等一下!别冲动!你先等我把这利害关系理一理——", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[hero]你给老子闭嘴。", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[hero]老子什么都不想听。", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[hero]老子现在想做的事情只有一件——", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[hero]剁掉你的头,把它放回我双亲的墓前。", - { - "type": "update" - } - ], - "6,4": { - "enable": false, - "data": [] - }, - "5,4": { - "enable": false, - "data": [] - }, - "7,4": { - "enable": false, - "data": [] - }, - "5,5": { - "enable": false, - "data": [] - }, - "7,5": { - "enable": false, - "data": [] - }, - "6,3": { - "trigger": "action", - "enable": false, - "data": [ - "\t[blackMagician]听不进去人话的蠢货,就要用疼痛来管教!", - { - "type": "changePos", - "direction": "up" - }, + "6,10": [ { "type": "playSound", - "name": "item.mp3" + "name": "door.mp3" }, - "\t[blackMagician]出来吧!禁忌——紫电凶杀阵!", - { - "type": "show", - "loc": [ - [ - 4, - 3 - ], - [ - 4, - 6 - ], - [ - 8, - 6 - ], - [ - 8, - 3 - ] - ], - "time": 500 - }, - { - "type": "sleep", - "time": 500 - }, - "\t[blackMagician]感受绝望吧!冥顽不化的蠢货!", - { - "type": "animate", - "name": "yongchang", - "loc": [ - 4, - 3 - ] - }, - { - "type": "animate", - "name": "yongchang", - "loc": [ - 4, - 6 - ] - }, - { - "type": "animate", - "name": "yongchang", - "loc": [ - 8, - 6 - ] - }, - { - "type": "animate", - "name": "yongchang", - "loc": [ - 8, - 3 - ] - }, - { - "type": "sleep", - "time": 200 - }, - { - "type": "playSound", - "name": "attack.mp3" - }, - { - "type": "animate", - "name": "thunder", - "loc": "hero" - }, - { - "type": "sleep", - "time": 200 - }, - "\t[hero]唔……!!(吐血)", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]我的魔力可是充足的很啊!我会一直折磨到你屈服于我为止!", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]人类!好好感受吧!当初你们施加于我的痛苦!如今我要百倍奉还!", { "type": "show", "loc": [ 6, - 6 - ], - "time": 1000 + 11 + ] }, { - "type": "sleep", - "time": 700 + "type": "hide" }, { "type": "trigger", "loc": [ 6, - 6 + 7 ] } - ] - }, - "4,3": { - "trigger": "action", - "displayDamage": false, - "enable": false, - "data": [] - }, - "8,3": { - "trigger": "action", - "displayDamage": false, - "enable": false, - "data": [] - }, - "4,6": { - "trigger": "action", - "displayDamage": false, - "enable": false, - "data": [] - }, - "8,6": { - "trigger": "action", - "displayDamage": false, - "enable": false, - "data": [] - }, - "6,6": { - "enable": false, - "data": [ + ], + "6,7": [ { "type": "playSound", "name": "item.mp3" }, - "\t[hero]…妖精…小姐……是你吗?", + "\t[hero]杰克,你究竟是什么人?", { "type": "playSound", "name": "item.mp3" }, - "\t[小妖精,fairy]不要绝望,也不要悲伤。", + "\t[杰克,thief]……", { "type": "playSound", "name": "item.mp3" }, - "\t[小妖精,fairy]你从来都不是独自一人在前进。", + "\t[hero]我们……是朋友对吧?\n是朋友就应该相互信任对吧?", { "type": "playSound", "name": "item.mp3" }, - "\t[小妖精,fairy]咱一直,一直都在注视着你。", + "\t[杰克,thief]……事到如今也没有什么好隐瞒的了。", { "type": "playSound", "name": "item.mp3" }, - "\t[小妖精,fairy]耍小聪明的你、笨笨的你呆呆的你、胆小的你、勇敢的你帅气的你……全部全部都是你。", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[小妖精,fairy]所以放心吧,无论发生什么,咱都会陪伴在你身边的。", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[小妖精,fairy]因为你要是离开我的话,立刻就会死掉吧?", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[hero]…妖精…小姐……其实一直以来,我都非常感激你……", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[小妖精,fairy]笨蛋!都这种时候了就不要作出像是临终遗言的发言了啊!!", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[小妖精,fairy]喂!那边穿衣品味差到极点的黑暗大法师,别左顾右盼说的就是你!你应该知道咱的身份吧?\n还不速速退下!", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]可恶…多管闲事的妖精族…明明只要再让他承受一点疼痛来瓦解他的意志力,我的计划就成功了!", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[小妖精,fairy]哼哼哼~抱歉哦,这个笨蛋的意志力可不像你想象的那么薄弱哦!", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]不甘心!我不甘心!妖精公主又如何!\n只要是阻挡我的,不管是谁我都要铲除!", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[小妖精,fairy]终于露出狐狸尾巴了,其实咱早就看出你有谋反的念头。你的计划就是拉拢这家伙入伙然后推翻魔王对魔塔的统治对吧?", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]呵呵呵……那个昏庸的魔王,掌握着那么庞大的魔物军队却只知道固守魔塔,而不主动侵略人类世界扩张领土!", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]我实在是看不过眼,所以我才决定把这个具备稀有勇者体质的家伙培养成新一任魔王!\n来让这个世界的势力重新洗牌!", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[小妖精,fairy]你觉得一个满脑子想着回家种田的废柴勇者会成为改变世界的魔王?你晃晃脑袋试试,是不是能听到大海的声音?", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]恼人至极的妖精族!呵呵呵……我干脆一不做二不休,连你也一块收拾了吧!", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[小妖精,fairy]别小瞧咱!咱好歹也是妖精族里实力数一数二的存在!", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]只会耍嘴皮子的恼人苍蝇!我倒要看看一块焦炭会不会说话!\n——招雷弹!!", - { - "type": "animate", - "name": "yongchang", - "loc": [ - 4, - 3 - ] - }, - { - "type": "animate", - "name": "yongchang", - "loc": [ - 4, - 6 - ] - }, - { - "type": "animate", - "name": "yongchang", - "loc": [ - 8, - 6 - ] - }, - { - "type": "animate", - "name": "yongchang", - "loc": [ - 8, - 3 - ] - }, - { - "type": "playSound", - "name": "attack.mp3" - }, - { - "type": "animate", - "name": "thunder", - "loc": [ - 6, - 6 - ] - }, - { - "type": "sleep", - "time": 500 - }, - "\t[小妖精,fairy]切,这点伤痛跟他刚才经历的身心地狱相比根本就不算什么。", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]哼!翅膀都被烧焦了还要嘴硬?你难不成真以为我不会对你动真格?", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[hero]……你这混蛋!给我离她远点!!", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[小妖精,fairy]!…你现在受了很严重的致命伤,乱动什么?\n乖。别怕,这里有咱顶着!", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[小妖精,fairy]对了,咱再问你一遍,你是很珍惜自己性命的对吧?", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[hero]!…等等…妖精小姐,你不会是……?", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[小妖精,fairy]喂,黑暗大法师,你作为魔塔里最博学多识的蠢货,应该对咱妖精族的特殊能力再清楚不过吧?", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]什么?!难不成你是想!!不可能……\n就为了一个渺小的人类,不可理喻!!", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[小妖精,fairy]哼哼哼!你害怕的表情可真美味!", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[小妖精,fairy]不过比起这个,咱更期待你吃到“妖精自灭冲击”之后的死状哦!~", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[blackMagician]不!!不应该是这样的!我完美的计划竟然会被一只小小的妖精破坏!", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[hero]不要!……千万不要!……为了我这种人……唔!", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[小妖精,fairy]笨蛋,动都动不了了就不要强撑着站起来了啊。", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[小妖精,fairy]真是的,都到最后一刻了,你这家伙好歹也让咱省点心吧。", - { - "type": "playSound", - "name": "item.mp3" - }, - "\t[小妖精,fairy]那么,再见了……我的勇者大人。", + "\t[杰克,thief]没错,我就是这一切的背后主谋。", { "type": "move", - "time": 700, "steps": [ { "direction": "up", "value": 3 } - ] - }, - { - "type": "playSound", - "name": "attack.mp3" - }, - { - "type": "sleep", - "time": 200 - }, - "\t[blackMagician]不可能!!!!!", - { - "type": "hide", - "loc": [ - 6, - 3 - ] - }, - { - "type": "hide", - "loc": [ - 4, - 3 - ] - }, - { - "type": "hide", - "loc": [ - 4, - 6 - ] - }, - { - "type": "hide", - "loc": [ - 8, - 6 - ] - }, - { - "type": "hide", - "loc": [ - 8, - 3 - ] - }, - { - "type": "changeFloor", - "floorId": "sample3", - "loc": [ - 6, - 6 ], - "direction": "up", "time": 1000 }, { "type": "show", "loc": [ 6, - 5 - ] + 4 + ], + "time": 1000 }, { "type": "sleep", - "time": 200 + "time": 500 }, { "type": "playSound", "name": "item.mp3" }, - { - "type": "sleep", - "time": 200 - }, - "\t[hero]…妖精…小姐……", + "\t[blackMagician]我的真名为——黑暗大法师,第四区域的头目。", { "type": "playSound", "name": "item.mp3" }, - "\t[hero]……妖精小姐!", + "\t[hero]呵呵,不知道为什么,我竟然对事情走到现在这一步毫不感觉意外。", { "type": "playSound", "name": "item.mp3" }, - "\t[hero]是梦吗?……不对,为什么我在流泪?", + "\t[blackMagician]以杰克的名义利用了你这么久,真是抱歉啊。", { "type": "playSound", "name": "item.mp3" }, - "\t[hero]这颗漂亮的宝石是……?", + "\t[hero]真正的杰克现在在哪里?", { "type": "playSound", "name": "item.mp3" }, - "\t[hero]我全都想起来了……妖精小姐为了我……\n牺牲了自己的性命。", + "\t[blackMagician]盗贼杰克这个人类从未存在过,他只是我用来接近你的一副皮囊而已。", { "type": "playSound", "name": "item.mp3" }, - "\t[hero]在这颗宝石上,我能感受到你的温度……\n熟悉而又令人安心,这就是你最后留给我的东西吗……", + "\t[hero]……这样啊,呵呵。", { "type": "playSound", "name": "item.mp3" }, - "\t[hero]好温暖……", + "\t[blackMagician]为什么你看上去丝毫不生气?", { - "type": "setValue", - "name": "item:yellowJewel", - "value": "1" + "type": "playSound", + "name": "item.mp3" }, + "\t[hero]多亏了鬼帝,我现在的脾气好得连我自己都害怕。", { - "type": "hide", - "loc": [ - 6, - 5 - ] + "type": "playSound", + "name": "item.mp3" }, + "\t[hero]说起来我还得好好感谢你呢,如果没有杰克……你的帮助,我早就死在第一区域了。", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[hero]不论你的目的如何,你的所作所为都是对我有利的。不是吗?", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]能够如此淡定的面对背叛,看来跟五年前相比,你确实成长了很多啊。", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[hero]五年前?……黑暗大法师,在这之前,我们好像素未谋面吧?", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]五年前那场屠城你应该这一生都不会忘记吧。", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]很不巧,那场屠城的主谋,也是我。", { "type": "playSound", "name": "item.mp3" }, "\t[hero]……", { - "type": "openDoor", + "type": "playSound", + "name": "item.mp3" + }, + "\t[hero]这么说,击中我双亲的那道紫色闪电,也就是你释放的吧……", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]你的双亲?这种事情我怎么可能会记得?\n你难道在踩死蚂蚁的时候还会一只只记下他们的样子吗?", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[hero]老 子 要 你 的 命", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]你应该对我心怀感激才对,如果不是那时的我看出了你隐藏的稀有勇者体质,你绝对不可能活到今天。", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]在暗中动手脚让你通过勇者选拔的人也是我,我一直一直在暗中引导你走到今天这一步。", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]是我救赎了一无是处的你。", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[hero]为什么只有我一个人活了下来!!!!", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[hero]为什么偏偏是我!!!!", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]我刚才不是说过了吗?因为我看出了你有稀有勇者体质啊。", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]你刚刚跟鬼帝交过手,应该已经很清楚这稀有勇者体质意味着什么了吧?", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[hero]……就因为我有这种体质,就不得不背负如此残酷的宿命吗?", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]愚蠢!这意味着只要我对你加以引导跟培养,你就能成为这世间实力最强的存在!", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[hero]……所以,你究竟想利用我干什么?", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]我利用你干的事情,你不是已经完成了吗?", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[hero]……你说什么?", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]不知不觉间,你已经在我的指引下跟鬼帝正面交手并且杀掉了他啊。", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[hero]就连我跟鬼帝的对决……也是被你安排好了的?", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]你们两个一个是人类勇者,一个是魔物勇者,迟早会有交手的一天。", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]我只不过是操纵了一系列的连锁事件让这一天提早了数十年到来而已。", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[hero]……你这样做对谁有好处?他可是你们魔物世界的救世主啊。", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]一个惧怕征战,爱好和平的懦夫,也配叫救世主?", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]获得了力量,却只会被动挨打而不主动向人类世界出击,龟缩在第二区域惶惶度日,他根本就不配拥有稀有勇者体质。", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]为了不让这种人霸占着积累多年的庞大灵魂能量无作为,我设计让你杀掉了他。", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]你没有辜负我的期待,成功战胜了那个废物,现在你体内累积的灵魂能量……也就是魔力,已经达到了能跟魔王匹敌的地步。", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[hero]……是吗?现在的我能与魔王匹敌?", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]不止如此,你现在的力量之强就算是统治世界也是绰绰有余!", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]怎么样?要不要加入我的麾下,跟随我去征战人类世界?", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[hero]能与魔王匹敌的话,也就是说。", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[hero]我 现 在 对 付 你 这 种 杂 碎 也 绰 绰 有 余 吧 ?", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]……什么?!", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]等一下!别冲动!你先等我把这利害关系理一理——", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[hero]你给老子闭嘴。", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[hero]老子什么都不想听。", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[hero]老子现在想做的事情只有一件——", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[hero]剁掉你的头,把它放回我双亲的墓前。", + { + "type": "update" + } + ], + "6,4": { + "enable": false, + "data": [] + }, + "5,4": { + "enable": false, + "data": [] + }, + "7,4": { + "enable": false, + "data": [] + }, + "5,5": { + "enable": false, + "data": [] + }, + "7,5": { + "enable": false, + "data": [] + }, + "6,3": { + "trigger": "action", + "enable": false, + "data": [ + "\t[blackMagician]听不进去人话的蠢货,就要用疼痛来管教!", + { + "type": "changePos", + "direction": "up" + }, + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]出来吧!禁忌——紫电凶杀阵!", + { + "type": "show", + "loc": [ + [ + 4, + 3 + ], + [ + 4, + 6 + ], + [ + 8, + 6 + ], + [ + 8, + 3 + ] + ], + "time": 500 + }, + { + "type": "sleep", + "time": 500 + }, + "\t[blackMagician]感受绝望吧!冥顽不化的蠢货!", + { + "type": "animate", + "name": "yongchang", + "loc": [ + 4, + 3 + ] + }, + { + "type": "animate", + "name": "yongchang", + "loc": [ + 4, + 6 + ] + }, + { + "type": "animate", + "name": "yongchang", + "loc": [ + 8, + 6 + ] + }, + { + "type": "animate", + "name": "yongchang", + "loc": [ + 8, + 3 + ] + }, + { + "type": "sleep", + "time": 200 + }, + { + "type": "playSound", + "name": "attack.mp3" + }, + { + "type": "animate", + "name": "thunder", + "loc": "hero" + }, + { + "type": "sleep", + "time": 200 + }, + "\t[hero]唔……!!(吐血)", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]我的魔力可是充足的很啊!我会一直折磨到你屈服于我为止!", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]人类!好好感受吧!当初你们施加于我的痛苦!如今我要百倍奉还!", + { + "type": "show", + "loc": [ + 6, + 6 + ], + "time": 1000 + }, + { + "type": "sleep", + "time": 700 + }, + { + "type": "trigger", + "loc": [ + 6, + 6 + ] + } + ] + }, + "4,3": { + "trigger": "action", + "displayDamage": false, + "enable": false, + "data": [] + }, + "8,3": { + "trigger": "action", + "displayDamage": false, + "enable": false, + "data": [] + }, + "4,6": { + "trigger": "action", + "displayDamage": false, + "enable": false, + "data": [] + }, + "8,6": { + "trigger": "action", + "displayDamage": false, + "enable": false, + "data": [] + }, + "6,6": { + "enable": false, + "data": [ + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[hero]…妖精…小姐……是你吗?", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[小妖精,fairy]不要绝望,也不要悲伤。", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[小妖精,fairy]你从来都不是独自一人在前进。", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[小妖精,fairy]咱一直,一直都在注视着你。", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[小妖精,fairy]耍小聪明的你、笨笨的你呆呆的你、胆小的你、勇敢的你帅气的你……全部全部都是你。", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[小妖精,fairy]所以放心吧,无论发生什么,咱都会陪伴在你身边的。", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[小妖精,fairy]因为你要是离开我的话,立刻就会死掉吧?", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[hero]…妖精…小姐……其实一直以来,我都非常感激你……", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[小妖精,fairy]笨蛋!都这种时候了就不要作出像是临终遗言的发言了啊!!", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[小妖精,fairy]喂!那边穿衣品味差到极点的黑暗大法师,别左顾右盼说的就是你!你应该知道咱的身份吧?\n还不速速退下!", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]可恶…多管闲事的妖精族…明明只要再让他承受一点疼痛来瓦解他的意志力,我的计划就成功了!", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[小妖精,fairy]哼哼哼~抱歉哦,这个笨蛋的意志力可不像你想象的那么薄弱哦!", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]不甘心!我不甘心!妖精公主又如何!\n只要是阻挡我的,不管是谁我都要铲除!", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[小妖精,fairy]终于露出狐狸尾巴了,其实咱早就看出你有谋反的念头。你的计划就是拉拢这家伙入伙然后推翻魔王对魔塔的统治对吧?", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]呵呵呵……那个昏庸的魔王,掌握着那么庞大的魔物军队却只知道固守魔塔,而不主动侵略人类世界扩张领土!", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]我实在是看不过眼,所以我才决定把这个具备稀有勇者体质的家伙培养成新一任魔王!\n来让这个世界的势力重新洗牌!", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[小妖精,fairy]你觉得一个满脑子想着回家种田的废柴勇者会成为改变世界的魔王?你晃晃脑袋试试,是不是能听到大海的声音?", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]恼人至极的妖精族!呵呵呵……我干脆一不做二不休,连你也一块收拾了吧!", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[小妖精,fairy]别小瞧咱!咱好歹也是妖精族里实力数一数二的存在!", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]只会耍嘴皮子的恼人苍蝇!我倒要看看一块焦炭会不会说话!\n——招雷弹!!", + { + "type": "animate", + "name": "yongchang", + "loc": [ + 4, + 3 + ] + }, + { + "type": "animate", + "name": "yongchang", + "loc": [ + 4, + 6 + ] + }, + { + "type": "animate", + "name": "yongchang", + "loc": [ + 8, + 6 + ] + }, + { + "type": "animate", + "name": "yongchang", + "loc": [ + 8, + 3 + ] + }, + { + "type": "playSound", + "name": "attack.mp3" + }, + { + "type": "animate", + "name": "thunder", + "loc": [ + 6, + 6 + ] + }, + { + "type": "sleep", + "time": 500 + }, + "\t[小妖精,fairy]切,这点伤痛跟他刚才经历的身心地狱相比根本就不算什么。", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]哼!翅膀都被烧焦了还要嘴硬?你难不成真以为我不会对你动真格?", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[hero]……你这混蛋!给我离她远点!!", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[小妖精,fairy]!…你现在受了很严重的致命伤,乱动什么?\n乖。别怕,这里有咱顶着!", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[小妖精,fairy]对了,咱再问你一遍,你是很珍惜自己性命的对吧?", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[hero]!…等等…妖精小姐,你不会是……?", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[小妖精,fairy]喂,黑暗大法师,你作为魔塔里最博学多识的蠢货,应该对咱妖精族的特殊能力再清楚不过吧?", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]什么?!难不成你是想!!不可能……\n就为了一个渺小的人类,不可理喻!!", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[小妖精,fairy]哼哼哼!你害怕的表情可真美味!", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[小妖精,fairy]不过比起这个,咱更期待你吃到“妖精自灭冲击”之后的死状哦!~", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[blackMagician]不!!不应该是这样的!我完美的计划竟然会被一只小小的妖精破坏!", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[hero]不要!……千万不要!……为了我这种人……唔!", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[小妖精,fairy]笨蛋,动都动不了了就不要强撑着站起来了啊。", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[小妖精,fairy]真是的,都到最后一刻了,你这家伙好歹也让咱省点心吧。", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[小妖精,fairy]那么,再见了……我的勇者大人。", + { + "type": "move", + "time": 700, + "steps": [ + { + "direction": "up", + "value": 3 + } + ] + }, + { + "type": "playSound", + "name": "attack.mp3" + }, + { + "type": "sleep", + "time": 200 + }, + "\t[blackMagician]不可能!!!!!", + { + "type": "hide", + "loc": [ + 6, + 3 + ] + }, + { + "type": "hide", + "loc": [ + 4, + 3 + ] + }, + { + "type": "hide", + "loc": [ + 4, + 6 + ] + }, + { + "type": "hide", + "loc": [ + 8, + 6 + ] + }, + { + "type": "hide", + "loc": [ + 8, + 3 + ] + }, + { + "type": "changeFloor", + "floorId": "sample3", + "loc": [ + 6, + 6 + ], + "direction": "up", + "time": 1000 + }, + { + "type": "show", + "loc": [ + 6, + 5 + ] + }, + { + "type": "sleep", + "time": 200 + }, + { + "type": "playSound", + "name": "item.mp3" + }, + { + "type": "sleep", + "time": 200 + }, + "\t[hero]…妖精…小姐……", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[hero]……妖精小姐!", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[hero]是梦吗?……不对,为什么我在流泪?", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[hero]这颗漂亮的宝石是……?", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[hero]我全都想起来了……妖精小姐为了我……\n牺牲了自己的性命。", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[hero]在这颗宝石上,我能感受到你的温度……\n熟悉而又令人安心,这就是你最后留给我的东西吗……", + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[hero]好温暖……", + { + "type": "setValue", + "name": "item:yellowJewel", + "value": "1" + }, + { + "type": "hide", + "loc": [ + 6, + 5 + ] + }, + { + "type": "playSound", + "name": "item.mp3" + }, + "\t[hero]……", + { + "type": "openDoor", + "loc": [ + 6, + 2 + ] + }, + { + "type": "openDoor", + "loc": [ + 6, + 11 + ] + } + ] + }, + "6,5": { + "enable": false, + "data": [] + } + }, + "changeFloor": { + "6,0": { + "floorId": "sample3", + "stair": "upFloor" + }, + "6,12": { + "floorId": "sample2", + "stair": "upFloor" + } + }, + "afterBattle": { + "6,4": [ + "\t[blackMagician]天真!你以为这样就能战胜我吗?", + { + "type": "show", "loc": [ - 6, - 2 - ] + 7, + 5 + ], + "time": 500 }, { - "type": "openDoor", + "type": "update" + } + ], + "7,5": [ + "\t[blackMagician]你打败的不过是我众多分身中的其中一个而已。", + { + "type": "show", + "loc": [ + 5, + 4 + ], + "time": 500 + }, + { + "type": "update" + } + ], + "5,4": [ + "\t[blackMagician]你的身体已经伤痕累累了,可我还留有着九成多的魔力。", + { + "type": "show", + "loc": [ + 5, + 5 + ], + "time": 500 + }, + { + "type": "update" + } + ], + "5,5": [ + "\t[blackMagician]顽固的家伙!放弃抵抗吧!", + { + "type": "show", + "loc": [ + 7, + 4 + ], + "time": 500 + }, + { + "type": "update" + } + ], + "7,4": [ + "\t[blackMagician]哈哈哈哈!我的灵魂远比你想象的强大!\n我即是永恒!", + { + "type": "show", "loc": [ 6, - 11 + 3 + ], + "time": 500 + }, + { + "type": "trigger", + "loc": [ + 6, + 3 ] } ] }, - "6,5": { - "enable": false, - "data": [] - } -}, -"changeFloor": { - "6,0": { - "floorId": "sample3", - "stair": "upFloor" - }, - "6,12": { - "floorId": "sample2", - "stair": "upFloor" - } -}, -"afterBattle": { - "6,4": [ - "\t[blackMagician]天真!你以为这样就能战胜我吗?", - { - "type": "show", - "loc": [ - 7, - 5 - ], - "time": 500 - }, - { - "type": "update" - } - ], - "7,5": [ - "\t[blackMagician]你打败的不过是我众多分身中的其中一个而已。", - { - "type": "show", - "loc": [ - 5, - 4 - ], - "time": 500 - }, - { - "type": "update" - } - ], - "5,4": [ - "\t[blackMagician]你的身体已经伤痕累累了,可我还留有着九成多的魔力。", - { - "type": "show", - "loc": [ - 5, - 5 - ], - "time": 500 - }, - { - "type": "update" - } - ], - "5,5": [ - "\t[blackMagician]顽固的家伙!放弃抵抗吧!", - { - "type": "show", - "loc": [ - 7, - 4 - ], - "time": 500 - }, - { - "type": "update" - } - ], - "7,4": [ - "\t[blackMagician]哈哈哈哈!我的灵魂远比你想象的强大!\n我即是永恒!", - { - "type": "show", - "loc": [ - 6, - 3 - ], - "time": 500 - }, - { - "type": "trigger", - "loc": [ - 6, - 3 - ] - } - ] -}, -"afterGetItem": {}, -"afterOpenDoor": {}, -"cannotMove": {}, -"bgmap": [ + "afterGetItem": {}, + "afterOpenDoor": {}, + "cannotMove": {}, + "bgmap": [ ], -"fgmap": [ + "fgmap": [ ], + "width": 13, + "height": 13, + "autoEvent": {} } \ No newline at end of file diff --git a/project/functions.js b/project/functions.js index 705a669f..3490a227 100644 --- a/project/functions.js +++ b/project/functions.js @@ -29,7 +29,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = // 初始化怪物和道具 core.material.enemys = core.enemys.getEnemys(); core.material.items = core.items.getItems(); - core.items._resetItems(); // 初始化全局数值和全局开关 core.values = core.clone(core.data.values); for (var key in values || {}) @@ -49,28 +48,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = core.showStatusBar(); // 隐藏右下角的音乐按钮 core.dom.musicBtn.style.display = 'none'; -}, - "setInitData": function () { - // 不同难度分别设置初始属性 - if (core.status.hard == 'Easy') { // 简单难度 - core.setFlag('hard', 1); // 可以用flag:hard来获得当前难度 - // 可以在此设置一些初始福利,比如设置初始生命值可以调用: - // core.setStatus("hp", 10000); - // 赠送一把黄钥匙可以调用 - // core.setItem("yellowKey", 1); - } - if (core.status.hard == 'Normal') { // 普通难度 - core.setFlag('hard', 2); // 可以用flag:hard来获得当前难度 - } - if (core.status.hard == 'Hard') { // 困难难度 - core.setFlag('hard', 3); // 可以用flag:hard来获得当前难度 - } - if (core.status.hard == 'Hell') { // 噩梦难度 - core.setFlag('hard', 4); // 可以用flag:hard来获得当前难度 - } - - // 设置已经到过的楼层 - core.setFlag("__visited__", {}); }, "win": function (reason, norank, noexit) { // 游戏获胜事件 @@ -114,15 +91,16 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = }); }) }, - "changingFloor": function (floorId, heroLoc, fromLoad) { + "changingFloor": function (floorId, heroLoc) { // 正在切换楼层过程中执行的操作;此函数的执行时间是“屏幕完全变黑“的那一刻 - // floorId为要切换到的楼层ID;heroLoc表示勇士切换到的位置;fromLoad表示是否是从读档造成的切换 + // floorId为要切换到的楼层ID;heroLoc表示勇士切换到的位置 // ---------- 此时还没有进行切换,当前floorId还是原来的 ---------- // var currentId = core.status.floorId || null; // 获得当前的floorId,可能为null + var fromLoad = core.hasFlag('__fromLoad__'); // 是否是读档造成的切换 if (!fromLoad) { if (!core.hasFlag("__leaveLoc__")) core.setFlag("__leaveLoc__", {}); - if (currentId != null) core.getFlag("__leaveLoc__")[currentId] = core.status.hero.loc; + if (currentId != null) core.getFlag("__leaveLoc__")[currentId] = core.clone(core.status.hero.loc); } // 可以对currentId进行判定,比如删除某些自定义图层等 @@ -132,6 +110,8 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = // 重置画布尺寸 core.maps.resizeMap(floorId); + // 设置勇士的位置 + core.status.hero.loc = heroLoc; // 检查重生怪并重置 if (!fromLoad) { core.status.maps[floorId].blocks.forEach(function (block) { @@ -139,10 +119,8 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = block.disable = false; } }); + core.control.gatherFollowers(); } - // 设置勇士的位置 - core.status.hero.loc = heroLoc; - core.control.gatherFollowers(); // ---------- 重绘新地图;这一步将会设置core.status.floorId ---------- // core.drawMap(floorId); @@ -171,12 +149,12 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = // ...可以新增一些其他内容,比如创建个画布在右上角显示什么内容等等 }, - "afterChangeFloor": function (floorId, fromLoad) { + "afterChangeFloor": function (floorId) { // 转换楼层结束的事件;此函数会在整个楼层切换完全结束后再执行 - // floorId是切换到的楼层;fromLoad若为true则代表是从读档行为造成的楼层切换 + // floorId是切换到的楼层 // 如果是读档,则进行检查(是否需要恢复事件) - if (fromLoad) { + if (core.hasFlag('__fromLoad__')) { core.events.recoverEvents(core.getFlag("__events__")); core.removeFlag("__events__"); } else { @@ -308,16 +286,16 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = core.status.hero.money += money; core.status.hero.statistics.money += money; - var experience = guards.reduce(function (curr, g) { - return curr + core.material.enemys[g[2]].experience; - }, enemy.experience); - if (core.hasFlag('curse')) experience = 0; - core.status.hero.experience += experience; - core.status.hero.statistics.experience += experience; + var exp = guards.reduce(function (curr, g) { + return curr + core.material.enemys[g[2]].exp; + }, enemy.exp); + if (core.hasFlag('curse')) exp = 0; + core.status.hero.exp += exp; + core.status.hero.statistics.exp += exp; var hint = "打败 " + enemy.name; - if (core.flags.enableMoney) hint += ",金币+" + money; - if (core.flags.enableExperience) hint += ",经验+" + experience; + if (core.flags.statusBarItems.indexOf('enableMoney')>=0) hint += ",金币+" + money; + if (core.flags.statusBarItems.indexOf('enableExp')>=0) hint += ",经验+" + exp; core.drawTip(hint, enemy.id); // 事件的处理 @@ -336,8 +314,8 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = if (core.enemys.hasSpecial(special, 14)) { core.push(todo, [{ "type": "insert", "name": "毒衰咒处理", "args": [2] }]); } - // 仇恨属性:减半 - if (core.flags.hatredDecrease && core.enemys.hasSpecial(special, 17)) { + // 仇恨属性 + if (core.enemys.hasSpecial(special, 17)) { core.setFlag('hatred', Math.floor(core.getFlag('hatred', 0) / 2)); } // 自爆 @@ -356,7 +334,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = core.setFlag('hatred', core.getFlag('hatred', 0) + core.values.hatred); // 战后的技能处理,比如扣除魔力值 - if (core.flags.enableSkill) { + if (core.flags.statusBarItems.indexOf('enableSkill') >=0 ) { // 检测当前开启的技能类型 var skill = core.getFlag('skill', 0); if (skill == 1) { // 技能1:二倍斩 @@ -402,6 +380,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = // 开一个门后触发的事件 var todo = []; + // 检查该点的获得开门后事件。 var event = core.floors[core.status.floorId].afterOpenDoor[x + "," + y]; if (event) core.unshift(todo, event); @@ -414,21 +393,22 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = if (callback) callback(); }, - "afterGetItem": function (itemId, x, y, callback) { + "afterGetItem": function (itemId, x, y, isGentleClick, callback) { // 获得一个道具后触发的事件 + // itemId:获得的道具ID;x和y是该道具所在的坐标 + // isGentleClick:是否是轻按触发的 core.playSound('item.mp3'); var todo = []; + // 检查该点的获得道具后事件。 var event = core.floors[core.status.floorId].afterGetItem[x + "," + y]; - if (event) core.unshift(todo, event); + if (event && (event instanceof Array || !isGentleClick || !event.disableOnGentleClick)) { + core.unshift(todo, event); + } if (todo.length > 0) core.insertAction(todo, x, y); if (callback) callback(); -}, - "afterChangeLight": function(x,y) { - // 改变亮灯之后,可以触发的事件 - }, "afterPushBox": function () { // 推箱子后的事件 @@ -443,40 +423,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = */ } }, - "afterUseBomb": function () { - // 使用炸弹/圣锤后的事件 - - // 这是一个使用炸弹也能开门的例子 - /* - if (core.status.floorId=='xxx' && core.terrainExists(x0,y0,'specialDoor') // 某个楼层,该机关门存在 - && !core.enemyExists(x1,y1) && !core.enemyExists(x2,y2)) // 且守门的怪物都不存在 - { - core.insertAction([ // 插入事件 - {"type": "openDoor", "loc": [x0,y0]} // 开门 - ]) - } - */ - -}, - "afterPassNet": function (x, y, id) { - // 经过特殊地形后的事件;x和y为当前坐标,id为当前的图块id - - // 这是个一次性血网的例子 - // if (id == 'lavaNet') core.removeBlock(x, y); - -}, - "canUseQuickShop": function(shopId) { - // 当前能否使用某个快捷商店 - // shopId:快捷商店ID - // 如果返回一个字符串,表示不能,字符串为不能使用的提示 - // 返回null代表可以使用 - - // 检查当前楼层的canUseQuickShop选项是否为false - if (core.status.thisMap.canUseQuickShop === false) - return '当前楼层不能使用快捷商店。'; - - return null; -} }, "enemys": { "getSpecials": function () { @@ -489,10 +435,10 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = [3, "坚固", "勇士每回合最多只能对怪物造成1点伤害"], [4, "2连击", "怪物每回合攻击2次"], [5, "3连击", "怪物每回合攻击3次"], - [6, function (enemy) { return (enemy.n || 4) + "连击"; }, function (enemy) { return "怪物每回合攻击" + (enemy.n || 4) + "次"; }], + [6, function (enemy) { return (enemy.n || '') + "连击"; }, 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 + "倍作为伤害"], + [9, "净化", "战斗前,怪物附加勇士护盾的" + core.values.purify + "倍作为伤害"], [10, "模仿", "怪物的攻防和勇士攻防相等"], [11, "吸血", function (enemy) { return "战斗前,怪物首先吸取角色的" + Math.floor(100 * enemy.value || 0) + "%生命(约" + Math.floor((enemy.value || 0) * core.getStatus('hp')) + "点)作为伤害" + (enemy.add ? ",并把伤害数值加到自身生命上" : ""); }], [12, "中毒", "战斗后,勇士陷入中毒状态,每一步损失生命" + core.values.poisonDamage + "点"], @@ -500,12 +446,12 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = [14, "诅咒", "战斗后,勇士陷入诅咒状态,战斗无法获得金币和经验"], [15, "领域", function (enemy) { return "经过怪物周围" + (enemy.zoneSquare ? "九宫格" : "十字") + "范围内" + (enemy.range || 1) + "格时自动减生命" + (enemy.value || 0) + "点"; }], [16, "夹击", "经过两只相同的怪物中间,勇士生命值变成一半"], - [17, "仇恨", "战斗前,怪物附加之前积累的仇恨值作为伤害" + (core.flags.hatredDecrease ? ";战斗后,释放一半的仇恨值" : "") + "。(每杀死一个怪物获得" + (core.values.hatred || 0) + "点仇恨值)"], + [17, "仇恨", "战斗前,怪物附加之前积累的仇恨值作为伤害;战斗后,释放一半的仇恨值。(每杀死一个怪物获得" + (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) + "点固定伤害,无视勇士魔防。"; }], + [22, "固伤", function (enemy) { return "战斗前,怪物对勇士造成" + (enemy.damage || 0) + "点固定伤害,无视勇士护盾。"; }], [23, "重生", "怪物被击败后,角色转换楼层则怪物将再次出现"], [24, "激光", function (enemy) { return "经过怪物同行或同列时自动减生命" + (enemy.value || 0) + "点"; }], [25, "光环", function (enemy) { return "同楼层所有怪物生命提升" + (enemy.value || 0) + "%,攻击提升" + (enemy.atkValue || 0) + "%,防御提升" + (enemy.defValue || 0) + "%," + (enemy.add ? "可叠加" : "不可叠加"); }], @@ -519,7 +465,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = // // 参数说明: // enemy:该怪物信息 - // hero_hp,hero_atk,hero_def,hero_mdef:勇士的生命攻防魔防数据 + // hero_hp,hero_atk,hero_def,hero_mdef:勇士的生命攻防护盾数据 // x,y:该怪物的坐标(查看手册和强制战斗时为undefined) // floorId:该怪物所在的楼层 // 后面三个参数主要是可以在光环等效果上可以适用(也可以按需制作部分范围光环效果) @@ -534,7 +480,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = mon_def = enemy.def, mon_special = enemy.special; var mon_money = enemy.money, - mon_experience = enemy.experience, + mon_exp = enemy.exp, mon_point = enemy.point; // 模仿 if (core.hasSpecial(mon_special, 10)) { @@ -625,7 +571,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = "atk": Math.floor(mon_atk), "def": Math.floor(mon_def), "money": Math.floor(mon_money), - "experience": Math.floor(mon_experience), + "exp": Math.floor(mon_exp), "point": Math.floor(mon_point), "special": mon_special, "guards": guards, // 返回支援情况 @@ -673,7 +619,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = if (core.hasSpecial(mon_special, 20) && !core.hasItem("cross")) return null; // 不可战斗 - // 战前造成的额外伤害(可被魔防抵消) + // 战前造成的额外伤害(可被护盾抵消) var init_damage = 0; // 吸血 @@ -761,13 +707,21 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = // 最终伤害:初始伤害 + 怪物对勇士造成的伤害 + 反击伤害 var damage = init_damage + (turn - 1) * per_damage + turn * counterDamage; - // 再扣去魔防 + // 再扣去护盾 damage -= hero_mdef; // 检查是否允许负伤 if (!core.flags.enableNegativeDamage) damage = Math.max(0, damage); + // 最后处理仇恨和固伤(因为这两个不能被护盾减伤) + if (core.hasSpecial(mon_special, 17)) { // 仇恨 + damage += core.getFlag('hatred', 0); + } + if (core.hasSpecial(mon_special, 22)) { // 固伤 + damage += enemy.damage || 0; + } + return { "mon_hp": Math.floor(mon_hp), "mon_atk": Math.floor(mon_atk), @@ -832,7 +786,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = case 90: // Z:转向 core.turnHero(); break; - case 75: case 86: // V:打开快捷商店列表 core.openQuickShop(true); break; @@ -846,9 +799,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = case 34: // PgUp/PgDn:浏览地图 core.ui.drawMaps(); break; - case 77: // M:绘图模式 - core.ui.drawPaint(); - break; case 66: // B:打开数据统计 core.ui.drawStatistics(); break; @@ -866,30 +816,14 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = break; case 49: // 快捷键1: 破 if (core.hasItem('pickaxe')) { - if (core.canUseItem('pickaxe')) { - core.status.route.push("key:49"); // 将按键记在录像中 - core.useItem('pickaxe', true); // 第二个参数true代表该次使用道具是被按键触发的,使用过程不计入录像 - } else { - core.drawTip('当前不能使用破墙镐'); - } + core.status.route.push("key:49"); // 将按键记在录像中 + core.useItem('pickaxe', true); // 第二个参数true代表该次使用道具是被按键触发的,使用过程不计入录像 } break; case 50: // 快捷键2: 炸 if (core.hasItem('bomb')) { - if (core.canUseItem('bomb')) { - core.status.route.push("key:50"); // 将按键记在录像中 - core.useItem('bomb', true); // 第二个参数true代表该次使用道具是被按键触发的,使用过程不计入录像 - } else { - core.drawTip('当前不能使用炸弹'); - } - } else if (core.hasItem('hammer')) { - if (core.canUseItem('hammer')) { - core.status.route.push("key:50"); // 将按键记在录像中 - core.useItem('hammer', true); // 第二个参数true代表该次使用道具是被按键触发的,使用过程不计入录像 - } else { - core.drawTip('当前不能使用圣锤'); - } - + core.status.route.push("key:50"); // 将按键记在录像中 + core.useItem('bomb', true); // 第二个参数true代表该次使用道具是被按键触发的,使用过程不计入录像 } break; case 51: // 快捷键3: 飞 @@ -983,20 +917,9 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = 'maps': core.maps.saveMap(), 'route': core.encodeRoute(core.status.route), 'values': values, - 'shops': {}, 'version': core.firstData.version, "time": new Date().getTime() }; - if (core.flags.checkConsole) { - data.hashCode = core.utils.hashCode(data.hero); - } - // 设置商店次数 - for (var shopId in core.status.shops) { - data.shops[shopId] = { - 'times': core.status.shops[shopId].times || 0, - 'visited': core.status.shops[shopId].visited || false - }; - } return data; }, @@ -1006,13 +929,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = // 重置游戏和路线 core.resetGame(data.hero, data.hard, data.floorId, core.maps.loadMap(data.maps), data.values); core.status.route = core.decodeRoute(data.route); - // 加载商店信息 - for (var shopId in core.status.shops) { - if (data.shops[shopId]) { - core.status.shops[shopId].times = data.shops[shopId].times; - core.status.shops[shopId].visited = data.shops[shopId].visited; - } - } // 文字属性,全局属性 core.status.textAttribute = core.getFlag('textAttribute', core.status.textAttribute); var toAttribute = core.getFlag('globalAttribute', core.status.globalAttribute); @@ -1030,6 +946,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = core.material.icons.hero.width = core.material.images.images[icon].width / 4; core.material.icons.hero.height = core.material.images.images[icon].height / 4; } + core.setFlag('__fromLoad__', true); // TODO:增加自己的一些读档处理 @@ -1041,7 +958,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = } if (callback) callback(); - }, true); + }); }, "updateStatusBar": function () { // 更新状态栏 @@ -1050,7 +967,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = core.events.checkLvUp(); // 检查HP上限 - if (core.flags.enableHPMax) { + if (core.flags.statusBarItems.indexOf('enableHPMax') >= 0) { core.setStatus('hp', Math.min(core.getStatus('hpmax'), core.getStatus('hp'))); } @@ -1064,8 +981,8 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = // 设置等级名称 core.setStatusBarInnerHTML('lv', core.getLvName()); - // 设置生命上限、生命值、攻防魔防金币和经验值 - var statusList = ['hpmax', 'hp', 'mana', 'atk', 'def', 'mdef', 'money', 'experience']; + // 设置生命上限、生命值、攻防护盾金币和经验值 + var statusList = ['hpmax', 'hp', 'mana', 'atk', 'def', 'mdef', 'money', 'exp']; statusList.forEach(function (item) { // 向下取整 core.status.hero[item] = Math.floor(core.status.hero[item]); @@ -1073,22 +990,17 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = core.setStatusBarInnerHTML(item, core.getRealStatus(item)); }); - // 设置魔力值 - if (core.flags.enableMana) { - // status:manamax 只有在非负时才生效。 - if (core.status.hero.manamax != null && core.getRealStatus('manamax') >= 0) { - core.status.hero.mana = Math.min(core.status.hero.mana, core.getRealStatus('manamax')); - core.setStatusBarInnerHTML('mana', core.status.hero.mana + "/" + core.getRealStatus('manamax')); - } - else { - core.setStatusBarInnerHTML("mana", core.status.hero.mana); - } + // 设置魔力值; status:manamax 只有在非负时才生效。 + if (core.status.hero.manamax != null && core.getRealStatus('manamax') >= 0) { + core.status.hero.mana = Math.min(core.status.hero.mana, core.getRealStatus('manamax')); + core.setStatusBarInnerHTML('mana', core.status.hero.mana + "/" + core.getRealStatus('manamax')); + } + else { + core.setStatusBarInnerHTML("mana", core.status.hero.mana); } // 设置技能栏 - if (core.flags.enableSkill) { - // 可以用flag:skill表示当前开启的技能类型,flag:skillName显示技能名;详见文档-个性化-技能塔的支持 - core.setStatusBarInnerHTML('skill', core.getFlag('skillName', '无')); - } + // 可以用flag:skill表示当前开启的技能类型,flag:skillName显示技能名;详见文档-个性化-技能塔的支持 + core.setStatusBarInnerHTML('skill', core.getFlag('skillName', '无')); // 可以在这里添加自己额外的状态栏信息,比如想攻击显示 +0.5 可以这么写: // if (core.hasFlag('halfAtk')) core.setStatusBarInnerHTML('atk', core.statusBar.atk.innerText + "+0.5"); @@ -1096,31 +1008,27 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = // 如果是自定义添加的状态栏,也需要在这里进行设置显示的数值 // 进阶 - if (core.flags.enableLevelUp && core.status.hero.lv < core.firstData.levelUp.length) { + if (core.flags.statusBarItems.indexOf('enableLevelUp')>=0 && core.status.hero.lv < core.firstData.levelUp.length) { var need = core.calValue(core.firstData.levelUp[core.status.hero.lv].need); - if (core.flags.levelUpLeftMode) - core.setStatusBarInnerHTML('up', core.formatBigNumber(need - core.getStatus('experience')) || ""); + if (core.flags.statusBarItems.indexOf('levelUpLeftMode')>=0) + core.setStatusBarInnerHTML('up', core.formatBigNumber(need - core.getStatus('exp')) || ""); else core.setStatusBarInnerHTML('up', core.formatBigNumber(need) || ""); } else core.setStatusBarInnerHTML('up', ""); // 钥匙 - var keys = ['yellowKey', 'blueKey', 'redKey']; + var keys = ['yellowKey', 'blueKey', 'redKey', 'greenKey']; keys.forEach(function (key) { core.setStatusBarInnerHTML(key, core.setTwoDigits(core.itemCount(key))); }); // 毒衰咒 - if (core.flags.enableDebuff) { - core.setStatusBarInnerHTML('poison', core.hasFlag('poison') ? "毒" : ""); - core.setStatusBarInnerHTML('weak', core.hasFlag('weak') ? "衰" : ""); - core.setStatusBarInnerHTML('curse', core.hasFlag('curse') ? "咒" : ""); - } + core.setStatusBarInnerHTML('poison', core.hasFlag('poison') ? "毒" : ""); + core.setStatusBarInnerHTML('weak', core.hasFlag('weak') ? "衰" : ""); + core.setStatusBarInnerHTML('curse', core.hasFlag('curse') ? "咒" : ""); // 破炸飞 - if (core.flags.enablePZF) { - core.setStatusBarInnerHTML('pickaxe', "破" + core.itemCount('pickaxe')); - core.setStatusBarInnerHTML('bomb', "炸" + core.itemCount('bomb')); - core.setStatusBarInnerHTML('fly', "飞" + core.itemCount('centerFly')); - } + core.setStatusBarInnerHTML('pickaxe', "破" + core.itemCount('pickaxe')); + core.setStatusBarInnerHTML('bomb', "炸" + core.itemCount('bomb')); + core.setStatusBarInnerHTML('fly', "飞" + core.itemCount('centerFly')); // 难度 core.statusBar.hard.innerText = core.status.hard; @@ -1154,10 +1062,12 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = id = block.event.id, enemy = core.material.enemys[id]; + type[loc] = type[loc] || {}; + // 血网 - if (id == 'lavaNet' && block.event.trigger == 'passNet' && !core.hasItem('shoes')) { + if (id == 'lavaNet' && !core.hasItem('shoes')) { damage[loc] = (damage[loc] || 0) + core.values.lavaDamage; - type[loc] = "血网伤害"; + type[loc]["血网伤害"] = true; } // 领域 @@ -1179,7 +1089,8 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = // 如果是十字领域,则还需要满足 |dx|+|dy|<=range if (!zoneSquare && Math.abs(dx) + Math.abs(dy) > range) continue; damage[currloc] = (damage[currloc] || 0) + (enemy.value || 0); - type[currloc] = "领域伤害"; + type[currloc] = type[currloc] || {}; + type[currloc]["领域伤害"] = true; } } } @@ -1193,7 +1104,8 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = currloc = nx + "," + ny; if (nx < 0 || nx >= width || ny < 0 || ny >= height) continue; damage[currloc] = (damage[currloc] || 0) + (enemy.value || 0); - type[currloc] = "阻击伤害"; + type[currloc] = type[currloc] || {}; + type[currloc]["阻击伤害"] = true; var rdir = core.reverseDirection(dir); // 检查下一个点是否存在事件(从而判定是否移动) @@ -1214,21 +1126,23 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = var currloc = nx + "," + y; if (nx != x) { damage[currloc] = (damage[currloc] || 0) + (enemy.value || 0); - type[currloc] = "激光伤害"; + type[currloc] = type[currloc] || {}; + type[currloc]["激光伤害"] = true; } } for (var ny = 0; ny < height; ny++) { var currloc = x + "," + ny; if (ny != y) { damage[currloc] = (damage[currloc] || 0) + (enemy.value || 0); - type[currloc] = "激光伤害"; + type[currloc] = type[currloc] || {}; + type[currloc]["激光伤害"] = true; } } } // 捕捉 // 如果要防止捕捉效果,可以直接简单的将 flag:no_ambush 设为true - if (enemy && core.enemys.hasSpecial(enemy.special, 27)) { + if (enemy && core.enemys.hasSpecial(enemy.special, 27) && !core.hasFlag("no_ambush")) { // 给周围格子加上【捕捉】记号 for (var dir in core.utils.scan) { var nx = x + core.utils.scan[dir].x, @@ -1249,36 +1163,40 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = for (var y = 0; y < height; y++) { var loc = x + "," + y; // 夹击怪物的ID - var enemyId = null; + var enemyId1 = null, enemyId2 = null; // 检查左右夹击 var leftBlock = blocks[(x - 1) + "," + y], rightBlock = blocks[(x + 1) + "," + y]; if (leftBlock && rightBlock && leftBlock.id == rightBlock.id) { if (core.hasSpecial(leftBlock.event.id, 16)) - enemyId = leftBlock.event.id; + enemyId1 = leftBlock.event.id; } // 检查上下夹击 var topBlock = blocks[x + "," + (y - 1)], bottomBlock = blocks[x + "," + (y + 1)]; if (topBlock && bottomBlock && topBlock.id == bottomBlock.id) { if (core.hasSpecial(topBlock.event.id, 16)) - enemyId = topBlock.event.id; + enemyId2 = topBlock.event.id; } - if (enemyId != null) { + if (enemyId1 != null || enemyId2 != null) { var leftHp = core.status.hero.hp - (damage[loc] || 0); if (leftHp > 1) { - // 上整/下整 - var value = Math.floor((leftHp + (core.flags.betweenAttackCeil ? 1 : 0)) / 2); + // 夹击伤害值 + var value = Math.floor(leftHp / 2); // 是否不超过怪物伤害值 if (core.flags.betweenAttackMax) { - var enemyDamage = core.getDamage(enemyId, x, y, floorId); - if (enemyDamage != null && enemyDamage < value) - value = enemyDamage; + var enemyDamage1 = core.getDamage(enemyId1, x, y, floorId); + if (enemyDamage1 != null && enemyDamage1 < value) + value = enemyDamage1; + var enemyDamage2 = core.getDamage(enemyId2, x, y, floorId); + if (enemyDamage2 != null && enemyDamage2 < value) + value = enemyDamage2; } if (value > 0) { damage[loc] = (damage[loc] || 0) + value; - type[loc] = "夹击伤害"; + type[loc] = type[loc] || {}; + type[loc]["夹击伤害"] = true; } } } @@ -1317,9 +1235,18 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = core.status.hero.hp = 0; core.updateStatusBar(); core.events.lose(); - return; + } else { + core.updateStatusBar(); } } + + // 从v2.7开始,每一步行走不会再刷新状态栏。 + // 如果有特殊要求(如每走一步都加buff之类),可手动取消注释下面这一句: + // core.updateStatusBar(true); + + // 检查自动事件 + core.checkAutoEvents(); + // 如需强行终止行走可以在这里条件判定: // core.stopAutomaticRoute(); }, @@ -1379,7 +1306,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = // 如果是隐藏状态栏模式,直接返回 if (!core.domStyle.showStatusBar) return; - // 作为样板,只绘制楼层、生命、攻击、防御、魔防、金币、钥匙这七个内容 + // 作为样板,只绘制楼层、生命、攻击、防御、护盾、金币、钥匙这七个内容 // 需要其他的请自行进行修改;横竖屏都需要进行适配绘制。 // (可以使用Chrome浏览器开控制台来模拟手机上的竖屏模式的显示效果,具体方式自行百度) // 横屏模式下的画布大小是 129*416 diff --git a/project/icons.js b/project/icons.js index 4c84391c..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, - "blueShop-left": 31, - "blueShop-right": 32, - "pinkShop-left": 33, - "pinkShop-right": 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/icons.png b/project/images/icons.png index 557b4808..d7494bb4 100644 Binary files a/project/images/icons.png and b/project/images/icons.png differ diff --git a/project/images/items.png b/project/images/items.png index cce829cc..dfb56a9a 100644 Binary files a/project/images/items.png and b/project/images/items.png differ diff --git a/project/images/keyboard.png b/project/images/keyboard.png index c2b9d241..9f2b057a 100644 Binary files a/project/images/keyboard.png and b/project/images/keyboard.png differ diff --git a/project/images/npc48.png b/project/images/npc48.png old mode 100755 new mode 100644 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/items.js b/project/items.js index 598488b7..0a68a3f0 100644 --- a/project/items.js +++ b/project/items.js @@ -2,19 +2,22 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a = { "items": { "yellowKey": { - "cls": "keys", + "cls": "tools", "name": "黄钥匙", - "text": "可以打开一扇黄门" + "text": "可以打开一扇黄门", + "hideInToolbox": true }, "blueKey": { - "cls": "keys", + "cls": "tools", "name": "蓝钥匙", - "text": "可以打开一扇蓝门" + "text": "可以打开一扇蓝门", + "hideInToolbox": true }, "redKey": { - "cls": "keys", + "cls": "tools", "name": "红钥匙", - "text": "可以打开一扇红门" + "text": "可以打开一扇红门", + "hideInToolbox": true }, "redJewel": { "cls": "items", @@ -29,7 +32,7 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a = "greenJewel": { "cls": "items", "name": "绿宝石", - "text": "',魔防+${core.values.greenJewel}'" + "text": "',护盾+${core.values.greenJewel}'" }, "yellowJewel": { "cls": "items", @@ -182,13 +185,15 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a = "book": { "cls": "constants", "name": "怪物手册", - "text": "可以查看当前楼层各怪物属性" + "text": "可以查看当前楼层各怪物属性", + "hideInToolbox": true }, "fly": { "cls": "constants", "name": "楼层传送器", "text": "可以自由往来去过的楼层", - "hideInReplay": true + "hideInReplay": true, + "hideInToolbox": true }, "coin": { "cls": "constants", @@ -288,7 +293,7 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a = "hammer": { "cls": "tools", "name": "圣锤", - "text": "可以炸掉勇士面前的怪物" + "text": "该道具尚未被定义" }, "lifeWand": { "cls": "tools", @@ -339,7 +344,7 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a = "itemEffectTip": { "redJewel": "',攻击+'+core.values.redJewel * ratio", "blueJewel": "',防御+'+core.values.blueJewel * ratio", - "greenJewel": "',魔防+'+core.values.greenJewel * ratio", + "greenJewel": "',护盾+'+core.values.greenJewel * ratio", "yellowJewel": "',全属性提升'", "redPotion": "',生命+'+core.values.redPotion * ratio", "bluePotion": "',生命+'+core.values.bluePotion * ratio", @@ -356,7 +361,7 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a = "shield2": "',防御+20'", "shield3": "',防御+40'", "shield4": "',防御+80'", - "shield5": "',防御+100,魔防+100'", + "shield5": "',防御+100,护盾+100'", "bigKey": "',全钥匙+1'", "superPotion": "',生命值翻倍'", "moneyPocket": "',金币+500'" @@ -364,22 +369,21 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a = "useItemEffect": { "book": "core.ui.drawBook(0);", "fly": "core.ui.drawFly(core.floorIds.indexOf(core.status.floorId));", - "earthquake": "core.removeBlockByIds(core.status.floorId, core.status.event.ui);\ncore.drawMap(core.status.floorId, function () {\n\tcore.drawTip(core.material.items[itemId].name + '使用成功');\n});", - "pickaxe": "core.playSound('pickaxe.mp3');\ncore.removeBlockByIds(core.status.floorId, core.status.event.ui);\ncore.drawMap(core.status.floorId, function () {\n\tcore.drawTip(core.material.items[itemId].name + '使用成功');\n});", - "icePickaxe": "core.removeBlockByIds(core.status.floorId, core.status.event.ui);\ncore.drawMap(core.status.floorId, function () {\n\tcore.drawTip(core.material.items[itemId].name + '使用成功');\n});", - "snow": "core.removeBlockByIds(core.status.floorId, core.status.event.ui);\ncore.drawMap(core.status.floorId, function () {\n\tcore.drawTip(core.material.items[itemId].name + '使用成功');\n});", - "bigKey": "(function () {\n\tvar actions = core.status.event.ui.map(function (id) {\n\t\tvar block = core.status.thisMap.blocks[id];\n\t\treturn { \"type\": \"openDoor\", \"loc\": [block.x, block.y], \"async\": true };\n\t});\n\tactions.push({ \"type\": \"waitAsync\" });\n\tactions.push({ \"type\": \"tip\", \"text\": core.material.items[itemId].name + \"使用成功\" });\n\tcore.insertAction(actions);\n})();", - "bomb": "core.playSound('bomb.mp3');\ncore.removeBlockByIds(core.status.floorId, core.status.event.ui);\ncore.drawMap(core.status.floorId, function () {\n\tcore.drawTip(core.material.items[itemId].name + '使用成功');\n\tcore.events.afterUseBomb();\n});", - "hammer": "core.playSound('bomb.mp3');\ncore.removeBlockByIds(core.status.floorId, core.status.event.ui);\ncore.drawMap(core.status.floorId, function () {\n\tcore.drawTip(core.material.items[itemId].name + '使用成功');\n\tcore.events.afterUseBomb();\n});", - "centerFly": "core.playSound('centerFly.mp3');\ncore.clearMap('hero');\ncore.setHeroLoc('x', core.bigmap.width-1-core.getHeroLoc('x'));\ncore.setHeroLoc('y', core.bigmap.height-1-core.getHeroLoc('y'));\ncore.drawHero();\ncore.drawTip(core.material.items[itemId].name + '使用成功');", - "upFly": "var loc = {'direction': core.status.hero.loc.direction, 'x': core.status.event.ui.x, 'y': core.status.event.ui.y};\nif (core.status.event.id == 'action') {\n\tcore.insertAction([\n\t\t{\"type\": \"changeFloor\", \"loc\": [loc.x, loc.y], \"direction\": loc.direction, \"floorId\": core.status.event.ui.id},\n\t\t{\"type\": \"tip\", \"text\": core.material.items[itemId].name + '使用成功'}\n\t]);\n}\nelse {\n\tcore.changeFloor(core.status.event.ui.id, null, loc, null, function (){\n\tcore.drawTip(core.material.items[itemId].name + '使用成功');\n\t\tcore.replay();\n\t});\n}", - "downFly": "var loc = {'direction': core.status.hero.loc.direction, 'x': core.status.event.ui.x, 'y': core.status.event.ui.y};\nif (core.status.event.id == 'action') {\n\tcore.insertAction([\n\t\t{\"type\": \"changeFloor\", \"loc\": [loc.x, loc.y], \"direction\": loc.direction, \"floorId\": core.status.event.ui.id},\n\t\t{\"type\": \"tip\", \"text\": core.material.items[itemId].name + '使用成功'}\n\t]);\n}\nelse {\n\tcore.changeFloor(core.status.event.ui.id, null, loc, null, function (){\n\tcore.drawTip(core.material.items[itemId].name + '使用成功');\n\t\tcore.replay();\n\t});\n}\n", + "earthquake": "(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(core.status.floorId, function () {\n\t\tcore.drawTip(core.material.items[itemId].name + '使用成功');\n\t});\n})();", + "pickaxe": "(function () {\n\tvar canBreak = function (x, y) {\n\t\tvar block = core.getBlock(x, y);\n\t\tif (block == null || block.block.disable) return false;\n\t\treturn block.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('pickaxe.mp3');\n\t\tcore.drawTip(core.material.items[itemId].name + '使用成功');\n\t} else {\n\t\t// 无法使用\n\t\tcore.drawTip(\"当前无法使用\" + core.material.items[itemId].name);\n\t\tcore.addItem(itemId, 1);\n\t\treturn;\n\t}\n})();", + "icePickaxe": "(function () {\n\tcore.removeBlock(core.nextX(), core.nextY());\n\tcore.drawTip(core.material.items[itemId].name + '使用成功');\n})();", + "snow": "(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.drawTip(core.material.items[itemId].name + '使用成功');\n\t} else {\n\t\tcore.drawTip(\"当前无法使用\" + core.material.items[itemId].name);\n\t\tcore.addItem(itemId, 1);\n\t\treturn;\n\t}\n})();", + "bigKey": "(function () {\n\tvar actions = core.searchBlock(\"yellowDoor\").map(function (block) {\n\t\treturn { \"type\": \"openDoor\", \"loc\": [block.x, block.y], \"async\": true };\n\t});\n\tactions.push({ \"type\": \"waitAsync\" });\n\tactions.push({ \"type\": \"tip\", \"text\": core.material.items[itemId].name + \"使用成功\" });\n\tcore.insertAction(actions);\n})();", + "bomb": "(function () {\n\tvar canBomb = function (x, y) {\n\t\tvar block = core.getBlock(x, y);\n\t\tif (block == null || block.block.disable || block.block.event.cls.indexOf('enemy') != 0) return false;\n\t\tvar enemy = core.material.enemys[block.block.event.id];\n\t\treturn enemy && !enemy.notBomb;\n\t};\n\n\tvar bombList = []; // 炸掉的怪物坐标列表\n\tvar bombFourDirections = false; // 是否四方向可炸;如果是将其改成true。\n\tif (bombFourDirections) {\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 (canBomb(nx, ny)) {\n\t\t\t\tbombList.push([nx, ny]);\n\t\t\t\tcore.removeBlock(nx, ny);\n\t\t\t}\n\t\t}\n\t} else {\n\t\t// 仅炸当前\n\t\tif (canBomb(core.nextX(), core.nextY())) {\n\t\t\tbombList.push([core.nextX(), core.nextY()]);\n\t\t\tcore.removeBlock(core.nextX(), core.nextY());\n\t\t}\n\t}\n\n\tif (bombList.length > 0) {\n\t\tcore.playSound('bomb.mp3');\n\t\tcore.drawTip(core.material.items[itemId].name + '使用成功');\n\t} else {\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})();", + "centerFly": "core.playSound('centerFly.mp3');\ncore.clearMap('hero');\ncore.setHeroLoc('x', core.bigmap.width - 1 - core.getHeroLoc('x'));\ncore.setHeroLoc('y', core.bigmap.height - 1 - core.getHeroLoc('y'));\ncore.drawHero();\ncore.drawTip(core.material.items[itemId].name + '使用成功');", + "upFly": "(function () {\n\tvar floorId = core.floorIds[core.floorIds.indexOf(core.status.floorId) + 1];\n\tif (core.status.event.id == 'action') {\n\t\tcore.insertAction([\n\t\t\t{ \"type\": \"changeFloor\", \"loc\": [core.getHeroLoc('x'), core.getHeroLoc('y')], \"floorId\": floorId },\n\t\t\t{ \"type\": \"tip\", \"text\": core.material.items[itemId].name + '使用成功' }\n\t\t]);\n\t} else {\n\t\tcore.changeFloor(floorId, null, core.status.hero.loc, null, function () {\n\t\t\tcore.drawTip(core.material.items[itemId].name + '使用成功');\n\t\t\tcore.replay();\n\t\t});\n\t}\n})();", + "downFly": "(function () {\n\tvar floorId = core.floorIds[core.floorIds.indexOf(core.status.floorId) - 1];\n\tif (core.status.event.id == 'action') {\n\t\tcore.insertAction([\n\t\t\t{ \"type\": \"changeFloor\", \"loc\": [core.getHeroLoc('x'), core.getHeroLoc('y')], \"floorId\": floorId },\n\t\t\t{ \"type\": \"tip\", \"text\": core.material.items[itemId].name + '使用成功' }\n\t\t]);\n\t} else {\n\t\tcore.changeFloor(floorId, null, core.status.hero.loc, null, function () {\n\t\t\tcore.drawTip(core.material.items[itemId].name + '使用成功');\n\t\t\tcore.replay();\n\t\t});\n\t}\n})();", "poisonWine": "core.removeFlag('poison');", "weakWine": "core.removeFlag('weak');\nif (core.values.weakValue>=1) { // >=1:直接扣数值\n\tcore.status.hero.atk += core.values.weakValue;\n\tcore.status.hero.def += core.values.weakValue;\n}\nelse { // <1:扣比例\n\tcore.addBuff(\"atk\", core.values.weakValue);\n\tcore.addBuff(\"def\", core.values.weakValue);\n}", "curseWine": "core.removeFlag('curse');", "superWine": "core.removeFlag('poison');\nif (core.hasFlag('weak')) {\n\tcore.removeFlag('weak');\n\tif (core.values.weakValue>=1) { // >=1:直接扣数值\n\t\tcore.status.hero.atk += core.values.weakValue;\n\t\tcore.status.hero.def += core.values.weakValue;\n\t}\n\telse { // <1:扣比例\n\t\tcore.addBuff(\"atk\", core.values.weakValue);\n\t\tcore.addBuff(\"def\", core.values.weakValue);\n\t}\n}\ncore.removeFlag('curse');", - "lifeWand": "core.insertAction([\n\t{\"type\": \"input\", \"text\": \"请输入生命魔杖使用次数:(0-${item:lifeWand})\"},\n\t{\"type\": \"if\", \"condition\": \"flag:input<=item:lifeWand\",\n\t\t\"true\": [\n\t\t\t{\"type\": \"setValue\", \"name\": \"item:lifeWand\", \"value\": \"item:lifeWand-flag:input\"},\n\t\t\t{\"type\": \"setValue\", \"name\": \"status:hp\", \"value\": \"status:hp+flag:input*100\"},\n\t\t\t\"成功使用${flag:input}次生命魔杖,恢复${flag:input*100}点生命。\"\n\t\t],\n\t\t\"false\": [\"输入不合法!\"]\n\t},\n]);\ncore.addItem('lifeWand', 1);", - "jumpShoes": "core.insertAction({\"type\":\"jumpHero\",\"loc\":[core.nextX(2),core.nextY(2)]});", + "lifeWand": null, + "jumpShoes": "core.insertAction({ \"type\": \"jumpHero\", \"loc\": [core.nextX(2), core.nextY(2)] });", "redPotion": "core.status.hero.hp += core.values.redPotion", "bluePotion": "core.status.hero.hp += core.values.bluePotion", "greenPotion": "core.status.hero.hp += core.values.greenPotion", @@ -387,28 +391,27 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a = "redJewel": "core.status.hero.atk += core.values.redJewel", "blueJewel": "core.status.hero.def += core.values.blueJewel", "greenJewel": "core.status.hero.mdef += core.values.greenJewel", - "yellowJewel": "core.insertAction([\n\t{\"type\": \"choices\", \"choices\": [\n\t\t{\"text\": \"攻击+1\", \"action\": [\n\t\t\t{\"type\": \"setValue\", \"name\": \"status:atk\", \"value\": \"status:atk+1\"}\n\t\t]},\n\t\t{\"text\": \"防御+2\", \"action\": [\n\t\t\t{\"type\": \"setValue\", \"name\": \"status:def\", \"value\": \"status:def+2\"}\n\t\t]},\n\t\t{\"text\": \"生命+200\", \"action\": [\n\t\t\t{\"type\": \"setValue\", \"name\": \"status:hp\", \"value\": \"status:hp+200\"}\n\t\t]},\n\t]}\n]);", + "yellowJewel": null, "skill1": "// 二倍斩的flag:skill为1\nif (core.getFlag('skill', 0)==0) { // 判断当前是否已经开了技能\n\tif (core.getStatus('mana')>=5) { // 这里要写当前能否开技能的条件判断,比如魔力值至少要多少\n\t\tcore.setFlag('skill', 1); // 开技能1\n\t\tcore.setFlag('skillName', '二倍斩'); // 设置技能名\n\t}\n\telse {\n\t\tcore.drawTip(\"魔力不足,无法开启技能\");\n\t}\n}\nelse { // 关闭技能\n\tcore.setFlag('skill', 0); // 关闭技能状态\n\tcore.setFlag('skillName', '无');\n}" }, "canUseItemEffect": { "book": "true", "fly": "(function () {\n\treturn core.status.maps[core.status.floorId].canFlyTo;\n})();", - "pickaxe": "(function() {\n\tvar ids = [], id2s = [];\n\tfor (var i in core.status.thisMap.blocks) {\n\t\tvar block = core.status.thisMap.blocks[i];\n\t\tif (!block.disable && core.nearHero(block.x, block.y) && \n\t\t\t(block.event.canBreak || block.event.id == 'yellowWall' || block.event.id=='whiteWall' || block.event.id=='blueWall')) { // 能破哪些墙\n\t\t\t// 四个方向\n\t\t\tif (core.flags.pickaxeFourDirections || (block.x == core.nextX() && block.y == core.nextY()))\n\t\t\t\tids.push(i);\n\t\t\telse id2s.push(i);\n\t\t}\n\t}\n\tif (ids.length>0) {\n\t\tcore.status.event.ui = ids;\n\t\treturn true;\n\t}\n\telse if (id2s.length==1) {\n\t\tcore.status.event.ui = id2s;\n\t\treturn true;\n\t}\n\treturn false;\n})();", - "icePickaxe": "(function() {\n\tfor (var i in core.status.thisMap.blocks) {\n\t\tvar block = core.status.thisMap.blocks[i];\n\t\tif (!block.disable && block.x==core.nextX() && block.y==core.nextY() && block.event.id=='ice') {\n\t\t\tcore.status.event.ui = [i];\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n})();", - "bomb": "(function () {\n\tvar ids = [], id2s = [];\n\tfor (var i in core.status.thisMap.blocks) {\n\t\tvar block = core.status.thisMap.blocks[i];\n\t\tif (!block.disable && block.event.cls.indexOf('enemy')==0 && core.nearHero(block.x, block.y)) {\n\t\t\tvar enemy = core.material.enemys[block.event.id];\n\t\t\tif (core.isset(enemy) && enemy.notBomb) continue;\n\t\t\tif (core.flags.bombFourDirections || (block.x==core.nextX() && block.y==core.nextY()))\n\t\t\t\tids.push(i);\n\t\t\telse\n\t\t\t\tid2s.push(i);\n\t\t}\n\t}\n\tif (ids.length>0) {\n\t\tcore.status.event.ui = ids;\n\t\treturn true;\n\t}\n\tif (id2s.length==1) {\n\t\tcore.status.event.ui = id2s;\n\t\treturn true;\n\t}\n\treturn false;\n})();", - "hammer": "(function() {\n\tvar ids = [], id2s = [];\n\tfor (var i in core.status.thisMap.blocks) {\n\t\tvar block = core.status.thisMap.blocks[i];\n\t\tif (!block.disable && block.event.cls.indexOf('enemy')==0 && core.nearHero(block.x, block.y)) {\n\t\t\tvar enemy = core.material.enemys[block.event.id];\n\t\t\tif (core.isset(enemy) && enemy.notBomb) continue;\n\t\t\tif (block.x==core.nextX() && block.y==core.nextY())\n\t\t\t\tids.push(i);\n\t\t\telse\n\t\t\t\tid2s.push(i);\n\t\t}\n\t}\n\tif (ids.length>0) {\n\t\tcore.status.event.ui = ids;\n\t\treturn true;\n\t}\n\telse if (id2s.length==1) {\n\t\tcore.status.event.ui = id2s;\n\t\treturn true;\n\t}\n\treturn false;\n})();", - "earthquake": "(function () {\n\tvar able=false;\n\tvar ids = [];\n\tfor (var i in core.status.thisMap.blocks) {\n\t\tvar block = core.status.thisMap.blocks[i];\n\t\tif (!block.disable &&\n\t\t\t(block.event.canBreak || block.event.id == 'yellowWall' || block.event.id == 'blueWall' || block.event.id == 'whiteWall')) { // 能炸的墙壁\n\t\t\tids.push(i);\n\t\t}\n\t}\n\tif (ids.length>0) {\n\t\tcore.status.event.ui = ids;\n\t\table=true;\n\t}\n\treturn able;\n})();", - "centerFly": "(function () {\n\tvar toX = core.bigmap.width-1-core.getHeroLoc('x'), toY = core.bigmap.height-1-core.getHeroLoc('y');\n\tvar id = core.getBlockId(toX, toY);\n\treturn id == null;\n})();", - "upFly": "(function() {\n\tvar floorId = core.status.floorId, index = core.floorIds.indexOf(floorId);\n\tif (index=0 && toX=0 && toY0) {\n\t\tvar toId = core.floorIds[index-1], toX = core.getHeroLoc('x'), toY = core.getHeroLoc('y');\n\t\tvar mw = core.floors[toId].width, mh = core.floors[toId].height;\n\t\tif (toX>=0 && toX=0 && toY0) {\n\t\tcore.status.event.ui = ids;\n\t\treturn true;\n\t}\n\tif (id2s.length==1) {\n\t\tcore.status.event.ui = id2s;\n\t\treturn true;\n\t}\n\treturn false;\n})();", - "bigKey": "(function () {\n\tvar able = false,\n\t\tids = [];\n\tfor (var i in core.status.thisMap.blocks) {\n\t\tvar block = core.status.thisMap.blocks[i];\n\t\tif (!block.disable && block.event.id == 'yellowDoor') {\n\t\t\tids.push(i);\n\t\t}\n\t}\n\tif (ids.length > 0) {\n\t\tcore.status.event.ui = ids;\n\t\table = true;\n\t}\n\treturn able;\n})();", + "pickaxe": "true", + "icePickaxe": "(function () {\n\treturn core.getBlockId(core.nextX(), core.nextY()) == 'ice';\n})();", + "bomb": "true", + "earthquake": "(function () {\n\treturn core.status.thisMap.blocks.filter(function (block) {\n\t\treturn !block.disable && block.event.canBreak;\n\t}).length > 0;\n})();", + "centerFly": "(function () {\n\tvar toX = core.bigmap.width - 1 - core.getHeroLoc('x'),\n\t\ttoY = core.bigmap.height - 1 - core.getHeroLoc('y');\n\tvar id = core.getBlockId(toX, toY);\n\treturn id == null;\n})();", + "upFly": "(function () {\n\tvar floorId = core.status.floorId,\n\t\tindex = core.floorIds.indexOf(floorId);\n\tif (index < core.floorIds.length - 1) {\n\t\tvar toId = core.floorIds[index + 1],\n\t\t\ttoX = core.getHeroLoc('x'),\n\t\t\ttoY = core.getHeroLoc('y');\n\t\tvar mw = core.floors[toId].width,\n\t\t\tmh = core.floors[toId].height;\n\t\tif (toX >= 0 && toX < mw && toY >= 0 && toY < mh && core.getBlock(toX, toY, toId) == null) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n})();", + "downFly": "(function () {\n\tvar floorId = core.status.floorId,\n\t\tindex = core.floorIds.indexOf(floorId);\n\tif (index > 0) {\n\t\tvar toId = core.floorIds[index - 1],\n\t\t\ttoX = core.getHeroLoc('x'),\n\t\t\ttoY = core.getHeroLoc('y');\n\t\tvar mw = core.floors[toId].width,\n\t\t\tmh = core.floors[toId].height;\n\t\tif (toX >= 0 && toX < mw && toY >= 0 && toY < mh && core.getBlock(toX, toY, toId) == null) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n})();", + "snow": "true", + "bigKey": "(function () {\n\treturn core.searchBlock('yellowDoor').length > 0;\n})();", "poisonWine": "core.hasFlag('poison');", "weakWine": "core.hasFlag('weak');", "curseWine": "core.hasFlag('curse');", "superWine": "(function() {\n\treturn core.hasFlag('poison') || core.hasFlag('weak') || core.hasFlag('curse');\n})();", "lifeWand": "true", - "jumpShoes": "(function() {\n\tvar nx=core.nextX(2), ny=core.nextY(2);\n\treturn nx>=0 && nx=0 && ny= 0 && nx < core.bigmap.width && ny >= 0 && ny < core.bigmap.height && core.getBlockId(nx, ny) == null;\n})();", "redPotion": "true", "bluePotion": "true", "greenPotion": "true", @@ -419,5 +422,83 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a = "yellowJewel": "true", "skill1": "true" }, - "equipCondition": {} + "equipCondition": {}, + "useItemEvent": { + "yellowJewel": [ + { + "type": "choices", + "choices": [ + { + "text": "攻击+1", + "action": [ + { + "type": "setValue", + "name": "status:atk", + "operator": "+=", + "value": "1" + } + ] + }, + { + "text": "防御+2", + "action": [ + { + "type": "setValue", + "name": "status:def", + "operator": "+=", + "value": "2" + } + ] + }, + { + "text": "生命+200", + "action": [ + { + "type": "setValue", + "name": "status:hp", + "operator": "+=", + "value": "200" + } + ] + } + ] + } + ], + "lifeWand": [ + { + "type": "comment", + "text": "先恢复一个魔杖(因为使用道具必须消耗一个)" + }, + { + "type": "function", + "function": "function(){\ncore.addItem('lifeWand', 1);\n}" + }, + { + "type": "input", + "text": "请输入生命魔杖使用次数:(0-${item:lifeWand})" + }, + { + "type": "if", + "condition": "flag:input<=item:lifeWand", + "true": [ + { + "type": "setValue", + "name": "item:lifeWand", + "operator": "-=", + "value": "flag:input" + }, + { + "type": "setValue", + "name": "status:hp", + "operator": "+=", + "value": "flag:input*100" + }, + "成功使用${flag:input}次生命魔杖,恢复${flag:input*100}点生命。" + ], + "false": [ + "输入不合法!" + ] + } + ] + } } \ No newline at end of file diff --git a/project/maps.js b/project/maps.js index fc9bd45f..b21de5b9 100644 --- a/project/maps.js +++ b/project/maps.js @@ -1,22 +1,22 @@ 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}, - "4": {"cls":"animates","id":"star","noPass":true}, - "5": {"cls":"animates","id":"lava","noPass":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","name":"星空"}, + "5": {"cls":"animates","id":"lava","name":"岩浆"}, "6": {"cls":"terrains","id":"ice"}, - "7": {"cls":"terrains","id":"blueShop-left"}, - "8": {"cls":"terrains","id":"blueShop-right"}, - "9": {"cls":"terrains","id":"pinkShop-left"}, - "10": {"cls":"terrains","id":"pinkShop-right"}, - "11": {"cls":"animates","id":"lavaNet","noPass":false,"trigger":"passNet"}, - "12": {"cls":"animates","id":"poisonNet","noPass":false,"trigger":"passNet"}, - "13": {"cls":"animates","id":"weakNet","noPass":false,"trigger":"passNet"}, - "14": {"cls":"animates","id":"curseNet","noPass":false,"trigger":"passNet"}, - "15": {"cls":"animates","id":"blueWater","noPass":true}, - "16": {"cls":"animates","id":"water","noPass":true}, - "20": {"cls":"autotile","id":"autotile","noPass":true}, + "7": {"cls":"terrains","id":"blueShopLeft"}, + "8": {"cls":"terrains","id":"blueShopRight"}, + "9": {"cls":"terrains","id":"pinkShopLeft"}, + "10": {"cls":"terrains","id":"pinkShopRight"}, + "11": {"cls":"animates","id":"lavaNet","canPass":true,"trigger":"null","script":"(function () {\n\t// 血网的伤害效果移动到 checkBlock 中处理\n\n\t// 如果要做一次性血网,可直接注释掉下面这句话:\n\t// core.removeBlock(core.getHeroLoc('x'), core.getHeroLoc('y'));\n})();","name":"血网"}, + "12": {"cls":"animates","id":"poisonNet","canPass":true,"trigger":"null","script":"(function () {\n\t// 直接插入公共事件进行毒处理\n\tif (!core.hasItem('shoes')) {\n\t\tcore.insertAction({ \"type\": \"insert\", \"name\": \"毒衰咒处理\", \"args\": [0] });\n\t}\n\n\t// 如果要做一次性毒网,可直接注释掉下面这句话:\n\t// core.removeBlock(core.getHeroLoc('x'), core.getHeroLoc('y'));\n})()","name":"毒网"}, + "13": {"cls":"animates","id":"weakNet","canPass":true,"trigger":"null","script":"(function () {\n\t// 直接插入公共事件进行衰处理\n\tif (!core.hasItem('shoes')) {\n\t\tcore.insertAction({ \"type\": \"insert\", \"name\": \"毒衰咒处理\", \"args\": [1] });\n\t}\n\n\t// 如果要做一次性衰网,可直接注释掉下面这句话:\n\t// core.removeBlock(core.getHeroLoc('x'), core.getHeroLoc('y'));\n})()","name":"衰网"}, + "14": {"cls":"animates","id":"curseNet","canPass":true,"trigger":"null","script":"(function () {\n\t// 直接插入公共事件进行咒处理\n\tif (!core.hasItem('shoes')) {\n\t\tcore.insertAction({ \"type\": \"insert\", \"name\": \"毒衰咒处理\", \"args\": [2] });\n\t}\n\n\t// 如果要做一次性咒网,可直接注释掉下面这句话:\n\t// core.removeBlock(core.getHeroLoc('x'), core.getHeroLoc('y'));\n})()","name":"咒网"}, + "15": {"cls":"animates","id":"blueWater"}, + "16": {"cls":"animates","id":"water"}, + "20": {"cls":"autotile","id":"autotile"}, "21": {"cls":"items","id":"yellowKey"}, "22": {"cls":"items","id":"blueKey"}, "23": {"cls":"items","id":"redKey"}, @@ -68,20 +68,20 @@ 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"}, - "87": {"cls":"terrains","id":"upFloor","noPass":false}, - "88": {"cls":"terrains","id":"downFloor","noPass":false}, - "89": {"cls":"animates","id":"portal","noPass":false}, - "90": {"cls":"animates","id":"starPortal","noPass":false}, - "91": {"cls":"animates","id":"upPortal","noPass":false}, - "92": {"cls":"animates","id":"leftPortal","noPass":false}, - "93": {"cls":"animates","id":"downPortal","noPass":false}, - "94": {"cls":"animates","id":"rightPortal","noPass":false}, + "81": {"cls":"animates","id":"yellowDoor","trigger":"openDoor","animate":1,"doorInfo":[{"yellowKey":1},"door.mp3","door.mp3"],"name":"黄门"}, + "82": {"cls":"animates","id":"blueDoor","trigger":"openDoor","animate":1,"doorInfo":[{"blueKey":1},"door.mp3","door.mp3"],"name":"蓝门"}, + "83": {"cls":"animates","id":"redDoor","trigger":"openDoor","animate":1,"doorInfo":[{"redKey":1},"door.mp3","door.mp3"],"name":"红门"}, + "84": {"cls":"animates","id":"greenDoor","trigger":"openDoor","animate":1,"doorInfo":[{"greenKey":1},"door.mp3","door.mp3"],"name":"绿门"}, + "85": {"cls":"animates","id":"specialDoor","trigger":"openDoor","animate":1,"doorInfo":[null,"door.mp3","door.mp3"],"name":"机关门"}, + "86": {"cls":"animates","id":"steelDoor","trigger":"openDoor","animate":1,"doorInfo":[{"steelKey":1},"door.mp3","door.mp3"],"name":"铁门"}, + "87": {"cls":"terrains","id":"upFloor","canPass":true}, + "88": {"cls":"terrains","id":"downFloor","canPass":true}, + "89": {"cls":"animates","id":"portal","canPass":true}, + "90": {"cls":"animates","id":"starPortal","canPass":true}, + "91": {"cls":"animates","id":"upPortal","canPass":true}, + "92": {"cls":"animates","id":"leftPortal","canPass":true}, + "93": {"cls":"animates","id":"downPortal","canPass":true}, + "94": {"cls":"animates","id":"rightPortal","canPass":true}, "101": {"cls":"animates","id":"crystalUp"}, "102": {"cls":"animates","id":"crystalBottom"}, "103": {"cls":"animates","id":"fire"}, @@ -102,19 +102,19 @@ var maps_90f36752_8815_4be8_b32b_d7fad1d0542e = "134": {"cls":"npc48","id":"npc1","faceIds":{"down":"npc0","left":"npc1","right":"npc2","up":"npc3"}}, "135": {"cls":"npc48","id":"npc2","faceIds":{"down":"npc0","left":"npc1","right":"npc2","up":"npc3"}}, "136": {"cls":"npc48","id":"npc3","faceIds":{"down":"npc0","left":"npc1","right":"npc2","up":"npc3"}}, - "151": {"cls":"autotile","id":"autotile1","noPass":true}, - "152": {"cls":"autotile","id":"autotile2","noPass":true}, - "153": {"cls":"autotile","id":"autotile3","noPass":true}, - "161": {"cls":"terrains","id":"arrowUp","noPass":false,"cannotOut":["left","right","down"],"cannotIn":["down"]}, - "162": {"cls":"terrains","id":"arrowDown","noPass":false,"cannotOut":["left","right","up"],"cannotIn":["up"]}, - "163": {"cls":"terrains","id":"arrowLeft","noPass":false,"cannotOut":["up","down","right"],"cannotIn":["right"]}, - "164": {"cls":"terrains","id":"arrowRight","noPass":false,"cannotOut":["up","down","left"],"cannotIn":["left"]}, - "165": {"cls":"terrains","id":"light","trigger":"changeLight","noPass":false}, - "166": {"cls":"terrains","id":"darkLight","noPass":true}, - "167": {"cls":"terrains","id":"ski","trigger":"ski","noPass":false}, - "168": {"cls":"terrains","id":"flower","noPass":false}, - "169": {"cls":"terrains","id":"box","trigger":"pushBox","noPass":true}, - "170": {"cls":"terrains","id":"boxed","trigger":"pushBox","noPass":true}, + "151": {"cls":"autotile","id":"autotile1"}, + "152": {"cls":"autotile","id":"autotile2"}, + "153": {"cls":"autotile","id":"autotile3"}, + "161": {"cls":"terrains","id":"arrowUp","canPass":true,"cannotOut":["left","right","down"],"cannotIn":["up"]}, + "162": {"cls":"terrains","id":"arrowDown","canPass":true,"cannotOut":["left","right","up"],"cannotIn":["down"]}, + "163": {"cls":"terrains","id":"arrowLeft","canPass":true,"cannotOut":["up","down","right"],"cannotIn":["left"]}, + "164": {"cls":"terrains","id":"arrowRight","canPass":true,"cannotOut":["up","down","left"],"cannotIn":["right"]}, + "165": {"cls":"terrains","id":"light","trigger":"null","canPass":true,"script":"(function () {\n\tcore.setBlock(core.getNumberById('darkLight'), core.getHeroLoc('x'), core.getHeroLoc('y'));\n})();"}, + "166": {"cls":"terrains","id":"darkLight"}, + "167": {"cls":"terrains","id":"ski","trigger":"ski","canPass":true}, + "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":"wlt"}, "182": {"cls":"npcs","id":"wt"}, "183": {"cls":"npcs","id":"wrt"}, @@ -194,5 +194,24 @@ var maps_90f36752_8815_4be8_b32b_d7fad1d0542e = "261": {"cls":"enemy48","id":"angel"}, "262": {"cls":"enemy48","id":"elemental"}, "263": {"cls":"enemy48","id":"steelGuard"}, - "264": {"cls":"enemy48","id":"evilBat"} + "264": {"cls":"enemy48","id":"evilBat"}, + "300": {"cls":"terrains","id":"ground"}, + "301": {"cls":"terrains","id":"grass"}, + "302": {"cls":"terrains","id":"grass2"}, + "303": {"cls":"terrains","id":"snowGround"}, + "304": {"cls":"terrains","id":"ground2"}, + "305": {"cls":"terrains","id":"ground3"}, + "306": {"cls":"terrains","id":"ground4"}, + "307": {"cls":"terrains","id":"sand"}, + "308": {"cls":"terrains","id":"ground5"}, + "309": {"cls":"terrains","id":"yellowWall2"}, + "310": {"cls":"terrains","id":"whiteWall2"}, + "311": {"cls":"terrains","id":"blueWall2"}, + "312": {"cls":"terrains","id":"blockWall"}, + "313": {"cls":"terrains","id":"grayWall"}, + "314": {"cls":"terrains","id":"white"}, + "315": {"cls":"terrains","id":"ground6"}, + "316": {"cls":"terrains","id":"soil"}, + "317": {"cls":"terrains","id":"ground7"}, + "318": {"cls":"terrains","id":"ground8"} } \ No newline at end of file diff --git a/project/plugins.js b/project/plugins.js index 63637164..b8a4776e 100644 --- a/project/plugins.js +++ b/project/plugins.js @@ -39,7 +39,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = // core.plugin.drawLight('ui', 0.95, [[25,11,46]]); // 在ui层绘制全图不透明度0.95,其中在(25,11)点存在一个半径为46的灯光效果。 // core.plugin.drawLight('test', 0.2, [[25,11,46,0.1]]); // 创建一个test图层,不透明度0.2,其中在(25,11)点存在一个半径为46的灯光效果,灯光中心不透明度0.1。 // core.plugin.drawLight('test2', 0.9, [[25,11,46],[105,121,88],[301,221,106]]); // 创建test2图层,且存在三个灯光效果,分别是中心(25,11)半径46,中心(105,121)半径88,中心(301,221)半径106。 - // core.plugin.drawLight('xxx', 0.3, [[25,11,46],[105,121,88,0.2]], 0.4); // 存在两个灯光效果,它们在内圈40%范围内保持全亮,且40%后才开始衰减。 + // core.plugin.drawLight('xxx', 0.3, [[25,11,46],[105,121,88,0.2]], 0.4); // 存在两个灯光效果,它们在内圈40%范围内保持全亮,40%后才开始衰减。 this.drawLight = function (name, color, lights, lightDec) { // 清空色调层;也可以修改成其它层比如animate/weather层,或者用自己创建的canvas @@ -84,6 +84,142 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ctx.globalCompositeOperation = 'source-over'; // 可以在任何地方(如afterXXX或自定义脚本事件)调用函数,方法为 core.plugin.xxx(); } +}, + "shop": function () { + // 【全局商店】相关的功能 + // + // 打开一个全局商店 + // shopId:要打开的商店id;noRoute:是否不计入录像 + this.openShop = function (shopId, noRoute) { + var shop = core.status.shops[shopId]; + // Step 1: 检查能否打开此商店 + if (!this.canOpenShop(shopId)) { + core.drawTip("该商店尚未开启"); + return false; + } + + // Step 2: (如有必要)记录打开商店的脚本事件 + if (!noRoute) { + core.status.route.push("shop:" + shopId); + } + + // Step 3: 检查道具商店 or 公共事件 + if (shop.item) { + if (core.openItemShop) { + core.openItemShop(shopId); + } else { + core.insertAction("道具商店插件不存在!请检查是否存在该插件!"); + } + return; + } + if (shop.commonEvent) { + core.insertAction({ "type": "insert", "name": shop.commonEvent, "args": shop.args }); + return; + } + + // Step 4: 执行标准公共商店 + core.insertAction(this._convertShop(shop)); + return true; + } + + ////// 将一个全局商店转变成可预览的公共事件 ////// + this._convertShop = function (shop) { + return [{ + "type": "while", + "condition": "true", + "data": [ + // 检测能否访问该商店 + { + "type": "if", + "condition": "core.isShopVisited('" + shop.id + "')", + "true": [ + // 可以访问,直接插入执行效果 + { "type": "function", "function": "function() { core.plugin._convertShop_replaceChoices('" + shop.id + "', false) }" }, + ], + "false": [ + // 不能访问的情况下:检测能否预览 + { + "type": "if", + "condition": shop.disablePreview, + "true": [ + // 不可预览,提示并退出 + "当前无法访问该商店!", + { "type": "break" }, + ], + "false": [ + // 可以预览:将商店全部内容进行替换 + { "type": "tip", "text": "当前处于预览模式,不可购买" }, + { "type": "function", "function": "function() { core.plugin._convertShop_replaceChoices('" + shop.id + "', true) }" }, + ] + } + ] + } + ] + }]; + } + + this._convertShop_replaceChoices = function (shopId, previewMode) { + var shop = core.status.shops[shopId]; + var choices = (shop.choices || []).filter(function (choice) { + if (choice.condition == null || choice.condition == '') return true; + try { return core.calValue(choice.condition); } catch (e) { return true; } + }).map(function (choice) { + var ableToBuy = core.calValue(choice.need); + return { + "text": choice.text, + "icon": choice.icon, + "color": ableToBuy && !previewMode ? choice.color : [153, 153, 153, 1], + "action": ableToBuy && !previewMode ? choice.action : [ + { "type": "tip", "text": previewMode ? "预览模式下不可购买" : "购买条件不足" } + ] + }; + }).concat({ "text": "离开", "action": [{ "type": "break" }] }); + core.insertAction({ "type": "choices", "text": shop.text, "choices": choices }); + } + + /// 是否访问过某个快捷商店 + this.isShopVisited = function (id) { + if (!core.hasFlag("__shops__")) core.setFlag("__shops__", {}); + var shops = core.getFlag("__shops__"); + if (!shops[id]) shops[id] = {}; + return shops[id].visited; + } + + /// 当前应当显示的快捷商店列表 + this.listShopIds = function () { + return Object.keys(core.status.shops).filter(function (id) { + return core.isShopVisited(id) || !core.status.shops[id].mustEnable; + }); + } + + /// 是否能够打开某个商店 + this.canOpenShop = function (id) { + if (this.isShopVisited(id)) return true; + var shop = core.status.shops[id]; + if (shop.item || shop.commonEvent || shop.mustEnable) return false; + return true; + } + + /// 启用或禁用某个快捷商店 + this.setShopVisited = function (id, visited) { + if (!core.hasFlag("__shops__")) core.setFlag("__shops__", {}); + var shops = core.getFlag("__shops__"); + if (!shops[id]) shops[id] = {}; + if (visited) shops[id].visited = true; + else delete shops[id].visited; + } + + /// 能否使用快捷商店 + this.canUseQuickShop = function (id) { + // 如果返回一个字符串,表示不能,字符串为不能使用的提示 + // 返回null代表可以使用 + + // 检查当前楼层的canUseQuickShop选项是否为false + if (core.status.thisMap.canUseQuickShop === false) + return '当前楼层不能使用快捷商店。'; + return null; + } + }, "itemShop": function () { // 道具商店相关的插件 @@ -97,6 +233,8 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = var totalPage = 0; var totalMoney = 0; var list = []; + var shopInfo = null; // 商店信息 + var choices = []; // 商店选项 var bigFont = core.ui._buildFont(20, false), middleFont = core.ui._buildFont(18, false); @@ -107,16 +245,15 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = // Step 1: 背景和固定的几个文字 core.ui._createUIEvent(); core.clearMap('uievent'); - core.ui._uievent_drawSelector({ "code": 1 }); - core.ui._uievent_drawSelector({ "code": 2 }); + core.ui._clearUIEventSelector([1, 2]); core.setTextAlign('uievent', 'left'); core.setTextBaseline('uievent', 'top'); core.fillRect('uievent', 0, 0, 416, 416, 'black'); - core.ui._uievent_drawBackground({ background: 'winskin.png', x: 0, y: 0, width: 416, height: 56 }); - core.ui._uievent_drawBackground({ background: 'winskin.png', x: 0, y: 56, width: 312, height: 56 }); - core.ui._uievent_drawBackground({ background: 'winskin.png', x: 0, y: 112, width: 312, height: 304 }); - core.ui._uievent_drawBackground({ background: 'winskin.png', x: 312, y: 56, width: 104, height: 56 }); - core.ui._uievent_drawBackground({ background: 'winskin.png', x: 312, y: 112, width: 104, height: 304 }); + core.drawWindowSkin('winskin.png', 'uievent', 0, 0, 416, 56); + core.drawWindowSkin('winskin.png', 'uievent', 0, 56, 312, 56); + core.drawWindowSkin('winskin.png', 'uievent', 0, 112, 312, 304); + core.drawWindowSkin('winskin.png', 'uievent', 312, 56, 104, 56); + core.drawWindowSkin('winskin.png', 'uievent', 312, 112, 104, 304); core.setFillStyle('uievent', 'white'); core.setStrokeStyle('uievent', 'white'); core.fillText("uievent", "购买", 32, 74, 'white', bigFont); @@ -138,14 +275,13 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = if (selectItem != null) { core.setTextAlign('uievent', 'center'); core.fillText("uievent", type == 0 ? "买入个数" : "卖出个数", 364, 320, null, bigFont); - core.fillText("uievent", "◀ " + selectCount + " ▶", 364, 350); + core.fillText("uievent", "< " + selectCount + " >", 364, 350); core.fillText("uievent", "确定", 364, 380); } // Step 2:获得列表并展示 - var choices = core.status.shops[shopId].choices; list = choices.filter(function (one) { - if (one.condition != null) { + if (one.condition != null && one.condition != '') { try { if (!core.calValue(one.condition)) return false; } catch (e) {} } return (type == 0 && one.money != null) || (type == 1 && one.sell != null); @@ -181,7 +317,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = var text = core.material.items[item.id].text || "该道具暂无描述"; try { text = core.replaceText(text); } catch (e) {} for (var fontSize = 20; fontSize >= 8; fontSize -= 2) { - var config = { left: 10, fontSize: fontSize, maxWidth: 403, lineHeight: 1.4 }; + var config = { left: 10, fontSize: fontSize, maxWidth: 403 }; var height = core.getTextContentHeight(text, config); if (height <= 50) { config.top = (56 - height) / 2; @@ -319,7 +455,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = } if (px >= 222 && px <= 282 && py >= 71 && py <= 102) // 离开 return core.insertAction({ "type": "break" }); - // ◀,▶ + // < > if (px >= 318 && px <= 341 && py >= 348 && py <= 376) return _add(item, -1); if (px >= 388 && px <= 416 && py >= 348 && py <= 376) @@ -330,11 +466,17 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = // 上一页/下一页 if (px >= 45 && px <= 105 && py >= 388) { - if (page > 1) selectItem -= 6; + if (page > 1) { + selectItem -= 6; + selectCount = 0; + } return; } if (px >= 208 && px <= 268 && py >= 388) { - if (page < totalPage) selectItem = Math.min(selectItem + 6, list.length - 1); + if (page < totalPage) { + selectItem = Math.min(selectItem + 6, list.length - 1); + selectCount = 0; + } return; } @@ -363,6 +505,10 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = page = 0; selectItem = null; selectCount = 0; + shopInfo = flags.__shops__[shopId]; + if (shopInfo.choices == null) shopInfo.choices = core.clone(core.status.shops[shopId].choices); + choices = shopInfo.choices; + core.insertAction([{ "type": "while", "condition": "true", @@ -372,44 +518,13 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = { "type": "function", "function": "function() { core.performItemShopAction(); }" } ] }, - { "type": "function", "function": "function () { " + - "core.deleteCanvas('uievent'); " + - "core.ui._uievent_drawSelector({ \"code\": 1 }); " + - "core.ui._uievent_drawSelector({ \"code\": 2 }); " + - "}" } + { + "type": "function", + "function": "function () { core.deleteCanvas('uievent'); core.ui._clearUIEventSelector([1, 2]); }" + } ]); } - // Write item number to save - core.control.saveData = function () { - var data = this.controldata.saveData(); - for (var shopId in core.status.shops) { - if (core.status.shops[shopId].item) { - data.shops[shopId].choices = core.status.shops[shopId].choices.map(function (t) { - return { - number: t.number, - money_count: t.money_count || 0, - sell_count: t.sell_count || 0 - } - }); - } - } - return data; - } - - core.control.loadData = function (data, callback) { - this.controldata.loadData(data, callback); - for (var shopId in data.shops) { - if (data.shops[shopId].choices) { - for (var i = 0; i < data.shops[shopId].choices.length; ++i) { - core.status.shops[shopId].choices[i].number = data.shops[shopId].choices[i].number; - core.status.shops[shopId].choices[i].money_count = data.shops[shopId].choices[i].money_count; - core.status.shops[shopId].choices[i].sell_count = data.shops[shopId].choices[i].sell_count; - } - } - } - } - }, "smoothCamera": function () { @@ -552,8 +667,8 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = }; // 更变楼层的行为追加,重置镜头 - events.prototype.changingFloor = function (floorId, heroLoc, fromLoad) { - this.eventdata.changingFloor(floorId, heroLoc, fromLoad); + events.prototype.changingFloor = function (floorId, heroLoc) { + this.eventdata.changingFloor(floorId, heroLoc); core.plugin.camera.resetCamera(); }; diff --git a/runtime.d.ts b/runtime.d.ts index 6528aa45..d07c908b 100644 --- a/runtime.d.ts +++ b/runtime.d.ts @@ -58,7 +58,7 @@ type Enemy = { atk: number def: number money: number - experience: number + exp: number point: number [key: string]: any } @@ -81,8 +81,6 @@ type SystemFlags = { enableXxx: boolean flyNearStair: boolean steelDoorWithoutKey: boolean - hatredDecrease: boolean - betweenAttackCeil: boolean betweenAttackMax: boolean ignoreChangeFloor: boolean disableShopOnDamage: boolean @@ -105,7 +103,7 @@ type HeroStatus = { def: number mdef: number money: number - experience: number + exp: number loc: { direction: direction x: number @@ -123,7 +121,7 @@ type HeroStatus = { battle: number battleDamage: number currTime: number - experience: number + exp: number extraDamage: number hp: number ignoreSteps: number @@ -407,7 +405,7 @@ declare class control { /** * 设置主角的某个属性 * @example core.setStatus('loc', {x : 0, y : 0, direction : 'up'}); // 设置主角位置为地图左上角,脸朝上 - * @param name 属性的英文名,其中'x'、'y'和'direction'会被特殊处理为 core.setHeroLoc(name, value),其他的('exp'被视为'experience')会直接对 core.status.hero[name] 赋值 + * @param name 属性的英文名,其中'x'、'y'和'direction'会被特殊处理为 core.setHeroLoc(name, value),其他的('exp'被视为'exp')会直接对 core.status.hero[name] 赋值 * @param value 属性的新值 */ setStatus(name: K, value: HeroStatus[K]): void @@ -423,7 +421,7 @@ declare class control { /** * 读取主角的某个属性,不包括百分比修正 * @example core.getStatus('loc'); // 读取主角的坐标和朝向 - * @param name 属性的英文名,其中'x'、'y'和'direction'会被特殊处理为 core.getHeroLoc(name),其他的('exp'被视为'experience')会直接读取 core.status.hero[name] + * @param name 属性的英文名,其中'x'、'y'和'direction'会被特殊处理为 core.getHeroLoc(name),其他的('exp'被视为'exp')会直接读取 core.status.hero[name] * @returns 属性值 */ getStatus(name: K): HeroStatus[K] @@ -833,17 +831,6 @@ declare class enemys { */ getDamage(enemy: string | Enemy, x?: number, y?: number, floorId?: string): number - /** - * 获得某只敌人的固伤加仇恨伤害 - * @example core.getExtraDamage('greenSlime',0,0,'MT0') // 绿头怪的固伤加仇恨伤害 - * @param enemy 敌人id或敌人对象 - * @param x 敌人的横坐标,可选 - * @param y 敌人的纵坐标,可选 - * @param floorId 敌人所在的地图,可选 - * @returns 伤害值,【关闭负伤】时不可被魔防抵挡 - */ - getExtraDamage(enemy: string | Enemy, x?: number, y?: number, floorId?: string): number - /** * 获得某只敌人的地图显伤,包括颜色 * @example core.getDamageString('greenSlime', 0, 0, 'MT0') // 绿头怪的地图显伤 @@ -1203,7 +1190,7 @@ declare class maps { * @param callback 动画停止后的回调函数,可选 * @returns 一个数字,可作为core.stopAnimate()的参数来立即停止播放(届时还可选择是否执行此次播放的回调函数) */ - drawAnimate(name: string, x: number, y: number, callback?: () => void): number + drawAnimate(name: string, x: number, y: number, alignWindow: boolean, callback?: () => void): number } /** @file items.js 主要负责一切和道具相关的内容。 */ @@ -1506,7 +1493,7 @@ declare class utils { * @param times 全局商店已购次数,一般可省略 * @returns 替换完毕后的字符串 */ - replaceText(text: string, need?: number, times?: number): string + replaceText(text: string, prefix?: string, need?: number, times?: number): string /** * 对一个表达式中的特殊规则进行替换,如status:xxx等。 @@ -1880,7 +1867,6 @@ type core = { height: number tempCanvas: CanvasRenderingContext2D // A temp canvas for drawing } - paint: {}; saves: { saveIndex: number ids: { [key: number]: boolean } diff --git a/server.py b/server.py index 7302d2ad..c6d279ff 100644 --- a/server.py +++ b/server.py @@ -24,7 +24,7 @@ except: p("需要flask才可使用本服务。\n安装方式:%s install flask" % ("pip3" if isPy3 else "pip")) exit(1) -app = Flask(__name__, static_folder='') +app = Flask(__name__, static_folder='__static__') app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 0 @app.after_request @@ -45,7 +45,7 @@ def get_mimetype(path): return mimetypes.guess_type(path)[0] or 'application/octet-stream' def get_file(path): - if not os.path.exists(path): + if not os.path.isfile(path): abort(404) return None if not is_sub(path): @@ -61,6 +61,12 @@ def root(): @app.route('/', methods=['GET']) def static_file(path): + if os.path.isdir(path): + if not path.endswith('/'): path += '/' + path += 'index.html' + if not os.path.isfile(path): + abort(404) + return None return Response(get_file(path), mimetype = get_mimetype(path)) def process_request(): diff --git a/styles.css b/styles.css index 9fe80446..dec14381 100644 --- a/styles.css +++ b/styles.css @@ -219,6 +219,7 @@ } #statusBar span{ font: bold italic 1.1em Verdana; + display: inline; } #statusBar p { display: inline-block; @@ -294,22 +295,27 @@ p#name { #bg { z-index: 10; + image-rendering: pixelated; } #event { z-index: 30; + image-rendering: pixelated; } #hero { z-index: 40; + image-rendering: pixelated; } #event2 { z-index: 50; + image-rendering: pixelated; } #fg { z-index: 60; + image-rendering: pixelated; } #damage { diff --git a/v2.x-final更新.txt b/v2.x-final更新.txt new file mode 100644 index 00000000..ffcb1d30 --- /dev/null +++ b/v2.x-final更新.txt @@ -0,0 +1,135 @@ +(已完成!) 1.(来自鹿神)门和像三种基础墙一样的墙应当提供一个“需要消耗多少把哪种钥匙、开关门分别播放什么音效”的属性,如[{"yellowKey": 2, "blueKey": 1}, "door.mp3", "close.mp3"],多种钥匙之间的关系可以为&&或|| +(已完成!) 2.(来自小艾)请求修复瞬移判定无视图块属性script项的bug +(已完成!) 3. 请求修复(如果还没修复)core.drawTip()不能使用系统图标和clear参数的bug,建议增加一个参数来表示多帧图块绘制第几帧 +(已完成!) 3.1 (“UI绘制”类事件中的“绘制图标”同理) +(已完成!\b[up,null]可实现此效果) 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,建议修复 + +------------- + +(已完成!) defaultGround全局可用 +(已完成!) 对floorIds和图片进行检测 +(已完成!) 删除绘图模式 +(已完成!) 清除最近使用图块 +(已完成!) cannotIn / cannotOut使用选项框 +(已完成!) noPass->canPass改成选择框 +初始化&读档优化:不一次读取全部楼层并创建 +(已完成!) 绿钥匙进状态栏 +(已完成!) 图块ID不可全数字 +怪物详细信息富文本化 +(已完成!) for和forEach事件 +转向:顺时针/逆时针/反向 +事件转向 +(已完成!) 合并数值操作事件 +(已完成!) fromLoad,聚集问题 +(已完成!) 注释优化 +(已完成!) 状态栏显示项的优化 +(已完成!) 动画/音乐/音效自动补全 +(已完成!) 重构全局商店! +(已完成!) 读档时色调数据丢失 +圆角边框 +像素高分辨率问题 +(已完成!) 道具效果优化,删除部分道具相关的开关 +素材列表选择 + +------------- + +(不处理) 0. 部分文案的修改,如“地图编辑器”(启动服务.exe中)、“enemys”、“snipe” +(造塔工具相关都给鹿神) 1. 便捷PS工具希望加入自定义单位宽高功能,希望把“白底转透明”增强为“纯色底转透明”(弹窗由作者输入RGB或RGBA值)。 +(已修复) 2. 请求修复(如果还没修复)新建单张空白地图无法自定义宽高的bug +(文档相关给秋橙) 3. 希望给M键“追加素材”功能写个更详细的说明,在线文档中没有所以离线文档中也没写成 +(已解决;现在注册会进行判定) 4. 请求修复图块id可以使用“0-9A-Za-z和下划线”以外的字符的bug(如贪婪之神和经验之神的两个耳朵使用了减号,它们会干扰显示文章等事件块的解析) +(已修复) 5. (接上)请求修复\t[xxx,yyy.png]解析后全部被放入标题框的bug,yyy.png应放入图像框才对 +(已删除此函数) 6. 增强core.getStatusName()的适用面,目前它只用于装备栏属性变化非图标模式的绘制,事实上很多写死的文案值得改为此函数的调用(如rmxp默认的“力量”、“灵巧”、“G”),同理还有一些道具名称文案也存在此问题(如“楼层传送器似乎失效了”) +(不处理) 7. (来自鹿神)core.insertAction()在接受单个字符串参数时存在不稳定性(如跨塔抄别人脚本时),建议优化 +(不处理) 8. core.changeFloor()等函数的参数列表过于混乱,建议优化 +(文档相关给秋橙) 9. useItemEvent用于有afterGetItem事件(浅蓝点)的即捡即用类道具时,其执行次序与itemEffect相反,建议在表格注释中强调一下 +(文档相关给秋橙) 10. 装备孔的最大总个数在15*15为8而不再是6,在线文档没有提到 +(已完成!) 11. (来自鹿神)门和像三种基础墙一样的墙应当提供一个“需要消耗多少把哪种钥匙、开关门分别播放什么音效”(如[{"yellowKey": 1}, "door.mp3", "close.mp3"])的属性(还可以提供多种钥匙组合,关系可以为&&和||),而不是通过id去机械地对应 +(不处理) 12. (来自鹿神和君浪)坚固属性建议按照描述来,去修改turn或hero_per_damage而不是mon_def(rmxp魔塔的坚固属性是通过一个全局量去指定hero_per_damage的,默认为1)以免和模仿(或者说仿防)冲突 +(不处理) 13. 破甲、反击、净化倍率、仇恨增量和是否减半,建议允许使用怪物的属性去覆盖全塔属性中的值,如不同的破甲怪破甲倍率不同 +(已完成!) 14. (来自小艾)仇恨伤害和固伤合并进总伤害以免和负伤抵消 +(已完成!) 15. 单点阻激夹域和血网伤害同时存在多种时,气泡提示的伤害类型存在覆盖现象,建议优化 +(已完成!) 16. (来自小艾)建议修复瞬移判定无视图快属性script项的bug +(已完成!) 17. 建议修复(如果还没修复)core.drawTip()不能使用系统图标和clear参数的bug,并建议增加一个参数来表示多帧图块使用第几帧(UI绘制事件中的绘制图标同理),增加另一个参数来表示32*48图块绘制上2/3(当前实现,和手册一致)还是下2/3 +(不处理) 18. (来自群友)推箱子、阻击、捕捉、重生、炸锤和afterXxx事件的系列问题... +(不处理) 19. (来自群友)建议删除2连击和3连击 +(不处理) 20. (来自群友)建议优化怪物图块属性中value的结构(退化和攻防光环同理),君浪为此配置了一个独立的表格可供使用(基于在getEnemyInfo、getDamageInfo和afterBattle中各eval一串脚本) +(不处理) 21. (来自群友)建议大幅缩减表格的长度,譬如把勾选项和单个数值类紧凑摆放 +(已完成!) 22. betweenAttackMax在被四个怪同时夹击时(比如上下楼后或通过事件使勇士和其中一只怪重合了)目前是以上下方向的怪为准,建议在表格注释中予以强调,更合理的做法是在两种怪的战损中取max或min +(不处理) 23. displayIdInBook属性不能用于夹击QAQ,同时建议给core.getBlockId()追加一个“如果是怪物,是否按displayIdInBook进行映射”的参数。此外此属性会导致core.hasEnemyLeft()在指定id时失真(不一定是坏事) +(已完成!) 24. core.hasEnemyLeft()不应该调用core.getCurrentEnemys(),因为后者是用于手册的,它为了按伤害升序排列而调用了core.getDamageInfo(),而core.getDamageInfo()又会调用core.getEnemyInfo(),但作者完全可能在core.getDamageInfo()或core.getEnemyInfo()中使用core.hasEnemyLeft()判断特定id的怪物是否存在从而实现一些类似光环的效果(如协同),这样就会造成死递归 +25. 建议新增一个类似“勇士转向”的事件指令————“图块转向”,用于NPC甚至怪物(比如基于索引/数字对4取余),毕竟用转变图块的话不够通用 +(已完成!) 26. “勇士转向”会导致跟随者聚集,这不利于演出,建议改成像core.turnHero()一样不聚集跟随者 +(已完成!) 27. 勇士后退时跟随者很鬼畜,建议优化(每步聚集算是一种简陋的办法) +(不处理) 28. 勇士的移动帧只有2,建议改为允许作者指定 +(不处理) 29. 建议加一对“勇士开始抖动”和“勇士停止抖动”事件指令,来让勇士像图块一样原地抖动(即全局动画)。目前这个效果还只能通过隐藏勇士(或切换透明行走图)并转变图块/图层块来实现且只能用于事件处理中QAQ +30. 建议加一个“视角锁定”事件指令,从而允许用事件改变勇士位置、朝向或行走图时不会使视角重置到以其为中心,用于一些演出效果 +(已完成!) 31. 楼层切换事件(绿点)一旦使用blockly编辑就会无视全塔属性的切换时间,只能手动在表格中删除时间(数据相关“楼层切换”事件指令也有这个问题,有群友还希望这个默认时间能像步时和音量一样由玩家设定来节约拆塔时间)。使用blockly编辑也无法做出“ignore:true”的效果(用来覆盖全塔属性的禁止穿透),建议优化 +(已完成!) 32. (关于CC的来回回档优化版)据其称,清空存档后会出现bug,此外他使用了W键导致二倍斩失效了(js的switch语句遇到duplicate cases居然不报错吗...) +(已完成!) 33. (疑似已被CC修复)楼传平面塔模式在记录离开位置时会错误地把读档也算作离开 +(已完成!) 34. (接上)还有很多像这样在楼层切换中对读档处理不当的问题,如天气色调bgm(前两者应当像bgm一样提供keep勾选项) +(已完成!) 35. (来自群友)自动寻路有绕过血瓶的勾选项,但不会绕过绿宝石,这在卡血的净化塔是噩梦 +(已修复!) 36. (疑似)一年前小雨等人提到“可穿透的楼梯”旁边没有不可通行图块时,桌面端和移动端中只有一种端能停在楼梯上。如果确有此现象,希望修复 +(不处理) 37. animates.png的四种箭头的右键绑定目前都只有":next",希望也提供":before" +(已修复!) 38. 建议移除afterUseBomb函数,合并进炸弹和圣锤的useItemEffect甚至useItemEvent +(已修复!) 38.1 现在强制要求面向要破的墙/要炸的怪物了 +(已修复!) 38.2 移除圣锤道具的定义 +(不处理) 39. 建议把样板自带的大部分tools类道具的useItemEffect用useItemEvent重写,以方便作者参照学习(我能说266都几个月了好多新作者和老作者压根不知道useItemEvent的存在吗) +(已修复!) 40. 希望显示文章的\b提供top和bottom这两种新写法来实现在顶部或底部显示对话框,目前只有firstArrive和eachArrive等没有当前点的事件中才能用up和down来临时实现这种效果,否则就得设置剧情文本的属性,这在频繁来回切换时是致命的,就像《无上之光》RMXP版地上40层一样 +(已完成!) 41. 建议优化core.splitLines()来避免出现标点禁则(如点号和右标号不能用于行首,左标号不能用于行尾),同时也能更好地支持字母文字语言如英语(日语韩语等同样是方块字的倒不要紧) +(已修复!) 42. core.drawAnimate()和对应的事件指令,建议增加一个参数来表示坐标是绝对坐标(即当前的实现)还是在视野中的相对坐标(以13*13为例相对坐标总是在0~12之间),毕竟有些动画按相对坐标绘制才是作者的演出需求。 +(不处理) 43. (来自鹿神)希望给animate文件支持多音效、画面闪烁和图块闪烁 +(已修复!) 44. 希望给“播放背景音乐”事件像core.playBgm()函数一样添加“从第几秒开始”的参数,以用于一些演出(比如适当的剧情处直接从高潮开始)。同理可以让“暂停背景音乐”记录下当前播放到了第几秒,并在“恢复背景音乐”中自动从这个秒数恢复。作者还可以手动配合音量渐变效果 +(文档相关给秋橙) 45. 希望API列表和在线文档介绍一下多个bgm同时播放和独立启停甚至独立调节音量的具体用法,以用于一些演出。 +(已修复!) 46. 希望在线文档提供一两个“事件中原生脚本勾选async并以core.doAction作为回调”的用法举例,并修复它也会导致弹窗警告缺少{"type": "waitAsync"}的bug +(不处理) 47. (来自灯绫)建议标题画面右下角的圆形bgm开关按钮在进入游戏后也一直显示 +(文档相关给秋橙) 48. statusBarOnClick在横屏时的有效点击区并不包括最下方六个按钮和难度单词,建议改正该函数的注释 +(已修复!) 49. 系统设置菜单中音量和步时的点击区并不是根据文本长度自动适配的,这导致作者修改文本(包括但不限于翻译)后玩家难以找到准确的点击区,建议优化 +(不处理) 50. 建议给录像播放时的N键提供一个对应的移动端操作,以方便移动端作者 +(已完成!) 51. 希望给“显示选择项”、“显示确认框”、“等待用户操作”这三个事件添加一个“若多少毫秒内不响应则触发的分支”,用来实现一些QTE,录像中可以记录“choice: timeout”、“confirm: timeout”和“wait: timeout”来表示触发了超时分支 +52. 希望给“转变图块”加一个淡入时间参数(显隐和转变图层块也希望加个淡入淡出时间参数,图层块也希望提供移动和跳跃事件),专门用于原本是空地或空气墙的情况。目前要实现这样的效果必须使用红点,然而红点有着“推箱子、阻击、捕捉、重生、炸锤和afterXxx事件”的系列问题,且会导致core.removeBlock()(隐藏事件)退化为core.hideBlock() +(不处理) 53. 希望“移动事件”的移速和淡出速度拆开成两个参数,目前这样捆绑在一起不太自由 +(已完成) 54. 建议把图块属性的noPass改为勾选框而不是下拉框,因为null一定表示不可通行(道具根本没有noPass) +(不处理,可以转变图块) 55. “移动事件”和“跳跃事件”会导致本来勾选了不显伤的怪物突然有了显伤,非常难看,建议优化 +(不处理) 56. 希望推出一套能够对跟随者位置和坐标进行读写的API甚至事件指令,并允许这些信息被计入存档,以实现一些演出甚至游戏性效果,如新新2用公主占位防冰块 +(不处理) 57. 希望\t[hero]和\t[xxx,hero]能像图块一样绘制原地抖动的4帧全局动画而不是不动,希望能使用勇士的当前朝向而不是一直朝下,希望能使用\t[hero1]和\t[xxx,hero1]这样的写法来使用跟随者的行走图作为头像 +(文档相关给秋橙) 58. 建议在在线文档中给\r支持的颜色单词做一下枚举并写出对应的RGB值 +(不处理) 59. 在标题画面调用core.hideStartAnimate(core.startGame)会立即开始游戏并跳过难度选择,可能造成非作者预期的效果,有办法优化吗? +(已完成!) 60. “设置怪物属性”事件的下拉框目前只支持一部分,另一部分只能通过手敲json再解析来得到,希望提供完整支持 +(已完成!) 61. 在事件编辑器中进行地图选点时,有些事件指令虽然只能用于同楼层,但实际生效时勇士可能已经不在当前正在编辑的楼层(比如在一个楼层切换事件指令后)了,所以希望地图选点始终提供楼层下拉表 +(文档相关给秋橙) 62. 希望在线文档介绍一下楼层和startText的独立开关的flag表示 +63. 希望给core.moveAction(callback)函数提供一个对应的事件指令,用于在事件流处理中让勇士进行一些有游戏性意义(即非纯演出)的移动。如果做不到的话希望参照本文的46号issue作为原生脚本勾选async的例子讲解如何使用 +(已完成!) 64. “打开全局商店”事件指令建议在用于公共事件版商店时简单地退化为“插入公共事件”而不要打断当前事件流,由作者在这个公共事件结尾去决定“立刻结束当前事件”还是不结束 +(已修复!) 65. “显隐贴图”的参数应为像素坐标而不是网格坐标,请修正在线文档的描述。同时建议加个淡入淡出时间参数,还建议贴图能像图片一样有透明度和被移动 +(不处理) 66. 读档建议换个和floor.mp3不一样的音效 +(不处理) 67. “画面震动”事件希望不要光左右晃,至少做成QQ窗口抖动的效果吧w +(不处理) 68. “自动存档”事件希望加一个“读此档后打断当前事件”的勾选项,否则这种自动存档用于强制战斗之前就没什么意义了,读了档还是会强制战斗。录像兼容性方面,不知道如果这种自动存档只用于事件开头是不是就不会有问题 +(已修复!) 69. “等待用户操作”虽然提供了场合块但还不支持将多个按键的场合合并(比如空格、回车和C键一般会被作者予以合并,执行内容如果只是大致相同也值得合并,在块内再行分歧),希望支持一下 +70. “显隐勇士”事件指令希望加个淡入淡出时间参数 +(不处理,请用等待事件) 1. 希望给core.drawTip()和core.playSound()出个同步版本,目前只有异步版本,后者如果要模拟同步就得绑在一个透明动画上 +(已完成!) 72. “绘制描边文本”事件希望加一个“描边颜色”参数,目前只能描黑边 +73. 画弧既然有现成的API,那建议也作为UI绘制事件提供。甚至希望提供画椭圆功能(长短轴水平或铅直的那种)参数为中心坐标和长短轴长度 +(已完成!) 74. “设置画布属性”的基准线建议增加'hanging'和'ideographic'这两种模式 +(已完成!) 75. 建议修复“绘制多行文本”时行距比字号大不太多会导致各行下缘丢失的bug(加大行距又会导致第一行的纵坐标难以估计),此bug在道具商店和1.3倍行距英文看的很明显 +(已完成!) 76. (来自群友)建议给第一代全局商店像“显示选择项”一样提供图标、颜色和出现条件 +(已完成!增加正则匹配) 77. 建议给core.searchBlock()新增问号通配符(匹配一个任意字符) +(已完成!) 78. 建议移除core.setInitData()并将其内容写在startText以方便作者仿照修改 +(不处理;有跟随情况下处理很麻烦) 79. 建议给core.drawHero()添加纵横两个偏移参数(目前只有一个),以用于做一些斜向移动的演出 +(文档都给秋橙) 80. 在线文档中“系统使用的flag变量”不够完整,建议加以补充 +(不处理,新增样板非常麻烦) 81. (来自群友)建议做一个17*13的纯横屏样板(大地图只能纵向实现),状态栏自绘在最右边四列,从而彻底摆脱乱七八糟的dom操作