Merge pull request #9 from ckcz123/v2.x

merge V2.x
This commit is contained in:
tocque 2020-05-15 14:20:30 +08:00 committed by GitHub
commit 5426e09e81
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 3613 additions and 3874 deletions

View File

@ -1,6 +1,5 @@
# 元件说明
?> 目前版本**v2.6.6**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.7**,上次更新时间:* {docsify-updated} *
在本章中,将对样板里的各个元件进行说明。各个元件主要包括道具、门、怪物、楼梯等等。
@ -9,29 +8,22 @@
![生成地图](./img/sample0.png)
## 道具
本塔目前支持的所有道具列表在样板0层中已全部给出。当你在样板0层中拿到某个宝物时会有提示这里不再赘述详见拿到该道具的说明。
样板自带的所有道具在样板0层中已全部给出。当你在样板0层中拿到某个宝物时会有提示这里不再赘述详见拿到该道具的说明。
大多数宝物都有默认的效果,屠龙匕首暂未定义,如有自己的需求可参见[自定义道具效果](personalization#自定义道具效果)。
拿到道具后将触发`afterGetItem`事件,有关事件的详细介绍请参见[事件](event)。
如需修改某个道具的效果,在不同区域宝石数据发生变化等问题,请参见[自定义道具效果](personalization#自定义道具效果)的说明。
**有关轻按在data.js的系统变量中有定义。如果`enableGentleClick`为true则鼠标触摸屏通过双击勇士键盘通过空格可达到轻按效果即不向前移动而获得前方物品。**
<br>**有关轻按,在全塔属性的系统开关中有定义。如果勾选了 `enableGentleClick` ,则鼠标(触摸屏)通过双击勇士,键盘通过空格,手机通过虚拟数字键 7 可达到轻按效果,即不移动而获得周围物品。**
## 装备
如果需要让剑盾等变成装备,可以直接在`data.js`中设置`'equipment': true`即可。
如果需要让剑盾等变成装备,可以直接在它们的图块属性中把 `cls` 一项改为 `equips`<br>
从V2.4.1开始HTML5魔塔样板终于拥有了属于自己的装备页面。
### 装备栏的设置,装备类型
在全塔属性中,有一个`equipName`项,其定义了本塔的所有可装备的装备栏。
其需要是一个不小于1且不大于6的数组其中每一项为装备栏的名称**建议是两个汉字**。
<br>其需要是一个长度为正数且不大于 6 15×15 样板为不大于 8 )的一维数组,其中每一项为装备栏的名称,**建议是两个汉字**。<br>
例如下面这种写法就是定义了四个装备孔,名称分别为武器、防御、首饰和魔杖。
``` js
@ -47,9 +39,8 @@
如果要将一个道具设置为装备,首先需要将其`cls`设为`equips`。
然后在图块属性的`equip`一项中设置装备的具体属性。该项写法如下:
``` js
{"type": 0, "atk": 0, "def": 0, "mdef"0, "animate": "hand", "percentage": true}
``` json
{"type": 0, "atk": 0, "def": 0, "mdef": 0, "animate": "hand", "percentage": true}
```
type为该装备的类型必填和上面装备栏一一对应。例如0就是武器2就是首饰等等。
@ -63,8 +54,7 @@ animate为该装备的攻击动画仅对type为0时有效。具体可参见[
percentage为该装备是否按比例增加属性。
下面是几个写法例子。
``` js
``` json
{"type": 0, "atk": 10} // 装备类型是武器,效果是攻击+10使用默认的攻击动画
{"type": 0, "atk": 40, "animate": "sword"} // 装备类型为武器,效果是攻击+10攻击动画是sword
{"type": 1, "def": 40, "percentage": true} // 装备类型是防具效果是防御提升40%
@ -75,8 +65,8 @@ percentage为该装备是否按比例增加属性。
所有取值全部向下取整。
值得注意的是如果多个装备同时按比例增加属性使用加法计算。比如武器增加30%攻击防具增加10%攻击最终合起来增加的是40%而不是43%的属性。
值得注意的是如果多个装备同时按比例增加属性使用加法计算。比如武器增加30%攻击防具增加10%攻击最终合起来增加的是40%而不是43%的属性。<br>
如果某件装备需要按常数增加一种属性但按百分比增加另一种属性,请参考[插件库](https://h5mota.com/plugins/)
### 检测是否存在装备
可以使用`core.hasEquip(itemId)`来检测是否装上某个装备。
@ -92,9 +82,7 @@ percentage为该装备是否按比例增加属性。
从V2.5.4开始,允许支持多重装备,即有若干的装备可共用若干的格子(例如永不复还那样)。
要实现这一点,上面的写法有所改变。
在全塔属性中的`equipName`项写法不变不过可以写重复的装备孔名称。但仍然最多只能写6个
<br>在全塔属性中的`equipName`项写法不变,不过可以写重复的装备孔名称。(但仍然最多只能写 6 或 8 个)
``` js
"equipName": ["武器", "武器", "武器", "防具", "防具", "首饰"]
```
@ -112,95 +100,52 @@ percentage为该装备是否按比例增加属性。
装备动画仍然会取第一个装备类型为0的装备的`animate`项,即使装备了多个有动画的武器。
## 门
本塔支持6种门黄蓝红绿铁花。前五种门需要有对应的钥匙打开花门只能通过调用`openDoor`事件进行打开。
开门后可触发该层的`afterOpenDoor`事件,有关事件的详细介绍请参见[事件](event)。
样板自带6种门黄蓝红绿铁花。前五种门需要有对应的钥匙打开花门只能通过调用 `openDoor` 事件进行打开。<br>
开门后可触发该点的 `afterOpenDoor` 事件,有关事件的详细介绍请参见[事件](event)。<br>
如果要新增自己的门,请参见[新增门和对应的钥匙](personalization#新增门和对应的钥匙)。
## 暗墙
本塔支持暗墙。
要制作一个暗墙非常简单:在该点直接放一个普通墙壁,然后事件写“开门”,坐标为该点就行。
``` js
样板支持暗墙。要制作一个暗墙非常简单:在该点直接放一个普通墙壁,然后事件写“开门”,坐标为该点就行。
``` json
// 该点画一个普通的墙壁,比如`yellowWall`
// 在该点的事件events中:
"x,y": [
{"type": "openDoor"} // 直接使用开门事件,坐标可忽略表示当前点
]
[{"type": "openDoor"}] // 直接使用开门事件,坐标可忽略表示当前点
```
系统会自动调用animates中的开暗墙动画。
目前只有如下ID支持以这种方式开门
系统会自动调用animates中的开暗墙动画。样板自带如下ID支持以这种方式开门
``` text
yellowDoor, blueDoor, redDoor, greenDoor, specialDoor, steelDoor,
yellowWall, blueWall, whiteWall
```
## 怪物
本塔支持的怪物列表参见`project/enemys.js`。其与images目录下的`enemys.png`素材按顺序一一对应。
样板自带的怪物列表参见 `project\enemys.js` 。其与 `images\enemys.png` 素材按顺序一一对应。<br>
如有自己的怪物素材需求请参见[自定义素材](personalization#自定义素材)的内容。
怪物可以有特殊属性,每个怪物可以有多个自定义属性。
怪物的特殊属性所对应的数字special在脚本编辑中的`getSpecials`中定义,请勿对已有的属性进行修改。
多属性可采用数组的写法,比如`'special': [1,3]`视为同时拥有先攻和坚固属性;`'special': [5,10,14,18]`视为拥有3连击、模仿、诅咒、阻击四个属性。
怪物可以负伤,在全塔属性的全局变量`enableNegativeDamage`中指定。
<br>多属性可直接从图块属性勾选。怪物可以负伤,由全塔属性的系统开关 `enableNegativeDamage` 指定。<br>
打败怪物后可以进行加点操作。有关加点塔的制作可参见[加点事件](event#加点事件)。
如果全塔属性中的enableexp为false即不启用经验的话怪物手册里将不显示怪物的经验值打败怪物也不获得任何经验。
拿到幸运金币后,打怪获得的金币将翻倍。
如果怪物有`"notBomb": true`,则该系列诖怪物均不可被炸。
<br>如果全塔属性中的“显示经验值”未勾选,即不启用经验的话,怪物手册里将不显示怪物的经验值,打败怪物也不获得任何经验。<br>
拿到幸运金币后,打怪获得的金币将翻倍。如果怪物勾选了 `notBomb` ,则这个种类的怪物均不可被炸。<br>
N连击怪物的special是6且我们可以为它定义n代表实际连击数。参见样板中剑王的写法。
吸血怪需要给怪物设置value代表吸血的比例。
可以给吸血怪添加`'add': true`来将吸血的数值加到自身上。
中毒怪让勇士中毒后,每步扣减的生命值由`data.js`中的values定义。
衰弱怪让勇士衰弱后,攻防会下降一定比例或固定数值(直到衰弱状态解除恢复);其在`data.js`中的values定义。
<br>吸血怪需要给怪物设置value代表吸血的比例。可以给吸血怪勾选 `add` 来将吸血的数值加到自身上。<br>但这样做以后,红色的预估伤害往往带有误导性,这点还务请注意!<br>
中毒怪让勇士中毒后,每步扣减的生命值由全塔属性中的 `poisonDamage` 定义。<br>
衰弱怪让勇士衰弱后,攻防会下降一定比例或固定数值(直到衰弱状态解除恢复);由全塔属性中的 `weakValue` 定义。<br>
诅咒怪将让勇士陷入诅咒状态,诅咒状态下杀怪不获得金币和经验值。
领域怪需要在怪物后添加value代表领域伤害的数值。如果勇士生命值扣减到0则直接死亡触发lose事件。
领域是十字伤害还是九宫格伤害由`zoneSquare`设定如设置为true则为九宫格伤害不指定或为false则为十字伤害。
<br>领域怪需要需要给怪物设置 `value` 代表领域伤害的数值。如果勇士生命值扣减到0则直接死亡触发 `lose` 事件。<br>
领域是锯齿形状还是正方形由 `zoneSquare` 设定,如勾选则为正方形,不勾选则为锯齿形状。<br>
领域怪还可以设置`range`选项代表该领域怪的范围不写则默认为1。
**将`flag:no_zone`设置为true可以取消领域效果。**
<br>**将 `flags.no_zone` 设置为 `true` 可以免疫领域效果。**<br>
阻击怪同样需要设置value代表阻击伤害的数值。如果勇士生命值扣减到0则直接死亡触发lose事件。
**将`flag:no_snipe`设置为true可以取消阻击效果。**
!> 阻击怪后退的地点不能有任何事件存在,即使是已经被禁用的自定义事件!
<br>**将`flags.no_snipe`设置为true可以免疫阻击效果包括伤害和移动。**<br>
!> 阻击怪后退的地点不能有任何事件存在,即使是已经被禁用的红绿事件或重生怪!(会导致此事件意外被重新启用)<br>
激光怪同样需要设置value代表激光伤害的数值。
请注意如果吸血、领域、阻击中任何两个同时存在则value会冲突。**因此请勿将吸血、领域、阻击或激光放置在同一个怪物身上。**
**将`flag:no_laser`设置为true可以免疫激光效果。**
<br>请注意如果吸血、领域、阻击、生命光环中任何两个同时存在,则 `value` 会冲突。**因此请勿将吸血、领域、阻击或激光放置在同一个怪物身上。退化和攻防光环同理!<br>**
**将 `flags.no_laser` 设置为 `true` 可以免疫激光效果。将 `flags.no_ambush` 设置为 `true` 可以免疫捕捉效果。**<br>
退化怪需要设置'atkValue'和'defValue'表示退化的数值也可以不设置默认为0。
**将`flag:no_betweenAttack`设置为true可以免疫夹击效果。**
<br>**将`flags.no_betweenAttack`设置为true可以免疫夹击效果在全塔属性中还有一个系统开关可以控制夹击伤害是否封顶至夹击怪的战斗伤害。**<br>
固伤怪则需要设置`damage`选项,代表战前扣血数值。
如有额外需求,可参见[自定义怪物属性](personalization#自定义自定义怪物属性),里面讲了如何设置一个新的怪物属性。
@ -226,9 +171,7 @@ N连击怪物的special是6且我们可以为它定义n代表实际连击数
我们可以给`E301`和`E302`怪物属性中的`displayIdInBook`项填写为`"E300"`。
这样的话在怪物手册中所有的E301和E302均会被视为E300并进行合并。即使只有一只朝向左的怪物E301怪物手册仍然会按E300进行显示。
从而完美解决了同种怪物不同朝向在怪物手册的显示问题。
<br>从而完美解决了同种怪物不同朝向在怪物手册的显示问题。此做法不兼容夹击属性,漏怪检测也以映射后的怪物为准。
### NPC的朝向问题
和怪物不同的是NPC朝向问题更复杂一点。
@ -238,12 +181,10 @@ N连击怪物的special是6且我们可以为它定义n代表实际连击数
举个例子假设我存在一个NPC其向上的图块ID是N333向下的图块ID是N334向左的图块ID是N335不存在向右的图块ID。
则可以在这几个图块属性中的`faceIds`中写:`{"up": "N333", "down": "N334", "left": "N335"}`。
当勇士从左边撞上此怪物后将从该图块的图块属性中的faceIds中寻求`left`所对应的ID。
如果存在定义如N335则会在触发对话事件前改变当前图块为N335看起来就是在对话前进行了转向面向勇士。
<br>当勇士从左边撞上此NPC后将从该图块的图块属性中的 `faceIds` 中寻求 `left` 所对应的ID。
如果存在定义如N335则会在触发对话事件前改变当前图块为N335看起来就是在对话前进行了转向面向勇士。<br>
!> 请注意,在对话结束后朝向不会切换回来,因此如果有必要切换朝向请在事件结束前调用转变图块事件。
<br>从v2.7起也提供了“事件转向”指令来执行这种转变图块从而省去了手动填写ID的不便。<br>
同理使用移动事件让NPC在行走时不同朝向的行走会自动调用`faceIds`中不同朝向的ID所对应的行走图看起来就是在行走时也可以不断转向了。
从而完美解决了NPC的朝向问题碰触时面向勇士、行走时改变朝向
@ -253,23 +194,11 @@ N连击怪物的special是6且我们可以为它定义n代表实际连击数
血网的伤害数值、中毒后每步伤害数值、衰弱时暂时攻防下降的数值都在全塔属性的values内定义。
路障同样会尽量被自动寻路绕过。
有关楼梯和传送门必须在该层样板的changeFloor里指定传送点的目标。
floorId指定的是目标楼层的唯一标识符ID
也可以写`"floorId": ":before"`和`"floorId": ":next"`表示上一楼和下一楼。
后面可以写stair到upFloor或downFloor表示将前往目标楼层的上楼梯/下楼梯位置。你也可以写loc然后指定目标点的坐标。
请注意的是如果目标楼层有多个楼梯写stair可能会导致到达的楼梯不确定这时候请使用loc方式来指定具体的点位置。
可以指定direction为up/left/right/down指定后勇士将面向该方向。
可以指定time指定后切换动画时长为指定的数值。
**从2.1.1开始,楼层属性中提供了`upFloor`和`downFloor`两项。如果设置此项(比如`"upFloor": [2,3]`则写stair:upFloor或者楼传器的落点将用此点来替换楼梯位置即类似于RM中的上箭头。**
<br>有关楼梯和传送门,必须在该点的 `changeFloor` 事件里指定传送点的目标。![生成地图](./img/changeFloorBlockly.png)<br>
楼层ID指定的是目标楼层的唯一标识符ID也可以在第一个下拉框中选择“前一楼”和“后一楼”。<br>
第二个下拉框可以选择传送到哪个楼梯,或选择三种对称位置,或显式指定坐标(比如目标楼层有多个楼梯时)。<br>
“朝向”为勇士上下楼后面对的方向,不填则不改变。“动画时间”为上下楼的黑屏时间,不填则使用玩家设定值。<br>“穿透性”表示鼠标或触屏寻路时勇士能否穿过此传送点,在转不开身的狭窄区域建议设为可穿透。<br>
**从v2.1.1开始,楼层属性中提供了 `upFloor``downFloor` 两项。如果设置此项(比如`"upFloor": [2,3]`则写传送到哪个楼梯或者楼传器的落点将用此点来替换楼梯位置即类似于RMXP中的上箭头。**
## 剧情文本控制与对话框效果
在写剧情文本时,可以:
@ -312,16 +241,12 @@ floorId指定的是目标楼层的唯一标识符ID
从V2.4开始H5魔塔开始支持大地图。
大地图在创建时可以指定宽高,要求**宽和高都不得小于1315x15版本则是不小于15且宽高之积不超过1000**。
大地图一旦创建成功则不得修改宽高数值。
<br>大地图一旦创建成功则难以修改宽高数值,如确需修改,请手动打开 `floors` 文件夹中的 `JS` 文件并同时修改宽高和地图矩阵。
## 动画和天气系统
现在我们的H5魔塔支持播放动画也支持天气系统了。
要播放动画你需要先使用“RM动画导出器”将动画导出放在animates目录下然后在全塔属性的animates中定义。
``` js
<br>要播放动画你可以先使用“RM动画导出器”将动画导出放在animates目录下然后在全塔属性的animates中定义。
``` json
// 在此存放所有可能使用的动画必须是animate格式在这里不写后缀名
// 动画必须放在animates目录下文件名不能使用中文不能带空格或特殊字符
"animates": ["hand", "sword", "zone", "yongchang", "thunder"]
@ -332,18 +257,15 @@ floorId指定的是目标楼层的唯一标识符ID
导出动画时可能会进行一些压缩以节省流量,因此清晰度可能不如原版。
从2.3.2开始,动画可以同时导出所用的音效。**如果导出音效,请确保将所用到的音效复制到了`sounds`目录下,并且在全塔属性中注册过。**
<br>确切地说,动画文件中记录着第几帧该用什么音效的文件名,您可以用记事本等文本编辑器打开动画文件并手动修改用到的音效文件名(原本可能是中文甚至日文),以和实际的文件名相匹配
动画播放时是按照每秒20帧的速度即50ms/帧)。
定义完毕后,我们可以调用`animate`事件来播放该动画,有关事件的详细介绍请参见[事件](event)。
!> 播放录像时,将默认忽略所有动画。
目前天气系统支持雨和雪和雾两种天气。
在每层楼的楼层属性中存在一个weather选项表示该层楼的默认天气。
``` js
<br>目前天气系统支持雨、雪和雾三种天气。在每层楼的楼层属性中存在一个weather选项表示该层楼的默认天气。
``` json
// 该层的默认天气。本项可忽略表示晴天,如果写则第一项为"rain""snow"或"fog"代表雨雪雾第二项为1-10之间的数代表强度。
"weather": ["snow",5]
```
@ -351,12 +273,8 @@ floorId指定的是目标楼层的唯一标识符ID
我们也可以使用`setWeather`事件来设置当前天气,有关事件的详细介绍请参见[事件](event)。
## 背景音乐
本塔支持BGM和SE的播放。
要播放音乐和音效你需要将对应的文件放在sounds目录下然后在全塔属性中进行定义
``` js
样板支持BGM和SE的播放。要播放音乐和音效你需要将对应的文件放在sounds目录下然后在全塔属性中进行定义
``` json
// 在此存放所有的bgm和文件名一致。
// 音频名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好
"bgms": ["bgm.mp3"]
@ -366,9 +284,7 @@ floorId指定的是目标楼层的唯一标识符ID
```
!> 音频名不能使用中文,不能带空格或特殊字符。
目前BGM支持主流的音乐格式如mp3, ogg等。不支持mid格式的播放。
<br>目前BGM支持主流的音乐格式`wav, mp3, ogg, flac, m4r` 等。不支持 `mid` 格式的播放。<br>`iOS` 系统对 `ogg` 的支持性较差,但 `ogg``mp3` 体积小,请注意权衡。<br>
定义完毕后,我们可以调用`playBgm`/`playSound`事件来播放对应的音乐/音效,有关事件的详细介绍请参见[事件](event)。
**另外,考虑到用户的流量问题,将遵循如下规则:**
@ -382,11 +298,7 @@ floorId指定的是目标楼层的唯一标识符ID
从V2.5.3开始,可以使用`loadBgm`事件来预加载一个bgm这样到播放时无需等待直接播放。
同时BGM将使用LRU算法增加缓存机制。默认最多缓存4个BGM在core.js的musicStatus.cachedBgmCount控制
系统会自动释放最久未使用的BGM。
也可以使用`freeBgm`事件来手动释放一个无需再用的bgm。
<br>系统会自动释放最久未使用的BGM。也可以使用 `freeBgm` 脚本来手动释放一个无需再用的 `bgm`
## 录像
HTML5魔塔一大亮点就是存在录像系统可以很方便进行录像回放。
@ -404,6 +316,7 @@ HTML5魔塔一大亮点就是存在录像系统可以很方便进行录像回
录像播放过程中,可以进行如下操作:
- **步进:** 暂停状态下,按 `N` 键可以单步执行录像,常用于调试。
- **暂停/播放:** 按空格可以随时暂停或播放录像。
- **加速:** 按X可以加速录像播放最高可达6倍速。
- **减速:** 按Z可以减速录像播放最低可达0.3倍速。
@ -413,8 +326,7 @@ HTML5魔塔一大亮点就是存在录像系统可以很方便进行录像回
- **查看手册:** 按C可以在录像播放过程中查看怪物手册。
- **浏览地图:** 按PgUp/PgDn可以在录像播放过程中浏览地图。
如果录像出现问题请加群539113091找小艾反馈Bug。
如果录像出现问题,请加 QQ 群 [959329661](https://jq.qq.com/?_wv=1027&k=5C87qeQ) 找小艾反馈Bug。
## 操作说明
![](img/keyboard.png)

File diff suppressed because it is too large Load Diff

BIN
_docs/img/bigKey.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 372 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 315 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 222 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 KiB

After

Width:  |  Height:  |  Size: 382 KiB

BIN
_docs/img/forEach.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -1,18 +1,17 @@
# HTML5 魔塔样板说明文档
?> 目前版本**v2.7**,上次更新时间:* {docsify-updated} *
<br>当您打开这份帮助文档的瞬间,相信您一定是抱着幼年时的游戏开发梦想前来的。<br>
众所周知,即时制游戏的开发要比非即时游戏难上许多,像素级游戏的开发又要比网格地图游戏难上许多。<br>在非即时的网格地图游戏譬如策略战棋有一类游戏叫做“固定数值RPG”或者简称“魔塔”。<br>这是一种基于运筹学的数学优化建模游戏,虽然小众,却不失有自己的圈子。
?> 目前版本**v2.6.6**,上次更新时间:* {docsify-updated} *
众所周知魔塔的趋势是向移动端发展贴吧中也常常能见到“求手机魔塔”的帖子。然而现有的工具中NekoRPG有着比较大的局限性游戏感较差更是完全没法在iOS上运行。而一些APP的魔塔虽然可用但是必须要下载安装对于Android和iOS还必须开发不同的版本非常麻烦。
在当下魔塔的趋势是向移动端发展网络上也常常能见到“求手机魔塔”的提问。然而现有的工具中NekoRPG有着比较大的局限性游戏感较差更是完全没法在iOS上运行。而一些APP的魔塔譬如《魔塔盛宴》和一些登陆了TapTap的魔塔以及最新的由RPG Maker MV制作的《盖伦排位记》等虽然可用但是必须要下载安装对于Android和iOS还必须开发不同的版本非常麻烦。
但是现在我们有了HTML5。 HTML5的画布canvas以及它被Android/iOS内置浏览器所支持的特性可以让我们做出真正意义上的全平台覆盖的魔塔。
然而一般而言使用非RMXP制作魔塔往往需要一定的编程技术HTML5魔塔自然也不例外。但是为了能让大家更加注重于“做塔”本身而不用考虑做塔以外的各种脚本问题我特意制作了这样一部HTML5的魔塔样板。
然而一般而言使用非RPG Maker MV制作魔塔往往需要一定的编程技术HTML5魔塔自然也不例外。但是为了能让大家更加注重于“做塔”本身而不用考虑做塔以外的各种脚本问题@艾之葵GitHub ckcz123特意制作了这样一部HTML5的魔塔样板。
> 这个魔塔样板可以让你在完全不懂任何编程语言的情况下做出自己的H5魔塔。不会代码没关系只要你想做就能做出来
> 这个魔塔样板可以让你在完全不懂任何编程的情况下做出自己的H5魔塔。不会代码没关系只要你想做就能做出来
继续查看文档的详细介绍让你学会如何使用这一个样板来制作属于自己的HTML5魔塔。
本说明文档配有B站视频教程对照查看效果更佳哦[https://www.bilibili.com/video/av32781473/](https://www.bilibili.com/video/av32781473/)。
继续查看文档的详细介绍让你学会如何使用这一个样板来制作属于自己的HTML5魔塔或者……任何非即时的网格地图游戏。<br>
本说明文档配有较为过时的B站视频教程可供参考[https://www.bilibili.com/video/av32781473/](https://www.bilibili.com/video/av32781473/)。
==========================================================================================

View File

@ -1,6 +1,5 @@
# 个性化
?> 目前版本**v2.6.6**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.7**,上次更新时间:* {docsify-updated} *
有时候只靠样板本身可能是不够的。我们需要一些个性化、自定义的素材,道具效果,怪物属性,等等。
@ -69,13 +68,6 @@ core.fillText('test', '这是一段文字', 10, 30, '#FF0000', '16px Verdana');
- `terrains.png` 为所有地形的图标。
系统会读取`icon.js`文件并获取每个ID对应的图标所在的位置。
### 使用预定义的素材
在images目录的“默认素材”下给定了若干预定义的自定义素材。
如果你需要某个素材已经存在则可以直接将其覆盖images目录下的同名文件就能看到效果。
### 背景和前景图层
从V2.4.1开始,样板允许多个图层叠加,最多支持背景层、事件层和前景层三个图层。
@ -246,15 +238,14 @@ ID必须由数字字母下划线组成数字在1000以内且均不能和
额外素材可以使用“tileset贴图”的方式进行绘制一次绘制一个矩形区域。
“辅助工具”中提供了“额外素材合并”如果使用此功能请不要对额外素材进行基于ID、索引和数字的判定和读写等操作如确有此需求可以创建一些玩家不可达也不可预览的隐藏样板层然后用等量代换的办法去从样板层取用。
## 自定义道具效果
本节中将继续介绍如何自己编辑一个道具的效果。
道具效果的具体实现都在`items.js`中。
道具效果的具体实现都在 `project\items.js` 中。
### 即捡即用类道具cls: items
对于即捡即用类道具,如宝石、血瓶、剑盾等,我们可以简单地修改`data.js`中的value一栏即可。
对于即捡即用类道具,如宝石、血瓶等,我们可以简单地修改全塔属性中的 `values` 一栏即可。
如果你想要同种宝石在不同层效果不同的话,可以进行如下操作:
@ -281,11 +272,14 @@ core.status.hero.atk += core.values.redJewel + 2*ratio
具体过程比较复杂需要一定的JS能力在这里就不多说了有需求可以找`艾之葵`进行了解。
从V2.6.6起,道具的“图块属性”中,提供了 `useItemEvent` 项,您可以用事件而不是脚本去书写道具的使用效果(对 `cls: items` 也有效但会打断寻路),参见样板的黄宝石和生命魔杖。
如果弄不清楚 `canUseItem` ,也可以干脆统一填写为 `"true"`,先斩后奏,并在使用效果中再行判定,如果发现其实使用失败了,就悄咪咪返还给勇士一个该道具,参见样板的破墙镐和炸弹。
### 实战!拿到神圣盾后免疫吸血、领域、夹击效果
1. 在itemEffect中修改拿到神圣盾时的效果标记一个自定义Flag。
``` js
core.status.hero.def += core.values.shield5 * ratio;
core.status.hero.def += 100;
core.setFlag("shield5", true); // 增加一个自定义Flag已经拿到神圣盾
```
2. 免疫吸血效果在脚本编辑的getDamageInfo中编辑成如果存在神圣盾标记吸血伤害为0。
@ -310,31 +304,24 @@ function (enemy, hero_hp, hero_atk, hero_def, hero_mdef, x, y, floorId) {
// ... 下略
```
3. 免疫领域、夹击、阻击效果在2.4.1之后可以直接将flag:no_zone设为true来免疫领域效果其他几个同理。
``` js
// 写在获得道具后事件
[
``` json
[ // 写在获得道具后事件
// 设置不同的flag可以分别无视对应的阻激夹域效果
{"type": "setValue", "name": "flag:no_zone", "value": "true"}, // 免疫领域
{"type": "setValue", "name": "flag:no_snipe", "value": "true"}, // 免疫阻击
{"type": "setValue", "name": "flag:no_laser", "value": "true"}, // 免疫激光
{"type": "setValue", "name": "flag:no_betweenAttack", "value": "true"}, // 免疫夹击
{"type": "setValue", "name": "flag:no_ambush", "value": "true"}, // 免疫捕捉
{"type": "setValue", "name": "item:shoes", "value": "1"} // 免疫路障
]
```
4. 如果有更高的需求,例如想让吸血效果变成一半,则还是在上面这些地方进行对应的修改即可。
## 新增门和对应的钥匙
如果要新增一个门和对应的钥匙,需要进行如下几步:
1. 在terrains.png中添加新的门的素材并在地图编辑器中注册门的ID。该ID必须是以`Door`结尾,例如`abcDoor`。
2. 在animates.png中添加开门的四格动画然后直接打开icons.js文件在animates下直接添加ID和索引信息例如`'abcDoor': 34`。
3. 在items.png中添加钥匙的素材并在地图编辑器中注册钥匙的ID。该ID必须是和门对应且以`Key`结尾,例如`abcKey`。
4. 该道具的cls应为`tools`,可以自行写道具描述,最下面几项均留`null`即可。
!> **请勿在animates中对门的动画素材进行注册而是请直接打开icons.js文件并添加ID和索引信息**
!> terrains和animates的门ID必须完全一致且以`Door`结尾所对应的钥匙ID应当是把`Door`换成`Key`,这样才能对应的上!
如果要新增一个门和对应的钥匙,只需要进行如下三步:
1. 在 `project\images\animates.png` 中添加开门的四帧动画并注册,其中第一帧也作为未开启的静止门。
2. 在图块属性中将其默认触发器改为 `openDoor` ,动画帧数填 `1` 表示门未开启时静止在第一帧。
3. 在 `doorInfo` 中填写需要哪些钥匙(可以填任何消耗类道具)各多少把,开关门分别播放什么音效等。
## 覆盖楼传事件
对于特殊的塔,我们可以考虑修改楼传事件来完成一些特殊的要求,比如镜子可以按楼传来切换表里。
@ -354,23 +341,25 @@ function (enemy, hero_hp, hero_atk, hero_def, hero_mdef, x, y, floorId) {
如果你对现有的怪物不满意想自行添加怪物属性也是可以的。具体参见脚本编辑的getSpecials。
你需自己指定一个special数字修改属性名和属性提示文字。后两者可以直接写字符串或写个函数传入怪物。
你需自己指定一个special数字修改属性名和属性提示文字。提示文字可以直接写字符串或写个函数传入怪物。
如果要改动怪物在手册中的显示数值(也会被用于伤害计算,如模仿),请修改下面的 `getEnemyInfo` 函数。
如果要修改伤害计算公式请修改下面的getDamageInfo函数。请注意如果无法战斗该函数必须返回`null`。
!> 如果改动了伤害计算公式,可能导致临界计算崩掉,因此建议将全塔属性中的`useLoop`置为true。
对于毒衰弱怪物的战斗后结算在脚本编辑中的afterBattle函数中。
对于领域、夹击、阻击怪物的检查在`control.js`中的checkBlock函数中。
对于毒衰咒、自爆、退化怪物和加点、仇恨值累加等战斗后结算在脚本编辑中的 `afterBattle` 函数中。
对于领域、夹击、阻击、激光、捕捉怪物的检查在脚本编辑中的 `updateCheckBlock` 函数中。
## 自定义快捷键
如果需要绑定某个快捷键为处理一段事件,也是可行的。
要修改按键,我们可以在脚本编辑的`onKeyUp`进行处理:
比如,我们设置一个快捷键进行绑定,比如`Y`其keycode是89。有关每个键的keycode搜一下就能得到
我们设置一个快捷键进行绑定,比如 `Y`,其 `keycode``89`<br>
(大键盘数字键 `0-9``keycode``48-57, A-Z` 键的 `keycode``65-90` ,其他键的 `keycode` 搜一下就能得到)
然后在脚本编辑的`onKeyUp`函数的`switch`中进行处理。
@ -387,8 +376,7 @@ case 89: // 使用该按键的keyCode比如Y键就是89
break;
```
强烈建议所有新增的自定义快捷键均给个对应的永久道具可点击,以方便手机端的行为。
强烈建议所有新增的自定义非数字快捷键均给个对应的永久道具可点击,以方便手机端的行为。
使用`core.status.route.push("key:"+keyCode)`可以将这次按键记录在录像中。
@ -457,7 +445,7 @@ this.myfunc = function(x) {
可以在脚本编辑的onKeyUp中定义每个快捷键的使用效果比如使用道具或释放技能等。
默认值下1使用破2使用炸3使用飞4使用其他存在的道具5-8未定义。可以相应修改成自己的效果。
默认值下1使用破2使用炸3使用飞4使用其他存在的道具5读取上一个自动存档6读取下一个自动存档7轻按8未定义。可以相应修改成自己的效果。
也可以替换icons.png中的对应图标以及修改main.js中`main.statusBar.image.btn1~8`中的onclick事件来自定义按钮和对应按键。
@ -475,6 +463,7 @@ this.myfunc = function(x) {
具体可详见脚本编辑的`drawStatusBar`函数。
自绘状态栏开启后,金币图标将失去打开快捷商店的功能,您可以修改脚本编辑的 `onStatusBarCLick` 函数来适配。
## 自定义状态栏的显示项
在V2.2以后,我们可以自定义状态栏背景图(全塔属性 - statusLeftBackground等等。
@ -534,13 +523,9 @@ core.statusBar.speed.innerHTML = core.getStatus('speed');
// 设置其显示内容为flag:speed值无需额外进行定义。
core.statusBar.speed.innerHTML = core.getFlag('speed', 0);
```
总的来说不建议这样做,因为 `main.js` 和几个 `html` 文件不在 `project` 文件夹,会导致随样板更新迁移接档变得困难。
## 技能塔的支持
要支持技能塔,可能需要如下几个方面:
从V2.5开始,内置了"二倍斩"技能,可以仿照其制作自己的技能。
从V2.5开始,内置了"二倍斩"技能,可以仿照其制作自己的技能。要支持技能塔,可能需要如下几个方面:
- 魔力(和上限)的添加;技能的定义
- 状态栏的显示
- 技能的触发(按键与录像问题)
@ -548,11 +533,9 @@ core.statusBar.speed.innerHTML = core.getFlag('speed', 0);
### 魔力的定义添加;技能的定义
从V2.5开始提供了status:mana选项可以直接代表当前魔力值。
从V2.5开始,提供了 `status:mana` 选项,可以直接代表当前魔力值。可以在全塔属性勾选来启用它。
如果要启用需要开启全塔属性的enableMana选项。
如果需要魔力上限则可以使用flag:manaMax来表示当前的魔力最大值。
如果需要魔力上限,则可以使用 `status:manaMax` 来表示当前的魔力最大值,负数表示没有上限。
同时我们可以使用flag:skill表示当前开启的技能编号flag:skillName表示当前开启的技能名称。
@ -581,8 +564,7 @@ core.statusBar.skill.innerHTML = core.getFlag('skillName', '无');
### 技能的触发
#### 使用道具作为技能
由于手机端按键十分不方便,虚拟键盘不好用,因此强烈推荐**给每个技能设置一个道具图标,在道具栏点击使用!**
由于手机端按字母键不方便,虚拟键盘不好用,因此强烈推荐**给每个字母键技能设置一个道具,在道具栏点击使用!**
下面是个很简单的例子,要制作一个技能"二倍斩"。
@ -616,19 +598,17 @@ else { // 关闭技能
在技能的道具定义完毕后,再将该道具绑定到一个快捷键上。有关绑定按键请参见[自定义快捷键](#自定义快捷键)。
下面是一个很简单的例子当勇士按下W后触发我们上面定义的二倍斩技能。
下面是一个很简单的例子,当勇士按下 `F` 后,触发我们上面定义的二倍斩技能。
``` js
case 87: // W:开启技能“二倍斩”
case 70: // F:开启技能“二倍斩”
// 是否拥有“二倍斩”这个技能道具
if (core.hasItem('skill1')) {
core.status.route.push("key:87");
core.status.route.push("key:70");
core.useItem('skill1', true);
}
break;
```
在勇士处于停止的条件下按下W键时判断技能的道具是否存在如果存在再使用它。
在勇士处于停止的条件下,按下 `F` 键时,判断技能的道具是否存在,如果存在再使用它。
!> 由于现在手机端存在拓展键盘也强烈建议直接覆盖1-8的使用效果这样手机端使用也非常方便。

View File

@ -1,37 +1,34 @@
# 快速上手
?> 目前版本**v2.6.6**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.7**,上次更新时间:* {docsify-updated} *<br>
在这一节中,将详细介绍做一部塔的流程。现在,让我们来做一部单层塔!
## 前置需求
你需要有满足如下条件才能进行制作:
- Windows 8以上操作系统Windows 7需要安装.Net Framework 4.0。(能打开同目录下的“启动服务.exe”即可
- Mac系统则需OS X 10.7及以上,能正确打开启动服务(Mac版).app即可。
- 安卓手机端需要下载最新版的HTML5安卓造塔器。
- Chrome浏览器。其他浏览器可能会导致本地服务器产生闪退等现象。
- 强烈推荐安装一个很好的文本编辑器VSCode。在某些需要直接修改文件的场合可能会非常重要。
上述软件均可以在群文件的常用软件中找到下载安装包。
你需要满足如下条件才能进行制作:
- Windows 8 以上操作系统Windows 7 需要安装 .Net Framework 4.0。(能打开同目录下的“启动服务.exe”即可
- 其他电脑则需安装 [python 3.8.2](https://www.python.org/getit/) 或更高版本能打开server.py即可 Windows 也可以这样做)。
- 安卓手机端需要下载最新版的 [HTML5安卓造塔器](https://h5mota.com/games/_client/H5motaMaker.apk)。
- [Chrome浏览器](https://www.google.cn/chrome/)。其他浏览器可能会导致本地服务器产生闪退等现象。
- 强烈推荐安装一个很好的文本编辑器:[VSCode](https://code.visualstudio.com/download)。在某些需要直接修改文件的场合,可能会非常重要。
只要满足了上述条件,你就可以开始做自己的塔啦!
## 启动HTTP服务
在根目录下有一个“启动服务.exe”运行之。Mac版本则双击运行“启动服务(Mac版).app”手机端则使用造塔APP。
与编辑器闭源的 RPG Maker MV 不同,本样板对文件的绝大部分修改是通过网页编辑器经由本地 HTTP 服务完成的,这样做也有助于编辑器跨平台并最大限度地复用运行时代码,还可以让玩家在在线游戏时查看游戏工程。<br>
在根目录下有一个“启动服务.exe”运行之。非 Windows 电脑则需使用命令行运行 server.py手机端则使用造塔APP。
![启动服务](img/server.png)
* “启动游戏”按钮将打开一个网页,你能在里面看到现在游戏的效果。
* “地图编辑器”允许你以可视化的方式进行编辑地图。
* “启动游戏”按钮将打开一个网页(您也可以手动在浏览器中键入 127.0.0.1:1055/index.html 同时开启多个启动服务则1056、1057顺延你能在里面看到现在游戏的效果。
* “地图编辑器”允许你以可视化的方式进行编辑游戏(这个名称为历史遗留,两年前它真的只能编辑地图)。您也可以手动在浏览器中键入 127.0.0.1:1055/editor.html
* 以下为 Windows 专用的一些辅助工具由C#编写:
* “便捷PS工具”能让你很方便的对自定义素材进行添加。参见[自定义素材](personalization#自定义素材)。
* “地图生成器”能让你从已有的截图如RMXP项目中立刻生成可被本样板识别的地图数据。
* “怪物数据导出”能让你从RMXP中导出怪物数据而被H5魔塔使用。
* “RM动画导出器”能让你从RMXP中导出动画而被H5魔塔使用。
* “JS代码压缩工具”能对JS代码进行压缩从而减少IO请求数和文件大小。
* “怪物数据导出”能让你从RMXPRPG Maker XP 1.03下同中导出怪物数据而被HTML5魔塔使用。
* “RM动画导出”能让你从RMXP中导出动画而被HTML5魔塔使用。
* “JS代码压缩”能对JS代码和音像素材进行压缩从而减少IO请求数和文件大小。
* “额外素材合并”能将用到的tileset素材重新拼成更少的图片并更新对应的地图矩阵。
* “伤害和临界值计算器”是一个很便捷的小工具,能对怪物的伤害和临界值进行计算。
* “动画编辑器”能让你编辑已有的animate动画文件或自己利用图片制作全新的动画。
* “[怪物数据生成机](https://pan.baidu.com/s/1w-JMg-ZPRvbsqbbtOwORGA#list/path=%2F
)”能够借助AI生成适当强度的怪物此工具需要手动下载。
!> **整个造塔过程中,启动服务必须全程处于开启状态!切不可手滑关闭,否则做的都是无用功!**
@ -48,15 +45,10 @@
![绘制地图](./img/drawmap.jpg)
如果提示“该素材未被定义”或有红色问号框,请参见[素材注册](#素材注册)。
绘制地图时可以右键弹出菜单,移动图块和事件。
从V2.4.2开始,可以使用`Alt+0~9`对一个图块素材快速保存,`Ctrl+0~9`来快速选用。
<br>绘制地图时可以右键弹出菜单,复制、交换、删除图块、选中素材、更改出生点或快速创建常用事件。<br>从V2.4.2开始,可以使用 `Alt+0~9` 对一个图块素材快速保存,大键盘 `0~9` 来快速选用。<br>
从V2.6.6开始,最近使用的图块也会直接显示在地图下方,您可以随时选取或清空它们。
### 从RMXP导入已有的地图
!> 注现在已经不推荐此方法如需从RM刻塔请使用 [RM转H5刻塔器使用教程](https://www.bilibili.com/video/av43125840) 进行操作。
!> 注现在已经不推荐此方法如需从RMXP复刻魔塔请观看 [RM转H5刻塔器使用教程](https://www.bilibili.com/video/av43125840) 进行操作。<br>
如果我们想复刻一个现有的已经被RMXP所制作的塔也有很便捷的方式那就是用到我们的“地图生成器”。
首先我们打开RMXP和对应的项目可以看到它的地图。
@ -64,9 +56,7 @@
![绘制地图](./img/rmxp2.png)
我们打开地图编辑器创建一个地图宽高需要和RM中的地图一致。
之后我们打开Windows自带的“截图工具”并将整个地图有效区域截图下来并将其复制到剪切板。
<br>之后,我们打开 Windows 10 自带的“截图工具”(非 Windows 10 请使用 Print Screen 键全屏截图后粘贴到“画图”中裁剪,或使用微信/QQ等自带的截图功能并将整个地图有效区域截图下来复制到剪切板。
![绘制地图](./img/rmxp3.png)
截图时请注意:**只截取有效游戏空间内数据并且有效空间内的范围必须是创建的地图的大小至少为13x13。**
@ -78,8 +68,7 @@
然后点击“复制地图”,即可将地图数据复制到剪切板,然后再地图编辑器中切换到“地图编辑”,并在左边的框进行粘贴。
!> **地图生成器默认只支持已被定义的素材。如果有自定义素材需求例如原版的1层小塔那种素材请先[导入并注册素材](#素材注册)后再进行操作。**
!> **请确保截图范围为你创建的地图大小并且保证每个位置的像素都是32x32。**
!> **请确保截图范围为你创建的地图大小并且保证每个位置的像素都是32x32譬如48×48的RPG Maker MV就需要缩小到2/3比例再截图。**
!> **如果宽度超过13地图生成器将无法显示完全但是仍然可以粘贴到地图编辑器中进行修改。**
@ -90,9 +79,7 @@
## 编辑属性
当地图绘制完毕后,我们可能需要进行属性的编辑。属性编辑有四类:楼层属性、怪物属性、道具属性、全塔属性。
### 楼层属性
### 楼层属性快捷键V
我们切换到楼层属性,并进行一项项的编辑。将鼠标放在中间有具体的每一项注释,这里不再细说。
![楼层属性](./img/floor.png)
@ -110,13 +97,9 @@
同理,点击道具可以对道具属性进行编辑。
目前大多数道具都已有默认效果。更多信息可参见[元件说明:道具](element#道具)。
### 全塔属性
### 全塔属性快捷键B
我们切换到全塔属性,并进行一项项的编辑。同样鼠标放在中间可以查看注释。
我们可以在这里定义一些全局的属性,比如开始剧情、宝石血瓶剑盾数值,破甲反击净化的比例,以及一些系统开关比如是否启用加点,是否允许负伤害等等。
<br>我们可以在这里定义一些全局的属性,比如开始剧情、宝石血瓶数值,破甲反击净化的比例,以及一些系统开关比如是否启用加点,是否允许负伤害等等。<br>
!> **注name作为游戏的唯一标识符必须进行修改否则可能会导致存档等出现问题。**
&nbsp;
@ -142,9 +125,7 @@
从上至下有若干项,分别代表该点的一些事件。有关事件的详细信息请参见[事件](event)。
如果一个点存在事件,则在地图编辑器中该点的左下角会有一个小方框表示。
红色为自定义事件,绿色为楼层传送事件,黄色为战后事件,青色为道具获得后的事件,粉色为开门后的事件。
<br>红色为普通事件,橙色为自动事件,黄色为战后事件,绿色为楼层转换,青色为拾获道具后事件,靛色为不可通行性(不是事件),粉(紫)色为开门后事件。
## 自定义素材的添加与注册
有关素材的更多详细信息,包括素材的机制等内容,请参见[自定义素材](personalization#自定义素材)。
@ -154,15 +135,10 @@
### 新素材的添加
如果我们需要新增加一些素材,比如样板中没有的怪物等。
我们可以从启动服务打开编辑PS工具然后选择对应的图片进行添加。
<br>我们可以从启动服务打开便捷PS工具然后选择对应的图片进行添加。
![便捷PS工具](img/ps.png)
在左边选择你要导入到的位置比如怪物就是enemy.png道具就是items.png等等再在右边导入你的新素材图片。
之后就可以简单的使用Ctrl+C和Ctrl+V来复制粘贴了。
在左边选择你要导入到的文件比如怪物就是enemy.png道具就是items.png等等再在右边导入你的新素材图片。<br>
之后就可以简单的使用 C 和 V 来复制粘贴了。<br>
保存后,刷新地图编辑器即可生效。
### 素材注册
@ -172,15 +148,11 @@
![素材注册](./img/register.png)
出现这种情况,是因为我们没有将该素材定义到游戏中,也无法进行使用。
要解决这个问题只需要在左边的图块属性中定义新的图块ID和图块数字即可。ID必须由数字字母下划线组成数字在1000以内且均不能和已有的进行重复。
<br>要解决这个问题只需要在左边的图块属性中定义新的图块ID和图块数字即可。ID必须由数字字母下划线组成ID不允许使用纯数字。图块数字在1000以内ID和图块数字均不能和已有的进行重复。<br>
有关图块的ID和数字定义请参见[素材的机制](personalization#素材的机制)。
之后刷新编辑器即可。
也可以进行自动注册只需要点击“自动注册”按钮将对该栏下所有未注册的素材进行自动注册自动分配ID和数字
<br>也可以进行自动注册只需要点击“自动注册”按钮将对该栏下所有未注册的素材进行自动注册自动分配ID和数字随后强烈建议手动修改ID<br>
素材注册完毕后,即可在游戏中正常使用,也可以被地图生成器所识别(需要重开地图生成器)。
### 额外素材
@ -194,11 +166,8 @@
有关额外素材的更多说明参见[额外素材](personalization#额外素材)
## 控制台调试
HTML5的塔都是可以进行控制台调试的。
当我们使用Chrome进入游戏后可以按 `Ctrl+Shift+I` ,并找到 `Console` 控制台。
HTML5游戏都是可以进行控制台调试的。<br>
当我们使用Chrome进入游戏后可以按 `Ctrl+Shift+I` F12并找到 `Console` 控制台。
![控制台](./img/console.png)
在控制台中,我们可以输入一些命令对游戏进行调试,常见的命令有:
@ -209,21 +178,21 @@ HTML5的塔都是可以进行控制台调试的。
- `core.status.hero` 获得当前勇士状态信息。例如`core.status.hero.atk`就是当前勇士的攻击力数值。
- `core.material.enemys` 获得所有怪物信息。例如`core.material.enemys.greenSlime`就是获得绿色史莱姆的属性数据。
- `core.material.items` 获得所有道具的信息。例如`core.material.items.pickaxe`就是获得破墙镐的信息。
- `core.debug()` 开启调试模式此模式下可以按住Ctrl键进行穿墙。
- `core.updateStatusBar()` 立刻更新状态栏和地图显伤。
- `flags.debug = true` 开启调试模式;此模式下可以按住 Ctrl 键进行穿墙。
- `core.updateStatusBar()` 立刻更新状态栏和地图显伤,并检查自动事件
- `core.setStatus('atk', 1000)` 直接设置勇士的某项属性。本句等价于 `core.status.hero.atk = 1000`
- `core.getStatus('atk')` 返回勇士当前某项属性数值。本句等价于 `core.status.hero.atk`
- `core.setItem('pickaxe', 10)` 直接设置勇士某个道具的个数。这里可以需要写道具的ID。
- `core.getItem('pickaxe', 2)` 令勇士获得两个破墙镐。
- `core.itemCount('pickaxe')` 返回勇士某个道具的个数。
- `core.hasItem('pickaxe')` 返回勇士是否拥有某个道具。等价于`core.itemCount('pickaxe')!=0`。
- `core.hasItem('pickaxe')` 返回勇士是否拥有某个道具。等价于`core.itemCount('pickaxe') > 0`。
- `core.getEquip(0)` 返回0号装备类型武器的当前装备的itemId不存在则返回null
- `core.hasEquip('sword1')` 返回某个装备当前是否处于被装备状态
- `core.setFlag('xxx', 1)` 设置某个flag/自定义变量的值。
- `core.getFlag('xxx', 10)` 获得某个flag/自定义变量的值;如果该项不存在(未被定义),则返回第二个参数的值。
- `core.hasFlag('xxx')` 返回是否存在某个变量且不为0。等价于`core.getFlag('xxx', 0)!=0`
- `core.removeFlag('xxx')` 删除某个flag/自定义变量
- `core.insertAction(list)` 执行一段自定义事件。比如 `core.insertAction(["剧情文本"])` 将执行一个剧情文本显示事件。
- `core.hasFlag('xxx')` 返回是否存在某个变量且不为六种广义 `false` 。等价于 `!!core.getFlag('xxx')`
- `core.setFlag('xxx')` 删除某个flag/自定义变量
- `core.insertAction(list)` 执行一个公共事件或一段自定义事件。比如 `core.insertAction(["剧情文本"])` 将执行一个剧情文本显示事件。
- `core.changeFloor('MT2', 'downFloor')` 立刻执行楼层切换到MT2层的下楼点位置。
- `core.changeFloor('MT5', null, {'x': 4, 'y': 7})` 立刻切换楼层到MT5层的(4,7)点。
- `core.getBlock(3, 5, 'MT1')` 获得当前地图上某一个块的信息。第三个参数为floorId可省略表示当前楼层。
@ -234,16 +203,16 @@ HTML5的塔都是可以进行控制台调试的。
更多API和详细参数介绍可参见[API列表](api)。
## 编辑器的基本操作
- **H** 查看所有快捷键
- **Alt+0~9, 0~9** 保存和读取当前选中图块
- **W/A/S/D** 移动大地图
- **Ctrl+Z** 撤销上次绘图
- **Ctrl+Y** 重做上次绘图
- **PgUp/PgDn** 切换楼层
- **PgUp/PgDn,或滚轮** 切换楼层
- **Ctrl+S** 保存事件编辑器/脚本编辑器
- **地图上单击** 选中该点
- **地图上双击** 选中该点图块
- **地图上右键** 弹出菜单栏,包括选中、复制、清除等操作
- **地图上右键** 弹出菜单栏,包括选中、复制、交换、清除、更改出生点、快速绑定等操作
- **事件编辑器中Ctrl+C, Ctrl+X, 右键等** 执行相应操作
## 报错处理
@ -273,10 +242,7 @@ HTML5的塔都是可以进行控制台调试的。
![删除ID](./img/floorid.png)
请注意手动删除楼层时一定要确保“初始楼层ID”是一个有效且存在的floorId
&nbsp;
如有任何无法解决的问题,欢迎加群**539113091**寻求帮助。
<br>如有任何无法解决的问题,欢迎加 QQ 群 [959329661](https://jq.qq.com/?_wv=1027&k=5C87qeQ) 寻求帮助。
==========================================================================================

View File

@ -34,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 = {
@ -102,78 +102,52 @@ var code = ' \n';
return code;
*/;
shopcommonevent
: '公共事件版商店 id' IdString '快捷商店栏中名称' EvalString BGNL? '未开启状态则不显示在列表中' Bool BGNL? '执行的公共事件 id' 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;
*/;
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
@ -187,7 +161,7 @@ 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;
*/;
@ -210,6 +184,28 @@ var code = '{"id": "' + IdString_0 + '"' + IntString_0 + EvalString_0 + EvalStri
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;
*/;
//afterBattle 事件编辑器入口之一
afterBattle_m
: '战斗结束后' BGNL? Newline action+ BEND
@ -224,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 事件编辑器入口之一
@ -284,6 +283,7 @@ 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+'"';
if (DirectionEx_List_0 == 'null') DirectionEx_List_0 = '';
DirectionEx_List_0 = DirectionEx_List_0 && (', "direction": "'+DirectionEx_List_0+'"');
IntString_0 = IntString_0 ?(', "time": '+IntString_0):'';
if (IgnoreChangeFloor_List_0!='null') {
@ -340,9 +340,9 @@ action
| trigger_s
| insert_1_s
| insert_2_s
| revisit_s
| exit_s
| setBlock_s
| turnBlock_s
| showFloorImg_s
| hideFloorImg_s
| showBgFgMap_s
@ -362,8 +362,7 @@ action
| openDoor_s
| closeDoor_s
| changeFloor_s
| changePos_0_s
| changePos_1_s
| changePos_s
| setViewport_s
| moveViewport_s
| useItem_s
@ -380,8 +379,7 @@ action
| hideImage_s
| showTextImage_s
| moveImage_s
| showGif_0_s
| showGif_1_s
| showGif_s
| setCurtain_0_s
| setCurtain_1_s
| screenFlash_s
@ -700,13 +698,13 @@ return code;
*/;
hide_s
: '隐藏事件' 'x' EvalString? ',' 'y' EvalString? '楼层' IdString? '动画时间' IntString? '不等待执行完毕' Bool? Newline
: '隐藏事件' 'x' EvalString? ',' 'y' EvalString? '楼层' IdString? '同时删除' Bool '动画时间' IntString? '不等待执行完毕' Bool? Newline
/* hide_s
tooltip : hide: 将一个启用事件禁用,所有参数均可不填,代表禁用事件自身,xy可用逗号分隔表示多个点
tooltip : hide: 隐藏事件,同时可删除
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 : ["","","","",false]
default : ["","","",true,"",false]
colour : this.mapColor
var floorstr = '';
if (EvalString_0 && EvalString_1) {
@ -727,8 +725,9 @@ if (EvalString_0 && EvalString_1) {
}
IdString_0 = IdString_0 && (', "floorId": "'+IdString_0+'"');
IntString_0 = IntString_0 ?(', "time": '+IntString_0):'';
Bool_0 = Bool_0 ?', "async": true':'';
var code = '{"type": "hide"'+floorstr+IdString_0+''+IntString_0+Bool_0+'},\n';
Bool_0 = Bool_0 ?', "remove": true':'';
Bool_1 = Bool_1 ?', "async": true':'';
var code = '{"type": "hide"'+floorstr+IdString_0+Bool_0+IntString_0+Bool_1+'},\n';
return code;
*/;
@ -786,18 +785,6 @@ var code = '{"type": "insert", "loc": ['+PosString_0+','+PosString_1+']'+Event_L
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';
return code;
*/;
exit_s
: '立刻结束当前事件' Newline
@ -841,6 +828,39 @@ var code = '{"type": "setBlock", "number": "'+EvalString_0+'"'+floorstr+IdString
return code;
*/;
turnBlock_s
: '事件转向' DirectionEx_List 'x' EvalString? ',' 'y' EvalString? '楼层' IdString? Newline
/* turnBlock_s
tooltip : turnBlock事件转向自动检索faceIds
helpUrl : https://h5mota.com/games/template/_docs/#/event?id=setblock%EF%BC%9A%E8%AE%BE%E7%BD%AE%E6%9F%90%E4%B8%AA%E5%9B%BE%E5%9D%97
colour : this.mapColor
default : [null,"","",""]
var floorstr = '';
if (EvalString_0 && EvalString_1) {
var pattern1 = MotaActionFunctions.pattern.id;
if(pattern1.test(EvalString_0) || pattern1.test(EvalString_1)){
EvalString_0=MotaActionFunctions.PosString_pre(EvalString_0);
EvalString_1=MotaActionFunctions.PosString_pre(EvalString_1);
EvalString_0=[EvalString_0,EvalString_1]
} else {
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<EvalString_0.length;ii++)EvalString_0[ii]='['+EvalString_0[ii]+','+EvalString_1[ii]+']';
}
floorstr = ', "loc": ['+EvalString_0.join(',')+']';
}
if (DirectionEx_List_0 == 'null') DirectionEx_List_0 = '';
DirectionEx_List_0 = DirectionEx_List_0 && (', "direction": "'+DirectionEx_List_0+'"');
IdString_0 = IdString_0 && (', "floorId": "'+IdString_0+'"');
var code = '{"type": "turnBlock"'+DirectionEx_List_0+floorstr+IdString_0+'},\n';
return code;
*/;
showFloorImg_s
: '显示贴图' 'x' EvalString? ',' 'y' EvalString? '楼层' IdString? Newline
@ -1011,14 +1031,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;
*/;
@ -1157,48 +1179,40 @@ return code;
*/;
changeFloor_s
: '楼层切换' IdString? 'x' PosString? ',' 'y' PosString? '朝向' DirectionEx_List '动画时间' IntString? Newline
: '楼层切换' Floor_List IdString? Stair_List 'x' Number ',' 'y' Number '朝向' 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,""]
default : [null,"",null,"","",null,"",null]
colour : this.dataColor
var toFloorId = IdString_0;
if (Floor_List_0!='floorId') toFloorId = Floor_List_0;
toFloorId = toFloorId ? (', "floorId": ' + toFloorId) : '';
var loc = ', "loc": ['+Number_0+', '+Number_1+']';
if (Stair_List_0===':now') loc = '';
else if (Stair_List_0!=='loc')loc = ', "stair": "'+Stair_List_0+'"';
if (DirectionEx_List_0 == 'null') DirectionEx_List_0 = '';
DirectionEx_List_0 = DirectionEx_List_0 && (', "direction": "'+DirectionEx_List_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+IntString_0+' },\n';
IntString_0 = IntString_0 ?(', "time": '+IntString_0):'';
var code = '{"type": "changeFloor"'+toFloorId+loc+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+']') : '';
if (DirectionEx_List_0 == 'null') DirectionEx_List_0 = '';
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;
*/;
@ -1242,15 +1256,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;
*/;
@ -1434,28 +1449,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;
*/;
@ -1910,8 +1915,8 @@ 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 (!/^switch:[A-Z]$/.test(expression_0)) {
throw new Error('循环遍历仅允许使用独立开关');
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';
*/;
@ -1923,8 +1928,8 @@ 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 (!/^switch:[A-Z]$/.test(expression_0)) {
throw new Error('循环遍历仅允许使用独立开关');
if (!/^temp:[A-Z]$/.test(expression_0)) {
throw new Error('循环遍历仅允许使用临时变量');
}
if (JsonEvalString_0 == '' || !(JSON.parse(JsonEvalString_0) instanceof Array)) {
throw new Error('参数列表必须是个有效的数组!');
@ -2483,6 +2488,7 @@ expression
| bool_e
| idString_e
| evFlag_e
| evTemp_e
| evalString_e
@ -2579,7 +2585,7 @@ idString_3_e
colour : this.idstring_eColor
default : ['greenSlime',"攻击"]
//todo 将其output改成'idString_e'
var code = 'enemy:'+IdString_0+'.'+EnemyId_List_0;
var code = 'enemy:'+IdString_0+':'+EnemyId_List_0;
return [code, Blockly.JavaScript.ORDER_ATOMIC];
*/;
@ -2635,6 +2641,18 @@ return [code, Blockly.JavaScript.ORDER_ATOMIC];
*/;
evTemp_e
: '临时变量' Letter_List
/* evTemp_e
colour : this.idstring_eColor
default : ["A"]
var code = "temp:"+Letter_List_0;
return [code, Blockly.JavaScript.ORDER_ATOMIC];
*/;
evalString_e
: EvalString
@ -2676,8 +2694,8 @@ FontString
;
Floor_List
: '楼层ID'|'前一楼'|'后一楼'
/*Floor_List ['floorId',':before',':next']*/;
: '楼层ID'|'前一楼'|'后一楼'|'当前楼'
/*Floor_List ['floorId',':before',':next',':now']*/;
Stair_List
: '坐标'|'上楼梯'|'下楼梯'|'保持不变'|'中心对称点'|'x对称点'|'y对称点'
@ -2728,7 +2746,7 @@ IgnoreChangeFloor_List
/*IgnoreChangeFloor_List ['null','true','false']*/;
Event_List
: '事件'|'战后事件'|'道具后事件'|'开门后事件'
: '普通事件'|'战后事件'|'道具后事件'|'开门后事件'
/*Event_List ['null','afterBattle','afterGetItem','afterOpenDoor']*/;
Floor_Meta_List
@ -2745,8 +2763,8 @@ Global_Value_List
Global_Flag_List
: '显示当前楼层'|'显示勇士图标'|'显示当前等级'|'启用生命上限'|'显示生命值'|'显示魔力值'|'显示攻击力'|'显示防御力'|'显示护盾值'|'显示金币值'|'显示经验值'|'允许等级提升'|'升级扣除模式'|'显示钥匙数量'|'显示绿钥匙'|'显示破炸飞'|'显示毒衰咒'|'显示当前技能'|'楼梯边才能楼传'|'楼传平面塔模式'|'破墙镐四方向'|'炸弹四方向'|'冰冻徽章四方向'|'铁门不需要钥匙'|'开启加点'|'开启负伤'|'夹击不超伤害值'|'循环计算临界'|'允许轻按'|'允许走到将死领域'|'允许瞬间移动'|'允许查看禁用商店'|'阻激夹域后禁用快捷商店'|'虚化前景层'|'检查控制台'
/*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', 'pickaxeFourDirections', 'bombFourDirections', 'snowFourDirections', 'steelDoorWithoutKey', 'enableAddPoint', 'enableNegativeDamage', 'betweenAttackMax', 'useLoop', 'enableGentleClick', 'canGoDeadZone', 'enableMoveDirectly', 'enableDisabledShop', 'disableShopOnDamage', 'blurFg']*/;
: '显示当前楼层'|'显示勇士图标'|'显示当前等级'|'启用生命上限'|'显示生命值'|'显示魔力值'|'显示攻击力'|'显示防御力'|'显示护盾值'|'显示金币值'|'显示经验值'|'允许等级提升'|'升级扣除模式'|'显示钥匙数量'|'显示绿钥匙'|'显示破炸飞'|'显示毒衰咒'|'显示当前技能'|'楼梯边才能楼传'|'楼传平面塔模式'|'铁门不需要钥匙'|'开启加点'|'开启负伤'|'夹击不超伤害值'|'循环计算临界'|'允许轻按'|'允许走到将死领域'|'允许瞬间移动'|'阻激夹域后禁用快捷商店'|'虚化前景层'|'检查控制台'
/*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'+ //为了被识别为复杂词法规则
@ -2779,8 +2797,8 @@ Direction_List
/*Direction_List ['up','down','left','right']*/;
DirectionEx_List
: '不变'|'上'|'下'|'左'|'右'
/*DirectionEx_List ['','up','down','left','right']*/;
: '不变'|'上'|'下'|'左'|'右'|'左转'|'右转'|'背对'
/*DirectionEx_List ['null','up','down','left','right',':left',':right',':back']*/;
StepString
: (Direction_List Int?)+
@ -2795,8 +2813,8 @@ FixedId_List
/*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
: '生命'|'攻击'|'防御'|'金币'|'经验'|'加点'|'属性'|'名称'|'映射名'|'value'|'atkValue'|'defValue'|'notBomb'|'zoneSquare'|'range'|'n'|'add'|'damage'
@ -2867,6 +2885,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
@ -2896,7 +2915,7 @@ ActionParser.prototype.parse = function (obj,type) {
obj.loc=[0,0];
if (!this.isset(obj.stair)) obj.stair=':now';
}
if (obj.floorId==':before'||obj.floorId==':next') {
if (obj.floorId==':before'||obj.floorId==':next'||obj.floorId==':now') {
obj.floorType=obj.floorId;
delete obj.floorId;
}
@ -2904,6 +2923,13 @@ ActionParser.prototype.parse = function (obj,type) {
obj.floorType||'floorId',obj.floorId,obj.stair||'loc',obj.loc[0],obj.loc[1],obj.direction,
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':
if(!obj)obj={};
@ -2918,22 +2944,12 @@ 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){
@ -3076,7 +3092,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,data.async||false,this.next]);
x_str.join(','),y_str.join(','),data.floorId||'',data.remove||false,data.time,data.async||false,this.next]);
break;
case "setBlock": // 设置图块
data.loc=data.loc||[];
@ -3090,6 +3106,18 @@ ActionParser.prototype.parseAction = function() {
this.next = MotaActionBlocks['setBlock_s'].xmlText([
data.number||0,x_str.join(','),y_str.join(','),data.floorId||'',this.next]);
break;
case "turnBlock": // 事件转向
data.loc=data.loc||[];
if (!(data.loc[0] instanceof Array))
data.loc = [data.loc];
var x_str=[],y_str=[];
data.loc.forEach(function (t) {
x_str.push(t[0]);
y_str.push(t[1]);
})
this.next = MotaActionBlocks['turnBlock_s'].xmlText([
data.direction,x_str.join(','),y_str.join(','),data.floorId||'',this.next]);
break;
case "showFloorImg": // 显示贴图
data.loc=data.loc||[];
if (!(data.loc[0] instanceof Array))
@ -3175,18 +3203,22 @@ ActionParser.prototype.parseAction = function() {
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,this.next]);
if (!data.loc) {
data.loc = data.loc || ['',''];
data.stair = data.stair || ':now';
}
if (data.floorId==':before'||data.floorId==':next'||data.floorId==':now') {
data.floorType=data.floorId;
delete data.floorId;
}
return MotaActionBlocks['changeFloor_s'].xmlText([
data.floorType||'floorId',data.floorId,data.stair||'loc',data.loc[0],data.loc[1],obj.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]);
@ -3240,14 +3272,10 @@ 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;
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);
@ -3291,7 +3319,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([
@ -3494,7 +3522,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([
@ -3538,10 +3566,6 @@ ActionParser.prototype.parseAction = function() {
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]);
@ -3782,6 +3806,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);
}
@ -3988,7 +4017,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) {
@ -4018,7 +4047,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) {

View File

@ -203,6 +203,8 @@ div.etableInputDiv {
div.checkboxSet {
position: relative !important;
max-height: 250px;
overflow: auto;
}
.etableInputDiv > * {

View File

@ -213,6 +213,8 @@ div.etableInputDiv {
div.checkboxSet {
position: relative !important;
max-height: 250px;
overflow: auto;
}
.etableInputDiv > * {

View File

@ -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';

View File

@ -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,8 +83,7 @@ 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(),
@ -111,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(),
@ -130,6 +128,7 @@ editor_blockly = function () {
MotaActionBlocks['show_s'].xmlText(),
MotaActionBlocks['hide_s'].xmlText(),
MotaActionBlocks['setBlock_s'].xmlText(),
MotaActionBlocks['turnBlock_s'].xmlText(),
MotaActionBlocks['move_s'].xmlText(),
MotaActionBlocks['jump_s'].xmlText(),
MotaActionBlocks['showBgFgMap_s'].xmlText(),
@ -145,13 +144,12 @@ editor_blockly = function () {
{"action": [{"type": "comment", "text": "当判别值是值的场合执行此事件"}]},
{"case": "default", "action": [{"type": "comment", "text": "当没有符合的值的场合执行default事件"}]},
]}),
MotaActionFunctions.actionParser.parseList({"type": "for", "name": "switch:A", "from": "0", "to": "12", "step": "1", "data": []}),
MotaActionFunctions.actionParser.parseList({"type": "forEach", "name": "switch:A", "list": ["status:atk","status:def"], "data": []}),
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(),
@ -222,6 +220,7 @@ editor_blockly = function () {
]),
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(),
@ -243,30 +242,30 @@ editor_blockly = function () {
}),
'<label text="商店购买属性/钥匙"></label>',
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": "setValue", "name": "status:money", "operator": "-=", "value": "9+flag:shop_times"},
{"type": "setValue", "name": "item:yellowKey", "operator": "+=", "value": "1"},
],
"false": [
"\\t[老人,man]你的金钱不足!",
{"type": "revisit"}
]
}
]},
{"text": "蓝钥匙(\\\${18+2*flag:shop_times}金币)", "color": [0,0,255,1], "action": [
]},
{"text": "离开", "action": [
{"type": "exit"}
]}
]
},
{"type": "setValue", "name": "flag:shop_times", "operator": "+=", "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'),
'<label text="战前剧情"></label>',
MotaActionFunctions.actionParser.parse({
"trigger": "action",
@ -674,7 +673,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;
@ -728,7 +727,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',
}
@ -751,12 +750,12 @@ function omitedcheckUpdateFunction(event) {
'hide_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'
@ -828,14 +827,15 @@ function omitedcheckUpdateFunction(event) {
var selectPointBlocks = {
"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"],
"changeFloor_s": ["Number_0", "Number_1", "IdString_0", true],
"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"],
"show_s": ["EvalString_0", "EvalString_1", "IdString_0"],
"hide_s": ["EvalString_0", "EvalString_1", "IdString_0"],
"setBlock_s": ["EvalString_1", "EvalString_2", "IdString_0"],
"turnBlock_s": ["EvalString_1", "EvalString_2", "IdString_0"],
"move_s": ["PosString_0", "PosString_1"],
"jump_s": ["PosString_2", "PosString_3"], // 跳跃暂时只考虑终点
"showBgFgMap_s": ["EvalString_0", "EvalString_1", "IdString_0"],
@ -876,16 +876,18 @@ function omitedcheckUpdateFunction(event) {
block.setFieldValue(xv+"", arr[0]);
block.setFieldValue(yv+"", arr[1]);
}
if (block.type == 'changeFloor_m') {
if (block.type == 'changeFloor_m' || block.type == 'changeFloor_s') {
block.setFieldValue("floorId", "Floor_List_0");
block.setFieldValue("loc", "Stair_List_0");
}
});
}
editor_blockly.getAutoCompletions = function (content) {
editor_blockly.getAutoCompletions = function (content, type, name) {
// --- content为当前框中输入内容将返回一个列表为后续所有可补全内容
// console.log(type, name);
// 检查 status:xxxitem:xxx和flag:xxx
var index = Math.max(content.lastIndexOf(":"), content.lastIndexOf(""));
if (index >= 0) {
@ -977,6 +979,114 @@ 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 allFloorIds = core.floorIds;
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);
}
// 对楼层名进行补全
if ((type == 'setFloor_s' || type == 'show_s' || type == 'hide_s' || type == 'insert_2_s'
|| type == 'setBlock_s' || type == 'turnBlock_s' || type == 'showFloorImg_s' || type == 'hideFloorImg_s'
|| type == 'showBgFgMap_s' || type == 'hideBgFgMap_s' || type == 'setBgFgBlock_s'
|| type == 'openDoor_s' || type == 'changeFloor_m') && name == "IdString_0") {
return filter(allFloorIds, 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 [];
}
@ -1079,11 +1189,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;
@ -1124,7 +1236,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)) {
@ -1133,13 +1245,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 -

View File

@ -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;
}
@ -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);
}
/**

View File

@ -18,7 +18,7 @@ editor_mode = function (editor) {
this._ids = {}
this.dom = {}
this.actionList = [];
this.mode = '';
this.mode = 'tower'; // 初始默认显示全塔属性
this.info = {};
this.appendPic = {};
this.doubleClickMode = 'change';
@ -176,6 +176,7 @@ editor_mode = function (editor) {
printe(err);
throw Error(err);
}
var notExist = null;
thiseval.map(function (v) {
var name = v.indexOf('.') < 0 ? (v+'.png') : v;
if (data.indexOf(name) < 0) notExist = name;

View File

@ -43,7 +43,7 @@ editor_table_wrapper = function (editor) {
return /* html */`<div class='checkboxSet'>${content.join('')}</div>\n`;
}
editor_table.prototype.checkboxSetMember = function (value,key,prefixString) {
return /* html */`${prefixString}<input key='${key}' type='checkbox' class='checkboxSetMember' onchange='editor.table.checkboxSetMemberOnchange(this)' ${(value ? 'checked ' : '')}/>\n`;
return /* html */`${prefixString}<input key='${key}' ctype='${typeof key}' type='checkbox' class='checkboxSetMember' onchange='editor.table.checkboxSetMemberOnchange(this)' ${(value ? 'checked ' : '')}/>\n`;
}
editor_table.prototype.editGrid = function (showComment, showEdit) {
var list = [];
@ -79,7 +79,11 @@ editor_table_wrapper = function (editor) {
var value=[]
for (var i in inputs) {
if (inputs[i].nodeName == 'INPUT') {
if (inputs[i].checked) value.push(inputs[i].getAttribute('key'));
if (inputs[i].checked) {
var one = inputs[i].getAttribute('key');
if (inputs[i].getAttribute('ctype') == 'number') one = parseFloat(one);
value.push(one);
}
}
}
thiseval = value;
@ -188,6 +192,7 @@ editor_table_wrapper = function (editor) {
// 当cobj的参数为函数时,代入args算出值
for (var key in cobj) {
if (key === '_data') continue;
if (key === '_transform' || key == '_onconfirm') cobj[key] = cobj[key].toString();
if (cobj[key] instanceof Function) cobj[key] = cobj[key](args);
}
pvobj[ii] = vobj = args.vobj;
@ -344,31 +349,6 @@ editor_table_wrapper = function (editor) {
}
}
/**
* cannotOut / cannotIn的表格值变化时
*/
editor_table.prototype.onCannotInOutChange = function (guid, obj, commentObj, thisTr, inputs, field, cobj, modeNode) {
editor_mode.onmode(editor_mode._ids[modeNode.getAttribute('id')]);
var value = [];
var directions = ['up', 'down', 'left', 'right'];
var index = 0;
for (var i in inputs) {
if (inputs[i].nodeName == 'INPUT') {
if (inputs[i].checked) value.push(directions[index]);
index++;
}
}
if (value.length == 0) thiseval = null;
else thiseval = value;
if (editor.table.checkRange(cobj, thiseval)) {
editor_mode.addAction(['change', field, thiseval]);
editor_mode.onmode('save');//自动保存 删掉此行的话点保存按钮才会保存
} else {
printe(field + ' : 输入的值不合要求,请鼠标放置在注释上查看说明');
}
}
/**
* "显示完整注释"被按下时
*/
@ -384,8 +364,10 @@ editor_table_wrapper = function (editor) {
var tr = button.parentNode.parentNode;
var guid = tr.getAttribute('id');
var cobj = JSON.parse(tr.children[1].getAttribute('cobj'));
var input = tr.children[2].children[0].children[0];
if (cobj._type === 'event') editor_blockly.import(guid, { type: cobj._event });
if (cobj._type === 'textarea') editor_multi.import(guid, { lint: cobj._lint, string: cobj._string });
if (cobj._type === 'material') editor.table.selectMaterial(input, cobj);
}
/**
@ -399,6 +381,7 @@ editor_table_wrapper = function (editor) {
if (editor_mode.doubleClickMode === 'change') {
if (cobj._type === 'event') editor_blockly.import(guid, { type: cobj._event });
if (cobj._type === 'textarea') editor_multi.import(guid, { lint: cobj._lint, string: cobj._string });
if (cobj._type === 'material') editor.table.selectMaterial(input, cobj);
} else if (editor_mode.doubleClickMode === 'add') {
editor_mode.doubleClickMode = 'change';
editor.table.addfunc(guid, obj, commentObj, thisTr, input, field, cobj, modeNode)
@ -408,6 +391,17 @@ editor_table_wrapper = function (editor) {
}
}
editor_table.prototype.selectMaterial = function (input, cobj) {
editor.uievent.selectMaterial(input.value, cobj._docs || cobj._data || '请选择素材', cobj._directory, function (one) {
if (!/^[-A-Za-z0-9_.]+$/.test(one)) return null;
if (cobj._transform) return eval("("+cobj._transform+")(one)");
return one;
}, function (data) {
input.value = JSON.stringify(cobj._onconfirm ? eval("("+cobj._onconfirm+")(JSON.parse(input.value), data)") : data);
input.onchange();
})
}
/**
* 删除表格项
*/

View File

@ -468,16 +468,7 @@ editor_ui_wrapper = function (editor) {
uievent.elements.canvas = document.getElementById('uievent');
uievent.elements.usedFlags = document.getElementById('uieventUsedFlags');
uievent.elements.usedFlagList = document.getElementById('uieventUsedFlagList');
uievent.confirm = function () {
var callback = uievent.values.callback, floorId = uievent.values.floorId,
x = uievent.values.x, y = uievent.values.y;
uievent.close();
if (callback) {
callback(floorId, x, y);
}
}
uievent.elements.yes.onclick = uievent.confirm;
uievent.elements.materialList = document.getElementById('uieventMaterialList');
uievent.close = function () {
uievent.isOpen = false;
@ -534,7 +525,6 @@ editor_ui_wrapper = function (editor) {
uievent.selectPoint = function (floorId, x, y, hideFloor, callback) {
uievent.values.hideFloor = hideFloor;
uievent.values.callback = callback;
uievent.values.size = editor.isMobile ? window.innerWidth / core.__SIZE__ : 32;
uievent.elements.selectPointBox.style.width = (uievent.values.size - 6) + "px";
uievent.elements.selectPointBox.style.height = (uievent.values.size - 6) + "px";
@ -545,12 +535,20 @@ 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';
uievent.elements.usedFlagList.style.display = 'none';
uievent.elements.body.style.overflow = "hidden";
uievent.elements.yes.onclick = function () {
var floorId = uievent.values.floorId, x = uievent.values.x, y = uievent.values.y;
uievent.close();
if (callback) {
callback(floorId, x, y);
}
}
// Append children
var floors = "";
@ -646,7 +644,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)
@ -743,6 +742,60 @@ editor_ui_wrapper = function (editor) {
return list;
}
// ------ 素材选择框 ------ //
uievent.selectMaterial = function (value, title, directory, transform, callback) {
fs.readdir(directory, function (err, data) {
if (err) {
printe(directory + '不存在!');
throw (directory + '不存在!');
}
if (!(data instanceof Array)) {
printe('没有可显示的内容')
return;
}
value = value || [];
data = (transform ? data.map(transform) : data).filter(function (one) {return one;}).sort();
uievent.isOpen = true;
uievent.elements.div.style.display = 'block';
uievent.mode = 'selectMaterial';
uievent.elements.selectPoint.style.display = 'none';
uievent.elements.yes.style.display = 'block';
uievent.elements.title.innerText = title;
uievent.elements.selectBackground.style.display = 'none';
uievent.elements.selectFloor.style.display = 'none';
uievent.elements.selectPointBox.style.display = 'none';
uievent.elements.canvas.style.display = 'none';
uievent.elements.usedFlags.style.display = 'none';
uievent.elements.usedFlagList.style.display = 'none';
uievent.elements.materialList.style.display = 'block';
uievent.elements.body.style.overflow = "auto";
uievent.elements.yes.onclick = function () {
var list = Array.from(document.getElementsByClassName('materialCheckbox')).filter(function (one) {
return one.checked;
}).map(function (one) {return one.getAttribute('key'); });
uievent.close();
if (callback) callback(list);
}
// 显示每一项内容
var html = "<p style='margin-left: 10px; line-height: 25px'>";
html += "<button onclick='editor.uievent._selectAll(true)'>全选</button><button style='margin-left: 10px' onclick='editor.uievent._selectAll(false)'>全不选</button><br/>";
data.forEach(function (one) {
html += `<input type="checkbox" key="${one}" class="materialCheckbox" ${value.indexOf(one) >= 0? 'checked' : ''} /> ${one}<br/>`;
});
html += "</p>";
uievent.elements.materialList.innerHTML = html;
});
}
uievent._selectAll = function (checked) {
Array.from(document.getElementsByClassName('materialCheckbox')).forEach(function (one) {
one.checked = checked;
})
}
editor.constructor.prototype.uievent=uievent;
}

View File

@ -162,10 +162,22 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = {
},
"special": {
"_leaf": true,
"_type": "textarea",
"_range": "thiseval==null || thiseval instanceof Array || (thiseval==~~thiseval && thiseval>=0)",
"_docs": "特殊属性",
"_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?'<br>':'')+name+'')
}
return {
"prefix":c,
"key":b
}
},
"_data": "特殊属性"
},
"value": {
"_leaf": true,
@ -228,7 +240,7 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = {
}
}
},
"enemys_template": { 'name': '新敌人', 'hp': 0, 'atk': 0, 'def': 0, 'money': 0, 'exp': 0, 'point': 0, 'special': 0 },
"enemys_template": { 'name': '新敌人', 'hp': 0, 'atk': 0, 'def': 0, 'money': 0, 'exp': 0, 'point': 0, 'special': [] },
// --------------------------- 【图块属性】相关的表格配置 --------------------------- //
@ -266,9 +278,8 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = {
"values": [
"null",
"openDoor",
"passNet",
"changeLight",
"pushBox",
"ski",
"custom"
]
},

View File

@ -19,36 +19,75 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = {
},
"images": {
"_leaf": true,
"_type": "textarea",
"_type": "material",
"_range": "editor.mode.checkImages(thiseval)",
"_directory": "./project/images/",
"_transform": function (one) {
if (one.endsWith('.png') || one.endsWith('.jpg') || one.endsWith('.jpeg') || end.endsWith('.gif'))
return one;
return null;
},
"_docs": "本塔使用图片",
"_data": "在此存放所有可能使用的图片tilesets除外 \n图片可以被作为背景图的一部分也可以直接用自定义事件进行显示。 \n 图片名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好 \n 建议对于较大的图片,在网上使用在线的“图片压缩工具(http://compresspng.com/zh/)”来进行压缩,以节省流量 \n 依次向后添加"
"_data": "在此存放所有可能使用的图片tilesets除外 \n图片可以被作为背景图的一部分也可以直接用自定义事件进行显示。 \n 图片名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好 \n 建议对于较大的图片,在网上使用在线的“图片压缩工具(http://compresspng.com/zh/)”来进行压缩,以节省流量 \n 依次向后添加",
},
"tilesets": {
"_leaf": true,
"_type": "textarea",
"_type": "material",
"_range": "editor.mode.checkImages(thiseval)",
"_directory": "./project/images/",
"_transform": function (one) {
if (one.endsWith('.png'))
return one;
return null;
},
"_onconfirm": function (previous, current) {
// 额外素材是有序的,因此根据之前的内容进行排序,然后在之后追加新的
previous = previous || [];
return current.sort(function (a, b) {
var i = previous.indexOf(a);
var j = previous.indexOf(b);
if (i >= 0 && j >= 0) return i - j;
return j >= 0 ? 1 : -1;
});
},
"_docs": "本塔额外素材",
"_data": "在此存放额外素材的图片名, \n可以自定导入任意张素材图片无需PS无需注册即可直接在游戏中使用 \n 形式如[\"1.png\", \"2.png\"] ,将需要的素材图片放在images目录下 \n 素材的宽高必须都是32的倍数且图片上的总图块数不超过1000即最多有1000个32*32的图块在该图片上"
},
"animates": {
"_leaf": true,
"_type": "textarea",
"_type": "material",
"_range": "editor.mode.checkUnique(thiseval)",
"_directory": "./project/animates/",
"_transform": function (one) {
if (one.endsWith(".animate")) return one.substring(0, one.lastIndexOf('.'));
return null;
},
"_docs": "本塔使用动画",
"_data": "在此存放所有可能使用的动画必须是animate格式在这里不写后缀名 \n动画必须放在animates目录下文件名不能使用中文不能带空格或特殊字符 \n \"jianji\", \"thunder\" 根据需求自行添加"
},
"bgms": {
"_leaf": true,
"_type": "textarea",
"_type": "material",
"_range": "editor.mode.checkUnique(thiseval)",
"_directory": "./project/sounds/",
"_transform": function (one) {
if (one.endsWith('.mp3') || one.endsWith('.wmv') || one.endsWith('.ogg') || end.endsWith('.wav'))
return one;
return null;
},
"_docs": "本塔使用音乐",
"_data": "在此存放所有的bgm和文件名一致。 \n音频名不能使用中文不能带空格或特殊字符可以直接改名拼音就好"
},
"sounds": {
"_leaf": true,
"_type": "textarea",
"_type": "material",
"_range": "editor.mode.checkUnique(thiseval)",
"_directory": "./project/sounds/",
"_transform": function (one) {
if (one.endsWith('.mp3') || one.endsWith('.wmv') || one.endsWith('.ogg') || end.endsWith('.wav'))
return one;
return null;
},
"_docs": "本塔使用音效",
"_data": "在此存放所有的SE和文件名一致 \n音频名不能使用中文不能带空格或特殊字符可以直接改名拼音就好"
},
@ -529,29 +568,6 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = {
"_docs": "楼传平面模式",
"_data": "传送器平面塔模式;此模式下楼层传送器将飞到上次离开该楼层的位置。"
},
"pickaxeFourDirections": {
"_leaf": true,
"_type": "checkbox",
"_docs": "四向破墙镐",
"_data": "使用破墙镐是否四个方向都破坏如果false则只破坏面前的墙壁"
},
"bombFourDirections": {
"_leaf": true,
"_type": "checkbox",
"_docs": "四向炸弹",
"_data": "使用炸弹是否四个方向都会炸如果false则只炸面前的怪物即和圣锤等价"
},
"snowFourDirections": {
"_leaf": true,
"_type": "checkbox",
"_docs": "四向破冰稿",
"_data": "使用冰冻徽章是否四个方向都会消除熔岩如果false则只消除面前的熔岩"
},
"bigKeyIsBox": {
"_leaf": true,
"_type": "checkbox",
"_data": "如果此项为true则视为钥匙盒红黄蓝钥匙+1若为false则视为大黄门钥匙"
},
"steelDoorWithoutKey": {
"_leaf": true,
"_type": "checkbox",
@ -564,12 +580,6 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = {
"_docs": "首次道具提示",
"_data": "首次获得道具是否提示"
},
"equipment": {
"_leaf": true,
"_type": "checkbox",
"_docs": "剑盾装备",
"_data": "剑和盾是否作为装备。如果此项为true则作为装备需要在装备栏使用否则将直接加属性。"
},
"equipboxButton": {
"_leaf": true,
"_type": "checkbox",
@ -667,12 +677,6 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = {
"_docs": "允许瞬移",
"_data": "是否允许瞬间移动"
},
"enableDisabledShop": {
"_leaf": true,
"_type": "checkbox",
"_docs": "商店预览",
"_data": "是否允许查看未开启状态的快捷商店内容;如果此项为真,则对于未开启状态的商店允许查看其内容(但不能购买)"
},
"disableShopOnDamage": {
"_leaf": true,
"_type": "checkbox",

View File

@ -70,29 +70,11 @@ var functions_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = {
"_lint": true,
"_data": "道具后脚本"
},
"afterChangeLight": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "改变亮灯后"
},
"afterPushBox": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "推箱子后"
},
"afterPassNet": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "特殊地形后"
},
"canUseQuickShop": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "能否快捷商店"
}
}
},

View File

@ -14,13 +14,19 @@ 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": "灯光效果"
},
"drawItemShop": {
"itemShop": {
"_leaf": true,
"_type": "textarea",
"_range": "typeof(thiseval)=='string' || thiseval==null",

View File

@ -565,6 +565,7 @@
<canvas class='gameCanvas' id='uievent' width='416' height='416'></canvas>
<div id="selectPointBox"></div>
<div id="uieventUsedFlagList" style="display: none"></div>
<div id="uieventMaterialList" style="display: none"></div>
</div>
<div id="selectPoint">
<select id="selectPointFloor"></select>

View File

@ -546,7 +546,8 @@
<div id='uieventBody'>
<canvas class='gameCanvas' id='uievent' width='416' height='416'></canvas>
<div id="selectPointBox"></div>
<div id="uieventUsedFlagList" style="display: none"></div>
<div id="uieventUsedFlagList" style="display: none; margin-top: -10px"></div>
<div id="uieventMaterialList" style="display: none; margin-top: -10px"></div>
</div>
<div id="selectPoint">
<select id="selectPointFloor"></select>

View File

@ -260,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':
@ -346,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;
@ -476,7 +470,6 @@ actions.prototype._sys_onmove_choices = function (x, y) {
switch (core.status.event.id) {
case 'action':
if (core.status.event.data.type != 'choices') break;
case 'shop':
case 'selectShop':
case 'switchs':
case 'settings':
@ -488,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;
}
@ -614,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;
@ -792,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) {
@ -886,7 +875,7 @@ actions.prototype._clickCenterFly = function (x, y) {
core.useItem('centerFly');
}
else {
core.drawTip('当前不能使用中心对称飞行器');
core.drawTip('当前不能使用' + core.material.items['centerFly'].name);
}
}
}
@ -898,7 +887,7 @@ actions.prototype._keyUpCenterFly = function (keycode) {
core.useItem('centerFly');
}
else {
core.drawTip('当前不能使用中心对称飞行器');
core.drawTip('当前不能使用' + core.material.items['centerFly'].name);
}
}
}
@ -939,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') {
@ -1280,61 +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) {
core.events.openShop(keys[y - topIndex], true);
if (core.status.event.id == 'shop')
core.status.event.data.fromList = true;
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;
}
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;
}
@ -1347,10 +1319,7 @@ 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;
}

View File

@ -656,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);
}
@ -745,7 +744,7 @@ control.prototype.waitHeroToStop = function(callback) {
core.setHeroLoc('direction', lastDirection);
core.drawHero();
callback();
}, 30);
}, core.status.replay.speed == 24 ? 0 : 30);
}
}
@ -757,8 +756,7 @@ control.prototype.turnHero = function(direction) {
core.status.route.push("turn:"+direction);
return;
}
var dirs = {'up':'right','right':'down','down':'left','left':'up'};
core.setHeroLoc('direction', dirs[core.getHeroLoc('direction')]);
core.setHeroLoc('direction', core.turnDirection(':right'));
core.drawHero();
core.status.route.push("turn");
}
@ -991,7 +989,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;
@ -1000,6 +999,8 @@ control.prototype.checkBlock = function () {
core.updateStatusBar();
core.events.lose();
return;
} else {
core.updateStatusBar();
}
}
this._checkBlock_snipe(core.status.checkBlock.snipe[loc]);
@ -1009,9 +1010,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);
});
}
}
@ -1020,7 +1021,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);
@ -1032,12 +1033,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);
}
@ -1265,7 +1268,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')
@ -1430,7 +1433,7 @@ 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;
}
@ -1463,7 +1466,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;
}
@ -1483,6 +1486,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);
@ -1496,6 +1503,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);
@ -1505,36 +1517,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;
}
@ -1542,14 +1531,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;
}
@ -1566,6 +1555,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 () {
@ -1578,7 +1572,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;
}

View File

@ -239,6 +239,10 @@ core.prototype._init_flags = function () {
core.values = core.clone(core.data.values);
core.firstData = core.clone(core.data.firstData);
this._init_sys_flags();
// 让你总是拼错!
window.on = true;
window.off = false;
core.dom.versionLabel.innerText = core.firstData.version;
core.dom.logoLabel.innerText = core.firstData.title;
@ -277,7 +281,6 @@ 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();
}

View File

@ -86,7 +86,7 @@ enemys.prototype.getSpecialHint = function (enemy, special) {
var hints = [];
for (var i = 0; i < specials.length; i++) {
if (this.hasSpecial(enemy, specials[i][0]))
hints.push(this._calSpecialContent(enemy, specials[i][1]) + "" + this._calSpecialContent(enemy, specials[i][2]));
hints.push("\r[#FF6A6A]\\d"+this._calSpecialContent(enemy, specials[i][1]) + "\\d\r[]" + this._calSpecialContent(enemy, specials[i][2]));
}
return hints;
}
@ -94,7 +94,7 @@ enemys.prototype.getSpecialHint = function (enemy, special) {
if (specials == null) return "";
for (var i = 0; i < specials.length; i++) {
if (special == specials[i][0])
return this._calSpecialContent(enemy, specials[i][1]) + "" + this._calSpecialContent(enemy, specials[i][2]);
return "\r[#FF6A6A]\\d"+this._calSpecialContent(enemy, specials[i][1]) + "\\d\r[]" + this._calSpecialContent(enemy, specials[i][2]);
}
return "";
}

View File

@ -317,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);
@ -402,7 +402,16 @@ events.prototype.openDoor = function (x, y, needKey, callback) {
});
return;
}
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) {
@ -477,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);
@ -510,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);
}
////// 获得面前的物品(轻按) //////
@ -545,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;
}
@ -593,6 +599,8 @@ events.prototype._changeFloor_getInfo = function (floorId, stair, heroLoc, time)
var index = core.floorIds.indexOf(core.status.floorId);
if (index < core.floorIds.length - 1) floorId = core.floorIds[index + 1];
else floorId = core.status.floorId;
} else if (floorId == ':now') {
floorId = core.status.floorId;
}
if (!core.status.maps[floorId]) {
main.log("不存在的楼层:" + floorId);
@ -702,33 +710,6 @@ events.prototype.visitFloor = function (floorId) {
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();
@ -743,7 +724,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;
@ -753,8 +742,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);
}
@ -780,27 +767,22 @@ 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;
// 检查是否需要改变朝向
if (ex == core.nextX() && ey == core.nextY()) {
var dir = core.reverseDirection();
var dir = core.turnDirection(":back");
var id = data.event.id, toId = (data.event.faceIds || {})[dir];
if (toId && id != toId) {
var number = core.getNumberById(toId);
@ -1269,14 +1251,12 @@ events.prototype._action_show = function (data, x, y, prefix) {
events.prototype._action_hide = function (data, x, y, prefix) {
data.loc = this.__action_getLoc2D(data.loc, x, y, prefix);
if (data.time > 0 && data.floorId == core.status.floorId) {
data.loc.forEach(function (t) {
core.hideBlock(t[0], t[1], data.floorId);
});
this.__action_doAsyncFunc(data.async, core.animateBlock, data.loc, 'hide', data.time);
this.__action_doAsyncFunc(data.async, core.animateBlock, data.loc, data.remove ? 'remove' : 'hide', data.time);
}
else {
data.loc.forEach(function (t) {
core.removeBlock(t[0], t[1], data.floorId)
if (data.remove) core.removeBlock(t[0], t[1], data.floorId);
else core.hideBlock(t[0], t[1], data.floorId);
});
core.doAction();
}
@ -1290,6 +1270,14 @@ events.prototype._action_setBlock = function (data, x, y, prefix) {
core.doAction();
}
events.prototype._action_turnBlock = function (data, x, y, prefix) {
data.loc = this.__action_getLoc2D(data.loc, x, y, prefix);
data.loc.forEach(function (t) {
core.turnBlock(data.number, t[0], t[1], data.floorId);
});
core.doAction();
}
events.prototype._action_showFloorImg = function (data, x, y, prefix) {
core.maps.showFloorImage(this.__action_getLoc2D(data.loc, x, y, prefix), data.floorId, core.doAction);
}
@ -1383,7 +1371,7 @@ 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.setHeroLoc('direction', core.turnDirection(data.direction), true);
core.drawHero();
return core.doAction();
}
@ -1391,7 +1379,7 @@ events.prototype._action_changePos = function (data, x, y, prefix) {
var loc = this.__action_getHeroLoc(data.loc, prefix);
core.setHeroLoc('x', loc[0]);
core.setHeroLoc('y', loc[1]);
if (data.direction) core.setHeroLoc('direction', data.direction);
if (data.direction) core.setHeroLoc('direction', core.turnDirection(data.direction));
core.drawHero();
core.doAction();
}
@ -1502,16 +1490,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();
}
@ -1820,9 +1805,9 @@ events.prototype._precompile_confirm = function (data) {
}
events.prototype._action_for = function (data, x, y, prefix) {
// Only support switch:A
if (!/^switch:[A-Z]$/.test(data.name)) {
core.insertAction(['循环遍历事件只支持独立开关!']);
// Only support temp:A
if (!/^temp:[A-Z]$/.test(data.name)) {
core.insertAction('循环遍历事件只支持临时变量!');
return core.doAction();
}
var from = core.calValue(data.from);
@ -1830,22 +1815,22 @@ events.prototype._action_for = function (data, x, y, prefix) {
core.insertAction('循环遍历事件要求【起始点】仅能是数字!');
return core.doAction();
}
this._setValue_setSwitch(data.name, from, prefix);
var toName = '__for@to@' + prefix + '@' + data.name.substring(7) + '__';
var stepName = '__for@step@' + prefix + '@' + data.name.substring(7) + '__';
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 clearAndReturn = function (v) { if (!v) { core.removeFlag('"+toName+"'); core.removeFlag('"+stepName+"'); } return v; };"+
"var to = core.calValue(core.getFlag('" + toName + "'));"+
"var step = core.calValue(core.getFlag('" + stepName + "'));"+
"if (typeof step != 'number' || typeof to != 'number') return clearAndReturn(false);"+
"if (step == 0) return clearAndReturn(true);"+
"var currentValue = core.calValue('switch:'+'" + data.name.substring(7) + "', '"+prefix+"');"+
"if (typeof step != 'number' || typeof to != 'number') return false;"+
"if (step == 0) return true;"+
"var currentValue = core.getFlag('@temp@" + letter + "');"+
"currentValue += step;"+
"core.events._setValue_setSwitch('switch:'+'" + data.name.substring(7) + "', currentValue, '"+prefix+"');"+
"if (step > 0) { return clearAndReturn(currentValue <= to); }"+
"else { return clearAndReturn(currentValue >= to); }"+
"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);
}
@ -1859,17 +1844,17 @@ events.prototype._precompile_for = function (data) {
}
events.prototype._action_forEach = function (data, x, y, prefix) {
// Only support switch:A
if (!/^switch:[A-Z]$/.test(data.name)) {
core.insertAction(['循环遍历事件只支持独立开关']);
// Only support temp:A
if (!/^temp:[A-Z]$/.test(data.name)) {
core.insertAction(['循环遍历事件只支持临时变量']);
return core.doAction();
}
var listName = '__forEach@' + prefix + '@' + data.name.substring(7) + '__';
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) { core.removeFlag('" + listName + "'); return false; }"+
"core.events._setValue_setSwitch('switch:'+'" + data.name.substring(7) + "', list.shift(), '"+prefix+"');"+
"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);
@ -1949,7 +1934,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();
}
@ -2086,13 +2071,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();
@ -2296,14 +2274,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;
@ -2343,8 +2321,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;
core.events.openShop(shopId, true);
if (core.status.event.id != null) return;
if (!core.canOpenShop(shopId)) {
core.drawTip("当前无法打开快捷商店!");
return;
}
var message = core.canUseQuickShop(shopId);
if (message != null) {
core.drawTip(message);
return;
}
core.openShop(shopId, false);
return;
}
@ -2452,6 +2439,7 @@ events.prototype.setValue = function (name, operator, value, prefix) {
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);
}
@ -2477,6 +2465,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);
@ -2487,16 +2480,6 @@ events.prototype.addValue = function (name, value, prefix) {
this.setValue(name, '+=', value, prefix);
}
////// 执行一个表达式的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);
});
}
////// 设置一个怪物属性 //////
events.prototype.setEnemy = function (id, name, value, prefix) {
if (!core.hasFlag('enemyInfo')) {
@ -2864,87 +2847,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);
var reason = core.events.canUseQuickShop(shop.id);
if (reason != null) return core.drawTip(reason);
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) {
if (!shop.visited) {
core.drawTip(shop.times ? "该商店已失效" : "该商店尚未开启");
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);

View File

@ -27,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;

View File

@ -26,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;
@ -81,6 +52,7 @@ items.prototype.getItemEffect = function (itemId, itemNum) {
main.log(e);
}
}
core.updateStatusBar();
}
else {
core.addItem(itemId, itemNum);

View File

@ -516,7 +516,7 @@ maps.prototype._canMoveHero_checkCannotInOut = function (number, name, direction
}
return false;
}
if (name == 'cannotIn') direction = core.reverseDirection(direction);
if (name == 'cannotIn') direction = core.turnDirection(":back", direction);
return core.inArray((this.getBlockByNumber(number).event || {})[name], direction);
}
@ -596,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];
@ -1464,19 +1464,35 @@ maps.prototype.hideBlock = function (x, y, floorId) {
core.clearMap('event2', x * 32, y * 32 + 32 - height, 32, height - 32);
}
block.block.disable = true;
core.hideBlockByIndex(block.index, floorId);
core.updateStatusBar();
}
////// 将某个块从启用变成禁用状态 //////
maps.prototype.removeBlock = function (x, y, floorId) {
////// 根据图块的索引来隐藏图块 //////
maps.prototype.hideBlockByIndex = function (index, floorId) {
floorId = floorId || core.status.floorId;
if (!floorId) return;
var block = core.getBlock(x, y, floorId, true);
if (block == null) return; // 不存在
var blocks = core.status.maps[floorId].blocks, block = blocks[index];
block.disable = true;
}
var index = block.index;
////// 一次性隐藏多个block //////
maps.prototype.hideBlockByIndexes = function (indexes, floorId) {
indexes.sort(function (a, b) {
return b - a;
}).forEach(function (index) {
core.hideBlockByIndex(index, floorId);
});
}
////// 删除某个图块 //////
maps.prototype.removeBlock = function (x, y, floorId) {
floorId = floorId || core.status.floorId;
if (!floorId) return false;
var block = core.getBlock(x, y, floorId, true);
if (block == null) return false; // 不存在
// 删除动画,清除地图
if (floorId == core.status.floorId) {
@ -1487,9 +1503,9 @@ maps.prototype.removeBlock = function (x, y, floorId) {
core.clearMap('event2', x * 32, y * 32 + 32 - height, 32, height - 32);
}
// 删除Index
core.removeBlockByIndex(index, floorId);
core.removeBlockByIndex(block.index, floorId);
core.updateStatusBar();
return true;
}
////// 根据block的索引尽可能删除该块 //////
@ -1498,13 +1514,7 @@ maps.prototype.removeBlockByIndex = function (index, floorId) {
if (!floorId) return;
var blocks = core.status.maps[floorId].blocks, block = blocks[index];
if (this.canRemoveBlock(block, floorId)) { // 能否彻底删除该图块
blocks.splice(index, 1);
}
else {
block.disable = true;
}
blocks.splice(index, 1);
}
////// 一次性删除多个block //////
@ -1516,19 +1526,6 @@ maps.prototype.removeBlockByIndexes = function (indexes, floorId) {
});
}
////// 能否彻底从地图中删除一个图块 //////
maps.prototype.canRemoveBlock = function (block, floorId) {
var x = block.x, y = block.y;
// 检查该点是否存在事件
if (core.floors[floorId].events[x + "," + y] || core.floors[floorId].changeFloor[x + "," + y])
return false;
// 检查是否存在重生
if (block.event && block.event.cls.indexOf('enemy') == 0 && core.hasSpecial(block.event.id, 23))
return false;
return true;
}
////// 显示前景/背景地图 //////
maps.prototype.showBgFgMap = function (name, loc, floorId, callback) {
this._triggerBgFgMap('show', name, loc, floorId, callback);
@ -1611,7 +1608,7 @@ maps.prototype.setBlock = function (number, x, y, floorId) {
var block = this.initBlock(x, y, number, true, core.floors[floorId]);
if (block.id == 0 && !block.event.trigger) {
// 转变图块为0且该点无事件视为隐藏
// 转变图块为0且该点无事件视为删除
core.removeBlock(x, y, floorId);
return;
}
@ -1641,6 +1638,26 @@ maps.prototype.setBlock = function (number, x, y, floorId) {
}
}
////// 事件转向 //////
maps.prototype.turnBlock = function (direction, x, y, floorId) {
var id = core.getBlockId(x, y, floorId, true);
var blockInfo = core.getBlockInfo(id);
if (blockInfo == null) return;
var faceIds = blockInfo.faceIds || {};
var currDirection = null;
for (var dir in core.utils.scan) {
if (faceIds[dir] == id) {
currDirection = dir;
}
}
if (currDirection == null) return;
var nextDirection = core.turnDirection(direction, currDirection);
var nextId = faceIds[nextDirection];
if (nextId != null && nextId != id) {
this.setBlock(nextId, x, y, floorId);
}
}
////// 将地图中所有某个图块替换成另一个图块 //////
maps.prototype.replaceBlock = function (fromNumber, toNumber, floorId) {
floorId = floorId || core.status.floorId;
@ -1778,6 +1795,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) {
@ -1939,24 +1957,24 @@ maps.prototype._moveJumpBlock_finished = function (blockInfo, canvases, info, an
////// 显示/隐藏某个块时的动画效果 //////
maps.prototype.animateBlock = function (loc, type, time, callback) {
var isHide = type == 'hide';
if (core.status.replay.speed == 24) time = 1;
if (typeof loc[0] == 'number' && typeof loc[1] == 'number')
loc = [loc];
// --- 检测所有是0的点
var list = this._animateBlock_getList(loc);
var list = this._animateBlock_getList(loc, type);
if (list.length == 0) {
if (callback) callback();
return;
}
this._animateBlock_drawList(list, isHide ? 1 : 0);
this._animateBlock_drawList(list, type != 'show' ? 1 : 0);
time /= Math.max(core.status.replay.speed, 1)
this._animateBlock_doAnimate(loc, list, isHide, 10 / time, callback);
this._animateBlock_doAnimate(loc, list, type, 10 / time, callback);
}
maps.prototype._animateBlock_doAnimate = function (loc, list, isHide, delta, callback) {
var opacity = isHide ? 1 : 0;
maps.prototype._animateBlock_doAnimate = function (loc, list, type, delta, callback) {
var opacity = type != 'show' ? 1 : 0;
var animate = setInterval(function () {
opacity += isHide ? -delta : delta;
opacity += type != 'show' ? -delta : delta;
core.maps._animateBlock_drawList(list, opacity);
if (opacity >= 1 || opacity <= 0) {
delete core.animateFrame.asyncId[animate];
@ -1966,8 +1984,9 @@ maps.prototype._animateBlock_doAnimate = function (loc, list, isHide, delta, cal
core.maps._deleteDetachedBlock(t.canvases);
});
loc.forEach(function (t) {
if (isHide) core.removeBlock(t[0], t[1]);
else core.showBlock(t[0], t[1]);
if (type == 'show') core.showBlock(t[0], t[1]);
else if (type == 'hide') core.hideBlock(t[0], t[1]);
else if (type == 'remove') core.removeBlock(t[0], t[1]);
});
if (callback) callback();
}
@ -1976,7 +1995,7 @@ maps.prototype._animateBlock_doAnimate = function (loc, list, isHide, delta, cal
core.animateFrame.asyncId[animate] = true;
}
maps.prototype._animateBlock_getList = function (loc) {
maps.prototype._animateBlock_getList = function (loc, type) {
var list = [];
loc.forEach(function (t) {
var block = core.getBlock(t[0], t[1], null, true);
@ -1988,6 +2007,16 @@ maps.prototype._animateBlock_getList = function (loc) {
list.push({ 'x': t[0], 'y': t[1] });
return;
}
// 该点是否已经被启用/删除
if ((type == 'show' && !block.disable) || ((type == 'hide' || type == 'remove') && block.disable)) {
list.push({ 'x': t[0], 'y': t[1] });
return;
}
if (type == 'hide' || type == 'remove') {
core.hideBlock(t[0], t[1]); // 暂时先隐藏
}
var canvases = core.maps._initDetachedBlock(blockInfo, t[0], t[1], block.event.displayDamage !== false);
list.push({

View File

@ -360,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;
}
}
}
}
}
}
@ -443,6 +476,14 @@ ui.prototype._uievent_drawIcon = function (data) {
////// 结束一切事件和绘制关闭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);
@ -652,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;
@ -1546,11 +1595,9 @@ ui.prototype.drawSettings = function () {
////// 绘制快捷商店选择栏 //////
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);
@ -1828,8 +1875,8 @@ ui.prototype.drawBookDetail = function (index) {
var left = 10, width = this.PIXEL - 2 * left, right = left + width;
var content_left = left + 25, validWidth = right - content_left - 13;
var contents = core.splitLines("data", content, validWidth, this._buildFont(16, false));
var height = Math.max(24 * contents.length + 55, 80), top = (this.PIXEL - height) / 2, bottom = top + height;
var height = Math.max(this.getTextContentHeight(content, {fontSize: 16, lineHeight: 24, maxWidth: validWidth}) + 58, 80),
top = (this.PIXEL - height) / 2, bottom = top + height;
core.setAlpha('data', 0.9);
core.fillRect('data', left, top, width, height, '#000000');
@ -1837,7 +1884,7 @@ ui.prototype.drawBookDetail = function (index) {
core.strokeRect('data', left - 1, top - 1, width + 1, height + 1,
core.status.globalAttribute.borderColor, 2);
this._drawBookDetail_drawContent(enemy, contents, {top: top, content_left: content_left, bottom: bottom});
this._drawBookDetail_drawContent(enemy, content, {top: top, content_left: content_left, bottom: bottom, validWidth: validWidth});
}
ui.prototype._drawBookDetail_getInfo = function (index) {
@ -1870,7 +1917,7 @@ ui.prototype._drawBookDetail_mofang = function (enemy, texts) {
var hp = enemy.hp;
var delta = core.status.hero.atk - core.status.hero.def;
if (delta<hp && hp<=10000 && hp>0) {
texts.push("模仿临界计算器:(当前攻防差"+core.formatBigNumber(delta)+"");
texts.push("\r[#FF6A6A]\\d模仿临界计算器:\\d\r[](当前攻防差"+core.formatBigNumber(delta)+"");
var u = [];
this._drawBookDetail_mofang_getArray(hp).forEach(function (t) {
if (u.length < 20) u.push(t);
@ -1921,7 +1968,7 @@ ui.prototype._drawBookDetail_vampire = function (enemy, texts) {
}
core.status.hero.hp = start;
if (core.canBattle(enemy.id)) {
texts.push("打死该怪物最低需要生命值:"+core.formatBigNumber(start));
texts.push("\r[#FF6A6A]\\d打死该怪物最低需要生命值:\\d\r[]"+core.formatBigNumber(start));
}
core.status.hero.hp = nowHp;
}
@ -1930,19 +1977,19 @@ ui.prototype._drawBookDetail_vampire = function (enemy, texts) {
ui.prototype._drawBookDetail_hatred = function (enemy, texts) {
if (core.enemys.hasSpecial(enemy.special, 17)) {
texts.push("当前仇恨伤害值:"+core.getFlag('hatred', 0));
texts.push("\r[#FF6A6A]\\d当前仇恨伤害值:\\d\r[]"+core.getFlag('hatred', 0));
}
}
ui.prototype._drawBookDetail_turnAndCriticals = function (enemy, floorId, texts) {
var damageInfo = core.getDamageInfo(enemy, null, null, null, floorId);
texts.push("战斗回合数:"+((damageInfo||{}).turn||0));
texts.push("\r[#FF6A6A]\\d战斗回合数:\\d\r[]"+((damageInfo||{}).turn||0));
// 临界表
var criticals = core.enemys.nextCriticals(enemy, 8, null, null, floorId).map(function (v) {
return core.formatBigNumber(v[0])+":"+core.formatBigNumber(v[1]);
});
while (criticals[0]=='0:0') criticals.shift();
texts.push("临界表:"+JSON.stringify(criticals));
texts.push("\r[#FF6A6A]\\d临界表:\\d\r[]"+JSON.stringify(criticals));
var prevInfo = core.getDamageInfo(enemy, {atk: core.status.hero.atk-1}, null, null, floorId);
if (prevInfo != null && damageInfo != null) {
if (damageInfo.damage != null) damageInfo = damageInfo.damage;
@ -1953,26 +2000,14 @@ ui.prototype._drawBookDetail_turnAndCriticals = function (enemy, floorId, texts)
}
}
ui.prototype._drawBookDetail_drawContent = function (enemy, contents, pos) {
ui.prototype._drawBookDetail_drawContent = function (enemy, content, pos) {
// 名称
core.setTextAlign('data', 'left');
core.fillText('data', enemy.name, pos.content_left, pos.top + 30, '#FFD700', this._buildFont(22, true));
var content_top = pos.top + 57;
var content_top = pos.top + 44;
for (var i=0;i<contents.length;i++) {
var text=contents[i];
var index=text.indexOf("");
if (index>=0) {
var x1 = text.substring(0, index+1);
core.fillText('data', x1, pos.content_left, content_top, '#FF6A6A', this._buildFont(16, true));
var len=core.calWidth('data', x1);
core.fillText('data', text.substring(index+1), pos.content_left+len, content_top, '#FFFFFF', this._buildFont(16, false));
}
else {
core.fillText('data', contents[i], pos.content_left, content_top, '#FFFFFF', this._buildFont(16, false));
}
content_top+=24;
}
this.drawTextContent('data', content, {left: pos.content_left, top: content_top, maxWidth: pos.validWidth,
fontSize: 16, lineHeight: 24});
}
////// 绘制楼层传送器 //////
@ -2028,37 +2063,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, null, need, times);
var use = shop.use=='exp'?'经验':'金币';
var choices = [];
for (var i=0;i<shop.choices.length;i++) {
var choice = shop.choices[i];
var text = core.replaceText(choice.text, null, need, times);
if (choice.need != null)
text += ""+core.calValue(choice.need, null, null, times)+use+"";
choices.push({"text": text, "color":shop.visited?null:"#999999"});
}
choices.push("离开");
core.ui.drawChoices(content, choices);
}
////// 绘制浏览地图界面 //////
ui.prototype.drawMaps = function (index, x, y) {
core.lockControl();
@ -2114,7 +2122,7 @@ ui.prototype._drawMaps_drawHint = function () {
core.fillText('ui', "后张地图 [▼ / PGDN]", this.HPIXEL, this.PIXEL - (32 * per + 48));
core.fillText('ui', "退出 [ESC / ENTER]", this.HPIXEL, this.HPIXEL);
core.fillText('ui', "[X] 可查看怪物手册", this.HPIXEL + 77, this.HPIXEL + 32, null, '13px Arial');
core.fillText('ui', "[X] 可查看" + core.material.items['book'].name, this.HPIXEL + 77, this.HPIXEL + 32, null, '13px Arial');
core.setTextBaseline('ui', 'alphabetic');
}
@ -2780,13 +2788,14 @@ 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)+"点,护盾"
@ -2794,11 +2803,6 @@ ui.prototype._drawStatistics_generateText = function (obj, type, data) {
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();
@ -2818,7 +2822,7 @@ ui.prototype.drawHelp = function () {
core.drawText([
"\t[键盘快捷键列表]"+
"[CTRL] 跳过对话 [Z] 转向\n" +
"[X] 怪物手册 [G] 楼层传送\n" +
"[X] "+core.material.items['book'].name + " [G] "+core.material.items['fly'].name+"\n" +
"[A] 读取自动存档 [W] 撤销读取自动存档\n" +
"[S/D] 存读档页面 [SPACE] 轻按\n" +
"[V] 快捷商店 [ESC] 系统菜单\n" +

View File

@ -62,10 +62,10 @@ utils.prototype._init = function () {
}
////// 将文字中的${和}(表达式)进行替换 //////
utils.prototype.replaceText = function (text, prefix, 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, prefix, need, times);
return core.calValue(value, prefix);
});
}
@ -82,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) {
@ -594,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");
@ -689,9 +691,19 @@ utils.prototype.strlen = function (str) {
return count;
};
utils.prototype.reverseDirection = function (direction) {
utils.prototype.turnDirection = function (turn, direction) {
direction = direction || core.getHeroLoc('direction');
return {"left":"right","right":"left","down":"up","up":"down"}[direction] || direction;
var directionList = ["left", "up", "right", "down"];
if (directionList.indexOf(turn) >= 0) return turn;
switch (turn) {
case ':left': turn = 3; break; // turn left
case ':right': turn = 1; break; // turn right
case ':back': turn = 2; break; // turn back
default: turn = 0; break;
}
var index = directionList.indexOf(direction);
if (index < 0) return direction;
return directionList[(index + (turn || 0)) % 4];
}
utils.prototype.matchWildcard = function (pattern, string) {

View File

@ -597,7 +597,7 @@ main.statusBar.image.keyboard.onclick = function (e) {
main.core.openKeyBoard(true);
}
////// 点击状态栏中的快捷商店键盘时 //////
////// 点击状态栏中的快捷商店时 //////
main.statusBar.image.shop.onclick = function (e) {
e.stopPropagation();
@ -610,7 +610,7 @@ main.statusBar.image.shop.onclick = function (e) {
main.core.openQuickShop(true);
}
////// 点击金币时也可以开启虚拟键盘 //////
////// 点击金币时也可以开启快捷商店 //////
main.statusBar.image.money.onclick = function (e) {
e.stopPropagation();

View File

@ -299,37 +299,100 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
],
"shops": [
{
"id": "moneyShop1",
"name": "贪婪之神",
"icon": "blueShop",
"id": "shop1",
"text": "\t[贪婪之神,blueShop]勇敢的武士啊, 给我${20+2*flag:shop1}金币就可以:",
"textInList": "1F金币商店",
"commonTimes": false,
"mustEnable": false,
"use": "money",
"need": "20+10*times*(times+1)",
"text": "勇敢的武士啊,给我${need}金币就可以:",
"disablePreview": false,
"choices": [
{
"text": "生命+800",
"effect": "status:hp+=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": "expShop1",
"name": "经验之神",
"icon": "pinkShop",
"id": "shop2",
"text": "\t[贪婪之神,pinkShop]勇敢的武士啊, 给我一定经验就可以:",
"textInList": "1F经验商店",
"commonTimes": false,
"mustEnable": false,
"use": "exp",
"need": "-1",
"text": "勇敢的武士啊,给我若干经验就可以:",
"disablePreview": true,
"choices": [
{
"text": "等级+1",
"need": "100",
"effect": "status:hp+=1000"
"text": "等级+1100经验",
"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"
}
]
}
]
},
@ -342,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": "回收钥匙商店"
@ -423,13 +487,8 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
],
"flyNearStair": true,
"flyRecordPosition": false,
"pickaxeFourDirections": false,
"bombFourDirections": false,
"snowFourDirections": false,
"bigKeyIsBox": false,
"steelDoorWithoutKey": false,
"itemFirstText": false,
"equipment": false,
"equipboxButton": false,
"enableAddPoint": false,
"enableNegativeDamage": false,
@ -446,7 +505,6 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
"ignoreChangeFloor": true,
"canGoDeadZone": false,
"enableMoveDirectly": true,
"enableDisabledShop": true,
"disableShopOnDamage": false,
"blurFg": false
}

View File

@ -1,67 +1,67 @@
var enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80 =
var enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80 =
{
"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":0},
"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":0},
"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":0},
"skeleton": {"name":"骷髅人","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
"skeletonSoilder": {"name":"骷髅士兵","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
"skeletonCaptain": {"name":"骷髅队长","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
"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":0},
"zombieKnight": {"name":"兽人武士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
"rock": {"name":"石头人","hp":100,"atk":120,"def":0,"money":4,"exp":0,"point":0,"special":3},
"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":0},
"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":0},
"blueGuard": {"name":"中级卫兵","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
"redGuard": {"name":"高级卫兵","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
"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":0},
"yellowKnight": {"name":"金骑士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
"redKnight": {"name":"红骑士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
"darkKnight": {"name":"黑骑士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
"blackKing": {"name":"黑衣魔王","hp":1000,"atk":500,"def":0,"money":1000,"exp":1000,"point":0,"special":0,"notBomb":true},
"yellowKing": {"name":"黄衣魔王","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
"greenKing": {"name":"青衣武士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
"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":0},
"poisonSkeleton": {"name":"紫骷髅","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
"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":0},
"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":0},
"skeletonWizard": {"name":"骷髅巫师","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
"redSkeletonCaption": {"name":"骷髅武士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
"badHero": {"name":"迷失勇者","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
"demon": {"name":"魔神武士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
"demonPriest": {"name":"魔神法师","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
"goldHornSlime": {"name":"金角怪","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
"redKing": {"name":"红衣魔王","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
"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":0},
"whiteHornSlime": {"name":"尖角怪","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
"badPrincess": {"name":"痛苦魔女","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
"badFairy": {"name":"黑暗仙子","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
"grayPriest": {"name":"中级法师","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
"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":0},
"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":0},
"octopus": {"name":"血影","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
"darkFairy": {"name":"仙子","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
"greenKnight": {"name":"强盾骑士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
"angel": {"name":"天使","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
"elemental": {"name":"元素生物","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":0},
"steelGuard": {"name":"铁守卫","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":18,"value":20},
"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,23],"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]}
}

View File

@ -163,7 +163,7 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
},
{
"type": "if",
"condition": "core.getBgNumber() == 167",
"condition": "core.onSki()",
"true": [
{
"type": "if",
@ -244,7 +244,7 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"回收钥匙商店": [
{
"type": "comment",
"text": "此事件在全局商店中被引用了(全局商店keyShop1)"
"text": "此事件在全局商店中被引用了(全局商店keyShop)"
},
{
"type": "comment",

View File

@ -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": {}
}

View File

@ -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, toolsequips。\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, toolsequips。\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": {}
}

File diff suppressed because it is too large Load Diff

View File

@ -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": {}
}

File diff suppressed because it is too large Load Diff

View File

@ -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 || {})
@ -112,6 +111,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
// 重置画布尺寸
core.maps.resizeMap(floorId);
// 设置勇士的位置
heroLoc.direction = core.turnDirection(heroLoc.direction);
core.status.hero.loc = heroLoc;
// 检查重生怪并重置
if (!fromLoad) {
@ -273,7 +273,12 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
// 删除该块
var guards = []; // 支援
if (x != null && y != null) {
core.removeBlock(x, y);
// 检查是否是重生怪物;如果是则仅隐藏不删除
if (core.hasSpecial(enemy.special, 23)) {
core.hideBlock(x, y);
} else {
core.removeBlock(x, y);
}
guards = core.getFlag("__guards__" + x + "_" + y, []);
core.removeFlag("__guards__" + x + "_" + y);
}
@ -381,6 +386,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);
@ -393,21 +399,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获得的道具IDx和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 () {
// 推箱子后的事件
@ -422,25 +429,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
*/
}
},
"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 () {
@ -453,7 +441,7 @@ 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 + "倍作为伤害"],
@ -834,22 +822,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('当前不能使用炸弹');
}
core.status.route.push("key:50"); // 将按键记在录像中
core.useItem('bomb', true); // 第二个参数true代表该次使用道具是被按键触发的使用过程不计入录像
}
break;
case 51: // 快捷键3: 飞
@ -943,17 +923,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()
};
// 设置商店次数
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;
},
@ -963,13 +935,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);
@ -1103,10 +1068,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;
}
// 领域
@ -1128,7 +1095,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;
}
}
}
@ -1142,9 +1110,10 @@ 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);
var rdir = core.turnDirection(":back", dir);
// 检查下一个点是否存在事件(从而判定是否移动)
var rnx = x + core.utils.scan[rdir].x,
rny = y + core.utils.scan[rdir].y;
@ -1163,14 +1132,16 @@ 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;
}
}
}
@ -1230,7 +1201,8 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
}
if (value > 0) {
damage[loc] = (damage[loc] || 0) + value;
type[loc] = "夹击伤害";
type[loc] = type[loc] || {};
type[loc]["夹击伤害"] = true;
}
}
}
@ -1269,9 +1241,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();
},

View File

@ -370,11 +370,11 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
"book": "core.ui.drawBook(0);",
"fly": "core.ui.drawFly(core.floorIds.indexOf(core.status.floorId));",
"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\tcore.playSound('pickaxe.mp3');\n\tif (core.flags.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}\n\t\t}\n\t} else {\n\t\t// 仅破当前\n\t\tcore.removeBlock(core.nextX(), core.nextY());\n\t}\n\tcore.drawTip(core.material.items[itemId].name + '使用成功');\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\tif (core.flags.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}\n\t\t}\n\t} else {\n\t\tcore.removeBlock(core.nextX(), core.nextY());\n\t}\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\tcore.playSound('bomb.mp3');\n\tvar bombList = []; // 炸掉的怪物坐标列表\n\tif (core.flags.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\tcore.removeBlock(core.nextX(), core.nextY());\n\t\tbombList.push([core.nextX(), core.nextY()]);\n\t}\n\n\tcore.drawTip(core.material.items[itemId].name + '使用成功');\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})();",
"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})();",
@ -397,14 +397,14 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
"canUseItemEffect": {
"book": "true",
"fly": "(function () {\n\treturn core.status.maps[core.status.floorId].canFlyTo;\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\tif (core.flags.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\tif (canBreak(core.getHeroLoc('x') + delta.x, core.getHeroLoc('y') + delta.y)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t} else {\n\t\t// 仅破当前\n\t\treturn canBreak(core.nextX(), core.nextY());\n\t}\n})();",
"pickaxe": "true",
"icePickaxe": "(function () {\n\treturn core.getBlockId(core.nextX(), core.nextY()) == 'ice';\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\tif (core.flags.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\tif (canBomb(core.getHeroLoc('x') + delta.x, core.getHeroLoc('y') + delta.y)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t} else {\n\t\t// 仅炸当前\n\t\treturn canBomb(core.nextX(), core.nextY());\n\t}\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": "(function () {\n\tif (core.flags.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\tif (core.getBlockId(core.getHeroLoc('x') + delta.x, core.getHeroLoc('y') + delta.y) == 'lava') {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t} else {\n\t\treturn core.getBlockId(core.nextX(), core.nextY()) == 'lava';\n\t}\n})();",
"snow": "true",
"bigKey": "(function () {\n\treturn core.searchBlock('yellowDoor').length > 0;\n})();",
"poisonWine": "core.hasFlag('poison');",
"weakWine": "core.hasFlag('weak');",

View File

@ -3,17 +3,17 @@ var maps_90f36752_8815_4be8_b32b_d7fad1d0542e =
"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"},
"5": {"cls":"animates","id":"lava"},
"4": {"cls":"animates","id":"star","name":"星空"},
"5": {"cls":"animates","id":"lava","name":"岩浆"},
"6": {"cls":"terrains","id":"ice"},
"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":"passNet"},
"12": {"cls":"animates","id":"poisonNet","canPass":true,"trigger":"passNet"},
"13": {"cls":"animates","id":"weakNet","canPass":true,"trigger":"passNet"},
"14": {"cls":"animates","id":"curseNet","canPass":true,"trigger":"passNet"},
"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"},
@ -68,12 +68,12 @@ var maps_90f36752_8815_4be8_b32b_d7fad1d0542e =
"71": {"cls":"items","id":"shield0"},
"72": {"cls":"items","id":"skill1"},
"73": {"cls":"items","id":"wand"},
"81": {"cls":"animates","id":"yellowDoor","trigger":"openDoor","animate":1,"doorInfo":[{"yellowKey":1},"door.mp3","door.mp3"]},
"82": {"cls":"animates","id":"blueDoor","trigger":"openDoor","animate":1,"doorInfo":[{"blueKey":1},"door.mp3","door.mp3"]},
"83": {"cls":"animates","id":"redDoor","trigger":"openDoor","animate":1,"doorInfo":[{"redKey":1},"door.mp3","door.mp3"]},
"84": {"cls":"animates","id":"greenDoor","trigger":"openDoor","animate":1,"doorInfo":[{"greenKey":1},"door.mp3","door.mp3"]},
"85": {"cls":"animates","id":"specialDoor","trigger":"openDoor","animate":1,"doorInfo":[null,"door.mp3","door.mp3"]},
"86": {"cls":"animates","id":"steelDoor","trigger":"openDoor","animate":1,"doorInfo":[{"steelKey":1},"door.mp3","door.mp3"]},
"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},
@ -109,7 +109,7 @@ var maps_90f36752_8815_4be8_b32b_d7fad1d0542e =
"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":"changeLight","canPass":true},
"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},

View File

@ -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要打开的商店idnoRoute是否不计入录像
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);
@ -143,9 +280,8 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
}
// 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);
@ -369,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",
@ -378,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 () {

View File

@ -295,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 {

View File

@ -3,7 +3,7 @@
(已完成!) 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()来避免把单词打断和触犯标点禁则,如点号和右标号禁止用于行首,左标号禁止用于行尾
(已完成!) 5. 建议优化core.splitLines()来避免把单词打断和触犯标点禁则,如点号和右标号禁止用于行首,左标号禁止用于行尾
(已完成!) 6. core.drawAnimate()和对应的事件建议增加一个boolean型参数来表示坐标是绝对坐标即当前的实现还是在视野中的相对坐标以13*13为例相对坐标总是在0~12之间以实现形如“在视野正中心播放某某动画”的需求小地图可以写6,6大地图怎么办
(已完成!) 7. 建议把core.playBgm(bgm, startTime)的startTime参数在事件中也提供出来以用于一些演出比如适当的剧情处直接从高潮开始。同理可以让“暂停背景音乐”记录下当前播放到了第几秒并在“恢复背景音乐”中自动从这个秒数恢复。作者还可以手动配合音量渐变效果
(已完成!) 8. 系统设置菜单中“音量”和“步时”的点击区并不是根据文本长度自动适配的,这导致作者修改文本(包括但不限于翻译)后玩家难以找到准确的点击区,建议优化
@ -12,14 +12,16 @@
(已完成!) 11. 建议修复勇士后退时跟随者的鬼畜行为并推出一套能够对跟随者位置和朝向进行读写的API甚至事件且允许这些信息被计入存档以实现一些演出效果甚至游戏要素如新新2用公主占位防冰块
(已完成!) 12. “设置怪物属性”事件的下拉框目前只支持一部分另一部分只能通过手敲json再解析来得到希望提供完整支持
13. 建议给core.moveAction(callback)提供对应的事件,用于在事件中让勇士像事件外一样移动,从而正常触发跑毒和阻激夹域捕等
14. core.openShop()和对应的事件,建议在用于公共事件时简单地退化为“插入公共事件”而不要打断当前事件,把决定权交给作者
(已完成!) 14. core.openShop()和对应的事件,建议在用于公共事件时简单地退化为“插入公共事件”而不要打断当前事件,把决定权交给作者
(已完成!) 15. “等待用户操作”虽然提供了场合块但还不支持将多个按键的场合合并比如空格、回车和C键一般会被作者予以合并执行内容如果只是大致相同也值得合并在块内由作者根据flag再行分歧建议支持一下
(已完成!) 16. “绘制描边文本”事件建议加一个“描边颜色”参数,目前只能描黑边
(已完成!) 17. “设置画布属性”的基准线建议增加'hanging'和'ideographic'这两种模式
(已完成!) 18. 建议修复“绘制多行文本”时行距比字号大不太多会导致各行下缘丢失的bug加大行距又会导致第一行的纵坐标难以估计此bug在道具商店和1.3倍行距英文看的很明显
19.(来自群友)建议给第一代全局商店的子选项像“显示选择项”一样提供图标、颜色和出现条件(注意长按的适配)
(已完成!) 19.(来自群友)建议给第一代全局商店的子选项像“显示选择项”一样提供图标、颜色和出现条件(注意长按的适配)
(已完成!) 20. 很多事件对应的脚本有默认参数但在事件中省略参数却会变成0建议修复
-------------
(已完成!) defaultGround全局可用
(已完成!) 对floorIds和图片进行检测
(已完成!) 删除绘图模式
@ -27,18 +29,28 @@
(已完成!) cannotIn / cannotOut使用选项框
(已完成!) noPass->canPass改成选择框
初始化&读档优化:不一次读取全部楼层并创建
绿钥匙进状态栏
(已完成!) 绿钥匙进状态栏
(已完成!) 图块ID不可全数字
怪物详细信息富文本化
(已完成!) 怪物详细信息富文本化
(已完成!) for和forEach事件
转向:顺时针/逆时针/反向
事件转向
(已完成!) 转向:顺时针/逆时针/反向
(已完成!) 事件转向
(已完成!) 修复core.removeBlock隐藏和删除问题
(已完成!) 合并数值操作事件
(已完成!) fromLoad聚集问题
(已完成!) 注释优化
状态栏显示项的优化
动画/音乐/音效自动补全
(已完成!) 状态栏显示项的优化
(已完成!) 动画/音乐/音效自动补全
(已完成!) 重构全局商店!
(已完成!) 读档时色调数据丢失
圆角边框
像素高分辨率问题
(已完成!) 道具效果优化,删除部分道具相关的开关
(已完成!) 素材列表选择
油漆桶,动态更改地图大小
地图拉框选择复制剪切删除
-------------
(不处理) 0. 部分文案的修改,如“地图编辑器”(启动服务.exe中、“enemys”、“snipe”
(造塔工具相关都给鹿神) 1. 便捷PS工具希望加入自定义单位宽高功能希望把“白底转透明”增强为“纯色底转透明”弹窗由作者输入RGB或RGBA值
@ -55,7 +67,7 @@
(不处理) 12. 来自鹿神和君浪坚固属性建议按照描述来去修改turn或hero_per_damage而不是mon_defrmxp魔塔的坚固属性是通过一个全局量去指定hero_per_damage的默认为1以免和模仿或者说仿防冲突
(不处理) 13. 破甲、反击、净化倍率、仇恨增量和是否减半,建议允许使用怪物的属性去覆盖全塔属性中的值,如不同的破甲怪破甲倍率不同
(已完成!) 14. (来自小艾)仇恨伤害和固伤合并进总伤害以免和负伤抵消
不处理) 15. 单点阻激夹域和血网伤害同时存在多种时,气泡提示的伤害类型存在覆盖现象,建议优化
已完成!) 15. 单点阻激夹域和血网伤害同时存在多种时,气泡提示的伤害类型存在覆盖现象,建议优化
(已完成!) 16. 来自小艾建议修复瞬移判定无视图快属性script项的bug
(已完成!) 17. 建议修复如果还没修复core.drawTip()不能使用系统图标和clear参数的bug并建议增加一个参数来表示多帧图块使用第几帧UI绘制事件中的绘制图标同理增加另一个参数来表示32*48图块绘制上2/3当前实现和手册一致还是下2/3
(不处理) 18. 来自群友推箱子、阻击、捕捉、重生、炸锤和afterXxx事件的系列问题...
@ -64,8 +76,8 @@
(不处理) 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取余毕竟用转变图块的话不够通用
已完成! 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建议改为允许作者指定
@ -83,7 +95,7 @@
(已修复!) 38.2 移除圣锤道具的定义
(不处理) 39. 建议把样板自带的大部分tools类道具的useItemEffect用useItemEvent重写以方便作者参照学习我能说266都几个月了好多新作者和老作者压根不知道useItemEvent的存在吗
(已修复!) 40. 希望显示文章的\b提供top和bottom这两种新写法来实现在顶部或底部显示对话框目前只有firstArrive和eachArrive等没有当前点的事件中才能用up和down来临时实现这种效果否则就得设置剧情文本的属性这在频繁来回切换时是致命的就像《无上之光》RMXP版地上40层一样
41. 建议优化core.splitLines()来避免出现标点禁则(如点号和右标号不能用于行首,左标号不能用于行尾),同时也能更好地支持字母文字语言如英语(日语韩语等同样是方块字的倒不要紧)
(已完成!) 41. 建议优化core.splitLines()来避免出现标点禁则(如点号和右标号不能用于行首,左标号不能用于行尾),同时也能更好地支持字母文字语言如英语(日语韩语等同样是方块字的倒不要紧)
(已修复!) 42. core.drawAnimate()和对应的事件指令建议增加一个参数来表示坐标是绝对坐标即当前的实现还是在视野中的相对坐标以13*13为例相对坐标总是在0~12之间毕竟有些动画按相对坐标绘制才是作者的演出需求。
(不处理) 43. 来自鹿神希望给animate文件支持多音效、画面闪烁和图块闪烁
(已修复!) 44. 希望给“播放背景音乐”事件像core.playBgm()函数一样添加“从第几秒开始”的参数,以用于一些演出(比如适当的剧情处直接从高潮开始)。同理可以让“暂停背景音乐”记录下当前播放到了第几秒,并在“恢复背景音乐”中自动从这个秒数恢复。作者还可以手动配合音量渐变效果
@ -95,18 +107,18 @@
(不处理) 50. 建议给录像播放时的N键提供一个对应的移动端操作以方便移动端作者
(已完成!) 51. 希望给“显示选择项”、“显示确认框”、“等待用户操作”这三个事件添加一个“若多少毫秒内不响应则触发的分支”用来实现一些QTE录像中可以记录“choice: timeout”、“confirm: timeout”和“wait: timeout”来表示触发了超时分支
52. 希望给“转变图块”加一个淡入时间参数显隐和转变图层块也希望加个淡入淡出时间参数图层块也希望提供移动和跳跃事件专门用于原本是空地或空气墙的情况。目前要实现这样的效果必须使用红点然而红点有着“推箱子、阻击、捕捉、重生、炸锤和afterXxx事件”的系列问题且会导致core.removeBlock()隐藏事件退化为core.hideBlock()
53. 希望“移动事件”的移速和淡出速度拆开成两个参数,目前这样捆绑在一起不太自由
不处理 54. 建议把图块属性的noPass改为勾选框而不是下拉框因为null一定表示不可通行道具根本没有noPass
(不处理) 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. 在事件编辑器中进行地图选点时,有些事件指令虽然只能用于同楼层,但实际生效时勇士可能已经不在当前正在编辑的楼层(比如在一个楼层切换事件指令后)了,所以希望地图选点始终提供楼层下拉表
(已完成!) 61. 在事件编辑器中进行地图选点时,有些事件指令虽然只能用于同楼层,但实际生效时勇士可能已经不在当前正在编辑的楼层(比如在一个楼层切换事件指令后)了,所以希望地图选点始终提供楼层下拉表
(文档相关给秋橙) 62. 希望在线文档介绍一下楼层和startText的独立开关的flag表示
63. 希望给core.moveAction(callback)函数提供一个对应的事件指令用于在事件流处理中让勇士进行一些有游戏性意义即非纯演出的移动。如果做不到的话希望参照本文的46号issue作为原生脚本勾选async的例子讲解如何使用
64. “打开全局商店”事件指令建议在用于公共事件版商店时简单地退化为“插入公共事件”而不要打断当前事件流,由作者在这个公共事件结尾去决定“立刻结束当前事件”还是不结束
(已完成!) 64. “打开全局商店”事件指令建议在用于公共事件版商店时简单地退化为“插入公共事件”而不要打断当前事件流,由作者在这个公共事件结尾去决定“立刻结束当前事件”还是不结束
(已修复!) 65. “显隐贴图”的参数应为像素坐标而不是网格坐标,请修正在线文档的描述。同时建议加个淡入淡出时间参数,还建议贴图能像图片一样有透明度和被移动
(不处理) 66. 读档建议换个和floor.mp3不一样的音效
(不处理) 67. “画面震动”事件希望不要光左右晃至少做成QQ窗口抖动的效果吧w
@ -118,7 +130,7 @@
73. 画弧既然有现成的API那建议也作为UI绘制事件提供。甚至希望提供画椭圆功能长短轴水平或铅直的那种参数为中心坐标和长短轴长度
(已完成!) 74. “设置画布属性”的基准线建议增加'hanging'和'ideographic'这两种模式
(已完成!) 75. 建议修复“绘制多行文本”时行距比字号大不太多会导致各行下缘丢失的bug加大行距又会导致第一行的纵坐标难以估计此bug在道具商店和1.3倍行距英文看的很明显
76. (来自群友)建议给第一代全局商店像“显示选择项”一样提供图标、颜色和出现条件
(已完成!) 76. (来自群友)建议给第一代全局商店像“显示选择项”一样提供图标、颜色和出现条件
(已完成!增加正则匹配) 77. 建议给core.searchBlock()新增问号通配符(匹配一个任意字符)
(已完成!) 78. 建议移除core.setInitData()并将其内容写在startText以方便作者仿照修改
(不处理;有跟随情况下处理很麻烦) 79. 建议给core.drawHero()添加纵横两个偏移参数(目前只有一个),以用于做一些斜向移动的演出