Merge pull request #324 from ckcz123/v2.0

V2.0
This commit is contained in:
Zhang Chen 2019-03-12 00:53:34 +08:00 committed by GitHub
commit aac13e4998
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 2275 additions and 4390 deletions

View File

@ -10,7 +10,7 @@ HTML5 canvas制作的魔塔样板支持全平台游戏
* [Docs / 使用文档说明](https://ckcz123.github.io/mota-js/)
* [Video / 视频教程](https://www.bilibili.com/video/av32781473/)
![样板](./docs/img/sample0.png)
![样板](./_docs/img/sample0.png)
## 目录结构

View File

@ -1,367 +0,0 @@
# 附录:API列表
?> 目前版本**v2.3.3**,上次更新时间:* {docsify-updated} *
所有系统支持的API都列在了这里。所有可能被用到的API都在前面用\*标记。
可以在chrome浏览器的控制台中`ctrl+shift+I`找到Console中直接进行调用以查看效果。
!> **`main.js`游戏入口所有其他JS文件都是被此文件加载。**
``` js
main.init // 初始化
main.loaderJs // 动态加载所有核心JS文件
main,loaderFloors // 动态加载所有楼层(剧本)
main.loadMod // 加载某一个JS文件
main.loadFloor // 加载某一个楼层
main.setMainTipsText // 加载过程提示
window.onresize // 窗口大小变化时
main.dom.body.onkeydown // 在界面上按下某按键时
main.dom.body.onkeydown // 在界面上放开某按键时
main.dom.body.onselectstart // 开始选择时
main.dom.data.onmousedown // 鼠标按下时
main.dom.data.onmousemove // 鼠标移动时
main.dom.data.onmouseup // 鼠标放开时
main.dom.data.onmousewheel // 鼠标滑轮滚动时
main.dom.data.ontouchstart // 手指在触摸屏开始触摸时
main.dom.data.ontouchmove // 手指在触摸屏上移动时
main.dom.data.ontouchend // 手指离开触摸屏时
main.statusBar.image.book.onclick // 点击状态栏中的怪物手册时
main.statusBar.image.fly.onclick // 点击状态栏中的楼层传送器时
main.statusBar.image.toolbox.onclick // 点击状态栏中的工具箱时
main.statusBar.image.keyboard.onclick // 点击状态栏中的快捷商店时
main.statusBar.image.save.onclick // 点击状态栏中的存档按钮时
main.statusBar.image.load.onclick // 点击状态栏中的读档按钮时
main.statusBar.image.settings.onclick // 点击状态栏中的系统菜单时
main.dom.playGame.onclick // 点击“开始游戏”时
main.dom.loadGame.onclick // 点击“载入游戏”时
main.dom.replayGame.onclick // 点击“录像回放”时
main.dom.easyLevel.onclick // 点击“简单难度”时
main.dom.normalLevel.onclick // 点击“普通难度”时
main.dom.hardLevel.onclick // 点击“困难难度”时
```
!> **`core.js`:系统核心文件。所有核心逻辑处理都在此文件完成。**
``` js
* core.status.floorId // 获得当前层floorId
* core.status.thisMap // 获得当前层的地图信息
* core.status.maps // 获得所有楼层的地图信息
* core.floors // 获得所有楼层的剧本
// ------ 初始化部分 ------
core.init // 初始化
core.showStartAnimate // 显示游戏开始界面
core.hideStartAnimate // 隐藏游戏开始界面
core.setStartProgressVal // 设置加载进度条进度
core.setStartLoadTipText // 设置加载进度条提示文字
core.loader // 加载图片和音频
core.loadAutotile // 加载Autotile
core.loadImage // 加载图片
core.loadMusic // 加载音频
core.isPlaying // 游戏是否已经开始
core.clearStatus // 清除游戏状态和数据
core.resetStatus // 重置游戏状态和初始数据
core.startGame // 开始游戏
* core.restart // 重新开始游戏;此函数将回到标题页面
// ------ 键盘、鼠标事件 ------
core.onKeyDown // 按下某个键时
core.onKeyUp // 放开某个键时
core.pressKey // 按住某个键时
core.keyDown // 根据按下键的code来执行一系列操作
core.keyUp // 根据放开键的code来执行一系列操作
core.ondown // 点击(触摸)事件按下时
core.onmove // 当在触摸屏上滑动时
core.onup // 当点击(触摸)事件放开时
core.getClickLoc // 获得点击事件相对左上角的坐标0到12之间
core.onclick // 具体点击屏幕上(x,y)点时,执行的操作
core.onmousewheel // 滑动鼠标滚轮时的操作
// ------ 自动寻路代码相关 ------
core.clearAutomaticRouteNode // 清除自动寻路路线
core.stopAutomaticRoute // 停止自动寻路操作
core.continueAutomaticRoute // 继续剩下的自动寻路操作
core.clearContinueAutomaticRoute // 清空剩下的自动寻路列表
core.setAutomaticRoute // 设置自动寻路路线
core.automaticRoute // 自动寻路算法,找寻最优路径
core.fillPosWithPoint // 显示离散的寻路点
core.clearStepPostfix // 清除已经寻路过的部分
// ------ 自动行走,行走控制 ------
core.stopAutoHeroMove // 停止勇士的自动行走
core.setAutoHeroMove // 设置勇士的自动行走路线
core.autoHeroMove // 让勇士开始自动行走
core.setHeroMoveInterval // 设置行走的效果动画
core.setHeroMoveTriggerInterval // 设置勇士行走过程中对事件的触发检测
core.moveAction // 实际每一步的行走过程
* core.turnHero(direction) // 设置勇士的方向(转向)
core.canMoveHero // 勇士能否前往某方向
core.moveHero // 让勇士开始移动
core.eventMoveHero // 使用事件让勇士移动。这个函数将不会触发任何事件。
core.moveOneStep // 每移动一格后执行的事件。中毒时在这里进行扣血判断。
core.waitHeroToStop(callback) // 停止勇士的一切行动等待勇士行动结束后再执行callback回调函数。
core.stopHero // 停止勇士的移动状态。
core.drawHero // 绘制勇士。
* core.setHeroLoc(name, value) // 设置勇士的位置。name为”direction”,”x”,”y”
* core.getHeroLoc(name) // 获得勇士的位置。
* core.nextX // 获得勇士面对位置的x坐标
* core.nextY // 获得勇士面对位置的y坐标
// ------ 地图和事件处理 ------
* core.openDoor(id, x, y, needKey, callback) // 打开一扇位于 (x,y) 的门
* core.battle(id, x, y, force, callback) // 进行战斗force表示是否强制战斗
core.afterBattle // 战斗完毕
core.trigger(x,y) // 触发x,y点的事件
* core.changeFloor(floorId, stair, heroLoc, time, callback) // 楼层切换。floorId为目标楼层Idstair可指定为上/下楼梯time动画时间
core.mapChangeAnimate // 地图切换动画效果
core.clearMap // 清除地图
core.fillText // 在某个canvas上绘制一段文字
core.fillRect // 在某个canvas上绘制一个矩形
core.strokeRect // 在某个canvas上绘制一个矩形的边框
core.drawLine // 在某个canvas上绘制一条线
core.setFont // 设置某个canvas的文字字体
core.setLineWidth // 设置某个canvas的线宽度
core.saveCanvas // 保存某个canvas状态
core.loadCanvas // 加载某个canvas状态
core.setStrokeStyle // 设置某个canvas边框属性
core.setAlpha // 设置某个canvas的alpha值
core.setOpacity // 设置某个canvas的透明度
core.setFillStyle // 设置某个canvas的绘制属性如颜色等
* core.drawMap(mapId, callback) // 绘制某张地图。mapId为地图Id绘制完毕将执行callback回调函数。
core.drawAutotile // 绘制Autotile
* core.noPassExists(x,y) // 某个点是否不可通行
core.noPass // 某个点是否在区域内且不可通行
* core.npcExists(x,y) // 某个点是否存在NPC
* core.terrainExists(x,y) // 某个点是否存在(指定的)地形
* core.stairExists(x,y) // 某个点是否存在楼梯
* core.nearStair // 当前位置是否在楼梯边
* core.enemyExists(x,y) // 某个点是否存在(指定的)怪物
* core.getBlock(x, y, floorId, needEnable) // 获得某个点的block。floorId指定目标楼层needEnable如果为false则即使该点的事件处于禁用状态也将被返回否则只有事件启用的点才被返回
core.moveBlock // 显示移动某块的动画,达到{“type”:”move”}的效果
core.animateBlock // 显示/隐藏某个块时的动画效果
core.showBlock // 将某个块从禁用变成启用状态
core.removeBlock // 将某个块从启用变成禁用状态
core.removeBlockById // 根据block的索引删除该块
core.removeBlockByIds // 一次性删除多个block
core.addGlobalAnimate // 添加一个全局动画
core.removeGlobalAnimate // 删除一个或所有全局动画
core.setGlobalAnimate // 设置全局动画的显示效果
core.syncGlobalAnimate // 同步所有的全局动画效果
core.drawBoxAnimate // 绘制UI层的box动画
core.updateCheckBlock // 更新领域、夹击、阻击的伤害地图
core.checkBlock // 检查并执行领域、夹击、阻击事件
core.snipe // 阻击事件(动画效果)
core.setFg // 更改画面色调
* core.updateFg // 更新全地图显伤
* core.itemCount // 获得某个物品的个数
* core.hasItem // 是否存在某个物品
* core.setItem // 设置某个物品的个数
* core.removeItem // 删除某个物品
* core.useItem // 使用某个物品直接调用items.js中的useItem函数。
* core.canUseItem // 能否使用某个物品。直接调用items.js中的canUseItem函数。
* core.addItem // 增加某个物品的个数
core.getNextItem // 获得面前的物品(轻按)
* core.getItem // 获得某个物品
* core.drawTip // 左上角绘制一段提示
* core.drawText // 地图中间绘制一段文字
// ------ 系统机制 ------
core.replaceText // 将文字中的${和}(表达式)进行替换
core.calValue // 计算表达式的值
core.doEffect // 执行一个表达式的effect操作
core.splitLines // 字符串自动换行的分割
core.unshift // 向某个数组前插入另一个数组或元素
core.setLocalStorage // 设置本地存储
core.getLocalStorage // 获得本地存储
core.removeLocalStorage // 移除本地存储
core.clone // 深拷贝一个对象
core.formatDate // 格式化时间为字符串
core.formatDate2 // 格式化时间为最简字符串
core.setTwoDigits // 两位数显示
core.debug // 进入Debug模式攻防血和钥匙都调成很高的数值
core.replay // 开始回放
core.checkStatus // 判断当前能否进入某个事件
core.openBook // 点击怪物手册时的打开操作
core.useFly // 点击楼层传送器时的打开操作
core.openToolbox // 点击工具栏时的打开操作
core.openQuickShop // 点击快捷商店时的打开操作
core.save // 点击保存按钮时的打开操作
core.load // 点击读取按钮时的打开操作
core.openSettings // 点击设置按钮时的打开操作
core.autosave // 自动存档
core.doSL // 实际进行存读档事件
core.syncSave // 存档同步操作
core.saveData // 存档到本地
core.loadData // 从本地读档
core.encodeRoute // 将路线压缩
core.decodeRoute // 将路线解压缩
* core.setStatus // 设置勇士属性
* core.getStatus // 获得勇士属性
core.getLvName // 获得某个等级的名称
* core.setFlag // 设置某个自定义变量或flag
* core.getFlag // 获得某个自定义变量或flag
* core.hasFlag // 是否存在某个自定义变量或flag且值为true
core.insertAction // 往当前事件列表之前插入一系列事件
* core.lockControl // 锁定状态栏,常常用于事件处理
* core.unlockControl // 解锁状态栏
* core.isset // 判断某对象是否不为undefined也不会null
core.readFile // 读取一个本地文件内容
core.download // 下载文件到本地
core.copy // 复制一段文字到剪切板
* core.playBgm // 播放背景音乐
* core.pauseBgm // 暂停背景音乐的播放
* core.resumeBgm // 恢复背景音乐的播放
* core.playSound // 播放音频
core.show // 动画显示某对象
core.hide // 动画使某对象消失
core.clearStatusBar // 清空状态栏
core.updateStatusBar // 更新状态栏
core.resize // 屏幕分辨率改变后重新自适应
core.domRenderer // 渲染DOM
// ------ core.js 结束 ------
```
!> **`data.js` 定义了一些初始化的数据信息。**
!> **`enemys.js` 定义了怪物信息。**
``` js
core.enemys.init // 初始化
* core.enemys.getEnemys // 获得一个或所有怪物数据
* core.enemys.hasSpecial // 判断是否含有某特殊属性
* core.enemys.getSpecialText // 获得所有特殊属性的名称
* core.enemys.getSpecialHint // 获得每个特殊属性的说明
* core.enemys.getDamage // 获得某个怪物的伤害
* core.enemys.getExtraDamage // 获得某个怪物的额外伤害
* core.enemys.getCritical // 临界值计算
* core.enemys.getCriticalDamage // 临界减伤计算
* core.enemys.getDefDamage // 1防减伤计算
* core.enemys.calDamage // 具体的伤害计算公式
core.enemys.getCurrentEnemys // 获得当前楼层的怪物列表
```
!> **`events.js` 定义了各个事件的处理流程。**
``` js
core.events.init // 初始化
core.events.getEvents // 获得一个或所有系统事件类型
core.events.startGame // 游戏开始事件
* core.events.setInitData // 不同难度分别设置初始属性
* core.events.win // 游戏获胜事件
* core.events.lose // 游戏失败事件
core.evens.gameOver // 游戏结束
core.events.afterChangeFloor // 转换楼层结束的事件
core.events.doEvents // 开始执行一系列自定义事件
core.events.doAction // 执行当前自定义事件列表中的下一个事件
core.events.insertAction // 往当前事件列表之前添加一个或多个事件
core.events.openShop // 打开一个全局商店
core.events.disableQuickShop // 禁用一个全局商店
* core.events.canUseQuickShop // 当前能否使用快捷商店
* core.events.checkLvUp // 检查升级事件
* core.events.useItem // 尝试使用道具
core.events.addPoint // 加点事件
core.events.afterBattle // 战斗结束后触发的事件
core.events.afterOpenDoor // 开一个门后触发的事件
core.events.passNet // 经过一个路障
core.events.changeLight // 改变亮灯(感叹号)的事件
* core.events.afterChangeLight // 改变亮灯之后,可以触发的事件
* core.events.afterUseBomb // 使用炸弹/圣锤后的事件
* core.events.beforeSaveData // 即将存档前可以执行的操作
* core.events.afterLoadData // 读档事件后,载入事件前,可以执行的操作
// ------ 点击事件和键盘事件的处理 ------
core.events.longClick // 长按
core.events.keyDownCtrl // 按下Ctrl键时快捷跳过对话
core.events.clickConfirmBox // 确认框界面时的点击操作
core.events.keyUpConfirmBox // 确认框界面时,放开某个键的操作
core.events.clickAction // 自定义事件时的点击操作
core.events.keyDownAction // 自定义事件时,按下某个键的操作
core.events.keyUpAction // 自定义事件时,放开某个键的操作
core.events.clickBook // 怪物手册界面的点击操作
core.events.keyDownBook // 怪物手册界面时,按下某个键的操作
core.events.keyUpBook // 怪物手册界面时,放开某个键的操作
core.events.clickBookDetail // 怪物手册属性显示界面时的点击操作
core.events.clickFly // 楼层传送器界面时的点击操作
core.events.keyDownFly // 楼层传送器界面时,按下某个键的操作
core.events.keyUpFly // 楼层传送器界面时,放开某个键的操作
core.events.clickViewMaps // 浏览地图界面时的点击操作
core.events.keyDownViewMaps // 浏览地图界面时,按下某个键的操作
core.events.keyUpViewMaps // 浏览地图界面时,放开某个键的操作
core.events.clickShop // 商店界面时的点击操作
core.events.keyDownShop // 商店界面时,按下某个键的操作
core.events.keyUpShop // 商店界面时,放开某个键的操作
core.events.clickQuickShop // 快捷商店界面时的点击操作
core.events.keyDownQuickShop // 快捷商店界面时,按下某个键的操作
core.events.keyUpQuickShop // 快捷商店界面时,放开某个键的操作
core.events.clickToolbox // 工具栏界面时的点击操作
core.events.clickToolboxIndex // 选择工具栏界面中某个Index后的操作
core.events.keyDownToolbox // 工具栏界面时,按下某个键的操作
core.events.keyUpToolbox // 工具栏界面时,放开某个键的操作
core.events.clickSL // 存读档界面时的点击操作
core.events.keyDownSL // 存读档界面时,按下某个键的操作
core.events.keyUpSL // 存读档界面时,放开某个键的操作
core.events.clickSwitchs // 系统设置界面时的点击操作
core.events.keyDownSwitchs // 系统设置界面时,按下某个键的操作
core.events.keyUpSwitchs // 系统设置界面时,放开某个键的操作
core.events.clickSettings // 系统菜单栏界面时的点击事件
core.events.keyDownSettings // 系统菜单栏界面时,按下某个键的操作
core.events.keyUpSettings // 系统菜单栏界面时,放开某个键的操作
core.events.clickSyncSave // 同步存档界面时的点击操作
core.events.keyDownSyncSave // 同步存档界面时,按下某个键的操作
core.events.keyUpSyncSave // 同步存档界面时,放开某个键的操作
core.events.clickKeyBoard // 虚拟键盘界面时的点击操作
core.events.clickAbout // “关于”界面时的点击操作
```
!> `icons.js` 定义了素材ID和它在图片上的索引的对应关系。
!> `items.js` 定义了每个道具的名称,以及使用效果。
``` js
core.items.init // 初始化
core.items.getItems // 获得所有道具
core.items.getItemEffect // “即捡即用类”道具的使用效果
core.items.getItemEffectTip // “即捡即用类”道具的文字提示
* core.items.useItem // 使用道具
* core.items.cauUseItem // 当前能否使用道具
```
!> `maps.js` 定义了数字-ID的对应关系。
``` js
core.maps.loadFloor // 加载某个楼层(从剧本或存档中)
core.maps.getBlock // 数字和ID的对应关系
core.maps.addEvent // 向该楼层添加剧本的自定义事件
core.maps.addChangeFloor // 向该楼层添加剧本的楼层转换事件
core.maps.initMaps // 初始化所有地图
core.maps.save // 将当前地图重新变成数字,以便于存档
core.maps.load // 将存档中的地图信息重新读取出来
core.maps.getMapArray // 将当前地图重新变成二维数组形式
```
!> `ui.js` 定义了各种界面的绘制。
``` js
core.ui.closePanel // 结束一切事件和绘制关闭UI窗口返回游戏进程
core.ui.drawTextBox // 绘制一个对话框
core.ui.drawChoices // 绘制一个选项界面
core.ui.drawConfirmBox // 绘制一个确认/取消的警告页面
core.ui.drawSwitchs // 绘制系统设置界面
core.ui.drawSettings // 绘制系统菜单栏
core.ui.drawQuickShop // 绘制快捷商店选择栏
core.ui.drawBattleAnimate // 绘制战斗动画
core.ui.drawWaiting // 绘制等待界面
core.ui.drawSyncSave // 绘制存档同步界面
core.ui.drawPagination // 绘制分页
core.ui.drawEnemyBook // 绘制怪物手册
core.ui.drawBookDetail // 绘制怪物属性的详细信息
core.ui.drawFly // 绘制楼层传送器
core.ui.drawMaps // 绘制浏览地图界面
core.ui.drawToolbox // 绘制道具栏
core.ui.drawSLPanel // 绘制存档/读档界面
core.ui.drawThumbnail // 绘制一个缩略图
core.ui.drawAbout // 绘制“关于”界面
core.ui.drawHelp // 绘制帮助界面
```

View File

@ -1,222 +0,0 @@
# 快速上手
?> 目前版本**v2.3.3**,上次更新时间:* {docsify-updated} *
在这一节中,将详细介绍做一部塔的流程。现在,让我们来做一部单层塔!
## 前置需求
你需要有满足如下条件才能进行制作:
- Windows 8以上操作系统Windows 7需要安装.Net Framework 4.0。(能打开同目录下的“启动服务.exe”即可
- Chrome浏览器。其他浏览器可能会导致本地服务器产生闪退等现象。
- 一个很好的文本编辑器。推荐带有高亮染色、错误提示等效果。例如WebStormVSCode或者至少也要Sublime Text。
- [VSCode下载地址](https://code.visualstudio.com/),群里的群文件中也有,强烈推荐之。)
- **2.0版本可以不需要但是仍然强烈推荐有一个从而能对H5造塔有更深的了解。**
只要满足了上述条件,你就可以开始做自己的塔啦!
## V2.0的使用
目前版本已经更新到V2.0在2.0版本中我们可以进行全GUI造塔。
下面的文档主要是讲如何通过代码编辑的方式来造,仍然强烈建议进行阅读从而有着一定的了解。
如果想直接知道如何在V2.0造塔,可以直接参见[V2.0版本介绍](V2.0)的说明,或者看[B站视频教程](http://www.bilibili.com/video/av17608025/)。
## 启动HTTP服务
在根目录下有一个“启动服务.exe”运行之。
![启动服务](img/server.png)
* “启动游戏”按钮将打开一个网页,你能在里面看到现在游戏的效果。
* “地图编辑器”允许你以可视化的方式进行编辑地图。
* “便捷PS工具”能让你很方便的对自定义素材进行添加。参见[自定义素材](personalization#自定义素材)。
* “地图生成器”能让你从已有的截图如RMXP项目中立刻生成可被本样板识别的地图数据。
* “RM动画导出器”能让你从RMXP中导出动画而被H5魔塔使用。
* “JS代码压缩工具”能对JS代码进行压缩从而减少IO请求数和文件大小。
* “伤害和临界值计算器”是一个很便捷的小工具,能对怪物的伤害和临界值进行计算。
!> **警告:** 非Chrome浏览器如Edge/IE等下本地服务器可能表现不正常会出现闪退等现象。请务必下载安装Chrome浏览器。
## 新建剧本
类似于RMXP本塔每层楼都是一个“剧本”剧本内主要定义了本层的地图和各种事件。主函数将读取每个剧本并生成实际的地图供游戏使用。
我们打开 `project/floors/` 目录这个目录是所有剧本的目录。我们需要指定一个楼层名例如MT1然后我们可以将`MT0.js`(模板)复制重命名为为`MT1.js`,并使用文本编辑器打开。
![新建剧本](./img/script.png)
然后将楼层名改为MT1floorId改名为MT1title可以改成任意内容将在切换楼层时进行显示比如可以改成“1层小塔”
具体样板文件的每个要素如下:
- **`floorId`** 楼层唯一标识符;必须和文件名,以及 `main.floors.xxx` 完全一致
- **`title`** 楼层中文名,将在切换楼层时进行显示
- **`name`** 楼层再状态栏显示的名称
- **`canFlyTo`** 当前楼层可否被楼传器飞到。如果该层不能飞到,则也在该层也不允许使用楼传器。
- **`canUseQuickShop`** 当前楼层可否使用快捷商店。
- **`defaultGround`** 该层的背景(地面)素材。
- **`images`** 该层默认显示的前景/背景图片
- **`color`** 该层的画面色调。
- **`bgm`** 到达该层后默认播放的BGM。本项可忽略。
- **`item_ratio`** 该层的宝石/血瓶倍率
- **`map`** 本层地图需要是13x13数组建议使用地图生成器或者可视化地图编辑器制作。
- **`firstArrive`** 第一次到该楼层触发的事件
- **`events`** 该楼的所有可能事件列表
- **`changeFloor`** 楼层转换事件该事件不能和上面的events有冲突同位置点否则会被覆盖
- **`afterBattle`** 战斗后可能触发的事件列表
- **`afterGetItem`** 获得道具后可能触发的事件列表
- **`afterOpenDoor`** 开完门后可能触发的事件列表
- **`cannotMove`** 每个图块不可通行的方向,也就是悬崖效果
我们最终的任务其实是,将每个楼层的剧本(地图&事件)给写完即可。
换句话说,只需要简单的复制操作,我们就可以新建一个剧本了。
## 绘制地图
有两种绘制地图的方式从头绘制地图从RMXP中导入已有的地图。
### 从头绘制地图
我们直接打开“地图编辑器”可以看到一个可视化的UI界面。
![地图编辑器](img/mapgui.png)
然后可以在上面任意进行绘制地图。
!> **如果地图的数字和ID未被定义则会进行提示数字和ID未被定义此时要对素材的ID和数字进行定义请参见[自定义素材](personalization#自定义素材)。**
绘制地图完毕后,点击"导出地图"即可在左边看到对应的JSON数组并且已经复制到了剪切板。将其粘贴到剧本中的map位置即可。
![地图数组](./img/maparray.png)
!> V2.0版本可以直接将当前地图进行保存或另存为,不需要这样手动打开进行编辑。
### 从RMXP导入已有的地图
如果我们想复刻一个现有的已经被RMXP所制作的塔也有很便捷的方式那就是用到我们的“地图生成器”。
首先我们打开RMXP和对应的项目可以看到它的地图。
![绘制地图](./img/rmxp2.png)
我们打开Windows自带的“截图工具”并将整个地图有效区域截图下来并将其复制到剪切板。
![绘制地图](./img/rmxp3.png)
截图时请注意:**只截取有效游戏空间内数据并且有效空间内的范围必须是13x13。如果地图小于13*13请用星空或墙壁填充到13x13。**
确认地图的图片文件已经复制到剪切板后我们打开“地图生成器”并点“加载图片”。大约1-2秒后可以得到地图的数据。
![生成地图](./img/map1.png)
然后点击“复制地图”,即可将地图数据复制到剪切板。
!> **如果有识别不一致的存在,即生成的地图和实际的地图不符,我们可以在地图编辑器中粘贴,再可视化进行编辑。**
!> **地图生成器默认只支持经典素材。如果有自定义素材需求例如原版的1层小塔那种素材请参见[自定义素材](personalization#自定义素材)。**
!> **请确保截图范围刚好为13x13并且保证每个位置的像素都是32x32。**
## 录入数据
有了地图后,我们下一步需要做的就是录入数据。数据主要包括如下几种:
- 勇士初始的属性
- 全局变量宝石效果、全局Flag等
- 怪物数据(每个怪物的攻防血金币经验等等)
下面依次进行说明。
我们打开`data.js`文件,这里面定义了各种全局属性和勇士初始值。
!> V2.0版本可以直接在地图编辑器的`全塔属性`中进行修改!
我们可以将本塔标题改名为“1层小塔”
游戏的唯一标识符叫onefloor然后可以直接修改勇士的各项初始数据.
!> **注name作为游戏的唯一标识符必须进行修改否则可能会导致存档等出现问题。**
![初始数据](./img/init.png)
!> **请注意勇士的初始位置一栏x为横坐标y为纵坐标x为从左到右第几列y为从上到下第几行均从0开始计算。**
修改完初始化信息后,接下来我们需要修改道具的信息(比如宝石加攻防的数值,血瓶加生命的数值等)。还是在这个`data.js`文件往下拉找到values一项并进行相应的设置
![修改数据](./img/moddata.png)
然后再设置一些系统Flag以进行游戏。继续将`data.js`往下拉我们注意到本塔是存在魔防的不存在经验因此我们可以简单地将enableMDef改为trueenableExperience改成falseenableDebuff改成false。
同理,本塔的破墙镐只能破面前的墙壁,因此`pickaxeFourDirections`需要改成`false`。
![系统标志](./img/flag.png)
其他的几项暂时不会被涉及到,因此不用考虑。
全局变量修改完毕后,我们需要告诉主函数加载该楼层。打开`data.js`,找到`floorIds`项将其值改为楼层ID即MT1。
最后一步就是录入怪物数据。打开`enemys.js`文件依次输入你在本塔内使用到的所有怪物的攻防血的数据。其中怪物的特殊属性special项与该文件下面的getSpecialText对应。
!> V2.0版本可以直接在“图块属性”一栏进行修改怪物属性!
![怪物数据](./img/enemyarray.png)
只需要修改自己用到的怪物属性即可,其他没有用到的怪物完全无所谓。
做完后保存所有文件,在本地服务器中“启动游戏”,就能立刻看到自己的塔并开始游戏啦!是不是很简单呢!
![保存](./img/save.png)
## 压缩与发布
当你将上述步骤完成后,你实际上已经做出来了一个魔塔,并且可以发布给大家进行游戏了。
目前而言发布有如下几种方式:
- 离线版本:直接将游戏文件夹打包,放到百度网盘等地方供用户下载;用户下载到本地后直接使用浏览器打开`index.html`进行游戏。
- 手机端的部分浏览器如chrome也支持本地网页可以下载到手机然后直接打开进行游戏。
- 在线版本:将游戏放到某个服务器上,大家在线联网游戏。
**离线版本的好处是:先全部下载后再游戏,无需考虑流量的问题,也可以支持高清音乐的播放。坏处是:没办法在多平台之间迁移,无法及时获得游戏更新(需要重新下载),而浏览器打开本地文件有丢失存档的风险。
在线版本的好处是:随时随地可以玩,可以多平台接档,还可以在后台看到一些统计信息,可以随时对游戏进行更新;坏处是需要一个服务器,且还要考虑到用户流量的问题。**
在此我们只讨论在线版本。当你决定发布游戏时强烈建议先将JS代码进行压缩以节省可能的IO请求以及网络流量。直接打开同目录下的“JS代码压缩工具”进行压缩即可。
压缩完毕后,你还需要将`main.js`中的useCompress从false改为true这样方才只会加载压缩后的文件。
如果你需要发布到服务器上且你没有服务器,可以直接将本塔发给我(`艾之葵`),我会给负责你部署上去的。我的服务器至少能保证两年内有效。
然后就是发布帖子、链接二维码,能让任何人在任何时候任何平台上都能进行游戏啦!是不是很简单呢!
## 注意事项和常见FAQ
1. 截图请务必刚好截取13x13的图片并需要保证每个位置必须为32x32像素。一般无放缩的RMXP符合条件。
2. 游戏的唯一标识符name请务必修改。如果不修改可能会导致存档出现异常。
3. 别忘了data.js中要修改floorIds指明所用到的所有楼层哦~
下面是几个常见的FAQ
**Q: 为什么截图识别不出来?**
**A:** 请保证刚好为13x13且每个位置必须32x32像素。如果不确定可以保存你的截图右键属性查看详细信息看像素的宽高是不是在416左右。多少几十像素都是没关系的。
![图片大小](./img/imginfo.png)
**Q: 打开游戏时卡死在了xxx.js加载完毕无法进入游戏。**
**A:** 最大的可能是因为少了逗号或者反括号等等。一般而言VSCode都会有错误提示你哪里少了东西。
如果没有可以采用如下方式debug
Ctrl+Shift+I 打开Chrome的控制台找到Console。
如果出现了语法错误,会有红色提示 **Unexpected xxx** 找到后面文件名和行号打开使用VSCode检查该处是否存在问题即可。
![检查错误](./img/chrome.png)
==========================================================================================
[继续阅读下一章:元件说明](element)

View File

@ -187,13 +187,6 @@ function() {
多属性可采用数组的写法,比如`'special': [1,3]`视为同时拥有先攻和坚固属性;`'special': [5,10,14,18]`视为拥有3连击、魔防、诅咒、阻击四个属性。
本塔支持战斗动画,在`data.js`中存在三个全局选项:`canOpenBattleAnimate`, `showBattleAnimateConfirm`, `battleAnimate`
- `canOpenBattleAnimate`代表是否允许用户开启战斗动画。如果你添加了一些自定义属性且不想修改战斗界面的UI则可以将其关闭。
- `showBattleAnimateConfirm`代表是否在游戏开始时给用户提供开启动画的选项。对于一些偏向于萌新的塔,可以开启此项。
- `battleAnimate`代表是否默认开启战斗动画。此项会被用户存储的设置给覆盖。
- 如果`canOpenBattleAnimate`为false则后面两个也强制为false。
怪物可以负伤,在`data.js`的全局变量`enableNegativeDamage`中指定。
下面的`getSpecialHint`函数则给定了每个特殊属性的详细描述。这个描述将在怪物手册中看到。

View File

@ -1316,13 +1316,11 @@ async可选如果为true则会异步执行即不等待当前事件执行
### pauseBgm暂停背景音乐
使用`{"type": "pauseBgm"}`可以暂停背景音乐的播放。
<!--
### resumeBgm恢复背景音乐
使用`{"type": "resumeBgm"}`可以恢复背景音乐的播放。
**从V2.5.4开始不再支持此事件,请通过设置音量来达到此效果。**
-->
### loadBgm预加载一个背景音乐
使用loadBgm可以预加载一个背景音乐。

View File

@ -966,7 +966,7 @@ this.getAchievements = function () {
- **`flag:heroIcon`**: 当前的勇士行走图名称。
- **`flag:saveEquips`**: 快速换装时保存的套装。
- **`flag:__visited__`**: 当前访问过的楼层。
- **`flag:equip_atk_buff`**, **`flag:equip_def_buff`**, **`flag:equip_mdef_buff`**: 当前攻防魔防的实际计算比例加成。
- **`flag:__atk_buff__`**, **`flag:__def_buff__`**, **`flag:__mdef_buff__`**: 当前攻防魔防的实际计算比例加成。
- **`flag:__color__`**, **`flag:__weather__`**, **`flag:__volume__`**: 当前的画面色调、天气和音量。
- **`flag:__events__`**: 当前保存的事件列表,读档时会恢复(适用于在事件中存档)
- **`flag:textAttribute`**, **`flag:globalAttribute`**, **`flag:globalFlags`**: 当前的剧情文本属性,当前的全局属性,当前的全局开关。

View File

@ -5,7 +5,7 @@ grammar MotaAction;
//事件 事件编辑器入口之一
event_m
: '事件' BGNL? Newline '覆盖触发器' Bool '启用' Bool '通行状态' B_0_List '动画' Bool '显伤' Bool BGNL? Newline action+ BEND
: '事件' BGNL? Newline '覆盖触发器' Bool '启用' Bool '通行状态' B_0_List '显伤' Bool BGNL? Newline action+ BEND
/* event_m
@ -17,11 +17,10 @@ var code = {
'trigger': Bool_0?'action':null,
'enable': Bool_1,
'noPass': B_0_List_0,
'animate': Bool_2,
'displayDamage': Bool_3,
'displayDamage': Bool_2,
'data': 'data_asdfefw'
}
if (!Bool_0 && Bool_1 && (B_0_List_0===null) && Bool_2 && Bool_3) code = 'data_asdfefw';
if (!Bool_0 && Bool_1 && (B_0_List_0===null) && Bool_2) code = 'data_asdfefw';
code=JSON.stringify(code,null,2).split('"data_asdfefw"').join('[\n'+action_0+']\n');
return code;
*/;
@ -1994,7 +1993,7 @@ ActionParser.prototype.parse = function (obj,type) {
if(typeof(obj)===typeof('')) obj={'data':[obj]};
if(obj instanceof Array) obj={'data':obj};
return MotaActionBlocks['event_m'].xmlText([
obj.trigger==='action',obj.enable,obj.noPass,obj.animate,obj.displayDamage,this.parseList(obj.data)
obj.trigger==='action',obj.enable,obj.noPass,obj.displayDamage,this.parseList(obj.data)
]);
case 'changeFloor':

View File

@ -263,6 +263,12 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc =
"_range": "thiseval==null||(thiseval instanceof Array)",
"_data": "该图块的不可入方向\n可以在这里定义不能朝哪个方向进入该图块可以达到悬崖之类的效果\n例如 [\"down\"] 代表不能从该图块的上方点朝向下进入此图块\n此值对背景层、事件层、前景层上的图块均有效"
},
"animate": {
"_leaf": true,
"_type": "textarea",
"_range": "thiseval==~~thiseval||thiseval==null",
"_data": "该图块的全局动画帧数。\n如果此项为null则对于除了npc48外使用素材默认帧数npc48默认是1帧即静止。"
},
"faceIds": {
"_leaf": true,
"_type": "textarea",

View File

@ -606,24 +606,6 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc =
"_range": "thiseval==null || (thiseval>0 && thiseval<=4)",
"_data": "竖屏模式下顶端状态栏canvas化后的行数。\n此项将决定竖屏的状态栏高度如果设置则不小于1且不大于4。\n仅在statusCanvas开启时才有效"
},
"canOpenBattleAnimate": {
"_leaf": true,
"_type": "checkbox",
"_bool": "bool",
"_data": "是否允许用户开启战斗过程如果此项为false则下面两项均强制视为false"
},
"showBattleAnimateConfirm": {
"_leaf": true,
"_type": "checkbox",
"_bool": "bool",
"_data": "是否在游戏开始时提供“是否开启战斗动画”的选项"
},
"battleAnimate": {
"_leaf": true,
"_type": "checkbox",
"_bool": "bool",
"_data": "是否默认显示战斗动画;用户可以手动在菜单栏中开关"
},
"displayEnemyDamage": {
"_leaf": true,
"_type": "checkbox",

View File

@ -49,7 +49,6 @@ editor.prototype.init = function (callback) {
editor.idsInit(core.maps, core.icons.icons); // 初始化图片素材信息
editor.drawInitData(core.icons.icons); // 初始化绘图
editor.drawMapBg();
editor.fetchMapFromCore();
editor.updateMap();
editor.buildMark();
@ -195,7 +194,7 @@ editor.prototype.mapInit = function () {
}
editor.prototype.fetchMapFromCore = function(){
var mapArray = core.maps.save(core.status.maps, core.status.floorId);
var mapArray = core.maps.saveMap(core.status.floorId);
editor.map = mapArray.map(function (v) {
return v.map(function (v) {
var x = parseInt(v), y = editor.indexs[x];
@ -242,7 +241,6 @@ editor.prototype.changeFloor = function (floorId, callback) {
core.bigmap.offsetY=0;
editor.moveViewport(0,0);
editor.drawMapBg();
editor.fetchMapFromCore();
editor.updateMap();
editor_mode.floor();
@ -253,12 +251,6 @@ editor.prototype.changeFloor = function (floorId, callback) {
/////////// 游戏绘图相关 ///////////
editor.prototype.drawMapBg = function (img) {
return;
//legacy
editor.main.editor.drawMapBg();
}
editor.prototype.drawEventBlock = function () {
var fg=document.getElementById('efg').getContext('2d');
@ -296,20 +288,30 @@ editor.prototype.drawPosSelection = function () {
}
editor.prototype.updateMap = function () {
var evs = {};
if (editor.currentFloorData && editor.currentFloorData.events) {
for (var loc in editor.currentFloorData.events) {
if ((editor.currentFloorData.events[loc]||{}).animate == false)
evs[loc] = {"animate": false};
}
}
var blocks = main.editor.mapIntoBlocks(editor.map.map(function (v) {
var blocks = core.maps._mapIntoBlocks(editor.map.map(function (v) {
return v.map(function (v) {
try {
return v.idnum || v || 0
})
}), {'events': evs, 'changeFloor': {}}, editor.currentFloorId);
}
catch (e) {
console.log("Unable to read idnum from "+v);
return 0;
}
});
}), {'events': editor.currentFloorData.events}, editor.currentFloorId);
core.status.thisMap.blocks = blocks;
main.editor.updateMap();
var updateMap = function () {
core.removeGlobalAnimate(null, null, true);
core.clearMap('bg');
core.clearMap('event');
core.clearMap('event2');
core.clearMap('fg');
core.maps._drawMap_drawBgFg();
core.maps._drawMap_drawEvent();
core.setGlobalAnimate(core.values.animateSpeed);
}
updateMap();
var drawTile = function (ctx, x, y, tileInfo) { // 绘制一个普通块
@ -498,7 +500,6 @@ editor.prototype.drawInitData = function (icons) {
dc.drawImage(tilesets[img], nowx, 0)
nowx += tilesets[img].width;
}
//editor.drawMapBg();
//editor.mapInit();
}
@ -990,7 +991,6 @@ editor.prototype.listen = function () {
return widthNoScroll - widthWithScroll;
}
var scrollBarHeight = getScrollBarHeight();
console.log(scrollBarHeight);
var dataSelection = document.getElementById('dataSelection');
var iconLib=document.getElementById('iconLib');

File diff suppressed because it is too large Load Diff

View File

@ -7,10 +7,10 @@ control.js游戏主要逻辑控制
"use strict";
function control() {
this.init();
this._init();
}
control.prototype.init = function () {
control.prototype._init = function () {
this.controldata = functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a.control;
}
@ -71,7 +71,8 @@ control.prototype.setRequestAnimationFrame = function () {
});
// Global floor images
core.maps.drawFloorImages(core.status.floorId, core.status.floorAnimateObjs||[], core.status.globalAnimateStatus);
core.maps.drawFloorImages(core.status.floorId, core.canvas.bg, 'bg', core.status.floorAnimateObjs||[], core.status.globalAnimateStatus);
core.maps.drawFloorImages(core.status.floorId, core.canvas.fg, 'fg', core.status.floorAnimateObjs||[], core.status.globalAnimateStatus);
// Global Autotile Animate
core.status.autotileAnimateObjs.blocks.forEach(function (block) {
@ -406,8 +407,8 @@ control.prototype.resetStatus = function(hero, hard, floorId, route, maps, value
core.status.floorId = floorId;
core.status.maps = core.clone(maps);
// 初始化怪物
core.material.enemys = core.clone(core.enemys.getEnemys());
core.material.items = core.clone(core.items.getItems());
core.material.enemys = core.enemys.getEnemys();
core.material.items = core.items.getItems();
// 初始化人物属性
core.status.hero = core.clone(hero);
// 初始化人物图标
@ -527,9 +528,10 @@ control.prototype.moveDirectly = function (destX, destY) {
control.prototype.tryMoveDirectly = function (destX, destY) {
if (Math.abs(core.getHeroLoc('x')-destX)+Math.abs(core.getHeroLoc('y')-destY)<=1)
return false;
var canMoveArray = core.maps._canMoveHero_generateArray();
var testMove = function (dx, dy, dir) {
if (dx<0 || dx>=core.bigmap.width|| dy<0 || dy>=core.bigmap.height) return false;
if (core.isset(dir) && !core.canMoveHero(dx,dy,dir)) return false;
if (core.isset(dir) && !core.inArray(canMoveArray[dx][dy],dir)) return false;
if (core.control.moveDirectly(dx, dy)) {
if (core.isset(dir)) core.moveHero(dir, function() {});
return true;
@ -651,6 +653,8 @@ control.prototype.automaticRoute = function (destX, destY) {
}});
var ans = [];
var canMoveArray = core.maps._canMoveHero_generateArray();
route[startX + fw * startY] = '';
queue.queue({depth: 0, x: startX, y: startY});
while (queue.length!=0) {
@ -658,7 +662,7 @@ control.prototype.automaticRoute = function (destX, destY) {
var deep = curr.depth, nowX = curr.x, nowY = curr.y;
for (var direction in core.utils.scan) {
if (!core.canMoveHero(nowX, nowY, direction))
if (!core.inArray(canMoveArray[nowX][nowY], direction))
continue;
var nx = nowX + core.utils.scan[direction].x;
@ -683,6 +687,9 @@ control.prototype.automaticRoute = function (destX, destY) {
if (nextBlock.block.event.trigger == 'changeFloor') deepAdd+=10;
}
deepAdd+=core.status.checkBlock.damage[nid]*10;
// 绕过捕捉
if ((core.status.checkBlock.ambush||[])[nid])
deepAdd += 10000;
if (nx == destX && ny == destY) {
route[nid] = direction;
@ -1284,6 +1291,21 @@ control.prototype.checkBlock = function () {
if (snipe.length>0)
core.snipe(snipe);
}
// 检查捕捉
var ambush = (core.status.checkBlock.ambush||[])[x+core.bigmap.width*y];
if (core.isset(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": "waitAsync"});
// 强制战斗
ambush.forEach(function (t) {
actions.push({"type": "battle", "id": t[2]});
})
core.insertAction(actions);
}
}
////// 阻击事件(动画效果) //////
@ -1485,26 +1507,31 @@ control.prototype.updateDamage = function (floorId, canvas) {
if (floorId != core.status.floorId) {
tempCheckBlock = core.clone(core.status.checkBlock);
core.status.thisMap = core.status.maps[floorId];
core.bigmap.width = core.floors[floorId].width || 13;
core.bigmap.height = core.floors[floorId].height || 13;
core.bigmap.width = core.floors[floorId].width;
core.bigmap.height = core.floors[floorId].height;
core.updateCheckBlock();
}
for (var x=0;x<core.bigmap.width;x++) {
for (var y=0;y<core.bigmap.height;y++) {
var damage = core.status.checkBlock.damage[x+core.bigmap.width*y];
if (damage>0) {
if (damage>0) { // 该点伤害
damage = core.formatBigNumber(damage, true);
core.fillBoldText(canvas, damage, 32*x+16, 32*(y+1)-14, '#FF7F00');
}
else { // 检查捕捉
if ((core.status.checkBlock.ambush||[])[x+core.bigmap.width*y]) {
core.fillBoldText(canvas, '!', 32*x+16, 32*(y+1)-14, '#FF7F00');
}
}
}
}
if (floorId!=core.status.floorId) {
core.status.thisMap = core.status.maps[core.status.floorId];
core.status.checkBlock = tempCheckBlock;
core.bigmap.width = core.floors[core.status.floorId].width || 13;
core.bigmap.height = core.floors[core.status.floorId].height || 13;
core.bigmap.width = core.floors[core.status.floorId].width;
core.bigmap.height = core.floors[core.status.floorId].height;
}
}
}
@ -1798,6 +1825,11 @@ control.prototype.replay = function () {
var action=core.status.replay.toReplay.shift();
if (action == 'input2:===') {
core.replay();
return;
}
if (action=='up' || action=='down' || action=='left' || action=='right') {
core.moveHero(action, function () {
setTimeout(function() {
@ -1902,7 +1934,7 @@ control.prototype.replay = function () {
core.events.openShop(shopId, false);
var shopInterval = setInterval(function () {
if (!core.actions.clickShop(6, topIndex+core.status.event.selection)) {
if (!core.actions._clickShop(6, topIndex+core.status.event.selection)) {
clearInterval(shopInterval);
core.stopReplay();
core.drawTip("录像文件出错");
@ -1910,7 +1942,7 @@ control.prototype.replay = function () {
}
if (selections.length==0) {
clearInterval(shopInterval);
core.actions.clickShop(6, topIndex+choices.length);
core.actions._clickShop(6, topIndex+choices.length);
core.replay();
return;
}
@ -2407,7 +2439,7 @@ control.prototype.saveData = function() {
'floorId': core.status.floorId,
'hero': hero,
'hard': core.status.hard,
'maps': core.maps.save(core.status.maps),
'maps': core.maps.saveMap(),
'route': core.encodeRoute(core.status.route),
'values': core.clone(core.values),
'shops': {},
@ -2430,7 +2462,7 @@ control.prototype.saveData = function() {
////// 从本地读档 //////
control.prototype.loadData = function (data, callback) {
core.resetStatus(data.hero, data.hard, data.floorId, core.decodeRoute(data.route), core.maps.load(data.maps),
core.resetStatus(data.hero, data.hard, data.floorId, core.decodeRoute(data.route), core.maps.loadMap(data.maps),
data.values);
// load shop times
@ -2543,13 +2575,27 @@ control.prototype.setStatus = function (statusName, statusVal) {
}
////// 获得勇士属性 //////
control.prototype.getStatus = function (statusName) {
control.prototype.getStatus = function (name) {
if (!core.isset(core.status.hero)) return null;
// support status:x
if (core.isset(core.status.hero.loc[statusName]))
return core.status.hero.loc[statusName];
if (statusName == 'exp') statusName = 'experience';
return core.status.hero[statusName];
if (core.isset(core.status.hero.loc[name]))
return core.status.hero.loc[name];
if (name == 'exp') name = 'experience';
return core.status.hero[name];
}
control.prototype.getStatusOrDefault = function (status, name) {
if (core.isset(status) && name in status)
return status[name];
return this.getStatus(name);
}
control.prototype.getRealStatus = function (name) {
return this.getRealStatusOrDefault(null, name);
}
control.prototype.getRealStatusOrDefault = function (status, name) {
return this.getStatusOrDefault(status, name) * core.getFlag('__'+name+'_buff__', 1);
}
////// 获得某个等级的名称 //////
@ -2585,6 +2631,12 @@ control.prototype.removeFlag = function(flag) {
delete core.status.hero.flags[flag];
}
////// 增加某个flag数值 //////
control.prototype.addFlag = function(flag, delta) {
if (!core.isset(core.status.hero)) return;
core.setFlag(flag, core.getFlag(flag, 0) + delta);
}
////// 锁定状态栏,常常用于事件处理 //////
control.prototype.lockControl = function () {
core.status.lockControl = true;
@ -2596,7 +2648,7 @@ control.prototype.unLockControl = function () {
}
////// 播放背景音乐 //////
control.prototype.playBgm = function (bgm) {
control.prototype.playBgm = function (bgm, startTime) {
if (main.mode!='play')return;
// 音频不存在
if (!core.isset(core.material.bgms[bgm])) return;
@ -2614,14 +2666,6 @@ control.prototype.playBgm = function (bgm) {
}
this.setMusicBtn();
/*
// 延迟播放
if (core.material.bgms[bgm] == 'loading') {
core.material.bgms[bgm] = 'starting';
return;
}
*/
try {
// 缓存BGM
core.loader.loadBgm(bgm);
@ -2635,7 +2679,7 @@ control.prototype.playBgm = function (bgm) {
}
// 播放当前BGM
core.material.bgms[bgm].volume = core.musicStatus.volume;
core.material.bgms[bgm].currentTime = 0;
core.material.bgms[bgm].currentTime = startTime || 0;
core.material.bgms[bgm].play();
core.musicStatus.playingBgm = bgm;
core.musicStatus.lastBgm = bgm;

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,10 @@
"use strict";
function data() {
this.init();
this._init();
}
data.prototype.init = function() {
data.prototype._init = function() {
this.firstData = data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.firstData;
this.values = data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.values;
this.flags = data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.flags;

View File

@ -1,11 +1,11 @@
"use strict";
function enemys() {
this.init();
this._init();
}
////// 初始化 //////
enemys.prototype.init = function () {
enemys.prototype._init = function () {
this.enemys = enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80;
this.enemydata = functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a.enemys;
if (main.mode=='play') {
@ -16,17 +16,12 @@ enemys.prototype.init = function () {
}
}
////// 获得一个或所有怪物数据 //////
enemys.prototype.getEnemys = function (enemyId) {
if (!core.isset(enemyId)) {
return this.enemys;
}
return this.enemys[enemyId];
enemys.prototype.getEnemys = function () {
return core.clone(this.enemys);
}
////// 判断是否含有某特殊属性 //////
enemys.prototype.hasSpecial = function (special, test) {
if (!core.isset(special)) return false;
if (special instanceof Array) {
@ -52,9 +47,9 @@ enemys.prototype.getSpecials = function () {
return this.enemydata.getSpecials();
}
enemys.prototype.calContent = function (enemy, content) {
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
enemys.prototype._calSpecialContent = function (enemy, content) {
if (typeof content == 'string') return content;
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
if (content instanceof Function) {
return content(enemy);
}
@ -63,8 +58,6 @@ enemys.prototype.calContent = function (enemy, content) {
////// 获得所有特殊属性的名称 //////
enemys.prototype.getSpecialText = function (enemy) {
// 移动到了脚本编辑 - getSpecials中
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
if (!core.isset(enemy)) return [];
var special = enemy.special;
@ -74,7 +67,7 @@ enemys.prototype.getSpecialText = function (enemy) {
if (core.isset(specials)) {
for (var i=0;i<specials.length;i++) {
if (this.hasSpecial(special, specials[i][0]))
text.push(this.calContent(enemy, specials[i][1]));
text.push(this._calSpecialContent(enemy, specials[i][1]));
}
}
return text;
@ -82,9 +75,6 @@ enemys.prototype.getSpecialText = function (enemy) {
////// 获得每个特殊属性的说明 //////
enemys.prototype.getSpecialHint = function (enemy, special) {
// 移动到了脚本编辑 - getSpecials中
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
var specials=this.getSpecials();
if (!core.isset(special)) {
@ -92,7 +82,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.calContent(enemy, specials[i][1])+""+this.calContent(enemy, specials[i][2]));
hints.push(this._calSpecialContent(enemy, specials[i][1])+""+this._calSpecialContent(enemy, specials[i][2]));
}
return hints;
}
@ -100,21 +90,22 @@ enemys.prototype.getSpecialHint = function (enemy, special) {
if (!core.isset(specials)) return "";
for (var i=0;i<specials.length;i++) {
if (special == specials[i][0])
return this.calContent(enemy, specials[i][1])+""+this.calContent(enemy, specials[i][2]);
return this._calSpecialContent(enemy, specials[i][1])+""+this._calSpecialContent(enemy, specials[i][2]);
}
return "";
}
////// 能否获胜 //////
enemys.prototype.canBattle = function (enemyId, x, y, floorId) {
var damage = this.getDamage(enemyId, x, y, floorId);
enemys.prototype.canBattle = function (enemy, x, y, floorId) {
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
var damage = this.getDamage(enemy, x, y, floorId);
return damage != null && damage < core.status.hero.hp;
}
////// 获得某个怪物的伤害 //////
enemys.prototype.getDamage = function (enemy, x, y, floorId) {
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
var damage = this.calDamage(enemy, core.status.hero.hp, core.status.hero.atk, core.status.hero.def, core.status.hero.mdef, x, y, floorId);
var damage = this.calDamage(enemy, null, x, y, floorId);
if (damage == null) return null;
return damage + this.getExtraDamage(enemy);
}
@ -134,7 +125,7 @@ enemys.prototype.getExtraDamage = function (enemy) {
enemys.prototype.getDamageString = function (enemy, x, y, floorId) {
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
var damage = core.enemys.getDamage(enemy, x, y, floorId);
var damage = this.getDamage(enemy, x, y, floorId);
var color = '#000000';
@ -164,70 +155,11 @@ enemys.prototype.getDamageString = function (enemy, x, y, floorId) {
};
}
////// 接下来N个临界值和临界减伤计算 //////
enemys.prototype.nextCriticals = function (enemy, number, x, y, floorId) {
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
var useTurn = !core.flags.useLoop;
number = number||1;
if (this.hasSpecial(enemy.special, 3)) {
if (core.status.hero.atk<=enemy.def) {
return [[enemy.def+1-core.status.hero.atk,'?']];
}
return [];
}
// 坚固、模仿怪物没有临界!
if (this.hasSpecial(enemy.special, 10)) return [];
var info = this.getDamageInfo(enemy, core.status.hero.hp, core.status.hero.atk, core.status.hero.def, core.status.hero.mdef, x, y, floorId);
if (info == null) {
info = this.getEnemyInfo(enemy, core.status.hero.hp, core.status.hero.atk, core.status.hero.def, core.status.hero.mdef, x, y, floorId);
if (core.status.hero.atk<=info.def) {
return [[info.def+1-core.status.hero.atk,'?']];
}
return [];
}
// getDamageInfo直接返回数字
if (typeof info == 'number') {
return [[0,0]];
}
if (info.damage<=0 && !core.flags.enableNegativeDamage) {
return [[0,0]];
}
var list = [], pre = null;
var mon_hp = info.mon_hp, hero_atk = core.status.hero.atk, mon_def = info.mon_def, turn = info.turn;
if (useTurn) { // 回合数计算法
for (var t = turn-1;t>=1;t--) {
var nextAtk = Math.ceil(mon_hp/t) + mon_def;
// 装备提升比例的计算临界
nextAtk = Math.ceil(nextAtk / core.getFlag('equip_atk_buff', 1));
if (nextAtk<=hero_atk) break;
if (nextAtk!=pre) {
var nextInfo = this.getDamageInfo(enemy, core.status.hero.hp, nextAtk, core.status.hero.def, core.status.hero.mdef, x, y, floorId);
if (nextInfo==null || (typeof nextInfo == 'number')) break;
list.push([nextAtk-hero_atk,Math.floor(info.damage-nextInfo.damage)]);
if (nextInfo.damage<=0 && !core.flags.enableNegativeDamage) break;
pre = nextAtk;
}
if (list.length>=number)
break;
}
}
else { // 暴力for循环法
// V2.5.3以后,大数据改为二分法进行计算
var LOOP_MAX_VALUE = 1;
pre = info.damage;
if (hero_atk <= LOOP_MAX_VALUE) { // 循环法
enemys.prototype._nextCriticals_useLoop = function (enemy, info, number, x, y, floorId) {
var mon_hp = info.mon_hp, hero_atk = core.status.hero.atk, mon_def = info.mon_def, pre = info.damage;
var list = [];
for (var atk=hero_atk+1;atk<=mon_hp+mon_def;atk++) {
var nextInfo = this.getDamageInfo(enemy, core.status.hero.hp, atk, core.status.hero.def, core.status.hero.mdef, x, y, floorId);
var nextInfo = this.getDamageInfo(enemy, {"atk": atk}, x, y, floorId);
if (nextInfo==null || (typeof nextInfo == 'number')) break;
if (pre>nextInfo.damage) {
pre = nextInfo.damage;
@ -236,20 +168,25 @@ enemys.prototype.nextCriticals = function (enemy, number, x, y, floorId) {
if (list.length>=number) break;
}
}
if (list.length==0) list.push([0,0]);
return list;
}
else { // 二分法算临界
enemys.prototype._nextCriticals_useBinarySearch = function (enemy, info, number, x, y, floorId) {
var mon_hp = info.mon_hp, hero_atk = core.status.hero.atk, mon_def = info.mon_def, pre = info.damage;
var list = [];
var calNext = function (currAtk, maxAtk) {
var start = Math.floor(currAtk), end = Math.floor(maxAtk);
if (start>end) return null;
while (start<end) {
var mid = Math.floor((start+end)/2);
var nextInfo = core.enemys.getDamageInfo(enemy, core.status.hero.hp, mid, core.status.hero.def, core.status.hero.mdef, x, y, floorId);
var nextInfo = core.enemys.getDamageInfo(enemy, {"atk": mid}, x, y, floorId);
if (nextInfo == null || (typeof nextInfo == 'number')) return null;
if (pre>nextInfo.damage) end = mid;
else start = mid+1;
}
var nextInfo = core.enemys.getDamageInfo(enemy, core.status.hero.hp, start, core.status.hero.def, core.status.hero.mdef, x, y, floorId);
var nextInfo = core.enemys.getDamageInfo(enemy, {"atk": start}, x, y, floorId);
return nextInfo==null||(typeof nextInfo == 'number')||nextInfo.damage>=pre?null:[start,nextInfo.damage];
}
var currAtk = hero_atk;
@ -262,39 +199,93 @@ enemys.prototype.nextCriticals = function (enemy, number, x, y, floorId) {
if (pre<=0 && !core.flags.enableNegativeDamage) break;
if (list.length>=number) break;
}
if (list.length==0) list.push([0,0]);
return list;
}
enemys.prototype._nextCriticals_useTurn = function (enemy, info, number, x, y, floorId) {
var mon_hp = info.mon_hp, hero_atk = core.status.hero.atk, mon_def = info.mon_def, turn = info.turn;
var list = [], pre = null;
for (var t = turn-1;t>=1;t--) {
var nextAtk = Math.ceil(mon_hp/t) + mon_def;
// 装备提升比例的计算临界
nextAtk = Math.ceil(nextAtk / core.getFlag('__atk_buff__', 1));
if (nextAtk<=hero_atk) break;
if (nextAtk!=pre) {
var nextInfo = this.getDamageInfo(enemy, {"atk": nextAtk}, x, y, floorId);
if (nextInfo==null || (typeof nextInfo == 'number')) break;
list.push([nextAtk-hero_atk,Math.floor(info.damage-nextInfo.damage)]);
if (nextInfo.damage<=0 && !core.flags.enableNegativeDamage) break;
pre = nextAtk;
}
if (list.length>=number)
break;
}
if (list.length==0) list.push([0,0]);
return list;
}
////// 接下来N个临界值和临界减伤计算 //////
enemys.prototype.nextCriticals = function (enemy, number, x, y, floorId) {
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
number = number||1;
if (this.hasSpecial(enemy.special, 10)) return []; // 模仿怪物临界
var info = this.getDamageInfo(enemy, null, x, y, floorId);
if (info == null || this.hasSpecial(enemy.special, 3)) { // 未破防,或是坚固怪
info = this.getEnemyInfo(enemy, null, x, y, floorId);
if (core.status.hero.atk<=info.def) {
return [[info.def+1-core.status.hero.atk,'?']];
}
return [];
}
// getDamageInfo直接返回数字0伤且无负伤
if (typeof info == 'number' || (info.damage<=0 && !core.flags.enableNegativeDamage)) {
return [[0,0]];
}
if (core.flags.useLoop) {
var LOOP_MAX_VALUE = 1;
if (core.status.hero.atk <= LOOP_MAX_VALUE) {
return this._nextCriticals_useLoop(enemy, info, number, x, y, floorId);
}
else {
return this._nextCriticals_useBinarySearch(enemy, info, number, x, y, floorId);
}
}
else {
return this._nextCriticals_useTurn(enemy, info, number, x, y, floorId);
}
}
////// N防减伤计算 //////
enemys.prototype.getDefDamage = function (enemy, k, x, y, floorId) {
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
k = k || 1;
var nowDamage = this.calDamage(enemy, core.status.hero.hp, core.status.hero.atk, core.status.hero.def, core.status.hero.mdef, x, y, floorId);
var nextDamage = this.calDamage(enemy, core.status.hero.hp, core.status.hero.atk, core.status.hero.def + k, core.status.hero.mdef, x, y, floorId);
var nowDamage = this.calDamage(enemy, null, x, y, floorId);
var nextDamage = this.calDamage(enemy, {"def": core.status.hero.def + k}, x, y, floorId);
if (nowDamage == null || nextDamage ==null) return "???";
return nowDamage - nextDamage;
}
enemys.prototype.getEnemyInfo = function (enemy, hero_hp, hero_atk, hero_def, hero_mdef, x, y, floorId) {
enemys.prototype.getEnemyInfo = function (enemy, hero, x, y, floorId) {
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
return this.enemydata.getEnemyInfo(enemy, hero_hp, hero_atk, hero_def, hero_mdef, x, y, floorId)
return this.enemydata.getEnemyInfo(enemy, hero, x, y, floorId)
}
////// 获得战斗伤害信息(实际伤害计算函数) //////
enemys.prototype.getDamageInfo = function(enemy, hero_hp, hero_atk, hero_def, hero_mdef, x, y, floorId) {
enemys.prototype.getDamageInfo = function(enemy, hero, x, y, floorId) {
// 移动到了脚本编辑 - getDamageInfo中
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
return this.enemydata.getDamageInfo(enemy, hero_hp, hero_atk, hero_def, hero_mdef, x, y, floorId);
return this.enemydata.getDamageInfo(enemy, hero, x, y, floorId);
}
////// 获得在某个勇士属性下怪物伤害 //////
enemys.prototype.calDamage = function (enemy, hero_hp, hero_atk, hero_def, hero_mdef, x, y, floorId) {
enemys.prototype.calDamage = function (enemy, hero, x, y, floorId) {
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
var info = this.getDamageInfo(enemy, hero_hp, hero_atk, hero_def, hero_mdef, x, y, floorId);
var info = this.getDamageInfo(enemy, hero, x, y, floorId);
if (info == null) return null;
if (typeof info == 'number') return info;
return info.damage;
@ -308,57 +299,56 @@ enemys.prototype.updateEnemys = function () {
////// 获得当前楼层的怪物列表 //////
enemys.prototype.getCurrentEnemys = function (floorId) {
floorId=floorId||core.status.floorId;
var enemys = [];
var used = {};
var enemys = [], used = {};
var mapBlocks = core.status.maps[floorId].blocks;
for (var b = 0; b < mapBlocks.length; b++) {
if (core.isset(mapBlocks[b].event) && !mapBlocks[b].disable
&& mapBlocks[b].event.cls.indexOf('enemy')==0) {
var enemyId = mapBlocks[b].event.id;
this._getCurrentEnemys_addEnemy(mapBlocks[b].event.id, enemys, used, floorId);
}
}
return this._getCurrentEnemys_sort(enemys);
}
enemys.prototype._getCurrentEnemys_getEnemy = function (enemyId) {
var enemy = core.material.enemys[enemyId];
if (!core.isset(enemy)) continue;
if (!core.isset(enemy)) return null;
// 检查displayIdInBook
var tmpId = enemy.displayIdInBook;
if (core.isset(core.material.enemys[tmpId])) {
enemyId = tmpId;
enemy = core.material.enemys[tmpId];
}
if (core.isset(used[enemyId])) continue;
return enemy;
}
var mon_hp = enemy.hp, mon_atk = enemy.atk, mon_def = enemy.def;
var hero_atk = core.status.hero.atk, hero_def = core.status.hero.def, hero_mdef = core.status.hero.mdef;
enemys.prototype._getCurrentEnemys_addEnemy = function (enemyId, enemys, used, floorId) {
var enemy = this._getCurrentEnemys_getEnemy(enemyId);
if (enemy==null || used[enemy.id]) return;
hero_atk = Math.floor(core.getFlag('equip_atk_buff',1)*hero_atk);
hero_def = Math.floor(core.getFlag('equip_def_buff',1)*hero_def);
hero_mdef = Math.floor(core.getFlag('equip_mdef_buff',1)*hero_mdef);
var enemyInfo = this.getEnemyInfo(enemy, core.status.hero.hp, hero_atk, hero_def, hero_mdef, null, null, floorId);
var specialText = core.enemys.getSpecialText(enemyId);
var enemyInfo = this.getEnemyInfo(enemy, null, null, null, floorId);
var specialText = core.enemys.getSpecialText(enemy);
if (specialText.length>=3) specialText = "多属性...";
else specialText = specialText.join(" ");
var critical = this.nextCriticals(enemyId, 1, null, null, floorId);
var critical = this.nextCriticals(enemy, 1, null, null, floorId);
if (critical.length>0) critical=critical[0];
var e = core.clone(enemy);
for (var x in enemyInfo) {
e[x] = enemyInfo[x];
}
e.id = enemyId;
e.specialText = specialText;
e.damage = this.getDamage(enemyId, null, null, floorId);
e.damage = this.getDamage(enemy, null, null, floorId);
e.critical = critical[0];
e.criticalDamage = critical[1];
e.defDamage = this.getDefDamage(enemyId,1,null,null,floorId);
e.defDamage = this.getDefDamage(enemy,1,null,null,floorId);
enemys.push(e);
used[enemyId] = true;
}
used[enemy.id] = true;
}
enemys.sort(function (a, b) {
enemys.prototype._getCurrentEnemys_sort = function (enemys) {
return enemys.sort(function (a, b) {
if (a.damage == b.damage) {
return a.money - b.money;
}
@ -370,5 +360,4 @@ enemys.prototype.getCurrentEnemys = function (floorId) {
}
return a.damage - b.damage;
});
return enemys;
}

View File

@ -1,11 +1,11 @@
"use strict";
function events() {
this.init();
this._init();
}
////// 初始化 //////
events.prototype.init = function () {
events.prototype._init = function () {
this.eventdata = functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a.events;
this.commonEvent = events_c12a15a8_c380_4b28_8144_256cba95f760.commonEvent;
this.events = {
@ -135,21 +135,7 @@ events.prototype.startGame = function (hard, seed, route, callback) {
var real_start = function () {
core.insertAction(core.clone(core.firstData.startText), null, null, function() {
if (!core.flags.startUsingCanvas && !core.isReplaying() && core.flags.showBattleAnimateConfirm) { // 是否提供“开启战斗动画”的选择项
core.status.event.selection = core.flags.battleAnimate ? 0 : 1;
core.ui.drawConfirmBox("你想开启战斗动画吗?\n之后可以在菜单栏中开启或关闭。\n强烈建议新手开启此项", function () {
core.flags.battleAnimate = true;
core.setLocalStorage('battleAnimate', true);
post_start();
}, function () {
core.flags.battleAnimate = false;
core.setLocalStorage('battleAnimate', false);
post_start();
});
}
else {
post_start();
}
});
}
@ -976,7 +962,6 @@ events.prototype.doAction = function() {
this.doAction();
break
case "loadBgm":
if (core.platform.isPC)
core.loadBgm(data.name);
this.doAction();
break;
@ -1505,16 +1490,27 @@ events.prototype.battle = function (id, x, y, force, callback) {
if (!core.isset(core.status.event.id)) // 自动存档
core.autosave(true);
if (core.flags.battleAnimate&&!core.isReplaying()) {
core.waitHeroToStop(function() {
core.ui.drawBattleAnimate(id, function() {
core.events.afterBattle(id, x, y, callback);
});
});
// ------ 支援技能 ------//
if (core.isset(x) && core.isset(y)) {
var index = x + "," + y, cache = (core.status.checkBlock.cache || {})[index] || {},
guards = cache.guards || [];
if (guards.length>0) {
core.setFlag("__guards__"+x+"_"+y, guards);
var actions = [];
guards.forEach(function (g) {
core.push(actions, {"type": "jump", "from": [g[0],g[1]], "to": [x, y],
"time": 300, "keep": false, "async": true});
})
core.push(actions, [
{"type": "waitAsync"},
{"type": "trigger", "loc": [x,y]}
]);
core.insertAction(actions);
return;
}
else {
core.events.afterBattle(id, x, y, callback);
}
core.events.afterBattle(id, x, y, callback);
}
////// 触发(x,y)点的事件 //////
@ -1983,6 +1979,64 @@ events.prototype.openShop = function(shopId, needVisited) {
core.ui.drawChoices(content, choices);
}
events.prototype._useShop = function (shop, index) {
// 检查能否使用快捷商店
var reason = core.events.canUseQuickShop(shop.id);
if (core.isset(reason)) {
core.drawText(reason);
return false;
}
if (!shop.visited) {
if (shop.times==0) core.drawTip("该商店尚未开启");
else core.drawTip("该商店已失效");
return false;
}
var money = core.getStatus('money'), experience = core.getStatus('experience');
var times = shop.times, need = core.calValue(shop.need, null, null, times);
var use = shop.use;
var use_text = use=='money'?"金币":"经验";
var choice = shop.choices[index];
if (core.isset(choice.need))
need = core.calValue(choice.need, null, null, times);
if (need > eval(use)) {
core.drawTip("你的"+use_text+"不足");
return false;
}
core.status.event.selection = index;
core.status.event.data.actions.push(index);
eval(use+'-='+need);
core.setStatus('money', money);
core.setStatus('experience', experience);
// 更新属性
choice.effect.split(";").forEach(function (t) {
core.doEffect(t, need, times);
});
core.updateStatusBar();
shop.times++;
if (shop.commonTimes)
core.setFlag('commonTimes', shop.times);
core.events.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;
@ -2033,7 +2087,7 @@ events.prototype.checkLvUp = function () {
}
////// 尝试使用道具 //////
events.prototype.useItem = function(itemId) {
events.prototype.tryUseItem = function(itemId) {
core.ui.closePanel();
if (itemId=='book') {

View File

@ -1,10 +1,10 @@
"use strict";
function icons() {
this.init();
this._init();
}
icons.prototype.init = function () {
icons.prototype._init = function () {
this.icons = icons_4665ee12_3a1f_44a4_bea3_0fccba634dc1;
//delete(icons_4665ee12_3a1f_44a4_bea3_0fccba634dc1);
@ -13,7 +13,29 @@ icons.prototype.init = function () {
}
icons.prototype.getIcons = function () {
return this.icons;
return core.clone(this.icons);
}
////// 根据道具ID获得其cls //////
icons.prototype.getClsFromId = function (id) {
for (var cls in core.material.icons) {
if (cls != 'hero' && id in core.material.icons[cls])
return cls;
}
return null;
}
icons.prototype._getAnimateFrames = function (cls, useOriginValue) {
if (cls=='enemys' || cls=='npcs') {
return 2;
}
if (cls == 'animates' || cls == 'enemy48') {
return 4;
}
if (cls == 'npc48') {
return useOriginValue? 4 : 1;
}
return 1;
}
////// 根据图块数字或ID获得所在的tileset和坐标信息 //////

View File

@ -1,26 +1,24 @@
"use strict";
function items() {
this.init();
this._init();
}
////// 初始化 //////
items.prototype.init = function () {
items.prototype._init = function () {
this.items = items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a.items;
this.itemEffect = items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a.itemEffect;
this.itemEffectTip = items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a.itemEffectTip;
this.useItemEffect = items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a.useItemEffect;
this.canUseItemEffect = items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a.canUseItemEffect;
if (!core.isset(items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a.canEquip))
if (!items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a.canEquip)
items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a.canEquip = {};
this.canEquip = items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a.canEquip;
//delete(items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a);
this.equipCondition = items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a.canEquip;
}
////// 获得所有道具 //////
items.prototype.getItems = function () {
return this.items;
return core.clone(this.items);
}
////// “即捡即用类”道具的使用效果 //////
@ -63,39 +61,42 @@ items.prototype.getItemEffectTip = function(itemId) {
return "";
}
////// 使用道具 //////
items.prototype.useItem = function (itemId, noRoute, callback) {
if (!this.canUseItem(itemId)) {
if (core.isset(callback)) callback();
return;
}
var itemCls = core.material.items[itemId].cls;
items.prototype._useItemEffect = function (itemId) {
if (itemId in this.useItemEffect) {
try {
var ratio = parseInt(core.status.thisMap.item_ratio) || 1;
eval(this.useItemEffect[itemId]);
}
catch (e) {
main.log(e);
}
}
// 记录路线
if (!noRoute) {
core.status.route.push("item:"+itemId);
}
items.prototype._afterUseItem = function (itemId) {
// 道具使用完毕:删除
var itemCls = core.material.items[itemId].cls;
if (itemCls=='tools')
core.status.hero.items[itemCls][itemId]--;
if (core.status.hero.items[itemCls][itemId]<=0)
delete core.status.hero.items[itemCls][itemId];
core.updateStatusBar();
if (!core.isset(core.status.event.id)) {
core.status.event.data = null;
core.status.event.ui = null;
core.updateStatusBar();
}
////// 使用道具 //////
items.prototype.useItem = function (itemId, noRoute, callback) {
if (!this.canUseItem(itemId)) {
if (core.isset(callback)) callback();
return;
}
// 执行道具效果
this._useItemEffect(itemId);
// 执行完毕
this._afterUseItem(itemId);
// 记录路线
if (!noRoute) core.status.route.push("item:"+itemId);
if (core.isset(callback)) callback();
}
@ -113,7 +114,7 @@ items.prototype.canUseItem = function (itemId) {
main.log(e);
}
}
if (!able) core.status.event.data = null;
if (!able) core.status.event.ui = null;
return able;
}
@ -171,7 +172,7 @@ items.prototype.setItem = function (itemId, itemNum) {
////// 删除某个物品 //////
items.prototype.removeItem = function (itemId, itemNum) {
if (!core.isset(core.status.hero)) return null;
itemNum = itemNum || 1;
if (!core.isset(itemNum)) itemNum = 1;
if (!core.hasItem(itemId)) return false;
var itemCls = core.material.items[itemId].cls;
core.status.hero.items[itemCls][itemId]-=itemNum;
@ -186,7 +187,7 @@ items.prototype.removeItem = function (itemId, itemNum) {
////// 增加某个物品的个数 //////
items.prototype.addItem = function (itemId, itemNum) {
if (!core.isset(core.status.hero)) return null;
itemNum = itemNum || 1;
if (!core.isset(itemNum)) itemNum = 1;
var itemData = core.material.items[itemId];
var itemCls = itemData.cls;
if (itemCls == 'items') return;
@ -208,6 +209,15 @@ items.prototype.addItem = function (itemId, itemNum) {
core.updateStatusBar();
}
// ---------- 装备相关 ------------ //
items.prototype.getEquipTypeById = function (equipId) {
var type = core.material.items[equipId].equip.type;
if (typeof type == 'string')
type = this.getEquipTypeByName(type);
return type;
}
items.prototype.getEquipTypeByName = function (name) {
var names = core.status.globalAttribute.equipName;
for (var i = 0; i < names.length; ++i) {
@ -218,125 +228,116 @@ items.prototype.getEquipTypeByName = function (name) {
return -1;
}
////// 换上 //////
items.prototype.loadEquip = function (equipId, callback) {
if (!core.isset(core.status.hero)) return null;
if (!core.isset(core.status.hero.equipment)) core.status.hero.equipment = [];
var loadEquip = core.material.items[equipId]||{};
if (!core.isset(loadEquip.equip)) {
if (core.isset(callback)) callback();
return;
// 当前能否撞上某装备
items.prototype.canEquip = function (equipId, hint) {
// 装备是否合法
var equip = core.material.items[equipId]||{};
if (!core.isset(equip.equip)) {
if (hint) core.drawTip("不合法的装备!");
return false;
}
var can = this.canEquip[equipId];
if (core.isset(can)) {
// 是否拥有该装备
if (!core.hasItem(equipId) && !core.hasEquip(equipId)) {
if (hint) core.drawTip("你当前没有"+equip.name+",无法换装");
return false;
}
// 可装备条件
var condition = this.equipCondition[equipId];
if (core.isset(condition) && condition.length>0) {
try {
if (!eval(can)) {
core.drawTip("当前不可换上"+loadEquip.name);
if (core.isset(callback)) callback();
return;
if (!eval(condition)) {
if (hint) core.drawTip("当前不可换上"+equip.name);
return false;
}
}
catch (e) {
main.log(e);
console.log(e);
return false;
}
}
core.playSound('equip.mp3');
var loadEquipType = loadEquip.equip.type;
// ------ 判定多重装备 ------
if (typeof loadEquipType === 'string') {
loadEquipType = this.getEquipTypeByName(loadEquipType);
if (loadEquipType < 0) {
core.drawTip("当前没有"+loadEquip.equip.type+"的空位!");
return;
}
return true;
}
var unloadEquipId = core.status.hero.equipment[loadEquipType];
var unloadEquip = core.material.items[unloadEquipId] || {};
// ------ 如果当前装备和目标装备的模式不同(一个百分比一个数值),则需要先脱再穿 ------ //
if (core.isset(unloadEquip.equip) && (unloadEquip.equip.percentage||false) != (loadEquip.equip.percentage||false)) {
this.unloadEquip(loadEquipType);
this.loadEquip(equipId);
if (core.isset(callback)) callback();
return;
}
// 下面保证了两者的模式是相同的
////// 实际换装的效果 //////
items.prototype._loadEquipEffect = function (equipId, unloadEquipId, isPercentage) {
// 比较能力值
var result = core.compareEquipment(equipId, unloadEquipId);
if (loadEquip.equip.percentage) {
core.setFlag('equip_atk_buff', core.getFlag('equip_atk_buff',1)+result.atk/100);
core.setFlag('equip_def_buff', core.getFlag('equip_def_buff',1)+result.def/100);
core.setFlag('equip_mdef_buff', core.getFlag('equip_mdef_buff',1)+result.mdef/100);
if (isPercentage) {
for (var v in result)
core.addFlag('__'+v+'_buff__', result[v]/100);
}
else {
core.status.hero.atk += result.atk;
core.status.hero.def += result.def;
core.status.hero.mdef += result.mdef;
for (var v in result)
core.status.hero[v] += result[v];
}
}
// 更新装备状态
core.status.hero.equipment[loadEquipType] = equipId;
core.updateStatusBar();
items.prototype._realLoadEquip = function (type, loadId, unloadId, callback) {
var loadEquip = core.material.items[loadId] || {}, unloadEquip = core.material.items[unloadId] || {};
if (!core.isset(loadEquip.equip)) loadEquip.equip = {};
if (!core.isset(unloadEquip.equip)) unloadEquip.equip = {};
// 装备更换完毕:删除换上的装备
core.removeItem(equipId);
var loadPercentage = loadEquip.equip.percentage, unloadPercentage = unloadEquip.equip.percentage;
// 装备更换完毕:增加卸下的装备
if (core.isset(unloadEquipId))
core.addItem(unloadEquipId, 1);
if (loadPercentage != null && unloadPercentage != null && loadPercentage != unloadPercentage) {
this.unloadEquip(type);
this.loadEquip(loadId);
if (core.isset(callback)) callback();
return;
}
core.drawTip("已装备上"+loadEquip.name, core.material.icons.items[equipId]);
// --- 音效
core.playSound('equip.mp3');
// --- 实际换装
this._loadEquipEffect(loadId, unloadId, loadPercentage==null?unloadPercentage:loadPercentage);
// --- 加减
if (loadId) core.removeItem(loadId);
if (unloadId) core.addItem(unloadId);
core.status.hero.equipment[type] = loadId||null;
// --- 提示
if (loadId) core.drawTip("已装备上"+loadEquip.name, core.material.icons.items[loadId]);
else if (unloadId) core.drawTip("已卸下"+unloadEquip.name, core.material.icons.items[unloadId]);
if (core.isset(callback)) callback();
}
////// 换上 //////
items.prototype.loadEquip = function (equipId, callback) {
if (!core.isset(core.status.hero)) return null;
if (!core.isset(core.status.hero.equipment)) core.status.hero.equipment = [];
if (!this.canEquip(equipId, true)) {
if (core.isset(callback)) callback();
return;
}
var loadEquip = core.material.items[equipId] || {};
var type = this.getEquipTypeById(equipId);
if (type < 0) {
core.drawTip("当前没有"+loadEquip.equip.type+"的空位!");
return;
}
this._realLoadEquip(type, equipId, core.status.hero.equipment[type], callback);
}
////// 卸下 //////
items.prototype.unloadEquip = function (equipType, callback) {
if (!core.isset(core.status.hero)) return null;
if (!core.isset(core.status.hero.equipment)) core.status.hero.equipment = [];
core.playSound('equip.mp3');
var unloadEquipId = core.status.hero.equipment[equipType];
if (!core.isset(unloadEquipId)) {
if (core.isset(callback)) callback();
return;
}
var unloadEquip = core.material.items[unloadEquipId] || {};
// 处理能力值改变
if (unloadEquip.equip.percentage) {
core.setFlag('equip_atk_buff', core.getFlag('equip_atk_buff',1)-(unloadEquip.equip.atk||0)/100);
core.setFlag('equip_def_buff', core.getFlag('equip_def_buff',1)-(unloadEquip.equip.def||0)/100);
core.setFlag('equip_mdef_buff', core.getFlag('equip_mdef_buff',1)-(unloadEquip.equip.mdef||0)/100);
}
else {
core.status.hero.atk -= unloadEquip.equip.atk || 0;
core.status.hero.def -= unloadEquip.equip.def || 0;
core.status.hero.mdef -= unloadEquip.equip.mdef || 0;
}
// 更新装备状态
core.status.hero.equipment[equipType] = null;
core.updateStatusBar();
// 装备更换完毕:增加卸下的装备
core.addItem(unloadEquipId, 1);
core.drawTip("已卸下"+unloadEquip.name, core.material.icons.items[unloadEquipId]);
if (core.isset(callback)) callback();
this._realLoadEquip(equipType, null, unloadEquipId, callback);
}
items.prototype.compareEquipment = function (compareEquipId, beComparedEquipId) {
@ -376,21 +377,9 @@ items.prototype.quickLoadEquip = function (index) {
var equipSize = core.status.globalAttribute.equipName.length;
for (var i=0;i<equipSize;i++) {
var v = current[i];
if (core.isset(v) && !core.hasItem(v) && !core.hasEquip(v)) {
if (core.isset(v) && !this.canEquip(v, true))
return;
}
if (core.isset(v)) {
if (!core.hasItem(v) && !core.hasEquip(v)) {
core.drawTip("你当前没有"+((core.material.items[v]||{}).name||"未知装备")+",无法换装");
return;
}
var can = this.canEquip[v];
if (core.isset(can) && !eval(can)) {
core.drawTip("当前不可换上"+((core.material.items[v]||{}).name||"未知装备"));
return;
}
}
}
// 快速换装
if (!core.isset(core.status.hero.equipment)) core.status.hero.equipment = [];
for (var i=0;i<equipSize;i++) {

View File

@ -5,10 +5,10 @@ loader.js负责对资源的加载
"use strict";
function loader() {
this.init();
this._init();
}
loader.prototype.init = function () {
loader.prototype._init = function () {
}
@ -22,27 +22,52 @@ loader.prototype.setStartLoadTipText = function (text) {
core.dom.startTopLoadTips.innerHTML = text;
}
loader.prototype.load = function (callback) {
loader.prototype._load = function (callback) {
this._loadIcons();
this._loadAnimates();
this._loadMusic();
// 加载icons
core.loader.loadIcons();
core.loader._loadMaterialImages(function () {
core.loader._loadExtraImages(function () {
core.loader._loadAutotiles(function () {
core.loader._loadTilesets(callback);
})
})
});
}
// 加载图片
core.loader.loadImages(core.materials, core.material.images, function () {
// 加载png图片
loader.prototype._loadIcons = function () {
this.loadImage("icons.png", function (id, image) {
var images = core.cropImage(image);
for (var key in core.statusBar.icons) {
if (typeof core.statusBar.icons[key] == 'number') {
core.statusBar.icons[key] = images[core.statusBar.icons[key]];
if (core.isset(core.statusBar.image[key]))
core.statusBar.image[key].src = core.statusBar.icons[key].src;
}
}
});
}
loader.prototype._loadMaterialImages = function (callback) {
this.loadImages(core.materials, core.material.images, callback);
}
loader.prototype._loadExtraImages = function (callback) {
core.material.images.images = {};
var images = core.clone(core.images);
if (images.indexOf("hero.png")<0)
images.push("hero.png");
core.loader.loadImages(images, core.material.images.images, function () {
// 加载autotile
this.loadImages(images, core.material.images.images, callback);
}
loader.prototype._loadAutotiles = function (callback) {
core.material.images.autotile = {};
var keys = Object.keys(core.material.icons.autotile);
var autotiles = {};
core.loader.loadImages(keys, autotiles, function () {
this.loadImages(keys, autotiles, function () {
keys.forEach(function (v) {
core.material.images.autotile[v] = autotiles[v];
});
@ -51,11 +76,14 @@ loader.prototype.load = function (callback) {
core.maps.makeAutotileEdges();
});
// 加载tilesets
callback();
});
}
loader.prototype._loadTilesets = function (callback) {
core.material.images.tilesets = {};
if (!core.isset(core.tilesets)) core.tilesets = [];
core.loader.loadImages(core.clone(core.tilesets), core.material.images.tilesets, function () {
// 检查宽高是32倍数如果出错在控制台报错
for (var imgName in core.material.images.tilesets) {
var img = core.material.images.tilesets[imgName];
@ -66,28 +94,7 @@ loader.prototype.load = function (callback) {
console.warn("警告!"+imgName+"上的图块素材个数大于3000");
}
}
core.loader.loadAnimates();
core.loader.loadMusic();
if (core.isset(callback))
callback();
})
})
})
})
}
loader.prototype.loadIcons = function () {
this.loadImage("icons.png", function (id, image) {
var images = core.cropImage(image);
for (var key in core.statusBar.icons) {
if (typeof core.statusBar.icons[key] == 'number') {
core.statusBar.icons[key] = images[core.statusBar.icons[key]];
if (core.isset(core.statusBar.image[key]))
core.statusBar.image[key].src = core.statusBar.icons[key].src;
}
}
});
}
@ -126,7 +133,7 @@ loader.prototype.loadImage = function (imgName, callback) {
}
}
loader.prototype.loadAnimates = function () {
loader.prototype._loadAnimates = function () {
core.animates.forEach(function (t) {
core.http('GET', 'project/animates/' + t + ".animate", null, function (content) {
try {
@ -182,79 +189,14 @@ loader.prototype.loadAnimates = function () {
}
////// 加载音频 //////
loader.prototype.loadMusic = function () {
loader.prototype._loadMusic = function () {
core.bgms.forEach(function (t) {
core.loader.loadOneMusic(t);
/*
// 判断是不是mid
if (/^.*\.mid$/i.test(t)) {
if (core.musicStatus.audioContext!=null) {
core.material.bgms[t] = 'loading';
core.http('GET', 'project/sounds/'+t, null, function (data) {
try {
var ff = [];
var mx = data.length;
for (var z = 0; z < mx; z++)
ff[z] = String.fromCharCode(data.charCodeAt(z) & 255);
var shouldStart = core.material.bgms[t] == 'starting';
core.material.bgms[t] = AudioPlayer(core.musicStatus.audioContext, Replayer(MidiFile(ff.join("")), Synth(44100)), true);
if (shouldStart)
core.playBgm(t);
}
catch (e) {
main.log(e);
core.material.bgms[t] = null;
}
}, function (e) {
main.log(e);
core.material.bgms[t] = null;
}, "text/plain; charset=x-user-defined")
}
else {
core.material.bgms[t] = null;
}
}
else {
core.loader.loadOneMusic(t);
}
*/
});
core.sounds.forEach(function (t) {
if (core.musicStatus.audioContext != null) {
core.http('GET', 'project/sounds/'+t, null, function (data) {
try {
core.musicStatus.audioContext.decodeAudioData(data, function (buffer) {
core.material.sounds[t] = buffer;
}, function (e) {
main.log(e);
core.material.sounds[t] = null;
})
}
catch (ee) {
main.log(ee);
core.material.sounds[t] = null;
}
}, function (e) {
main.log(e);
core.material.sounds[t] = null;
}, null, 'arraybuffer');
}
else {
var music = new Audio();
music.src = 'project/sounds/'+t;
core.material.sounds[t] = music;
}
core.loader.loadOneSound(t);
});
// 直接开始播放
core.playBgm(main.startBgm);
}
@ -268,6 +210,33 @@ loader.prototype.loadOneMusic = function (name) {
core.material.bgms[name] = music;
}
loader.prototype.loadOneSound = function (name) {
if (core.musicStatus.audioContext != null) {
core.http('GET', 'project/sounds/'+name, null, function (data) {
try {
core.musicStatus.audioContext.decodeAudioData(data, function (buffer) {
core.material.sounds[name] = buffer;
}, function (e) {
main.log(e);
core.material.sounds[name] = null;
})
}
catch (e) {
main.log(e);
core.material.sounds[name] = null;
}
}, function (e) {
main.log(e);
core.material.sounds[name] = null;
}, null, 'arraybuffer');
}
else {
var music = new Audio();
music.src = 'project/sounds/'+name;
core.material.sounds[name] = music;
}
}
loader.prototype.freeBgm = function (name) {
if (!core.isset(core.material.bgms[name])) return;
// 从cachedBgms中删除
@ -285,6 +254,11 @@ loader.prototype.freeBgm = function (name) {
}, 3000);
}
loader.prototype._preloadBgm = function (bgm) {
bgm.volume = 0;
bgm.play();
}
loader.prototype.loadBgm = function (name) {
if (!core.isset(core.material.bgms[name])) return;
// 如果没开启音乐,则不预加载
@ -296,7 +270,8 @@ loader.prototype.loadBgm = function (name) {
}
else {
// 预加载BGM
core.material.bgms[name].load();
this._preloadBgm(core.material.bgms[name]);
// core.material.bgms[name].load();
// 清理尾巴
if (core.musicStatus.cachedBgms.length == core.musicStatus.cachedBgmCount) {
this.freeBgm(core.musicStatus.cachedBgms.pop());

File diff suppressed because it is too large Load Diff

View File

@ -7,11 +7,11 @@
"use strict";
function ui() {
this.init();
this._init();
}
// 初始化UI
ui.prototype.init = function () {
ui.prototype._init = function () {
this.uidata = functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a.ui;
}
@ -349,20 +349,17 @@ ui.prototype.getTitleAndIcon = function (content) {
var id=null, name=null, image=null, icon=null, iconHeight=32, animate=null;
var getInfo = function (v) {
["enemy48", "enemys", "npc48", "npcs"].forEach(function (x) {
if (core.isset(core.material.icons[x][v])) {
image = core.material.images[x];
icon = core.material.icons[x][v];
if (x.indexOf("48")>=0) {
iconHeight = 48;
animate = 4;
}
else {
iconHeight = 32;
animate = 2;
var number = core.maps.getNumberById(v);
if (number>0) {
var block = core.maps.initBlock(0,0,number,true);
if (core.isset(block.event)) {
var cls = block.event.cls;
image = core.material.images[cls];
icon = core.material.icons[cls][v];
iconHeight = block.event.height;
animate = block.event.animate;
}
}
});
};
if (content.indexOf("\t[")==0 || content.indexOf("\\t[")==0) {
@ -1120,7 +1117,6 @@ ui.prototype.drawSwitchs = function() {
var choices = [
"背景音乐: "+(core.musicStatus.bgmStatus ? "[ON]" : "[OFF]"),
"背景音效: "+(core.musicStatus.soundStatus ? "[ON]" : "[OFF]"),
"战斗动画: "+(core.flags.battleAnimate ? "[ON]" : "[OFF]"),
"怪物显伤: "+(core.flags.displayEnemyDamage ? "[ON]" : "[OFF]"),
"临界显伤: "+(core.flags.displayCritical ? "[ON]" : "[OFF]"),
"领域显伤: "+(core.flags.displayExtraDamage ? "[ON]" : "[OFF]"),
@ -1155,311 +1151,6 @@ ui.prototype.drawQuickShop = function () {
this.drawChoices(null, choices);
}
////// 绘制战斗动画 //////
ui.prototype.drawBattleAnimate = function(monsterId, callback) {
// UI层
core.lockControl();
if (!core.isset(core.status.event.id)) {
core.status.event = {'id': 'battle'};
}
var hero_hp = core.getStatus('hp'), hero_atk = core.getStatus('atk'), hero_def = core.getStatus('def'),
hero_mdef = core.getStatus('mdef');
hero_hp=Math.max(0, hero_hp);
hero_atk=Math.max(0, hero_atk);
hero_def=Math.max(0, hero_def);
hero_mdef=Math.max(0, hero_mdef);
hero_atk = Math.floor(core.getFlag('equip_atk_buff',1)*hero_atk);
hero_def = Math.floor(core.getFlag('equip_def_buff',1)*hero_def);
hero_mdef = Math.floor(core.getFlag('equip_mdef_buff',1)*hero_mdef);
var enemy = core.material.enemys[monsterId];
var enemyInfo = core.enemys.getEnemyInfo(enemy, hero_hp, hero_atk, hero_def, hero_mdef);
var mon_hp = enemyInfo.hp, mon_atk = enemyInfo.atk, mon_def = enemyInfo.def, mon_money=enemyInfo.money,
mon_exp = enemyInfo.experience, mon_special=enemyInfo.special;
var initDamage = 0; // 战前伤害
// 吸血
if (core.enemys.hasSpecial(mon_special, 11)) {
var vampireDamage = hero_hp * enemy.value;
// 如果有神圣盾免疫吸血等可以在这里写
vampireDamage = Math.floor(vampireDamage) || 0;
// 加到自身
if (enemy.add) // 如果加到自身
mon_hp += vampireDamage;
initDamage += vampireDamage;
}
hero_hp -= core.enemys.getExtraDamage(enemy);
if (core.enemys.hasSpecial(mon_special, 2)) hero_def=0; // 魔攻
// 实际操作
var turn = 0; // 0为勇士攻击
if (core.enemys.hasSpecial(mon_special, 1)) turn=1;
// 回合
var turns = 2;
if (core.enemys.hasSpecial(mon_special, 4)) turns=3;
if (core.enemys.hasSpecial(mon_special, 5)) turns=4;
if (core.enemys.hasSpecial(mon_special, 6)) turns=1+(enemy.n||4);
// 初始伤害
if (core.enemys.hasSpecial(mon_special, 7)) initDamage+=Math.floor(core.values.breakArmor * hero_def);
if (core.enemys.hasSpecial(mon_special, 9)) initDamage+=Math.floor(core.values.purify * hero_mdef);
hero_mdef-=initDamage;
if (hero_mdef<0) {
hero_hp+=hero_mdef;
hero_mdef=0;
}
var specialTexts = core.enemys.getSpecialText(monsterId);
core.clearMap('ui');
var left=10, right=416-2*left;
var lines = 3;
if (core.flags.enableMDef || core.flags.enableMoney || core.flags.enableExperience) lines=4;
if (core.flags.enableMoney && core.flags.enableExperience) lines=5;
var lineHeight = 60;
var height = lineHeight * lines + 50;
var top = (416-height)/2, bottom = height;
core.fillRect('ui', left, top, right, bottom, 'rgba(0,0,0,0.85)');
core.setAlpha('ui', 1);
core.strokeRect('ui', left - 1, top - 1, right + 1, bottom + 1, '#FFFFFF', 2);
core.clearMap('data');
clearInterval(core.interval.tipAnimate);
core.setAlpha('data', 1);
core.status.boxAnimateObjs = [];
var globalFont = core.status.globalAttribute.font;
var margin = 35;
var boxWidth = 40;
var monsterHeight = 32, animate=2;
var image = core.material.images.enemys, icon = core.material.icons.enemys;
if (core.isset(core.material.icons.enemy48[monsterId])) {
image = core.material.images.enemy48;
icon = core.material.icons.enemy48;
monsterHeight = 48;
animate=4;
}
// 方块
var heroHeight = core.material.icons.hero.height;
core.strokeRect('ui', left + margin - 1, top + margin - 1, boxWidth+2, heroHeight+boxWidth-32+2, '#FFD700', 2);
core.strokeRect('ui', left + right - margin - boxWidth - 1 , top+margin-1, boxWidth+2, monsterHeight+boxWidth-32+2);
// 名称
core.setTextAlign('ui', 'center');
core.fillText('ui', core.status.hero.name, left+margin+boxWidth/2, top+margin+heroHeight+40, '#FFD700', 'bold 22px '+globalFont);
core.fillText('ui', "怪物", left+right-margin-boxWidth/2, top+margin+monsterHeight+40);
for (var i=0, j=0; i<specialTexts.length;i++) {
if (specialTexts[i]!='') {
core.fillText('ui', specialTexts[i], left+right-margin-boxWidth/2, top+margin+monsterHeight+44+20*(++j), '#FF6A6A', '15px '+globalFont);
}
}
// 图标
core.clearMap('ui', left + margin, top + margin, boxWidth, heroHeight+boxWidth-32);
core.fillRect('ui', left + margin, top + margin, boxWidth, heroHeight+boxWidth-32, core.material.groundPattern);
var heroIcon = core.material.icons.hero['down'];
core.drawImage('ui', core.material.images.hero, heroIcon.stop * 32, heroIcon.loc *heroHeight, 32, heroHeight, left+margin+(boxWidth-32)/2, top+margin+(boxWidth-32)/2, 32, heroHeight);
// 怪物的
core.status.boxAnimateObjs = [];
core.status.boxAnimateObjs.push({
'bgx': left+right-margin-40, 'bgy': top+margin, 'bgWidth': boxWidth, 'bgHeight': monsterHeight+boxWidth-32,
'x': left + right - margin - 40 + (boxWidth-32)/2, 'y': top + margin + (boxWidth-32)/2, 'height': monsterHeight,
'image': image, 'pos': monsterHeight*icon[monsterId], 'animate': animate
})
core.drawBoxAnimate();
var lineWidth = 80;
var left_start = left + margin + boxWidth + 10;
var left_end = left_start+lineWidth;
var right_end = left+right-margin-boxWidth-10;
var right_start = right_end-lineWidth;
// 勇士的线
core.setTextAlign('ui', 'left');
var textTop = top+margin+10;
core.fillText('ui', "生命值", left_start, textTop, '#DDDDDD', '16px '+globalFont);
core.drawLine('ui', left_start, textTop+8, left_end, textTop+8, '#FFFFFF', 2);
core.setTextAlign('data', 'right');
core.fillText('data', hero_hp, left_end, textTop+26, '#DDDDDD', 'bold 16px '+globalFont);
textTop+=lineHeight;
core.setTextAlign('ui', 'left');
core.fillText('ui', "攻击", left_start, textTop, '#DDDDDD', '16px '+globalFont);
core.drawLine('ui', left_start, textTop+8, left_end, textTop+8, '#FFFFFF', 2);
core.setTextAlign('ui', 'right');
core.fillText('ui', hero_atk, left_end, textTop+26, '#DDDDDD', 'bold 16px '+globalFont);
textTop+=lineHeight;
core.setTextAlign('ui', 'left');
core.fillText('ui', "防御", left_start, textTop, '#DDDDDD', '16px '+globalFont);
core.drawLine('ui', left_start, textTop+8, left_end, textTop+8, '#FFFFFF', 2);
core.setTextAlign('ui', 'right');
core.fillText('ui', hero_def, left_end, textTop+26, '#DDDDDD', 'bold 16px '+globalFont);
if (core.flags.enableMDef) {
textTop += lineHeight;
core.setTextAlign('ui', 'left');
core.fillText('ui', "护盾", left_start, textTop, '#DDDDDD', '16px '+globalFont);
core.drawLine('ui', left_start, textTop + 8, left_end, textTop + 8, '#FFFFFF', 2);
core.setTextAlign('data', 'right');
core.fillText('data', hero_mdef, left_end, textTop+26, '#DDDDDD', 'bold 16px '+globalFont);
}
// 怪物的线
core.setTextAlign('ui', 'right');
var textTop = top+margin+10;
core.fillText('ui', "生命值", right_end, textTop, '#DDDDDD', '16px '+globalFont);
core.drawLine('ui', right_start, textTop+8, right_end, textTop+8, '#FFFFFF', 2);
core.setTextAlign('data', 'left');
core.fillText('data', mon_hp, right_start, textTop+26, '#DDDDDD', 'bold 16px '+globalFont);
textTop+=lineHeight;
core.setTextAlign('ui', 'right');
core.fillText('ui', "攻击", right_end, textTop, '#DDDDDD', '16px '+globalFont);
core.drawLine('ui', right_start, textTop+8, right_end, textTop+8, '#FFFFFF', 2);
core.setTextAlign('ui', 'left');
core.fillText('ui', mon_atk, right_start, textTop+26, '#DDDDDD', 'bold 16px '+globalFont);
textTop+=lineHeight;
core.setTextAlign('ui', 'right');
core.fillText('ui', "防御", right_end, textTop, '#DDDDDD', '16px '+globalFont);
core.drawLine('ui', right_start, textTop+8, right_end, textTop+8, '#FFFFFF', 2);
core.setTextAlign('ui', 'left');
core.fillText('ui', mon_def, right_start, textTop+26, '#DDDDDD', 'bold 16px '+globalFont);
if (core.flags.enableMoney) {
textTop += lineHeight;
core.setTextAlign('ui', 'right');
core.fillText('ui', "金币", right_end, textTop, '#DDDDDD', '16px '+globalFont);
core.drawLine('ui', right_start, textTop + 8, right_end, textTop + 8, '#FFFFFF', 2);
core.setTextAlign('ui', 'left');
core.fillText('ui', mon_money, right_start, textTop + 26, '#DDDDDD', 'bold 16px '+globalFont);
}
if (core.flags.enableExperience) {
textTop += lineHeight;
core.setTextAlign('ui', 'right');
core.fillText('ui', "经验", right_end, textTop, '#DDDDDD', '16px '+globalFont);
core.drawLine('ui', right_start, textTop + 8, right_end, textTop + 8, '#FFFFFF', 2);
core.setTextAlign('ui', 'left');
core.fillText('ui', mon_exp, right_start, textTop+26, '#DDDDDD', 'bold 16px '+globalFont);
}
core.setTextAlign('ui', 'left');
core.fillText("ui", "V", left_end+8, 208-15, "#FFFFFF", "italic bold 40px "+globalFont);
core.setTextAlign('ui', 'right');
core.fillText("ui", "S", right_start-8, 208+15, "#FFFFFF", "italic bold 40px "+globalFont);
var battleInterval = setInterval(function() {
core.playSound("attack.mp3");
if (turn==0) {
// 勇士攻击
core.drawLine('data', left + right - margin - boxWidth + 6, top+margin+monsterHeight+boxWidth-32-6,
left+right-margin-6, top+margin+6, '#FF0000', 4);
setTimeout(function() {
core.clearMap('data', left + right - margin - boxWidth, top+margin,
boxWidth, boxWidth+monsterHeight-32);
}, 250);
if (hero_atk-mon_def>0)
mon_hp-=hero_atk-mon_def;
if (mon_hp<0) mon_hp=0;
// 更新怪物伤害
core.clearMap('data', right_start, top+margin+10, lineWidth, 40);
core.setTextAlign('data', 'left');
core.fillText('data', mon_hp, right_start, top+margin+10+26, '#DDDDDD', 'bold 16px '+globalFont);
// 反击
if (core.enemys.hasSpecial(mon_special, 8)) {
hero_mdef -= Math.floor(core.values.counterAttack * hero_atk);
if (hero_mdef<0) {
hero_hp+=hero_mdef;
hero_mdef=0;
}
// 更新勇士数据
core.clearMap('data', left_start, top+margin+10, lineWidth, 40);
core.setTextAlign('data', 'right');
core.fillText('data', hero_hp, left_end, top+margin+10+26, '#DDDDDD', 'bold 16px '+globalFont);
if (core.flags.enableMDef) {
core.clearMap('data', left_start, top+margin+10+3*lineHeight, lineWidth, 40);
core.fillText('data', hero_mdef, left_end, top+margin+10+26+3*lineHeight);
}
}
}
else {
// 怪物攻击
core.drawLine('data', left + margin + 6, top+margin+heroHeight+(boxWidth-32)-6,
left+margin+boxWidth-6, top+margin+6, '#FF0000', 4);
setTimeout(function() {
core.clearMap('data', left + margin, top+margin, boxWidth, heroHeight+boxWidth-32);
}, 250);
var per_damage = mon_atk-hero_def;
if (per_damage < 0) per_damage = 0;
hero_mdef-=per_damage;
if (hero_mdef<0) {
hero_hp+=hero_mdef;
hero_mdef=0;
}
// 更新勇士数据
core.clearMap('data', left_start, top+margin+10, lineWidth, 40);
core.setTextAlign('data', 'right');
core.fillText('data', hero_hp, left_end, top+margin+10+26, '#DDDDDD', 'bold 16px '+globalFont);
if (core.flags.enableMDef) {
core.clearMap('data', left_start, top+margin+10+3*lineHeight, lineWidth, 40);
core.fillText('data', hero_mdef, left_end, top+margin+10+26+3*lineHeight);
}
}
turn++;
if (turn>=turns) turn=0;
if (hero_hp<=0 || mon_hp<=0) {
// 战斗结束
clearInterval(battleInterval);
core.status.boxAnimateObjs = [];
core.clearMap('ui');
core.setAlpha('ui', 1.0);
core.clearMap('data');
if (core.status.event.id=='battle') {
core.unLockControl();
core.status.event.id=null;
}
if (core.isset(callback))
callback();
return;
}
}, 400);
}
////// 绘制等待界面 //////
ui.prototype.drawWaiting = function(text) {
@ -1977,7 +1668,7 @@ ui.prototype.drawMaps = function (index, x, y) {
if (index<0) index=0;
if (index>=core.floorIds.length) index=core.floorIds.length-1;
var floorId = core.floorIds[index], mw = core.floors[floorId].width||13, mh = core.floors[floorId].height||13;
var floorId = core.floorIds[index], mw = core.floors[floorId].width, mh = core.floors[floorId].height;
if (!core.isset(x)) x = parseInt(mw/2);
if (!core.isset(y)) y = parseInt(mh/2);
if (x<6) x=6;
@ -1989,14 +1680,14 @@ ui.prototype.drawMaps = function (index, x, y) {
clearTimeout(core.interval.tipAnimate);
core.clearLastEvent();
core.status.checkBlock.buff = {};
core.status.checkBlock.cache = {};
this.drawThumbnail(floorId, 'ui', core.status.maps[floorId].blocks, 0, 0, 416, x, y);
// 绘图
if (core.status.event.data.paint) {
var offsetX = core.clamp(x-6, 0, mw-13), offsetY = core.clamp(y-6, 0, mh-13);
var value = core.paint[floorId];
if (core.isset(value)) value = LZString.decompress(value).split(",");
if (core.isset(value)) value = lzw_decode(value).split(",");
core.utils.decodeCanvas(value, 32*mw, 32*mh);
core.drawImage('ui', core.bigmap.tempCanvas.canvas, offsetX*32, offsetY*32, 416, 416, 0, 0, 416, 416);
}
@ -2291,7 +1982,7 @@ ui.prototype.drawEquipbox = function(index) {
if (compare[name]<0) color = '#FF0000';
var nowValue = core.getStatus(name), newValue = nowValue + compare[name];
if (equip.equip.percentage) {
var nowBuff = core.getFlag('equip_'+name+"_buff",1), newBuff = nowBuff+compare[name]/100;
var nowBuff = core.getFlag('__'+name+"_buff__", 1), newBuff = nowBuff+compare[name]/100;
nowValue = Math.floor(nowBuff*core.getStatus(name));
newValue = Math.floor(newBuff*core.getStatus(name));
}
@ -2397,7 +2088,7 @@ ui.prototype.drawSLPanel = function(index, refresh) {
core.fillText('ui', i==0?"自动存档":name+id, (2*i+1)*u, 30, '#FFFFFF', "bold 17px "+globalFont);
core.strokeRect('ui', (2*i+1)*u-size/2, 45, size, size, i==offset?strokeColor:'#FFFFFF', i==offset?6:2);
if (core.isset(data) && core.isset(data.floorId)) {
core.ui.drawThumbnail(data.floorId, 'ui', core.maps.load(data.maps, data.floorId).blocks, (2*i+1)*u-size/2, 45, size, data.hero.loc.x, data.hero.loc.y, data.hero.loc, data.hero.flags.heroIcon||"hero.png");
core.ui.drawThumbnail(data.floorId, 'ui', core.maps.loadMap(data.maps, data.floorId).blocks, (2*i+1)*u-size/2, 45, size, data.hero.loc.x, data.hero.loc.y, data.hero.loc, data.hero.flags.heroIcon||"hero.png");
var v = core.formatBigNumber(data.hero.hp,true)+"/"+core.formatBigNumber(data.hero.atk,true)+"/"+core.formatBigNumber(data.hero.def,true);
var v2 = "/"+core.formatBigNumber(data.hero.mdef,true);
if (v.length+v2.length<=21) v+=v2;
@ -2413,7 +2104,7 @@ ui.prototype.drawSLPanel = function(index, refresh) {
core.fillText('ui', name+id, (2*i-5)*u, 218, '#FFFFFF', "bold 17px "+globalFont);
core.strokeRect('ui', (2*i-5)*u-size/2, 233, size, size, i==offset?strokeColor:'#FFFFFF', i==offset?6:2);
if (core.isset(data) && core.isset(data.floorId)) {
core.ui.drawThumbnail(data.floorId, 'ui', core.maps.load(data.maps, data.floorId).blocks, (2*i-5)*u-size/2, 233, size, data.hero.loc.x, data.hero.loc.y, data.hero.loc, data.hero.flags.heroIcon||"hero.png");
core.ui.drawThumbnail(data.floorId, 'ui', core.maps.loadMap(data.maps, data.floorId).blocks, (2*i-5)*u-size/2, 233, size, data.hero.loc.x, data.hero.loc.y, data.hero.loc, data.hero.flags.heroIcon||"hero.png");
var v = core.formatBigNumber(data.hero.hp,true)+"/"+core.formatBigNumber(data.hero.atk,true)+"/"+core.formatBigNumber(data.hero.def,true);
var v2 = "/"+core.formatBigNumber(data.hero.mdef,true);
if (v.length+v2.length<=21) v+=v2;
@ -2469,8 +2160,8 @@ ui.prototype.drawSLPanel = function(index, refresh) {
////// 绘制一个缩略图 //////
ui.prototype.drawThumbnail = function(floorId, canvas, blocks, x, y, size, centerX, centerY, heroLoc, heroIcon) {
var mw = core.floors[floorId].width || 13;
var mh = core.floors[floorId].height || 13;
var mw = core.floors[floorId].width;
var mh = core.floors[floorId].height;
// 绘制到tempCanvas上面
var tempCanvas = core.bigmap.tempCanvas;
var tempWidth = mw*32, tempHeight = mh*32;
@ -2500,7 +2191,7 @@ ui.prototype.drawThumbnail = function(floorId, canvas, blocks, x, y, size, cente
if (typeof t == 'string') t = [0,0,t];
var dx=parseInt(t[0]), dy=parseInt(t[1]), p=t[2], frame = core.clamp(parseInt(t[4]), 1, 8);
if (core.isset(dx) && core.isset(dy) &&
!core.hasFlag("floorimg_"+floorId+"_"+dx+"_"+dy) &&
!core.hasFlag("floorimg_"+floorId+"@"+dx+"@"+dy) &&
core.isset(core.material.images.images[p])) {
var image = core.material.images.images[p];
var width = image.width / frame, height = image.height;
@ -2554,7 +2245,7 @@ ui.prototype.drawThumbnail = function(floorId, canvas, blocks, x, y, size, cente
images.forEach(function (t) {
var dx=parseInt(t[0]), dy=parseInt(t[1]), p=t[2], frame = core.clamp(parseInt(t[4]), 1, 8);
if (core.isset(dx) && core.isset(dy) &&
!core.hasFlag("floorimg_"+floorId+"_"+dx+"_"+dy) &&
!core.hasFlag("floorimg_"+floorId+"@"+dx+"@"+dy) &&
core.isset(core.material.images.images[p])) {
var image = core.material.images.images[p];
var width = image.width / frame, height = image.height;
@ -2888,7 +2579,7 @@ ui.prototype.drawPaint = function () {
// 将已有的内容绘制到route上
var value = core.paint[core.status.floorId];
if (core.isset(value)) value = LZString.decompress(value).split(",");
if (core.isset(value)) value = lzw_decode(value).split(",");
core.utils.decodeCanvas(value, 32*core.bigmap.width, 32*core.bigmap.height);
core.drawImage('paint', core.bigmap.tempCanvas.canvas, 0, 0);

View File

@ -6,7 +6,7 @@ utils.js 工具类
"use strict";
function utils() {
this.init();
this._init();
this.scan = {
'up': {'x': 0, 'y': -1},
'left': {'x': -1, 'y': 0},
@ -15,7 +15,7 @@ function utils() {
};
}
utils.prototype.init = function () {
utils.prototype._init = function () {
// 定义Object.assign
if (typeof Object.assign != "function") {
Object.assign = function(target, varArgs) { // .length of function is 2
@ -136,12 +136,14 @@ utils.prototype.setLocalStorage = function(key, value) {
return;
}
var str = JSON.stringify(value);
var compressed = LZString.compress(str);
var str = JSON.stringify(value).replace(/[\u007F-\uFFFF]/g, function(chr) {
return "\\u" + ("0000" + chr.charCodeAt(0).toString(16)).substr(-4)
});
var compressed = lzw_encode(str);
// test if we can save to localStorage
localStorage.setItem("__tmp__", compressed);
if (LZString.decompress(localStorage.getItem("__tmp__"))==str) {
if (lzw_decode(localStorage.getItem("__tmp__"))==str) {
localStorage.setItem(core.firstData.name + "_" + key, compressed);
}
else {
@ -161,28 +163,30 @@ utils.prototype.setLocalStorage = function(key, value) {
}
}
////// 获得本地存储 //////
utils.prototype.getLocalStorage = function(key, defaultValue) {
try {
var value = localStorage.getItem(core.firstData.name+"_"+key);
if (core.isset(value)) {
var output = LZString.decompress(value);
if (core.isset(output) && output.length>0) {
utils.prototype.decompress = function (value) {
try {
var output = lzw_decode(value);
if (core.isset(output) && output.length > 0)
return JSON.parse(output);
}
catch (ee) {
// Ignore, use default value
}
catch (e) {}
try {
var output = LZString.decompress(value);
if (core.isset(output) && output.length > 0)
return JSON.parse(output);
}
catch (e) {}
try {
return JSON.parse(value);
}
return defaultValue;
}
catch (e) {
main.log(e);
return defaultValue;
catch (e) {main.log(e);}
return null;
}
////// 获得本地存储 //////
utils.prototype.getLocalStorage = function(key, defaultValue) {
var res = this.decompress(localStorage.getItem(core.firstData.name+"_"+key));
return res==null?defaultValue:res;
}
////// 移除本地存储 //////
@ -210,7 +214,9 @@ utils.prototype.setLocalForage = function (key, value, successCallback, errorCal
}
// Save to localforage
var compressed = LZString.compress(JSON.stringify(value));
var compressed = lzw_encode(JSON.stringify(value).replace(/[\u007F-\uFFFF]/g, function(chr) {
return "\\u" + ("0000" + chr.charCodeAt(0).toString(16)).substr(-4)
}));
localforage.setItem(core.firstData.name+"_"+key, compressed, function (err) {
if (core.isset(err)) {
if (core.isset(errorCallback)) errorCallback(err);
@ -240,18 +246,9 @@ utils.prototype.getLocalForage = function (key, defaultValue, successCallback, e
else {
if (!core.isset(successCallback)) return;
if (core.isset(value)) {
try {
var output = LZString.decompress(value);
if (core.isset(output) && output.length>0) {
try {
successCallback(JSON.parse(output));
var res = core.utils.decompress(value);
successCallback(res==null?defaultValue:res);
return;
} catch (ee) {main.log(ee);}
}
successCallback(JSON.parse(value));
return;
}
catch (e) {main.log(e);}
}
successCallback(defaultValue);
}
@ -400,16 +397,49 @@ utils.prototype.arrayToRGBA = function (color) {
return "rgba("+nowR+","+nowG+","+nowB+","+nowA+")";
}
////// 加密路线 //////
utils.prototype.encodeRoute = function (route) {
var ans="";
var lastMove = "", cnt=0;
var id2number = function (id) {
utils.prototype._encodeRoute_id2number = function (id) {
var number = core.maps.getNumberById(id);
return number==0?id:number;
}
utils.prototype._encodeRoute_encodeOne = function (t) {
if (t.indexOf('item:')==0)
return "I"+this._encodeRoute_id2number(t.substring(5))+":";
else if (t.indexOf('unEquip:')==0)
return "u"+t.substring(8);
else if (t.indexOf('equip:')==0)
return "e"+this._encodeRoute_id2number(t.substring(6))+":";
else if (t.indexOf('fly:')==0)
return "F"+t.substring(4)+":";
else if (t.indexOf('choices:')==0)
return "C"+t.substring(8);
else if (t.indexOf('shop:')==0)
return "S"+t.substring(5);
else if (t=='turn')
return 'T';
else if (t.indexOf('turn:')==0)
return "t"+t.substring(5).substring(0,1).toUpperCase()+":";
else if (t=='getNext')
return 'G';
else if (t.indexOf('input:')==0)
return "P"+t.substring(6);
else if (t.indexOf('input2:')==0)
return "Q"+t.substring(7)+":";
else if (t=='no')
return 'N';
else if (t.indexOf('move:')==0)
return "M"+t.substring(5);
else if (t.indexOf('key:')==0)
return 'K'+t.substring(4);
else if (t.indexOf('random:')==0)
return 'X'+t.substring(7);
return '';
}
////// 加密路线 //////
utils.prototype.encodeRoute = function (route) {
var ans="", lastMove = "", cnt=0;
route.forEach(function (t) {
if (t=='up' || t=='down' || t=='left' || t=='right') {
if (t!=lastMove && cnt>0) {
@ -426,117 +456,85 @@ utils.prototype.encodeRoute = function (route) {
if (cnt>1) ans+=cnt;
cnt=0;
}
if (t.indexOf('item:')==0)
ans+="I"+id2number(t.substring(5))+":";
else if (t.indexOf('unEquip:')==0)
ans+="u"+t.substring(8);
else if (t.indexOf('equip:')==0)
ans+="e"+id2number(t.substring(6))+":";
else if (t.indexOf('fly:')==0)
ans+="F"+t.substring(4)+":";
else if (t.indexOf('choices:')==0)
ans+="C"+t.substring(8);
else if (t.indexOf('shop:')==0)
ans+="S"+t.substring(5);
else if (t=='turn')
ans+='T';
else if (t.indexOf('turn:')==0)
ans+="t"+t.substring(5).substring(0,1).toUpperCase()+":";
else if (t=='getNext')
ans+='G';
else if (t.indexOf('input:')==0)
ans+="P"+t.substring(6);
else if (t.indexOf('input2:')==0)
ans+="Q"+t.substring(7)+":";
else if (t=='no')
ans+='N';
else if (t.indexOf('move:')==0)
ans+="M"+t.substring(5);
else if (t.indexOf('key:')==0)
ans+='K'+t.substring(4);
else if (t.indexOf('random:')==0)
ans+='X'+t.substring(7);
ans += core.utils._encodeRoute_encodeOne(t);
}
});
if (cnt>0) {
ans+=lastMove.substring(0,1).toUpperCase();
if (cnt>1) ans+=cnt;
}
// return ans;
// 压缩
return LZString.compressToBase64(ans);
}
utils.prototype._decodeRoute_getNumber = function (decodeObj, noparse) {
var num="";
while (decodeObj.index<decodeObj.route.length && !isNaN(decodeObj.route.charAt(decodeObj.index))) {
num+=decodeObj.route.charAt(decodeObj.index++);
}
if (num.length==0) num="1";
return core.isset(noparse)?num:parseInt(num);
}
utils.prototype._decodeRoute_getString = function (decodeObj) {
var str="";
while (decodeObj.index<decodeObj.route.length && decodeObj.route.charAt(decodeObj.index)!=':') {
str+=decodeObj.route.charAt(decodeObj.index++);
}
decodeObj.index++;
return str;
}
utils.prototype._decodeRoute_number2id = function (number) {
if (/^\d+$/.test(number)) {
var info = core.maps.blocksInfo[number];
if (core.isset(info)) return info.id;
}
return number;
}
utils.prototype._decodeRoute_decodeOne = function (decodeObj, c) {
var nxt=(c=='I'|| c=='e' ||c=='F'||c=='S'||c=='Q'||c=='t')?
this._decodeRoute_getString(decodeObj):this._decodeRoute_getNumber(decodeObj);
var mp = {"U": "up", "D": "down", "L": "left", "R": "right"};
switch (c) {
case "U": case "D": case "L": case "R": for (var i=0;i<nxt;i++) decodeObj.ans.push(mp[c]); break;
case "I": decodeObj.ans.push("item:"+this._decodeRoute_number2id(nxt)); break;
case "u": decodeObj.ans.push("unEquip:"+nxt); break;
case "e": decodeObj.ans.push("equip:"+this._decodeRoute_number2id(nxt)); break;
case "F": decodeObj.ans.push("fly:"+nxt); break;
case "C": decodeObj.ans.push("choices:"+nxt); break;
case "S": decodeObj.ans.push("shop:"+nxt+":"+this._decodeRoute_getNumber(decodeObj, true)); break;
case "T": decodeObj.ans.push("turn"); break;
case "t": decodeObj.ans.push("turn:"+mp[nxt]); break;
case "G": decodeObj.ans.push("getNext"); break;
case "P": decodeObj.ans.push("input:"+nxt); break;
case "Q": decodeObj.ans.push("input2:"+nxt); break;
case "N": decodeObj.ans.push("no"); break;
case "M": ++decodeObj.index; decodeObj.ans.push("move:"+nxt+":"+this._decodeRoute_getNumber(decodeObj)); break;
case "K": decodeObj.ans.push("key:"+nxt); break;
case "X": decodeObj.ans.push("random:"+nxt); break;
}
}
////// 解密路线 //////
utils.prototype.decodeRoute = function (route) {
if (!core.isset(route)) return route;
// 解压缩
try {
var v = LZString.decompressFromBase64(route);
if (core.isset(v) && /^[a-zA-Z0-9+\/=:]+$/.test(v)) {
if (core.isset(v) && /^[a-zA-Z0-9+\/=:]*$/.test(v)) {
route = v;
}
} catch (e) {}
var ans=[], index=0;
var getNumber = function (noparse) {
var num="";
while (index<route.length && !isNaN(route.charAt(index))) {
num+=route.charAt(index++);
var decodeObj = {route: route, index: 0, ans: []};
while (decodeObj.index < decodeObj.route.length) {
this._decodeRoute_decodeOne(decodeObj, decodeObj.route.charAt(decodeObj.index++));
}
if (num.length==0) num="1";
return core.isset(noparse)?num:parseInt(num);
}
var getString = function () {
var str="";
while (index<route.length && route.charAt(index)!=':') {
str+=route.charAt(index++);
}
index++;
return str;
}
var mp = {
"U": "up",
"D": "down",
"L": "left",
"R": "right"
}
var number2id = function (nxt) {
if (/^\d+$/.test(nxt)) {
var info = core.maps.blocksInfo[nxt];
if (core.isset(info)) return info.id;
}
return nxt;
}
while (index<route.length) {
var c=route.charAt(index++);
var nxt=(c=='I'|| c=='e' ||c=='F'||c=='S'||c=='Q'||c=='t')?getString():getNumber();
switch (c) {
case "U": case "D": case "L": case "R": for (var i=0;i<nxt;i++) ans.push(mp[c]); break;
case "I":ans.push("item:"+number2id(nxt)); break;
case "u": ans.push("unEquip:"+nxt); break;
case "e": ans.push("equip:"+number2id(nxt)); break;
case "F": ans.push("fly:"+nxt); break;
case "C": ans.push("choices:"+nxt); break;
case "S": ans.push("shop:"+nxt+":"+getNumber(true)); break;
case "T": ans.push("turn"); break;
case "t": ans.push("turn:"+mp[nxt]); break;
case "G": ans.push("getNext"); break;
case "P": ans.push("input:"+nxt); break;
case "Q": ans.push("input2:"+nxt); break;
case "N": ans.push("no"); break;
case "M": ++index; ans.push("move:"+nxt+":"+getNumber()); break;
case "K": ans.push("key:"+nxt); break;
case "X": ans.push("random:"+nxt); break;
}
}
return ans;
return decodeObj.ans;
}
////// 判断某对象是否不为undefined也不会null //////
@ -558,6 +556,10 @@ utils.prototype.subarray = function (a, b) {
return na;
}
utils.prototype.inArray = function (array, element) {
return this.isset(array) && (array instanceof Array) && array.indexOf(element)>=0;
}
utils.prototype.clamp = function (x, a, b) {
var min=Math.min(a, b), max=Math.max(a, b);
return Math.min(Math.max(x||0, min), max);
@ -1043,3 +1045,57 @@ utils.prototype.http = function (type, url, formData, success, error, mimeType,
xhr.send(formData);
else xhr.send();
}
// LZW-compress
// https://gist.github.com/revolunet/843889
function lzw_encode(s) {
var dict = {};
var data = (s + "").split("");
var out = [];
var currChar;
var phrase = data[0];
var code = 256;
for (var i=1; i<data.length; i++) {
currChar=data[i];
if (dict[phrase + currChar] != null) {
phrase += currChar;
}
else {
out.push(phrase.length > 1 ? dict[phrase] : phrase.charCodeAt(0));
dict[phrase + currChar] = code;
code++;
phrase=currChar;
}
}
out.push(phrase.length > 1 ? dict[phrase] : phrase.charCodeAt(0));
for (var i=0; i<out.length; i++) {
out[i] = String.fromCharCode(out[i]);
}
return out.join("");
}
// Decompress an LZW-encoded string
function lzw_decode(s) {
var dict = {};
var data = (s + "").split("");
var currChar = data[0];
var oldPhrase = currChar;
var out = [currChar];
var code = 256;
var phrase;
for (var i=1; i<data.length; i++) {
var currCode = data[i].charCodeAt(0);
if (currCode < 256) {
phrase = data[i];
}
else {
phrase = dict[currCode] ? dict[currCode] : (oldPhrase + currChar);
}
out.push(phrase);
currChar = phrase.charAt(0);
dict[code] = oldPhrase + currChar;
code++;
oldPhrase = phrase;
}
return out.join("");
}

10
main.js
View File

@ -195,7 +195,7 @@ main.prototype.init = function (mode, callback) {
if (mode === 'editor')main.editor = {'disableGlobalAnimate':true};
}
main.loaderJs('project', main.pureData, function(){
main.loadJs('project', main.pureData, function(){
var mainData = data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.main;
for(var ii in mainData)main[ii]=mainData[ii];
@ -213,7 +213,7 @@ main.prototype.init = function (mode, callback) {
main.dom.levelChooseButtons.appendChild(span);
});
main.loaderJs('libs', main.loadList, function () {
main.loadJs('libs', main.loadList, function () {
main.core = core;
for (i = 0; i < main.loadList.length; i++) {
@ -222,7 +222,7 @@ main.prototype.init = function (mode, callback) {
main.core[name] = new (eval(name))();
}
main.loaderFloors(function() {
main.loadFloors(function() {
var coreData = {};
["dom", "statusBar", "canvas", "images", "tilesets", "materials",
"animates", "bgms", "sounds", "floorIds", "floors"].forEach(function (t) {
@ -236,7 +236,7 @@ main.prototype.init = function (mode, callback) {
}
////// 动态加载所有核心JS文件 //////
main.prototype.loaderJs = function (dir, loadList, callback) {
main.prototype.loadJs = function (dir, loadList, callback) {
// 加载js
main.setMainTipsText('正在加载核心js文件...')
@ -272,7 +272,7 @@ main.prototype.loadMod = function (dir, modName, callback) {
}
////// 动态加载所有楼层(剧本) //////
main.prototype.loaderFloors = function (callback) {
main.prototype.loadFloors = function (callback) {
// 加载js
main.setMainTipsText('正在加载楼层文件...')

View File

@ -388,9 +388,6 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
"startDirectly": false,
"statusCanvas": false,
"statusCanvasRowsOnMobile": 3,
"canOpenBattleAnimate": true,
"showBattleAnimateConfirm": false,
"battleAnimate": false,
"displayEnemyDamage": true,
"displayCritical": true,
"displayExtraDamage": true,

View File

@ -102,14 +102,14 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"text": ">=1直接扣数值"
},
{
"type": "setValue",
"type": "setValue2",
"name": "status:atk",
"value": "status:atk-core.values.weakValue"
"value": "-core.values.weakValue"
},
{
"type": "setValue",
"type": "setValue2",
"name": "status:def",
"value": "status:def-core.values.weakValue"
"value": "-core.values.weakValue"
}
],
"false": [
@ -118,14 +118,14 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
"text": "<1扣比例"
},
{
"type": "setValue",
"name": "flag:equip_atk_buff",
"value": "core.getFlag('equip_atk_buff',1)-core.values.weakValue"
"type": "setValue2",
"name": "flag:__atk_buff__",
"value": "-core.values.weakValue"
},
{
"type": "setValue",
"name": "flag:equip_def_buff",
"value": "core.getFlag('equip_def_buff',1)-core.values.weakValue"
"type": "setValue2",
"name": "flag:__def_buff__",
"value": "-core.values.weakValue"
}
]
}

View File

@ -50,6 +50,12 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
if (hard == 'Hell') { // 噩梦难度
core.setFlag('hard', 4); // 可以用flag:hard来获得当前难度
}
// 设置三围的初始增幅属性均为1
["atk", "def", "mdef"].forEach(function (name) {
core.setFlag("__" + name + "_buff__", 1);
});
core.events.afterLoadData();
},
"win": function(reason, norank) {
@ -178,7 +184,8 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
var enemy = core.material.enemys[enemyId];
// 播放战斗音效和动画
var equipAnimate = 'hand', equipId = (core.status.hero.equipment||[])[0];
var equipAnimate = 'hand',
equipId = (core.status.hero.equipment || [])[0];
if (core.isset(equipId) && core.isset((core.material.items[equipId].equip || {}).animate))
equipAnimate = core.material.items[equipId].equip.animate;
// 检查equipAnimate是否存在SE如果不存在则使用默认音效
@ -202,13 +209,28 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
core.events.lose('战斗失败');
return;
}
// 删除该块
var guards = []; // 支援
if (core.isset(x) && core.isset(y)) {
core.removeBlock(x, y);
guards = core.getFlag("__guards__" + x + "_" + y, []);
core.removeFlag("__guards__" + x + "_" + y);
}
// 获得金币和经验
var money = enemy.money;
guards.forEach(function (g) {
money += core.material.enemys[g[2]].money;
});
if (core.hasItem('coin')) money *= 2;
if (core.hasFlag('curse')) money = 0;
core.status.hero.money += money;
core.status.hero.statistics.money += money;
var experience = enemy.experience;
guards.forEach(function (g) {
experience += core.material.enemys[g[2]].experience;
})
if (core.hasFlag('curse')) experience = 0;
core.status.hero.experience += experience;
core.status.hero.statistics.experience += experience;
@ -219,11 +241,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
hint += ",经验+" + experience;
core.drawTip(hint);
// 删除该块
if (core.isset(x) && core.isset(y)) {
core.removeBlock(x, y);
}
// 事件的处理
var todo = [];
@ -303,8 +320,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
// 如果已有事件正在处理中
if (core.status.event.id == null) {
core.continueAutomaticRoute();
}
else {
} else {
core.clearContinueAutomaticRoute();
}
if (core.isset(callback)) callback();
@ -446,10 +462,12 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
[22, "固伤", function (enemy) { return "战斗前,怪物对勇士造成" + (enemy.damage || 0) + "点固定伤害,无视勇士魔防。"; }],
[23, "重生", "怪物被击败后,角色转换楼层则怪物将再次出现"],
[24, "激光", function (enemy) { return "经过怪物同行或同列时自动减生命" + (enemy.value || 0) + "点"; }],
[25, "光环", function (enemy) {return "同楼层所有怪物生命提升"+(enemy.value||0)+"%,攻击提升"+(enemy.atkValue||0)+"%,防御提升"+(enemy.defValue||0)+"%"+(enemy.add?"可叠加":"不可叠加");}]
[25, "光环", function (enemy) { return "同楼层所有怪物生命提升" + (enemy.value || 0) + "%,攻击提升" + (enemy.atkValue || 0) + "%,防御提升" + (enemy.defValue || 0) + "%" + (enemy.add ? "可叠加" : "不可叠加"); }],
[26, "支援", "当周围一圈的怪物受到攻击时将上前支援,并组成小队战斗。"],
[27, "捕捉", "当走到怪物周围十字时会强制进行战斗。"]
];
},
"getEnemyInfo": function (enemy, hero_hp, hero_atk, hero_def, hero_mdef, x, y, floorId) {
"getEnemyInfo": function (enemy, hero, x, y, floorId) {
// 获得某个怪物变化后的数据;该函数将被伤害计算和怪物手册使用
// 例如:坚固、模仿、仿攻等等
//
@ -460,8 +478,18 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
// floorId该怪物所在的楼层
// 后面三个参数主要是可以在光环等效果上可以适用(也可以按需制作部分范围光环效果)
floorId = floorId || core.status.floorId;
var mon_hp = enemy.hp, mon_atk = enemy.atk, mon_def = enemy.def, mon_special = enemy.special;
var mon_money = enemy.money, mon_experience = enemy.experience, mon_point = enemy.point;
var hero_hp = core.getRealStatusOrDefault(hero, 'hp'),
hero_atk = core.getRealStatusOrDefault(hero, 'atk'),
hero_def = core.getRealStatusOrDefault(hero, 'def'),
hero_mdef = core.getRealStatusOrDefault(hero, 'mdef');
var mon_hp = enemy.hp,
mon_atk = enemy.atk,
mon_def = enemy.def,
mon_special = enemy.special;
var mon_money = enemy.money,
mon_experience = enemy.experience,
mon_point = enemy.point;
// 模仿
if (core.hasSpecial(mon_special, 10)) {
mon_atk = hero_atk;
@ -475,17 +503,23 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
// 光环检查
// 从V2.5.4开始,对光环效果增加缓存,以解决多次重复计算的问题,从而大幅提升运行效率。
// 检查当前楼层所有光环怪物数字25
var hp_buff = 0, atk_buff = 0, def_buff = 0, cnt = 0;
var hp_buff = 0,
atk_buff = 0,
def_buff = 0,
cnt = 0;
// ------ 支援 ------
var guards = [];
// 检查光环缓存
if (!core.isset(core.status.checkBlock.buff)) core.status.checkBlock.buff = {};
if (!core.isset(core.status.checkBlock.cache)) core.status.checkBlock.cache = {};
var index = core.isset(x) && core.isset(y) ? (x + "," + y) : "floor";
var cache = core.status.checkBlock.buff[index];
var cache = core.status.checkBlock.cache[index];
if (!core.isset(cache)) {
// 没有该点的缓存,则遍历每个图块
core.status.maps[floorId].blocks.forEach(function (block) {
if (core.isset(block.event) && !block.disable) {
// 获得该图块的ID
var id = block.event.id, enemy = core.material.enemys[id];
var id = block.event.id,
enemy = core.material.enemys[id];
// 检查是不是怪物,且是否拥有该特殊属性
if (core.isset(enemy) && core.hasSpecial(enemy.special, 25)) {
// 检查是否可叠加
@ -496,19 +530,27 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
cnt++;
}
}
// 检查【支援】技能
if (core.isset(enemy) && core.hasSpecial(enemy.special, 26) &&
// 检查支援条件坐标存在距离为1且不能是自己
// 其他类型的支援怪,比如十字之类的话.... 看着做是一样的
core.isset(x) && core.isset(y) && Math.abs(block.x - x) <= 1 && Math.abs(block.y - y) <= 1 && !(x == block.x && y == block.y)) {
// 记录怪物的x,yID
guards.push([block.x, block.y, id]);
}
// TODO如果有其他类型光环怪物在这里仿照添加检查
}
});
// TODO如果有其他类型光环怪物在这里仿照添加检查hp_buff, atk_buff和def_buff即可。
// 放入缓存中
core.status.checkBlock.buff[index] = {"hp_buff": hp_buff, "atk_buff": atk_buff, "def_buff": def_buff};
}
else {
core.status.checkBlock.cache[index] = { "hp_buff": hp_buff, "atk_buff": atk_buff, "def_buff": def_buff, "guards": guards };
} else {
// 直接使用缓存数据
hp_buff = cache.hp_buff;
atk_buff = cache.atk_buff;
def_buff = cache.def_buff;
guards = cache.guards;
}
// 增加比例;如果要增加数值可以直接在这里修改
@ -531,35 +573,42 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
"money": Math.floor(mon_money),
"experience": Math.floor(mon_experience),
"point": Math.floor(mon_point),
"special": mon_special
"special": mon_special,
"guards": guards, // 返回支援情况
};
},
"getDamageInfo": function (enemy, hero_hp, hero_atk, hero_def, hero_mdef, x, y, floorId) {
"getDamageInfo": function (enemy, hero, x, y, floorId) {
// 获得战斗伤害信息(实际伤害计算函数)
//
// 参数说明:
// enemy该怪物信息
// hero_hp,hero_atk,hero_def,hero_mdef勇士的生命攻防魔防数据
// hero勇士的当前数据如果对应项不存在则会从core.status.hero中取。
// x,y该怪物的坐标查看手册和强制战斗时为undefined
// floorId该怪物所在的楼层
// 后面三个参数主要是可以在光环等效果上可以适用
floorId = floorId || core.status.floorId;
var hero_hp = core.getRealStatusOrDefault(hero, 'hp'),
hero_atk = core.getRealStatusOrDefault(hero, 'atk'),
hero_def = core.getRealStatusOrDefault(hero, 'def'),
hero_mdef = core.getRealStatusOrDefault(hero, 'mdef'),
origin_hero_hp = hero_hp,
origin_hero_atk = hero_atk,
origin_hero_def = hero_def;
// 勇士的负属性都按0计算
hero_hp = Math.max(0, hero_hp);
hero_atk = Math.max(0, hero_atk);
hero_def = Math.max(0, hero_def);
hero_mdef = Math.max(0, hero_mdef);
// 计算装备按比例增加属性后的数值
hero_atk = Math.floor(core.getFlag('equip_atk_buff',1)*hero_atk);
hero_def = Math.floor(core.getFlag('equip_def_buff',1)*hero_def);
hero_mdef = Math.floor(core.getFlag('equip_mdef_buff',1)*hero_mdef);
// 怪物的各项数据
// 对坚固模仿等处理扔到了脚本编辑-getEnemyInfo之中
var enemyInfo = core.enemys.getEnemyInfo(enemy, hero_hp, hero_atk, hero_def, hero_mdef, x, y, floorId);
var mon_hp = enemyInfo.hp, mon_atk = enemyInfo.atk, mon_def = enemyInfo.def, mon_special = enemyInfo.special;
var enemyInfo = core.enemys.getEnemyInfo(enemy, hero, x, y, floorId);
var mon_hp = enemyInfo.hp,
mon_atk = enemyInfo.atk,
mon_def = enemyInfo.def,
mon_special = enemyInfo.special;
// 技能的处理
if (core.getFlag('skill', 0) == 1) { // 开启了技能1二倍斩
@ -624,6 +673,38 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
// 勇士的攻击回合数;为怪物生命除以每回合伤害向上取整
var turn = Math.ceil(mon_hp / hero_per_damage);
// ------ 支援 ----- //
// 这个递归最好想明白为什么flag:extra_turn是怎么用的
var guards = core.getFlag("__guards__" + x + "_" + y, enemyInfo.guards);
var guard_before_current_enemy = false; // ------ 支援怪是先打(true)还是后打(false)
turn += core.getFlag("__extraTurn__", 0);
if (guards.length > 0) {
if (!guard_before_current_enemy) { // --- 先打当前怪物,记录当前回合数
core.setFlag("__extraTurn__", turn);
}
// 获得那些怪物组成小队战斗
for (var i = 0; i < guards.length; i++) {
var gx = guards[i][0],
gy = guards[i][1],
gid = guards[i][2];
// 递归计算支援怪伤害信息这里不传x,y保证不会重复调用
// 这里的mdef传0因为护盾应该只会被计算一次
var info = core.enemys.getDamageInfo(core.material.enemys[gid], origin_hero_hp, origin_hero_atk, origin_hero_def, 0);
if (info == null) { // 小队中任何一个怪物不可战斗直接返回null
return null;
}
// 已经进行的回合数
core.setFlag("__extraTurn__", info.turn);
init_damage += info.damage;
}
if (guard_before_current_enemy) { // --- 先打支援怪物,增加当前回合数
turn += core.getFlag("__extraTurn__", 0);
}
}
core.removeFlag("__extraTurn__");
// ------ 支援END ------ //
// 最终伤害:初始伤害 + 怪物对勇士造成的伤害 + 反击伤害
var damage = init_damage + (turn - 1) * per_damage + turn * counterDamage;
// 再扣去魔防
@ -777,7 +858,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
break;
case 51: // 快捷键3: 飞
if (core.hasItem('centerFly')) {
core.events.useItem('centerFly');
core.events.tryUseItem('centerFly');
}
break;
case 52: // 快捷键4破冰/冰冻/地震/上下楼器/... 其他道具依次判断
@ -878,10 +959,8 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
// 向下取整
if (core.isset(core.status.hero[item]))
core.status.hero[item] = Math.floor(core.status.hero[item]);
// 装备按比例增加属性
var value = Math.floor(core.getStatus(item)*core.getFlag('equip_'+item+'_buff',1));
// 大数据格式化;
core.statusBar[item].innerHTML = core.formatBigNumber(value);
core.statusBar[item].innerHTML = core.formatBigNumber(core.getRealStatus(item));
});
// 设置魔力值
@ -908,8 +987,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
core.statusBar.up.innerHTML = core.formatBigNumber(need - core.getStatus('experience')) || " ";
else
core.statusBar.up.innerHTML = core.formatBigNumber(need) || " ";
}
else core.statusBar.up.innerHTML = " ";
} else core.statusBar.up.innerHTML = " ";
// 钥匙
var keys = ['yellowKey', 'blueKey', 'redKey'];
@ -951,7 +1029,8 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
for (var n = 0; n < blocks.length; n++) {
var block = blocks[n];
if (core.isset(block.event) && !block.disable && block.event.cls.indexOf('enemy') == 0) {
var id = block.event.id, enemy = core.material.enemys[id];
var id = block.event.id,
enemy = core.material.enemys[id];
if (core.isset(enemy)) {
core.status.checkBlock.map[block.x + core.bigmap.width * block.y] = id;
}
@ -966,6 +1045,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
// Step2: 更新领域、阻击伤害
core.status.checkBlock.damage = []; // 记录(x,y)点的伤害;(x,y)对应的值是 x+core.bigmap.width*y
for (var x = 0; x < core.bigmap.width * core.bigmap.height; x++) core.status.checkBlock.damage[x] = 0;
core.status.checkBlock.ambush = [];
for (var x = 0; x < core.bigmap.width; x++) {
for (var y = 0; y < core.bigmap.height; y++) {
@ -991,7 +1071,8 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
for (var dx = -range; dx <= range; dx++) {
for (var dy = -range; dy <= range; dy++) {
if (dx == 0 && dy == 0) continue;
var nx=x+dx, ny=y+dy;
var nx = x + dx,
ny = y + dy;
if (nx < 0 || nx >= core.bigmap.width || ny < 0 || ny >= core.bigmap.height) continue;
// 如果是十字领域,则还需要满足 |dx|+|dy|<=range
if (!zoneSquare && Math.abs(dx) + Math.abs(dy) > range) continue;
@ -1016,12 +1097,25 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
for (var dx = -1; dx <= 1; dx++) {
for (var dy = -1; dy <= 1; dy++) {
if (dx == 0 && dy == 0) continue;
var nx=x+dx, ny=y+dy;
var nx = x + dx,
ny = y + dy;
if (nx < 0 || nx >= core.bigmap.width || ny < 0 || ny >= core.bigmap.height || Math.abs(dx) + Math.abs(dy) > 1) continue;
core.status.checkBlock.damage[nx + ny * core.bigmap.width] += enemy.value || 0;
}
}
}
// 存在捕捉
if (core.enemys.hasSpecial(enemy.special, 27)) {
// 给周围格子加上【捕捉】记号
for (var dir in core.utils.scan) {
var nx = x + core.utils.scan[dir].x,
ny = y + core.utils.scan[dir].y;
if (nx < 0 || nx >= core.bigmap.width || ny < 0 || ny >= core.bigmap.height) continue;
if (!core.isset(core.status.checkBlock.ambush[nx + ny * core.bigmap.width]))
core.status.checkBlock.ambush[nx + ny * core.bigmap.width] = [];
core.status.checkBlock.ambush[nx + ny * core.bigmap.width].push([x, y, id, dir]);
}
}
}
}
}
@ -1171,6 +1265,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
"drawAbout": function() {
// 绘制“关于”界面
core.ui.closePanel();
core.lockControl();
core.status.event.id = 'about';
var left = 48, top = 36, right = 416 - 2 * left, bottom = 416 - 2 * top;

View File

@ -368,13 +368,13 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
"bigKey": "core.removeBlockByIds(core.status.floorId, core.status.event.ui);\ncore.drawMap(core.status.floorId, function () {\n\tcore.drawTip(core.material.items[itemId].name + '使用成功');\n});",
"bomb": "core.playSound('bomb.mp3');\ncore.removeBlockByIds(core.status.floorId, core.status.event.ui);\ncore.drawMap(core.status.floorId, function () {\n\tcore.drawTip(core.material.items[itemId].name + '使用成功');\n\tcore.events.afterUseBomb();\n});",
"hammer": "core.playSound('bomb.mp3');\ncore.removeBlockByIds(core.status.floorId, core.status.event.ui);\ncore.drawMap(core.status.floorId, function () {\n\tcore.drawTip(core.material.items[itemId].name + '使用成功');\n\tcore.events.afterUseBomb();\n});",
"centerFly": "core.playSound('centerFly.mp3');\ncore.clearMap('hero');\ncore.setHeroLoc('x', (core.bigmap.width||13)-1-core.getHeroLoc('x'));\ncore.setHeroLoc('y', (core.bigmap.height||13)-1-core.getHeroLoc('y'));\ncore.drawHero();\ncore.drawTip(core.material.items[itemId].name + '使用成功');",
"centerFly": "core.playSound('centerFly.mp3');\ncore.clearMap('hero');\ncore.setHeroLoc('x', core.bigmap.width-1-core.getHeroLoc('x'));\ncore.setHeroLoc('y', core.bigmap.height-1-core.getHeroLoc('y'));\ncore.drawHero();\ncore.drawTip(core.material.items[itemId].name + '使用成功');",
"upFly": "var loc = {'direction': core.status.hero.loc.direction, 'x': core.status.event.ui.x, 'y': core.status.event.ui.y};\nif (core.status.event.id == 'action') {\n\tcore.insertAction([\n\t\t{\"type\": \"changeFloor\", \"loc\": [loc.x, loc.y], \"direction\": loc.direction, \"floorId\": core.status.event.ui.id},\n\t\t{\"type\": \"tip\", \"text\": core.material.items[itemId].name + '使用成功'}\n\t]);\n}\nelse {\n\tcore.changeFloor(core.status.event.ui.id, null, loc, null, function (){\n\tcore.drawTip(core.material.items[itemId].name + '使用成功');\n\t\tcore.replay();\n\t});\n}",
"downFly": "var loc = {'direction': core.status.hero.loc.direction, 'x': core.status.event.ui.x, 'y': core.status.event.ui.y};\nif (core.status.event.id == 'action') {\n\tcore.insertAction([\n\t\t{\"type\": \"changeFloor\", \"loc\": [loc.x, loc.y], \"direction\": loc.direction, \"floorId\": core.status.event.ui.id},\n\t\t{\"type\": \"tip\", \"text\": core.material.items[itemId].name + '使用成功'}\n\t]);\n}\nelse {\n\tcore.changeFloor(core.status.event.ui.id, null, loc, null, function (){\n\tcore.drawTip(core.material.items[itemId].name + '使用成功');\n\t\tcore.replay();\n\t});\n}\n",
"poisonWine": "core.removeFlag('poison');",
"weakWine": "core.removeFlag('weak');\nif (core.values.weakValue>=1) { // >=1直接扣数值\n\tcore.status.hero.atk += core.values.weakValue;\n\tcore.status.hero.def += core.values.weakValue;\n}\nelse { // <1扣比例\n\tcore.setFlag(\"equip_atk_buff\", core.getFlag(\"equip_atk_buff\", 1) + core.values.weakValue);\n\tcore.setFlag(\"equip_def_buff\", core.getFlag(\"equip_def_buff\", 1) + core.values.weakValue);\n}",
"weakWine": "core.removeFlag('weak');\nif (core.values.weakValue>=1) { // >=1直接扣数值\n\tcore.status.hero.atk += core.values.weakValue;\n\tcore.status.hero.def += core.values.weakValue;\n}\nelse { // <1扣比例\n\tcore.addFlag(\"__atk_buff__\", core.values.weakValue);\n\tcore.addFlag(\"__def_buff__\", core.values.weakValue);\n}",
"curseWine": "core.removeFlag('curse');",
"superWine": "core.removeFlag('poison');\nif (core.hasFlag('weak')) {\n\tcore.removeFlag('weak');\n\tif (core.values.weakValue>=1) { // >=1直接扣数值\n\t\tcore.status.hero.atk += core.values.weakValue;\n\t\tcore.status.hero.def += core.values.weakValue;\n\t}\n\telse { // <1扣比例\n\t\tcore.setFlag(\"equip_atk_buff\", core.getFlag(\"equip_atk_buff\", 1) + core.values.weakValue);\n\t\tcore.setFlag(\"equip_def_buff\", core.getFlag(\"equip_def_buff\", 1) + core.values.weakValue);\n\t}\n}\ncore.removeFlag('curse');",
"superWine": "core.removeFlag('poison');\nif (core.hasFlag('weak')) {\n\tcore.removeFlag('weak');\n\tif (core.values.weakValue>=1) { // >=1直接扣数值\n\t\tcore.status.hero.atk += core.values.weakValue;\n\t\tcore.status.hero.def += core.values.weakValue;\n\t}\n\telse { // <1扣比例\n\t\tcore.addFlag(\"__atk_buff__\", core.values.weakValue);\n\t\tcore.addFlag(\"__def_buff__\", core.values.weakValue);\n\t}\n}\ncore.removeFlag('curse');",
"lifeWand": "core.insertAction([\n\t{\"type\": \"input\", \"text\": \"请输入生命魔杖使用次数:(0-${item:lifeWand})\"},\n\t{\"type\": \"if\", \"condition\": \"flag:input<=item:lifeWand\",\n\t\t\"true\": [\n\t\t\t{\"type\": \"setValue\", \"name\": \"item:lifeWand\", \"value\": \"item:lifeWand-flag:input\"},\n\t\t\t{\"type\": \"setValue\", \"name\": \"status:hp\", \"value\": \"status:hp+flag:input*100\"},\n\t\t\t\"成功使用${flag:input}次生命魔杖,恢复${flag:input*100}点生命。\"\n\t\t],\n\t\t\"false\": [\"输入不合法!\"]\n\t},\n]);\ncore.addItem('lifeWand', 1);",
"jumpShoes": "core.insertAction({\"type\":\"jumpHero\",\"loc\":[core.nextX(2),core.nextY(2)]});",
"redPotion": "core.status.hero.hp += core.values.redPotion",
@ -395,9 +395,9 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
"bomb": "(function () {\n\tvar ids = [], id2s = [];\n\tfor (var i in core.status.thisMap.blocks) {\n\t\tvar block = core.status.thisMap.blocks[i];\n\t\tif (core.isset(block.event) && !block.disable && block.event.cls.indexOf('enemy')==0 && core.nearHero(block.x, block.y)) {\n\t\t\tvar enemy = core.material.enemys[block.event.id];\n\t\t\tif (core.isset(enemy) && enemy.notBomb) continue;\n\t\t\tif (core.flags.bombFourDirections || (block.x==core.nextX() && block.y==core.nextY()))\n\t\t\t\tids.push(i);\n\t\t\telse\n\t\t\t\tid2s.push(i);\n\t\t}\n\t}\n\tif (ids.length>0) {\n\t\tcore.status.event.ui = ids;\n\t\treturn true;\n\t}\n\tif (id2s.length==1) {\n\t\tcore.status.event.ui = id2s;\n\t\treturn true;\n\t}\n\treturn false;\n})();",
"hammer": "(function() {\n\tvar ids = [], id2s = [];\n\tfor (var i in core.status.thisMap.blocks) {\n\t\tvar block = core.status.thisMap.blocks[i];\n\t\tif (core.isset(block.event) && !block.disable && block.event.cls.indexOf('enemy')==0 && core.nearHero(block.x, block.y)) {\n\t\t\tvar enemy = core.material.enemys[block.event.id];\n\t\t\tif (core.isset(enemy) && enemy.notBomb) continue;\n\t\t\tif (block.x==core.nextX() && block.y==core.nextY())\n\t\t\t\tids.push(i);\n\t\t\telse\n\t\t\t\tid2s.push(i);\n\t\t}\n\t}\n\tif (ids.length>0) {\n\t\tcore.status.event.ui = ids;\n\t\treturn true;\n\t}\n\telse if (id2s.length==1) {\n\t\tcore.status.event.ui = id2s;\n\t\treturn true;\n\t}\n\treturn false;\n})();",
"earthquake": "(function () {\n\tvar able=false;\n\tvar ids = [];\n\tfor (var i in core.status.thisMap.blocks) {\n\t\tvar block = core.status.thisMap.blocks[i];\n\t\tif (core.isset(block.event) && !block.disable &&\n\t\t\t(block.event.canBreak || block.event.id == 'yellowWall' || block.event.id == 'blueWall' || block.event.id == 'whiteWall')) { // 能炸的墙壁\n\t\t\tids.push(i);\n\t\t}\n\t}\n\tif (ids.length>0) {\n\t\tcore.status.event.ui = ids;\n\t\table=true;\n\t}\n\treturn able;\n})();",
"centerFly": "(function () {\n\tvar toX = (core.bigmap.width||13)-1-core.getHeroLoc('x'), toY = (core.bigmap.height||13)-1-core.getHeroLoc('y');\n\tvar id = core.getBlockId(toX, toY);\n\treturn id == null;\n})();",
"upFly": "(function() {\n\tvar floorId = core.status.floorId, index = core.floorIds.indexOf(floorId);\n\tif (index<core.floorIds.length-1) {\n\t\tvar toId = core.floorIds[index+1], toX = core.getHeroLoc('x'), toY = core.getHeroLoc('y');\n\t\tvar mw = core.floors[toId].width||13, mh = core.floors[toId].height||13;\n\t\tif (toX>=0 && toX<mw && toY>=0 && toY<mh && core.getBlock(toX, toY, toId)==null) {\n\t\t\tcore.status.event.ui = {'id': toId, 'x': toX, 'y': toY};\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n})();",
"downFly": "(function() {\n\tvar floorId = core.status.floorId, index = core.floorIds.indexOf(floorId);\n\tif (index>0) {\n\t\tvar toId = core.floorIds[index-1], toX = core.getHeroLoc('x'), toY = core.getHeroLoc('y');\n\t\tvar mw = core.floors[toId].width||13, mh = core.floors[toId].height||13;\n\t\tif (toX>=0 && toX<mw && toY>=0 && toY<mh && core.getBlock(toX, toY, toId)==null) {\n\t\t\tcore.status.event.ui = {'id': toId, 'x': toX, 'y': toY};\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n})();",
"centerFly": "(function () {\n\tvar toX = core.bigmap.width-1-core.getHeroLoc('x'), toY = core.bigmap.height-1-core.getHeroLoc('y');\n\tvar id = core.getBlockId(toX, toY);\n\treturn id == null;\n})();",
"upFly": "(function() {\n\tvar floorId = core.status.floorId, index = core.floorIds.indexOf(floorId);\n\tif (index<core.floorIds.length-1) {\n\t\tvar toId = core.floorIds[index+1], toX = core.getHeroLoc('x'), toY = core.getHeroLoc('y');\n\t\tvar mw = core.floors[toId].width, mh = core.floors[toId].height;\n\t\tif (toX>=0 && toX<mw && toY>=0 && toY<mh && core.getBlock(toX, toY, toId)==null) {\n\t\t\tcore.status.event.ui = {'id': toId, 'x': toX, 'y': toY};\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n})();",
"downFly": "(function() {\n\tvar floorId = core.status.floorId, index = core.floorIds.indexOf(floorId);\n\tif (index>0) {\n\t\tvar toId = core.floorIds[index-1], toX = core.getHeroLoc('x'), toY = core.getHeroLoc('y');\n\t\tvar mw = core.floors[toId].width, mh = core.floors[toId].height;\n\t\tif (toX>=0 && toX<mw && toY>=0 && toY<mh && core.getBlock(toX, toY, toId)==null) {\n\t\t\tcore.status.event.ui = {'id': toId, 'x': toX, 'y': toY};\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n})();",
"snow": "(function () {\n\tvar ids = [], id2s = [];\n\tfor (var i in core.status.thisMap.blocks) {\n\t\tvar block = core.status.thisMap.blocks[i];\n\t\tif (core.isset(block.event) && !block.disable && block.event.id == 'lava' && core.nearHero(block.x, block.y)) {\n\t\t\tif (core.flags.snowFourDirections || (block.x == core.nextX() && block.y == core.nextY()))\n\t\t\t\tids.push(i);\n\t\t\telse id2s.push(i);\n\t\t}\n\t}\n\tif (ids.length>0) {\n\t\tcore.status.event.ui = ids;\n\t\treturn true;\n\t}\n\tif (id2s.length==1) {\n\t\tcore.status.event.ui = id2s;\n\t\treturn true;\n\t}\n\treturn false;\n})();",
"bigKey": "(function() {\n\tvar able=false, ids = [];\n\tfor (var i in core.status.thisMap.blocks) {\n\t\tvar block = core.status.thisMap.blocks[i];\n\t\tif (core.isset(block.event) && !block.disable && block.event.id == 'yellowDoor') {\n\t\t\tids.push(i);\n\t\t}\n\t}\n\tif (ids.length>0) {\n\t\tcore.status.event.ui = ids;\n\t\table=true;\n\t}\n\treturn able;\n})();",
"poisonWine": "core.hasFlag('poison');",