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

|
||||

|
||||
|
||||
## 目录结构
|
||||
|
||||
|
||||
367
_docs/_api.md
367
_docs/_api.md
@ -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为目标楼层Id,stair可指定为上/下楼梯,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 // 绘制帮助界面
|
||||
```
|
||||
222
_docs/_start.md
222
_docs/_start.md
@ -1,222 +0,0 @@
|
||||
# 快速上手
|
||||
|
||||
?> 目前版本**v2.3.3**,上次更新时间:* {docsify-updated} *
|
||||
|
||||
在这一节中,将详细介绍做一部塔的流程。现在,让我们来做一部单层塔!
|
||||
|
||||
## 前置需求
|
||||
|
||||
你需要有满足如下条件才能进行制作:
|
||||
|
||||
- Windows 8以上操作系统;Windows 7需要安装.Net Framework 4.0。(能打开同目录下的“启动服务.exe”即可)
|
||||
- Chrome浏览器。其他浏览器可能会导致本地服务器产生闪退等现象。
|
||||
- 一个很好的文本编辑器。推荐带有高亮染色、错误提示等效果。例如:WebStorm,VSCode,或者至少也要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”,运行之。
|
||||
|
||||

|
||||
|
||||
* “启动游戏”按钮将打开一个网页,你能在里面看到现在游戏的效果。
|
||||
* “地图编辑器”允许你以可视化的方式进行编辑地图。
|
||||
* “便捷PS工具”能让你很方便的对自定义素材进行添加。参见[自定义素材](personalization#自定义素材)。
|
||||
* “地图生成器”能让你从已有的截图(如RMXP项目)中立刻生成可被本样板识别的地图数据。
|
||||
* “RM动画导出器”能让你从RMXP中导出动画而被H5魔塔使用。
|
||||
* “JS代码压缩工具”能对JS代码进行压缩,从而减少IO请求数和文件大小。
|
||||
* “伤害和临界值计算器”是一个很便捷的小工具,能对怪物的伤害和临界值进行计算。
|
||||
|
||||
!> **警告:** 非Chrome浏览器(如Edge/IE等)下本地服务器可能表现不正常,会出现闪退等现象。请务必下载安装Chrome浏览器。
|
||||
|
||||
## 新建剧本
|
||||
|
||||
类似于RMXP,本塔每层楼都是一个“剧本”,剧本内主要定义了本层的地图和各种事件。主函数将读取每个剧本,并生成实际的地图供游戏使用。
|
||||
|
||||
我们打开 `project/floors/` 目录,这个目录是所有剧本的目录。我们需要指定一个楼层名,例如MT1;然后,我们可以将`MT0.js`(模板)复制重命名为为`MT1.js`,并使用文本编辑器打开。
|
||||
|
||||

|
||||
|
||||
然后将楼层名改为MT1,floorId改名为MT1;title可以改成任意内容,将在切换楼层时进行显示(比如可以改成“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界面。
|
||||
|
||||

|
||||
|
||||
然后可以在上面任意进行绘制地图。
|
||||
|
||||
!> **如果地图的数字和ID未被定义,则会进行提示:数字和ID未被定义!此时要对素材的ID和数字进行定义,请参见[自定义素材](personalization#自定义素材)。**
|
||||
|
||||
绘制地图完毕后,点击"导出地图",即可在左边看到对应的JSON数组,并且已经复制到了剪切板。将其粘贴到剧本中的map位置即可。
|
||||
|
||||

|
||||
|
||||
!> V2.0版本可以直接将当前地图进行保存或另存为,不需要这样手动打开进行编辑。
|
||||
|
||||
### 从RMXP导入已有的地图
|
||||
|
||||
如果我们想复刻一个现有的,已经被RMXP所制作的塔,也有很便捷的方式,那就是用到我们的“地图生成器”。
|
||||
|
||||
首先,我们打开RMXP和对应的项目,可以看到它的地图。
|
||||
|
||||

|
||||
|
||||
我们打开Windows自带的“截图工具”,并将整个地图有效区域截图下来,并将其复制到剪切板。
|
||||
|
||||

|
||||
|
||||
截图时请注意:**只截取有效游戏空间内数据,并且有效空间内的范围必须是13x13。(如果地图小于13*13,请用星空或墙壁填充到13x13)。**
|
||||
|
||||
确认地图的图片文件已经复制到剪切板后,我们打开“地图生成器”,并点“加载图片”。大约1-2秒后,可以得到地图的数据。
|
||||
|
||||

|
||||
|
||||
然后点击“复制地图”,即可将地图数据复制到剪切板。
|
||||
|
||||
!> **如果有识别不一致的存在,即生成的地图和实际的地图不符,我们可以在地图编辑器中粘贴,再可视化进行编辑。**
|
||||
|
||||
!> **地图生成器默认只支持经典素材。如果有自定义素材需求(例如原版的1层小塔那种素材),请参见[自定义素材](personalization#自定义素材)。**
|
||||
|
||||
!> **请确保截图范围刚好为13x13,并且保证每个位置的像素都是32x32。**
|
||||
|
||||
|
||||
## 录入数据
|
||||
|
||||
有了地图后,我们下一步需要做的就是录入数据。数据主要包括如下几种:
|
||||
|
||||
- 勇士初始的属性
|
||||
- 全局变量(宝石效果、全局Flag等)
|
||||
- 怪物数据(每个怪物的攻防血金币经验等等)
|
||||
|
||||
下面依次进行说明。
|
||||
|
||||
我们打开`data.js`文件,这里面定义了各种全局属性和勇士初始值。
|
||||
|
||||
!> V2.0版本可以直接在地图编辑器的`全塔属性`中进行修改!
|
||||
|
||||
我们可以将本塔标题改名为“1层小塔”,
|
||||
|
||||
游戏的唯一标识符叫onefloor,然后可以直接修改勇士的各项初始数据.
|
||||
|
||||
!> **注:name作为游戏的唯一标识符必须进行修改,否则可能会导致存档等出现问题。**
|
||||
|
||||

|
||||
|
||||
!> **请注意,勇士的初始位置一栏,x为横坐标,y为纵坐标;即,x为从左到右第几列,y为从上到下第几行,均从0开始计算。**
|
||||
|
||||
修改完初始化信息后,接下来我们需要修改道具的信息(比如宝石加攻防的数值,血瓶加生命的数值等)。还是在这个`data.js`文件,往下拉,找到values一项,并进行相应的设置
|
||||
|
||||

|
||||
|
||||
然后,再设置一些系统Flag,以进行游戏。继续将`data.js`往下拉,我们注意到本塔是存在魔防的,不存在经验,因此我们可以简单地将enableMDef改为true,enableExperience改成false,enableDebuff改成false。
|
||||
|
||||
同理,本塔的破墙镐只能破面前的墙壁,因此`pickaxeFourDirections`需要改成`false`。
|
||||
|
||||

|
||||
|
||||
其他的几项暂时不会被涉及到,因此不用考虑。
|
||||
|
||||
全局变量修改完毕后,我们需要告诉主函数加载该楼层。打开`data.js`,找到`floorIds`项,将其值改为楼层ID即MT1。
|
||||
|
||||
最后一步就是录入怪物数据。打开`enemys.js`文件,依次输入你在本塔内使用到的所有怪物的攻防血的数据。其中怪物的特殊属性(special项)与该文件下面的getSpecialText对应。
|
||||
|
||||
!> V2.0版本可以直接在“图块属性”一栏进行修改怪物属性!
|
||||
|
||||

|
||||
|
||||
只需要修改自己用到的怪物属性即可,其他没有用到的怪物完全无所谓。
|
||||
|
||||
做完后保存所有文件,在本地服务器中“启动游戏”,就能立刻看到自己的塔并开始游戏啦!是不是很简单呢!
|
||||
|
||||

|
||||
|
||||
## 压缩与发布
|
||||
|
||||
当你将上述步骤完成后,你实际上已经做出来了一个魔塔,并且可以发布给大家进行游戏了。
|
||||
目前而言发布有如下几种方式:
|
||||
|
||||
- 离线版本:直接将游戏文件夹打包,放到百度网盘等地方供用户下载;用户下载到本地后直接使用浏览器打开`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左右。多少几十像素都是没关系的。
|
||||
|
||||

|
||||
|
||||
**Q: 打开游戏时卡死在了xxx.js加载完毕!无法进入游戏。**
|
||||
|
||||
**A:** 最大的可能是因为少了逗号,或者反括号等等。一般而言VSCode都会有错误提示,你哪里少了东西。
|
||||
|
||||
如果没有,可以采用如下方式debug:
|
||||
|
||||
Ctrl+Shift+I 打开Chrome的控制台,找到Console。
|
||||
|
||||
如果出现了语法错误,会有红色提示 **Unexpected xxx** ,找到后面文件名和行号,打开,使用VSCode检查该处是否存在问题,即可。
|
||||
|
||||

|
||||
|
||||
==========================================================================================
|
||||
|
||||
[继续阅读下一章:元件说明](element)
|
||||
@ -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`函数则给定了每个特殊属性的详细描述。这个描述将在怪物手册中看到。
|
||||
|
||||
@ -1316,13 +1316,11 @@ async可选,如果为true则会异步执行(即不等待当前事件执行
|
||||
### pauseBgm:暂停背景音乐
|
||||
|
||||
使用`{"type": "pauseBgm"}`可以暂停背景音乐的播放。
|
||||
<!--
|
||||
|
||||
### resumeBgm:恢复背景音乐
|
||||
|
||||
使用`{"type": "resumeBgm"}`可以恢复背景音乐的播放。
|
||||
|
||||
**从V2.5.4开始不再支持此事件,请通过设置音量来达到此效果。**
|
||||
-->
|
||||
### loadBgm:预加载一个背景音乐
|
||||
|
||||
使用loadBgm可以预加载一个背景音乐。
|
||||
|
||||
@ -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`**: 当前的剧情文本属性,当前的全局属性,当前的全局开关。
|
||||
|
||||
@ -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':
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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) {
|
||||
return v.idnum || v || 0
|
||||
})
|
||||
}), {'events': evs, 'changeFloor': {}}, editor.currentFloorId);
|
||||
try {
|
||||
return v.idnum || v || 0
|
||||
}
|
||||
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');
|
||||
|
||||
1590
libs/actions.js
1590
libs/actions.js
File diff suppressed because it is too large
Load Diff
106
libs/control.js
106
libs/control.js
@ -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;
|
||||
|
||||
1216
libs/core.js
1216
libs/core.js
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
|
||||
337
libs/enemys.js
337
libs/enemys.js
@ -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,137 +155,137 @@ 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) { // 循环法
|
||||
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);
|
||||
if (nextInfo==null || (typeof nextInfo == 'number')) break;
|
||||
if (pre>nextInfo.damage) {
|
||||
pre = nextInfo.damage;
|
||||
list.push([atk-hero_atk, info.damage-nextInfo.damage]);
|
||||
if (nextInfo.damage<=0 && !core.flags.enableNegativeDamage) break;
|
||||
if (list.length>=number) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else { // 二分法算临界
|
||||
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);
|
||||
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);
|
||||
return nextInfo==null||(typeof nextInfo == 'number')||nextInfo.damage>=pre?null:[start,nextInfo.damage];
|
||||
}
|
||||
var currAtk = hero_atk;
|
||||
while (true) {
|
||||
var next = calNext(currAtk+1, mon_hp+mon_def, pre);
|
||||
if (next == null) break;
|
||||
currAtk = next[0];
|
||||
pre = next[1];
|
||||
list.push([currAtk-hero_atk, info.damage-pre]);
|
||||
if (pre<=0 && !core.flags.enableNegativeDamage) break;
|
||||
if (list.length>=number) break;
|
||||
}
|
||||
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, {"atk": atk}, x, y, floorId);
|
||||
if (nextInfo==null || (typeof nextInfo == 'number')) break;
|
||||
if (pre>nextInfo.damage) {
|
||||
pre = nextInfo.damage;
|
||||
list.push([atk-hero_atk, info.damage-nextInfo.damage]);
|
||||
if (nextInfo.damage<=0 && !core.flags.enableNegativeDamage) break;
|
||||
if (list.length>=number) break;
|
||||
}
|
||||
}
|
||||
if (list.length==0) list.push([0,0]);
|
||||
return list;
|
||||
}
|
||||
|
||||
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, {"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, {"atk": start}, x, y, floorId);
|
||||
return nextInfo==null||(typeof nextInfo == 'number')||nextInfo.damage>=pre?null:[start,nextInfo.damage];
|
||||
}
|
||||
var currAtk = hero_atk;
|
||||
while (true) {
|
||||
var next = calNext(currAtk+1, mon_hp+mon_def, pre);
|
||||
if (next == null) break;
|
||||
currAtk = next[0];
|
||||
pre = next[1];
|
||||
list.push([currAtk-hero_atk, info.damage-pre]);
|
||||
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;
|
||||
|
||||
var enemy = core.material.enemys[enemyId];
|
||||
if (!core.isset(enemy)) continue;
|
||||
|
||||
// 检查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;
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
if (specialText.length>=3) specialText = "多属性...";
|
||||
else specialText = specialText.join(" ");
|
||||
|
||||
var critical = this.nextCriticals(enemyId, 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.critical = critical[0];
|
||||
e.criticalDamage = critical[1];
|
||||
e.defDamage = this.getDefDamage(enemyId,1,null,null,floorId);
|
||||
enemys.push(e);
|
||||
used[enemyId] = true;
|
||||
this._getCurrentEnemys_addEnemy(mapBlocks[b].event.id, enemys, used, floorId);
|
||||
}
|
||||
}
|
||||
return this._getCurrentEnemys_sort(enemys);
|
||||
}
|
||||
|
||||
enemys.sort(function (a, b) {
|
||||
enemys.prototype._getCurrentEnemys_getEnemy = function (enemyId) {
|
||||
var enemy = core.material.enemys[enemyId];
|
||||
if (!core.isset(enemy)) return null;
|
||||
|
||||
// 检查displayIdInBook
|
||||
var tmpId = enemy.displayIdInBook;
|
||||
if (core.isset(core.material.enemys[tmpId])) {
|
||||
enemy = core.material.enemys[tmpId];
|
||||
}
|
||||
return enemy;
|
||||
}
|
||||
|
||||
enemys.prototype._getCurrentEnemys_addEnemy = function (enemyId, enemys, used, floorId) {
|
||||
var enemy = this._getCurrentEnemys_getEnemy(enemyId);
|
||||
if (enemy==null || used[enemy.id]) return;
|
||||
|
||||
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(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.specialText = specialText;
|
||||
e.damage = this.getDamage(enemy, null, null, floorId);
|
||||
e.critical = critical[0];
|
||||
e.criticalDamage = critical[1];
|
||||
e.defDamage = this.getDefDamage(enemy,1,null,null,floorId);
|
||||
enemys.push(e);
|
||||
used[enemy.id] = true;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
112
libs/events.js
112
libs/events.js
@ -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();
|
||||
}
|
||||
post_start();
|
||||
});
|
||||
}
|
||||
|
||||
@ -976,8 +962,7 @@ events.prototype.doAction = function() {
|
||||
this.doAction();
|
||||
break
|
||||
case "loadBgm":
|
||||
if (core.platform.isPC)
|
||||
core.loadBgm(data.name);
|
||||
core.loadBgm(data.name);
|
||||
this.doAction();
|
||||
break;
|
||||
case "freeBgm":
|
||||
@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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') {
|
||||
|
||||
@ -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和坐标信息 //////
|
||||
|
||||
235
libs/items.js
235
libs/items.js
@ -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.status.event.ui = null;
|
||||
core.updateStatusBar();
|
||||
if (!core.isset(core.status.event.id)) {
|
||||
core.status.event.data = null;
|
||||
core.status.event.ui = null;
|
||||
}
|
||||
}
|
||||
|
||||
////// 使用道具 //////
|
||||
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;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
core.playSound('equip.mp3');
|
||||
////// 实际换装的效果 //////
|
||||
items.prototype._loadEquipEffect = function (equipId, unloadEquipId, isPercentage) {
|
||||
// 比较能力值
|
||||
var result = core.compareEquipment(equipId, unloadEquipId);
|
||||
|
||||
var loadEquipType = loadEquip.equip.type;
|
||||
|
||||
// ------ 判定多重装备 ------
|
||||
if (typeof loadEquipType === 'string') {
|
||||
loadEquipType = this.getEquipTypeByName(loadEquipType);
|
||||
if (loadEquipType < 0) {
|
||||
core.drawTip("当前没有"+loadEquip.equip.type+"的空位!");
|
||||
return;
|
||||
}
|
||||
if (isPercentage) {
|
||||
for (var v in result)
|
||||
core.addFlag('__'+v+'_buff__', result[v]/100);
|
||||
}
|
||||
else {
|
||||
for (var v in result)
|
||||
core.status.hero[v] += result[v];
|
||||
}
|
||||
}
|
||||
|
||||
var unloadEquipId = core.status.hero.equipment[loadEquipType];
|
||||
var unloadEquip = core.material.items[unloadEquipId] || {};
|
||||
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 = {};
|
||||
|
||||
// ------ 如果当前装备和目标装备的模式不同(一个百分比一个数值),则需要先脱再穿 ------ //
|
||||
if (core.isset(unloadEquip.equip) && (unloadEquip.equip.percentage||false) != (loadEquip.equip.percentage||false)) {
|
||||
this.unloadEquip(loadEquipType);
|
||||
this.loadEquip(equipId);
|
||||
var loadPercentage = loadEquip.equip.percentage, unloadPercentage = unloadEquip.equip.percentage;
|
||||
|
||||
if (loadPercentage != null && unloadPercentage != null && loadPercentage != unloadPercentage) {
|
||||
this.unloadEquip(type);
|
||||
this.loadEquip(loadId);
|
||||
if (core.isset(callback)) callback();
|
||||
return;
|
||||
}
|
||||
// 下面保证了两者的模式是相同的
|
||||
|
||||
// 比较能力值
|
||||
var result = core.compareEquipment(equipId,unloadEquipId);
|
||||
// --- 音效
|
||||
core.playSound('equip.mp3');
|
||||
|
||||
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);
|
||||
}
|
||||
else {
|
||||
core.status.hero.atk += result.atk;
|
||||
core.status.hero.def += result.def;
|
||||
core.status.hero.mdef += result.mdef;
|
||||
}
|
||||
// --- 实际换装
|
||||
this._loadEquipEffect(loadId, unloadId, loadPercentage==null?unloadPercentage:loadPercentage);
|
||||
|
||||
// 更新装备状态
|
||||
core.status.hero.equipment[loadEquipType] = equipId;
|
||||
core.updateStatusBar();
|
||||
// --- 加减
|
||||
if (loadId) core.removeItem(loadId);
|
||||
if (unloadId) core.addItem(unloadId);
|
||||
core.status.hero.equipment[type] = loadId||null;
|
||||
|
||||
// 装备更换完毕:删除换上的装备
|
||||
core.removeItem(equipId);
|
||||
|
||||
// 装备更换完毕:增加卸下的装备
|
||||
if (core.isset(unloadEquipId))
|
||||
core.addItem(unloadEquipId, 1);
|
||||
|
||||
core.drawTip("已装备上"+loadEquip.name, core.material.icons.items[equipId]);
|
||||
// --- 提示
|
||||
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,20 +377,8 @@ 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 = [];
|
||||
|
||||
221
libs/loader.js
221
libs/loader.js
@ -5,10 +5,10 @@ loader.js:负责对资源的加载
|
||||
"use strict";
|
||||
|
||||
function loader() {
|
||||
this.init();
|
||||
this._init();
|
||||
}
|
||||
|
||||
loader.prototype.init = function () {
|
||||
loader.prototype._init = function () {
|
||||
|
||||
}
|
||||
|
||||
@ -22,63 +22,21 @@ 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.loadImages(core.materials, core.material.images, function () {
|
||||
// 加载png图片
|
||||
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
|
||||
core.material.images.autotile = {};
|
||||
var keys = Object.keys(core.material.icons.autotile);
|
||||
var autotiles = {};
|
||||
core.loader.loadImages(keys, autotiles, function () {
|
||||
|
||||
keys.forEach(function (v) {
|
||||
core.material.images.autotile[v] = autotiles[v];
|
||||
});
|
||||
|
||||
setTimeout(function () {
|
||||
core.maps.makeAutotileEdges();
|
||||
});
|
||||
|
||||
// 加载tilesets
|
||||
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];
|
||||
if (img.width%32!=0 || img.height%32!=0) {
|
||||
console.warn("警告!"+imgName+"的宽或高不是32的倍数!");
|
||||
}
|
||||
if (img.width * img.height > 32*32*3000) {
|
||||
console.warn("警告!"+imgName+"上的图块素材个数大于3000!");
|
||||
}
|
||||
}
|
||||
|
||||
core.loader.loadAnimates();
|
||||
core.loader.loadMusic();
|
||||
if (core.isset(callback))
|
||||
callback();
|
||||
})
|
||||
core.loader._loadMaterialImages(function () {
|
||||
core.loader._loadExtraImages(function () {
|
||||
core.loader._loadAutotiles(function () {
|
||||
core.loader._loadTilesets(callback);
|
||||
})
|
||||
})
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
loader.prototype.loadIcons = function () {
|
||||
|
||||
loader.prototype._loadIcons = function () {
|
||||
this.loadImage("icons.png", function (id, image) {
|
||||
var images = core.cropImage(image);
|
||||
for (var key in core.statusBar.icons) {
|
||||
@ -91,6 +49,55 @@ loader.prototype.loadIcons = function () {
|
||||
});
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
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 = {};
|
||||
this.loadImages(keys, autotiles, function () {
|
||||
keys.forEach(function (v) {
|
||||
core.material.images.autotile[v] = autotiles[v];
|
||||
});
|
||||
|
||||
setTimeout(function () {
|
||||
core.maps.makeAutotileEdges();
|
||||
});
|
||||
|
||||
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];
|
||||
if (img.width%32!=0 || img.height%32!=0) {
|
||||
console.warn("警告!"+imgName+"的宽或高不是32的倍数!");
|
||||
}
|
||||
if (img.width * img.height > 32*32*3000) {
|
||||
console.warn("警告!"+imgName+"上的图块素材个数大于3000!");
|
||||
}
|
||||
}
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
loader.prototype.loadImages = function (names, toSave, callback) {
|
||||
if (!core.isset(names) || names.length==0) {
|
||||
if (core.isset(callback)) callback();
|
||||
@ -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());
|
||||
|
||||
994
libs/maps.js
994
libs/maps.js
File diff suppressed because it is too large
Load Diff
355
libs/ui.js
355
libs/ui.js
@ -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);
|
||||
|
||||
|
||||
326
libs/utils.js
326
libs/utils.js
@ -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.decompress = function (value) {
|
||||
try {
|
||||
var output = lzw_decode(value);
|
||||
if (core.isset(output) && output.length > 0)
|
||||
return JSON.parse(output);
|
||||
}
|
||||
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);
|
||||
}
|
||||
catch (e) {main.log(e);}
|
||||
return null;
|
||||
}
|
||||
|
||||
////// 获得本地存储 //////
|
||||
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) {
|
||||
try {
|
||||
return JSON.parse(output);
|
||||
}
|
||||
catch (ee) {
|
||||
// Ignore, use default value
|
||||
}
|
||||
}
|
||||
return JSON.parse(value);
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
catch (e) {
|
||||
main.log(e);
|
||||
return 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));
|
||||
return;
|
||||
} catch (ee) {main.log(ee);}
|
||||
}
|
||||
successCallback(JSON.parse(value));
|
||||
return;
|
||||
}
|
||||
catch (e) {main.log(e);}
|
||||
var res = core.utils.decompress(value);
|
||||
successCallback(res==null?defaultValue:res);
|
||||
return;
|
||||
}
|
||||
successCallback(defaultValue);
|
||||
}
|
||||
@ -400,15 +397,48 @@ utils.prototype.arrayToRGBA = function (color) {
|
||||
return "rgba("+nowR+","+nowG+","+nowB+","+nowA+")";
|
||||
}
|
||||
|
||||
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="";
|
||||
var lastMove = "", cnt=0;
|
||||
|
||||
var id2number = function (id) {
|
||||
var number = core.maps.getNumberById(id);
|
||||
return number==0?id:number;
|
||||
}
|
||||
var ans="", lastMove = "", cnt=0;
|
||||
|
||||
route.forEach(function (t) {
|
||||
if (t=='up' || t=='down' || t=='left' || t=='right') {
|
||||
@ -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++);
|
||||
}
|
||||
if (num.length==0) num="1";
|
||||
return core.isset(noparse)?num:parseInt(num);
|
||||
var decodeObj = {route: route, index: 0, ans: []};
|
||||
while (decodeObj.index < decodeObj.route.length) {
|
||||
this._decodeRoute_decodeOne(decodeObj, decodeObj.route.charAt(decodeObj.index++));
|
||||
}
|
||||
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
10
main.js
@ -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('正在加载楼层文件...')
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -34,22 +34,28 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
|
||||
},
|
||||
"setInitData": function (hard) {
|
||||
// 不同难度分别设置初始属性
|
||||
if (hard=='Easy') { // 简单难度
|
||||
if (hard == 'Easy') { // 简单难度
|
||||
core.setFlag('hard', 1); // 可以用flag:hard来获得当前难度
|
||||
// 可以在此设置一些初始福利,比如设置初始生命值可以调用:
|
||||
// core.setStatus("hp", 10000);
|
||||
// 赠送一把黄钥匙可以调用
|
||||
// core.setItem("yellowKey", 1);
|
||||
}
|
||||
if (hard=='Normal') { // 普通难度
|
||||
if (hard == 'Normal') { // 普通难度
|
||||
core.setFlag('hard', 2); // 可以用flag:hard来获得当前难度
|
||||
}
|
||||
if (hard=='Hard') { // 困难难度
|
||||
if (hard == 'Hard') { // 困难难度
|
||||
core.setFlag('hard', 3); // 可以用flag:hard来获得当前难度
|
||||
}
|
||||
if (hard=='Hell') { // 噩梦难度
|
||||
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) {
|
||||
@ -172,22 +178,23 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
|
||||
core.setFlag('point', point); // 设置flag:point
|
||||
return core.getCommonEvent('加点事件');
|
||||
},
|
||||
"afterBattle": function(enemyId,x,y,callback) {
|
||||
"afterBattle": function (enemyId, x, y, callback) {
|
||||
// 战斗结束后触发的事件
|
||||
|
||||
var enemy = core.material.enemys[enemyId];
|
||||
|
||||
// 播放战斗音效和动画
|
||||
var equipAnimate = 'hand', equipId = (core.status.hero.equipment||[])[0];
|
||||
if (core.isset(equipId) && core.isset((core.material.items[equipId].equip||{}).animate))
|
||||
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,如果不存在则使用默认音效
|
||||
if (!core.isset((core.material.animates[equipAnimate]||{}).se))
|
||||
if (!core.isset((core.material.animates[equipAnimate] || {}).se))
|
||||
core.playSound('attack.mp3');
|
||||
core.drawAnimate(equipAnimate, x, y);
|
||||
|
||||
var damage = core.enemys.getDamage(enemyId, x, y);
|
||||
if (damage == null) damage = core.status.hero.hp+1;
|
||||
if (damage == null) damage = core.status.hero.hp + 1;
|
||||
|
||||
// 扣减体力值
|
||||
core.status.hero.hp -= damage;
|
||||
@ -196,20 +203,35 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
|
||||
core.status.hero.statistics.battleDamage += damage;
|
||||
core.status.hero.statistics.battle++;
|
||||
|
||||
if (core.status.hero.hp<=0) {
|
||||
core.status.hero.hp=0;
|
||||
if (core.status.hero.hp <= 0) {
|
||||
core.status.hero.hp = 0;
|
||||
core.updateStatusBar();
|
||||
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;
|
||||
if (core.hasFlag('curse')) money = 0;
|
||||
core.status.hero.money += money;
|
||||
core.status.hero.statistics.money += money;
|
||||
var experience =enemy.experience;
|
||||
if (core.hasFlag('curse')) experience=0;
|
||||
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;
|
||||
var hint = "打败 " + enemy.name;
|
||||
@ -219,33 +241,28 @@ 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 = [];
|
||||
|
||||
var special = enemy.special;
|
||||
// 中毒
|
||||
if (core.enemys.hasSpecial(special, 12)) {
|
||||
core.push(todo, [{"type": "setValue", "name": "flag:debuff", "value": "'poison'"}]);
|
||||
core.push(todo, [{"type": "insert", "name": "毒衰咒处理"}]);
|
||||
core.push(todo, [{ "type": "setValue", "name": "flag:debuff", "value": "'poison'" }]);
|
||||
core.push(todo, [{ "type": "insert", "name": "毒衰咒处理" }]);
|
||||
}
|
||||
// 衰弱
|
||||
if (core.enemys.hasSpecial(special, 13)) {
|
||||
core.push(todo, [{"type": "setValue", "name": "flag:debuff", "value": "'weak'"}]);
|
||||
core.push(todo, [{"type": "insert", "name": "毒衰咒处理"}]);
|
||||
core.push(todo, [{ "type": "setValue", "name": "flag:debuff", "value": "'weak'" }]);
|
||||
core.push(todo, [{ "type": "insert", "name": "毒衰咒处理" }]);
|
||||
}
|
||||
// 诅咒
|
||||
if (core.enemys.hasSpecial(special, 14)) {
|
||||
core.push(todo, [{"type": "setValue", "name": "flag:debuff", "value": "'curse'"}]);
|
||||
core.push(todo, [{"type": "insert", "name": "毒衰咒处理"}]);
|
||||
core.push(todo, [{ "type": "setValue", "name": "flag:debuff", "value": "'curse'" }]);
|
||||
core.push(todo, [{ "type": "insert", "name": "毒衰咒处理" }]);
|
||||
}
|
||||
// 仇恨属性:减半
|
||||
if (core.flags.hatredDecrease && core.enemys.hasSpecial(special, 17)) {
|
||||
core.setFlag('hatred', parseInt(core.getFlag('hatred', 0)/2));
|
||||
core.setFlag('hatred', parseInt(core.getFlag('hatred', 0) / 2));
|
||||
}
|
||||
// 自爆
|
||||
if (core.enemys.hasSpecial(special, 19)) {
|
||||
@ -253,20 +270,20 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
|
||||
}
|
||||
// 退化
|
||||
if (core.enemys.hasSpecial(special, 21)) {
|
||||
core.status.hero.atk -= (enemy.atkValue||0);
|
||||
core.status.hero.def -= (enemy.defValue||0);
|
||||
if (core.status.hero.atk<0) core.status.hero.atk=0;
|
||||
if (core.status.hero.def<0) core.status.hero.def=0;
|
||||
core.status.hero.atk -= (enemy.atkValue || 0);
|
||||
core.status.hero.def -= (enemy.defValue || 0);
|
||||
if (core.status.hero.atk < 0) core.status.hero.atk = 0;
|
||||
if (core.status.hero.def < 0) core.status.hero.def = 0;
|
||||
}
|
||||
// 增加仇恨值
|
||||
core.setFlag('hatred', core.getFlag('hatred',0)+core.values.hatred);
|
||||
core.setFlag('hatred', core.getFlag('hatred', 0) + core.values.hatred);
|
||||
|
||||
// 战后的技能处理,比如扣除魔力值
|
||||
if (core.flags.enableSkill) {
|
||||
// 检测当前开启的技能类型
|
||||
var skill = core.getFlag('skill', 0);
|
||||
if (skill==1) { // 技能1:二倍斩
|
||||
core.status.hero.mana-=5; // 扣除5点魔力值
|
||||
if (skill == 1) { // 技能1:二倍斩
|
||||
core.status.hero.mana -= 5; // 扣除5点魔力值
|
||||
}
|
||||
// 关闭技能
|
||||
core.setFlag('skill', 0);
|
||||
@ -276,14 +293,14 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
|
||||
|
||||
// 如果有加点
|
||||
var point = core.material.enemys[enemyId].point;
|
||||
if (core.flags.enableAddPoint && core.isset(point) && point>0) {
|
||||
core.push(todo, [{"type": "setValue", "name": "flag:point", "value": point}]);
|
||||
core.push(todo, [{"type": "insert", "name": "加点事件"}]);
|
||||
if (core.flags.enableAddPoint && core.isset(point) && point > 0) {
|
||||
core.push(todo, [{ "type": "setValue", "name": "flag:point", "value": point }]);
|
||||
core.push(todo, [{ "type": "insert", "name": "加点事件" }]);
|
||||
}
|
||||
|
||||
// 如果该点存在,且有事件 -- V2.5.4 以后阻击怪也可以有战后事件了
|
||||
if (core.isset(x) && core.isset(y)) {
|
||||
core.push(todo, core.floors[core.status.floorId].afterBattle[x+","+y]);
|
||||
core.push(todo, core.floors[core.status.floorId].afterBattle[x + "," + y]);
|
||||
}
|
||||
|
||||
// 在这里增加其他的自定义事件需求
|
||||
@ -296,15 +313,14 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
|
||||
*/
|
||||
|
||||
// 如果事件不为空,将其插入
|
||||
if (todo.length>0) {
|
||||
core.events.insertAction(todo,x,y);
|
||||
if (todo.length > 0) {
|
||||
core.events.insertAction(todo, x, y);
|
||||
}
|
||||
|
||||
// 如果已有事件正在处理中
|
||||
if (core.status.event.id == null) {
|
||||
core.continueAutomaticRoute();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
core.clearContinueAutomaticRoute();
|
||||
}
|
||||
if (core.isset(callback)) callback();
|
||||
@ -417,7 +433,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
|
||||
}
|
||||
},
|
||||
"enemys": {
|
||||
"getSpecials": function() {
|
||||
"getSpecials": function () {
|
||||
// 获得怪物的特殊属性,每一行定义一个特殊属性。
|
||||
// 分为三项,第一项为该特殊属性的数字,第二项为特殊属性的名字,第三项为特殊属性的描述
|
||||
// 可以直接写字符串,也可以写个function将怪物传进去
|
||||
@ -427,29 +443,31 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
|
||||
[3, "坚固", "勇士每回合最多只能对怪物造成1点伤害"],
|
||||
[4, "2连击", "怪物每回合攻击2次"],
|
||||
[5, "3连击", "怪物每回合攻击3次"],
|
||||
[6, function(enemy) {return (enemy.n||4)+"连击";}, function(enemy) {return "怪物每回合攻击"+(enemy.n||4)+"次";}],
|
||||
[7, "破甲", "战斗前,怪物附加角色防御的"+Math.floor(100*core.values.breakArmor||0)+"%作为伤害"],
|
||||
[8, "反击", "战斗时,怪物每回合附加角色攻击的"+Math.floor(100*core.values.counterAttack||0)+"%作为伤害,无视角色防御"],
|
||||
[9, "净化", "战斗前,怪物附加勇士魔防的"+core.values.purify+"倍作为伤害"],
|
||||
[6, function (enemy) { return (enemy.n || 4) + "连击"; }, function (enemy) { return "怪物每回合攻击" + (enemy.n || 4) + "次"; }],
|
||||
[7, "破甲", "战斗前,怪物附加角色防御的" + Math.floor(100 * core.values.breakArmor || 0) + "%作为伤害"],
|
||||
[8, "反击", "战斗时,怪物每回合附加角色攻击的" + Math.floor(100 * core.values.counterAttack || 0) + "%作为伤害,无视角色防御"],
|
||||
[9, "净化", "战斗前,怪物附加勇士魔防的" + core.values.purify + "倍作为伤害"],
|
||||
[10, "模仿", "怪物的攻防和勇士攻防相等"],
|
||||
[11, "吸血", function (enemy) {return "战斗前,怪物首先吸取角色的"+Math.floor(100*enemy.value||0)+"%生命(约" + Math.floor((enemy.value||0)*core.getStatus('hp')) + "点)作为伤害"+(enemy.add?",并把伤害数值加到自身生命上":"");}],
|
||||
[12, "中毒", "战斗后,勇士陷入中毒状态,每一步损失生命"+core.values.poisonDamage+"点"],
|
||||
[13, "衰弱", "战斗后,勇士陷入衰弱状态,攻防暂时下降"+(core.values.weakValue>=1?core.values.weakValue+"点":parseInt(core.values.weakValue*100)+"%")],
|
||||
[11, "吸血", function (enemy) { return "战斗前,怪物首先吸取角色的" + Math.floor(100 * enemy.value || 0) + "%生命(约" + Math.floor((enemy.value || 0) * core.getStatus('hp')) + "点)作为伤害" + (enemy.add ? ",并把伤害数值加到自身生命上" : ""); }],
|
||||
[12, "中毒", "战斗后,勇士陷入中毒状态,每一步损失生命" + core.values.poisonDamage + "点"],
|
||||
[13, "衰弱", "战斗后,勇士陷入衰弱状态,攻防暂时下降" + (core.values.weakValue >= 1 ? core.values.weakValue + "点" : parseInt(core.values.weakValue * 100) + "%")],
|
||||
[14, "诅咒", "战斗后,勇士陷入诅咒状态,战斗无法获得金币和经验"],
|
||||
[15, "领域", function (enemy) {return "经过怪物周围"+(enemy.range||1)+"格时自动减生命"+(enemy.value||0)+"点";}],
|
||||
[15, "领域", function (enemy) { return "经过怪物周围" + (enemy.range || 1) + "格时自动减生命" + (enemy.value || 0) + "点"; }],
|
||||
[16, "夹击", "经过两只相同的怪物中间,勇士生命值变成一半"],
|
||||
[17, "仇恨", "战斗前,怪物附加之前积累的仇恨值作为伤害"+(core.flags.hatredDecrease?";战斗后,释放一半的仇恨值":"")+"。(每杀死一个怪物获得"+(core.values.hatred||0)+"点仇恨值)"],
|
||||
[18, "阻击", function (enemy) {return "经过怪物的十字领域时自动减生命"+(enemy.value||0)+"点,同时怪物后退一格";}],
|
||||
[17, "仇恨", "战斗前,怪物附加之前积累的仇恨值作为伤害" + (core.flags.hatredDecrease ? ";战斗后,释放一半的仇恨值" : "") + "。(每杀死一个怪物获得" + (core.values.hatred || 0) + "点仇恨值)"],
|
||||
[18, "阻击", function (enemy) { return "经过怪物的十字领域时自动减生命" + (enemy.value || 0) + "点,同时怪物后退一格"; }],
|
||||
[19, "自爆", "战斗后勇士的生命值变成1"],
|
||||
[20, "无敌", "勇士无法打败怪物,除非拥有十字架"],
|
||||
[21, "退化", function (enemy) {return "战斗后勇士永久下降"+(enemy.atkValue||0)+"点攻击和"+(enemy.defValue||0)+"点防御";}],
|
||||
[22, "固伤", function (enemy) {return "战斗前,怪物对勇士造成"+(enemy.damage||0)+"点固定伤害,无视勇士魔防。";}],
|
||||
[21, "退化", function (enemy) { return "战斗后勇士永久下降" + (enemy.atkValue || 0) + "点攻击和" + (enemy.defValue || 0) + "点防御"; }],
|
||||
[22, "固伤", function (enemy) { return "战斗前,怪物对勇士造成" + (enemy.damage || 0) + "点固定伤害,无视勇士魔防。"; }],
|
||||
[23, "重生", "怪物被击败后,角色转换楼层则怪物将再次出现"],
|
||||
[24, "激光", function (enemy) {return "经过怪物同行或同列时自动减生命"+(enemy.value||0)+"点";}],
|
||||
[25, "光环", function (enemy) {return "同楼层所有怪物生命提升"+(enemy.value||0)+"%,攻击提升"+(enemy.atkValue||0)+"%,防御提升"+(enemy.defValue||0)+"%,"+(enemy.add?"可叠加":"不可叠加");}]
|
||||
[24, "激光", function (enemy) { return "经过怪物同行或同列时自动减生命" + (enemy.value || 0) + "点"; }],
|
||||
[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 = {};
|
||||
var index = core.isset(x) && core.isset(y) ? (x+","+y) : "floor";
|
||||
var cache = core.status.checkBlock.buff[index];
|
||||
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.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,25 +530,33 @@ 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,y,ID
|
||||
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;
|
||||
}
|
||||
|
||||
// 增加比例;如果要增加数值可以直接在这里修改
|
||||
mon_hp *= (1+hp_buff/100);
|
||||
mon_atk *= (1+atk_buff/100);
|
||||
mon_def *= (1+def_buff/100);
|
||||
mon_hp *= (1 + hp_buff / 100);
|
||||
mon_atk *= (1 + atk_buff / 100);
|
||||
mon_def *= (1 + def_buff / 100);
|
||||
|
||||
|
||||
// TODO:可以在这里新增其他的怪物数据变化
|
||||
@ -531,38 +573,45 @@ 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;
|
||||
|
||||
// 勇士的负属性都按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);
|
||||
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;
|
||||
|
||||
// 计算装备按比例增加属性后的数值
|
||||
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);
|
||||
// 勇士的负属性都按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);
|
||||
|
||||
// 怪物的各项数据
|
||||
// 对坚固模仿等处理扔到了脚本编辑-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:二倍斩
|
||||
if (core.getFlag('skill', 0) == 1) { // 开启了技能1:二倍斩
|
||||
hero_atk *= 2; // 计算时攻击力翻倍
|
||||
}
|
||||
|
||||
@ -599,7 +648,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
|
||||
// 2连击 & 3连击 & N连击
|
||||
if (core.hasSpecial(mon_special, 4)) per_damage *= 2;
|
||||
if (core.hasSpecial(mon_special, 5)) per_damage *= 3;
|
||||
if (core.hasSpecial(mon_special, 6)) per_damage *= (enemy.n||4);
|
||||
if (core.hasSpecial(mon_special, 6)) per_damage *= (enemy.n || 4);
|
||||
|
||||
// 每回合的反击伤害;反击是按照勇士的攻击次数来计算回合
|
||||
var counterDamage = 0;
|
||||
@ -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;
|
||||
// 再扣去魔防
|
||||
@ -631,7 +712,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
|
||||
|
||||
// 检查是否允许负伤
|
||||
if (!core.flags.enableNegativeDamage)
|
||||
damage=Math.max(0, damage);
|
||||
damage = Math.max(0, damage);
|
||||
|
||||
return {
|
||||
"mon_hp": Math.floor(mon_hp),
|
||||
@ -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));
|
||||
});
|
||||
|
||||
// 设置魔力值
|
||||
@ -902,14 +981,13 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
|
||||
// 如果是自定义添加的状态栏,也需要在这里进行设置显示的数值
|
||||
|
||||
// 进阶
|
||||
if (core.flags.enableLevelUp && core.status.hero.lv<core.firstData.levelUp.length) {
|
||||
if (core.flags.enableLevelUp && core.status.hero.lv < core.firstData.levelUp.length) {
|
||||
var need = core.calValue(core.firstData.levelUp[core.status.hero.lv].need);
|
||||
if (core.flags.levelUpLeftMode)
|
||||
core.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'];
|
||||
@ -917,16 +995,16 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
|
||||
core.statusBar[key].innerHTML = core.setTwoDigits(core.status.hero.items.keys[key]);
|
||||
});
|
||||
// 毒衰咒
|
||||
if(core.flags.enableDebuff){
|
||||
core.statusBar.poison.innerHTML = core.hasFlag('poison')?"毒":"";
|
||||
core.statusBar.weak.innerHTML = core.hasFlag('weak')?"衰":"";
|
||||
core.statusBar.curse.innerHTML = core.hasFlag('curse')?"咒":"";
|
||||
if (core.flags.enableDebuff) {
|
||||
core.statusBar.poison.innerHTML = core.hasFlag('poison') ? "毒" : "";
|
||||
core.statusBar.weak.innerHTML = core.hasFlag('weak') ? "衰" : "";
|
||||
core.statusBar.curse.innerHTML = core.hasFlag('curse') ? "咒" : "";
|
||||
}
|
||||
// 破炸飞
|
||||
if (core.flags.enablePZF) {
|
||||
core.statusBar.pickaxe.innerHTML = "破"+core.itemCount('pickaxe');
|
||||
core.statusBar.bomb.innerHTML = "炸"+core.itemCount('bomb');
|
||||
core.statusBar.fly.innerHTML = "飞"+core.itemCount('centerFly');
|
||||
core.statusBar.pickaxe.innerHTML = "破" + core.itemCount('pickaxe');
|
||||
core.statusBar.bomb.innerHTML = "炸" + core.itemCount('bomb');
|
||||
core.statusBar.fly.innerHTML = "飞" + core.itemCount('centerFly');
|
||||
}
|
||||
|
||||
// 难度
|
||||
@ -948,33 +1026,35 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
|
||||
|
||||
// Step1: 更新怪物地图
|
||||
core.status.checkBlock.map = []; // 记录怪物地图
|
||||
for (var n=0;n<blocks.length;n++) {
|
||||
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];
|
||||
if (core.isset(block.event) && !block.disable && block.event.cls.indexOf('enemy') == 0) {
|
||||
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;
|
||||
core.status.checkBlock.map[block.x + core.bigmap.width * block.y] = id;
|
||||
}
|
||||
}
|
||||
// 血网
|
||||
if (core.isset(block.event) && !block.disable &&
|
||||
block.event.id=='lavaNet' && block.event.trigger=='passNet' && !core.hasItem("shoes")) {
|
||||
core.status.checkBlock.map[block.x+core.bigmap.width*block.y]="lavaNet";
|
||||
block.event.id == 'lavaNet' && block.event.trigger == 'passNet' && !core.hasItem("shoes")) {
|
||||
core.status.checkBlock.map[block.x + core.bigmap.width * block.y] = "lavaNet";
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
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++) {
|
||||
var id = core.status.checkBlock.map[x+core.bigmap.width*y];
|
||||
for (var x = 0; x < core.bigmap.width; x++) {
|
||||
for (var y = 0; y < core.bigmap.height; y++) {
|
||||
var id = core.status.checkBlock.map[x + core.bigmap.width * y];
|
||||
if (core.isset(id)) {
|
||||
|
||||
// 如果是血网,直接加上伤害值
|
||||
if (id=="lavaNet") {
|
||||
core.status.checkBlock.damage[x+core.bigmap.width*y]+=core.values.lavaDamage||0;
|
||||
if (id == "lavaNet") {
|
||||
core.status.checkBlock.damage[x + core.bigmap.width * y] += core.values.lavaDamage || 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -986,16 +1066,17 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
|
||||
var range = enemy.range || 1;
|
||||
// 是否是九宫格领域
|
||||
var zoneSquare = false;
|
||||
if (core.isset(enemy.zoneSquare)) zoneSquare=enemy.zoneSquare;
|
||||
if (core.isset(enemy.zoneSquare)) zoneSquare = enemy.zoneSquare;
|
||||
// 在范围内进行搜索,增加领域伤害值
|
||||
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;
|
||||
if (nx<0 || nx>=core.bigmap.width || ny<0 || ny>=core.bigmap.height) continue;
|
||||
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;
|
||||
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;
|
||||
core.status.checkBlock.damage[nx+ny*core.bigmap.width]+=enemy.value||0;
|
||||
if (!zoneSquare && Math.abs(dx) + Math.abs(dy) > range) continue;
|
||||
core.status.checkBlock.damage[nx + ny * core.bigmap.width] += enemy.value || 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1003,25 +1084,38 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
|
||||
// 如果要防止激光伤害,可以直接简单的将 flag:no_laser 设为true
|
||||
if (core.enemys.hasSpecial(enemy.special, 24) && !core.hasFlag("no_laser")) {
|
||||
// 检查同行和同列,增加激光伤害值
|
||||
for (var nx=0;nx<core.bigmap.width;nx++) {
|
||||
if (nx!=x) core.status.checkBlock.damage[nx+y*core.bigmap.width]+=enemy.value||0;
|
||||
for (var nx = 0; nx < core.bigmap.width; nx++) {
|
||||
if (nx != x) core.status.checkBlock.damage[nx + y * core.bigmap.width] += enemy.value || 0;
|
||||
}
|
||||
for (var ny=0;ny<core.bigmap.height;ny++) {
|
||||
if (ny!=y) core.status.checkBlock.damage[x+ny*core.bigmap.width]+=enemy.value||0;
|
||||
for (var ny = 0; ny < core.bigmap.height; ny++) {
|
||||
if (ny != y) core.status.checkBlock.damage[x + ny * core.bigmap.width] += enemy.value || 0;
|
||||
}
|
||||
}
|
||||
// 存在阻击
|
||||
// 如果要防止阻击伤害,可以直接简单的将 flag:no_snipe 设为true
|
||||
if (core.enemys.hasSpecial(enemy.special, 18) && !core.hasFlag("no_snipe")) {
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1030,15 +1124,15 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
|
||||
core.status.checkBlock.betweenAttack = []; // 记录(x,y)点是否有夹击
|
||||
// 如果要防止夹击伤害,可以简单的将 flag:no_betweenAttack 设为true
|
||||
if (!core.hasFlag('no_betweenAttack')) {
|
||||
for (var x=0;x<core.bigmap.width;x++) {
|
||||
for (var y=0;y<core.bigmap.height;y++) {
|
||||
for (var x = 0; x < core.bigmap.width; x++) {
|
||||
for (var y = 0; y < core.bigmap.height; y++) {
|
||||
// 该点是否存在夹击
|
||||
var has=false;
|
||||
var has = false;
|
||||
// 检测左右是否存在相同的怪物,且拥有夹击属性
|
||||
if (x>0 && x<core.bigmap.width-1) {
|
||||
var id1=core.status.checkBlock.map[x-1+core.bigmap.width*y],
|
||||
id2=core.status.checkBlock.map[x+1+core.bigmap.width*y];
|
||||
if (core.isset(id1) && core.isset(id2) && id1==id2) {
|
||||
if (x > 0 && x < core.bigmap.width - 1) {
|
||||
var id1 = core.status.checkBlock.map[x - 1 + core.bigmap.width * y],
|
||||
id2 = core.status.checkBlock.map[x + 1 + core.bigmap.width * y];
|
||||
if (core.isset(id1) && core.isset(id2) && id1 == id2) {
|
||||
var enemy = core.material.enemys[id1];
|
||||
if (core.isset(enemy) && core.enemys.hasSpecial(enemy.special, 16)) {
|
||||
has = true;
|
||||
@ -1046,10 +1140,10 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
|
||||
}
|
||||
}
|
||||
// 检测上下是否存在相同的怪物,且拥有夹击属性
|
||||
if (y>0 && y<core.bigmap.height-1) {
|
||||
var id1=core.status.checkBlock.map[x+core.bigmap.width*(y-1)],
|
||||
id2=core.status.checkBlock.map[x+core.bigmap.width*(y+1)];
|
||||
if (core.isset(id1) && core.isset(id2) && id1==id2) {
|
||||
if (y > 0 && y < core.bigmap.height - 1) {
|
||||
var id1 = core.status.checkBlock.map[x + core.bigmap.width * (y - 1)],
|
||||
id2 = core.status.checkBlock.map[x + core.bigmap.width * (y + 1)];
|
||||
if (core.isset(id1) && core.isset(id2) && id1 == id2) {
|
||||
var enemy = core.material.enemys[id1];
|
||||
if (core.isset(enemy) && core.enemys.hasSpecial(enemy.special, 16)) {
|
||||
has = true;
|
||||
@ -1058,12 +1152,12 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
|
||||
}
|
||||
// 计算夹击伤害
|
||||
if (has) {
|
||||
core.status.checkBlock.betweenAttack[x+core.bigmap.width*y]=true;
|
||||
core.status.checkBlock.betweenAttack[x + core.bigmap.width * y] = true;
|
||||
// 先扣除该点领域/阻击/激光造成的伤害,再算夹击
|
||||
var leftHp = core.status.hero.hp - core.status.checkBlock.damage[x+core.bigmap.width*y];
|
||||
var leftHp = core.status.hero.hp - core.status.checkBlock.damage[x + core.bigmap.width * y];
|
||||
// 1血不夹;core.flags.betweenAttackCeil控制向上还是向下
|
||||
if (leftHp>1)
|
||||
core.status.checkBlock.damage[x+core.bigmap.width*y] += Math.floor((leftHp+(core.flags.betweenAttackCeil?0:1))/2);
|
||||
if (leftHp > 1)
|
||||
core.status.checkBlock.damage[x + core.bigmap.width * y] += Math.floor((leftHp + (core.flags.betweenAttackCeil ? 0 : 1)) / 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
|
||||
@ -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');",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user