diff --git a/API列表.txt b/API列表.txt index 6271e411..4bbd2864 100644 --- a/API列表.txt +++ b/API列表.txt @@ -1,19 +1,20 @@ -附录:API列表(V2.6.3版) +# 附录:API列表 + +?> 目前版本**v2.6.5**,上次更新时间:* {docsify-updated} * 这里将列出所有被转发到core的API,没有被转发的函数此处不会列出,请自行在代码中查看。 -本文档较大,如有什么需求请自行Ctrl+F进行搜索。 +本附录量较大,如有什么需求请自行Ctrl+F进行搜索。 如有任何疑问,请联系小艾寻求帮助。 ------------------------------------- [core.js] ------------------------------------ +## core.js core.js中只有很少的几个函数,主要是游戏开始前的初始化等。 + 但是,core中定义了很多游戏运行时的状态,这些状态很多都会被使用到。 - - - +``` text core.__SIZE__, core.__PIXELS__ 游戏窗口大小;对于13x13的游戏而言这两个值分别是13和416,15x15来说分别是15和480。 @@ -163,17 +164,13 @@ core.doFunc(func, _this) 执行一个函数,func为函数体或者插件中的函数名,_this为使用的this。 如果func为一个字符串,则视为插件中的函数名,同时_this将被设置成core.plugin。 此函数剩余参数将作为参数被传入func。 +``` - - - ------------------------------------- [actions.js] ------------------------------------ +## actions.js actions.js主要是处理一些和用户交互相关的内容。 - - - +```text core.registerAction(action, name, func, priority) 注册一个用户交互行为。 action:要注册的交互类型,如 ondown, onclick, keyDown 等等。 @@ -259,11 +256,9 @@ core.longClick() 请勿直接覆盖或调用此函数,如有需要请注册一个"keyDownCtrl"的交互函数。 注册的交互函数如果某一项返回true,则之后仍然会继续触发该长按, 如果全部返回false则将停止本次长按行为,直到手指离开屏幕并重新进行长按为止。 +``` - - - ------------------------------------- [control.js] ------------------------------------ +## control.js control.js将负责整个游戏的核心控制系统,分为如下几个部分: - requestAnimationFrame相关 @@ -277,9 +272,7 @@ control.js将负责整个游戏的核心控制系统,分为如下几个部分 - 状态栏和工具栏相关 - 界面resize相关 - - - +```text // ------ requestAnimationFrame 相关 ------ // core.registerAnimationFrame(name, needPlaying, func) @@ -345,7 +338,7 @@ core.setHeroMoveInterval(callback) core.moveOneStep(x, y) -每走完一步后执行的操作,被转发到了脚本编辑中。 +每走完一步后执行的操作,被转发到了脚本编辑中,执行脚本编辑moveOneStep中的内容。 core.moveAction(callback) @@ -356,6 +349,7 @@ core.moveAction(callback) core.moveHero(direction, callback) 令勇士朝一个方向行走。如果设置了callback,则只会行走一步,并执行回调。 否则,将一直朝该方向行走,直到core.status.heroStop为true为止。 +direction可为"up","down","right","left",分别对应上,下,右,左。 core.isMoving() @@ -368,10 +362,11 @@ core.waitHeroToStop(callback) core.turnHero(direction) 转向。如果设置了direction则会转到该方向,否则会右转。该函数会自动计入录像。 +direction可为"up","down","right","left",分别对应上,下,右,左。 core.moveDirectly(destX, destY) -尝试瞬间移动到某点,被转发到了脚本编辑中。 +尝试瞬间移动到某点,被转发到了脚本编辑中,执行脚本编辑中的内容。 此函数返回非负值代表成功进行瞬移,返回值是省略的步数;如果返回-1则代表没有成功瞬移。 @@ -506,12 +501,12 @@ core.syncSave(type) / core.syncLoad() core.saveData() -获得要存档的内容,实际转发到了脚本编辑中。 +获得要存档的内容,实际转发到了脚本编辑中,执行脚本编辑中的内容。 core.loadData(data, callback) 实际执行一次读档行为,data为读取到的数据,callback为执行完毕的回调。 -实际转发到了脚本编辑中。 +实际转发到了脚本编辑中,执行脚本编辑中的内容。 core.getSave(index, callback) @@ -541,19 +536,23 @@ core.removeSave(index) // ------ 属性、状态、位置、变量等 ------ // core.setStatus(name, value) -设置勇士当前的某个属性。 +设置勇士当前的某个属性,name可为"atk","def","hp"等。 +如core.setStatus("atk", 100)则为设置勇士攻击为100。 core.addStatus(name, value) -加减勇士当前的某个属性。等价于 core.setStatus(name, core.getStatus(name) + value) +加减勇士当前的某个属性,name可为"atk","def","hp"等。 +如core.addStatus("atk", 100)则为增加勇士攻击100点。 +等价于 core.setStatus(name, core.getStatus(name) + value)。 core.getStatus(name) -获得勇士的某个原始属性值。 +获得勇士的某个原始属性值,该值不受百分比增幅影响。 +譬如你有一件道具加10%的攻击,你可以使用该函数获得你的攻击被增幅前的数值 core.getStatusOrDefault(status, name) -尝试从status中获得某个原始属性值;如果status为null或不存在对应属性值则从勇士属性中获取。 +尝试从status中获得某个原始属性值,该值不受百分比增幅影响;如果status为null或不存在对应属性值则从勇士属性中获取。 此项在伤害计算函数中使用较多,例如传递新的攻击和防御来计算临界和1防减伤。 @@ -579,12 +578,14 @@ core.getBuff(name) core.setHeroLoc(name, value, noGather) -设置勇士位置属性。name只能为'x', 'y'和'direction'之一。 +设置勇士位置属性。name只能为'x'(勇士x坐标), 'y'(勇士y坐标)和'direction'(勇士朝向)之一。 如果noGather为true,则不会聚集所有的跟随者。 +譬如core.setHeroLoc("x", 1, true)则为设置勇士x坐标为1,不聚集所有跟随者。 core.getHeroLoc(name) 获得勇士的某个位置属性。如果name为null则直接返回core.status.hero.loc。 +譬如core.getHeroLoc("x")则返回勇士当前x坐标 core.getLvName(lv) @@ -593,19 +594,26 @@ core.getLvName(lv) core.setFlag(name, value) 设置某个自定义变量或flag。如果value为null则会调用core.removeFlag进行删除。 +这里的变量与事件中使用的变量等价 +譬如core.setFlag("xxx",1)则为设置变量xxx为1。 core.addFlag(name, value) 加减某个自定义的变量或flag。等价于 core.setFlag(name, core.getFlag(name, 0) + value) +这里的变量与事件中使用的变量等价 +譬如core.addFlag("xxx",1)则为增加变量xxx1 core.getFlag(name, defaultValue) -获得某个自定义的变量或flag。如果该flag不存在(从未赋值过),则返回defaultValue值。 +获得某个自定义的变量或flag。如果该flag不存在(从未赋值过),则返回defaultValue的值。 +这里的变量与事件中使用的变量等价 +譬如core.getFlag("xxx",1)则为获得变量xxx的值,如变量xxx不存在则返回1 core.hasFlag(name) 判定是否拥有某个自定义变量或flag。等价于 !!core.getFlag(name, 0) - +这里的变量与事件中使用的变量等价 +譬如core.hasFlag("xxx",1)则为判断变量xxx是否存在 core.removeFlag(name) 删除一个自定义变量或flag。 @@ -626,6 +634,8 @@ core.setWeather(type, level) core.setCurtain(color, time, callback) 更改画面色调。color为更改到的色调,是个三元或四元组;time为渐变时间,0代表立刻切换。 +譬如core.setCurtain([255,255,255,1], 0)即为无回调无等待更改画面色调为白色 + core.screenFlash(color, time, times, callback) @@ -665,7 +675,6 @@ core.updateStatusBar(doNotCheckAutoEvents) 更新状态栏,被转发到了脚本编辑中。此函数还会根据是否在回放来设置工具栏的图标。 如果doNotCheckAutoEvents为true则此时不检查自动事件。 - core.showStatusBar() / core.hideStatusBar(showToolbox) 显示和隐藏状态栏。 如果showToolbox为true,则在竖屏模式下不隐藏工具栏,方便手机存读档操作。 @@ -698,17 +707,13 @@ core.unregisterResize(name) core.resize() 屏幕分辨率改变后的重新自适应。 此函数将根据当前的屏幕分辨率信息,生成一个obj,并传入各个注册好的resize函数中执行。 +``` - - - ------------------------------------- [enemys.js] ------------------------------------ +## enemys.js enemys.js中定义了一系列和怪物相关的API函数。 - - - +```text core.hasSpecial(special, test) 判断是否含有某个特殊属性。test为要检查的特殊属性编号。 special为要测试的内容,允许接收如下类型参数: @@ -719,7 +724,7 @@ special为要测试的内容,允许接收如下类型参数: core.getSpecials() -获得所有特殊属性的列表。实际上被转发到了脚本编辑中。 +获得所有特殊属性的列表。实际上被转发到了脚本编辑中,执行脚本编辑中的内容。 core.getSpecialText(enemy) @@ -759,7 +764,7 @@ number为要计算的临界值数量,不填默认为1。 core.getDefDamage(enemy, k, x, y, floorId) -获得某个怪物的k防减伤值。k可不填默认为1。 +获得某个怪物的k防减伤值。k可不填默认为1,x,y,floorId为当前xy坐标和楼层。 core.getEnemyInfo(enemy, hero, x, y, floorId) @@ -784,13 +789,11 @@ core.getCurrentEnemys(floorId) core.hasEnemyLeft(enemyId, floorId) 检查某个楼层是否还有剩余的(指定)怪物。 -floorId为楼层ID,可忽略表示当前楼层。也可以传数组如["MT0","MT1"]同时检测多个楼层。 +floorId为楼层ID,可忽略表示当前楼层。也可以填数组如["MT0","MT1"]同时检测多个楼层。 enemyId如果不填或null则检查是否剩余任何怪物,否则只检查是否剩余指定的某类怪物。 +``` - - - ------------------------------------- [events.js] ------------------------------------ +## events.js events.js将处理所有和事件相关的操作,主要分为五个部分: - 游戏的开始和结束 @@ -800,8 +803,7 @@ events.js将处理所有和事件相关的操作,主要分为五个部分: - 一些具体事件的执行内容 - - +```text // ------ 游戏的开始和结束 ------ // core.resetGame(hero, hard, floorId, maps, values) @@ -817,16 +819,16 @@ seed为开始时要设置的的种子,route为要开始播放的录像,callb core.setInitData() 根据难度分歧来初始化难度,包括设置flag:hard,设置初始属性等。 -该函数实际被转发到了脚本编辑中。 +该函数实际被转发到了脚本编辑中,执行脚本编辑中的内容。 core.win(reason, norank) 游戏胜利,reason为结局名,norank如果为真则该结局不计入榜单。 -该函数实际被转发到了脚本编辑中。 +该函数实际被转发到了脚本编辑中,执行脚本编辑中的内容。 core.lose(reason) -游戏失败,reason为结局名。该函数实际被转发到了脚本编辑中。 +游戏失败,reason为结局名。该函数实际被转发到了脚本编辑中,执行脚本编辑中的内容。 core.gameOver(ending, fromReplay, norank) @@ -866,7 +868,7 @@ id为怪物的ID,x和y为怪物坐标,force如果为真将强制战斗,cal core.beforeBattle(enemyId, x, y) -战前事件。实际被转发到了脚本编辑中,可以在这里加上一些战前特效。 +战前事件。实际被转发到了脚本编辑中,执行脚本编辑中的内容,可以用于加上一些战前特效。 此函数在“检测能否战斗和自动存档”【之后】执行。 如果需要更早的战前事件,请在插件中覆重写 core.events.doSystemEvent 函数。 此函数返回true则将继续本次战斗,返回false将不再战斗。 @@ -874,7 +876,7 @@ core.beforeBattle(enemyId, x, y) core.afterBattle(enemyId, x, y, callback) 战后事件,将执行扣血、加金币经验、特殊属性处理、战后事件处理等操作。 -实际被转发到了脚本编辑中。 +实际被转发到了脚本编辑中,执行脚本编辑中的内容。 core.openDoor(x, y, needKey, callback) @@ -883,16 +885,17 @@ core.openDoor(x, y, needKey, callback) core.afterOpenDoor(doorId, x, y, callback) -开完一个门后执行的事件,实际被转发到了脚本编辑中。 +开完一个门后执行的事件,实际被转发到了脚本编辑中,执行脚本编辑中的内容。 core.getItem(id, num, x, y, callback) 获得若干个道具。itemId为道具ID,itemNum为获得的道具个数,不填默认为1。 -x和y为道具点的坐标,如果设置则会擦除地图上的该点。 +x和y为道具点的坐标,如果设置则会擦除地图上的该点,也可不填。 +譬如core.getItem("yellowKey",2)会直接获得两把黄钥匙。 core.afterGetItem(id, x, y, callback) -获得一个道具后执行的事件,实际被转发到了脚本编辑中。 +获得一个道具后执行的事件,实际被转发到了脚本编辑中,执行脚本编辑中的内容。 core.getNextItem(noRoute) @@ -929,7 +932,7 @@ core.pushBox(data) core.afterPushBox() -推箱子之后触发的事件,实际被转发到了脚本编辑中。 +推箱子之后触发的事件,实际被转发到了脚本编辑中,执行脚本编辑中的内容。 core.changeLight(id, x, y) @@ -962,10 +965,11 @@ core.startEvents(list, x, y, callback) 此函数将调用core.setEvents,然后停止勇士,再执行core.doAction()。 -core.doAction() +core.doAction(keepUI) 执行下一个自定义事件。 此函数将检测事件列表是否全部执行完毕,如果是则执行回调函数。 否则,将从事件列表中弹出下一个事件,并调用core.doEvent进行执行。 +如果keepUI为true,则不会清掉UI层和selector,适合于自己用脚本的绘制。 core.insertAction(action, x, y, callback, addToLast) @@ -983,6 +987,15 @@ core.getCommonEvent(name) core.recoverEvents(data) 恢复事件现场。一般用于呼出怪物手册、呼出存读档页面等时,恢复事件执行流。 + +core.checkAutoEvents() +检测自动事件并执行。 + + +core.precompile(events) +尝试预编译一段事件。 + + // ------ 点击状态栏图标时执行的一些操作 ------ // core.openBook(fromUserAction) @@ -1030,15 +1043,21 @@ core.follow(name) / core.unfollow(name) core.setValue(name, value, prefix) / core.addValue(name, value, prefix) 设置/增减某个数值。name可以是status:xxx,item:xxx或flag:xxx。 -value可以是一个表达式,将调用core.calValue()计算。prefix为前缀,独立开关使用。 +value可以是一个表达式,将调用core.calValue()计算。prefix为前缀,独立开关使用,脚本中一般忽略。 core.doEffect(effect, need, times) 执行一个effect操作。该函数目前仅被全局商店的status:xxx+=yyy所调用。 +core.setEnemy(id, name, value, prefix) +设置一个怪物属性。id为怪物的ID,name为要设置的项,比如hp,atk,def等等。 +value可以是一个表达式,将调用core.calValue()计算。prefix为前缀,独立开关使用,脚本中一般忽略。 + + core.setFloorInfo(name, values, floorId, prefix) -设置某层楼的楼层属性。 +设置某层楼的楼层属性,其中name为该楼层属性对应的条目,values为要设置的值,floorId为楼层id,prefix一般直接忽略。 +譬如core.setFloorInfo("name","4", "MT1")则为设置MT1显示在状态栏中的层数为4 core.setGlobalAttribute(name, value) @@ -1126,17 +1145,13 @@ core.tryUseItem(itemId) core.afterUseBomb() 使用炸弹或圣锤后的事件。实际被转发到了脚本编辑中。 +``` - - - ------------------------------------- [icons.js] ------------------------------------ +## icons.js icons.js主要是负责素材相关信息,比如某个素材在对应的图片上的位置。 - - - +```text core.getClsFromId(id) 根据某个素材的ID获得该素材的cls @@ -1144,17 +1159,13 @@ core.getClsFromId(id) core.getTilesetOffset(id) 根据某个素材来获得对应的tileset和坐标信息。 如果该素材不是tileset,则返回null。 +``` - - - ------------------------------------- [items.js] ------------------------------------ +## items.js items.js主要负责一切和道具相关的内容。 - - - +```text core.getItemEffect(itemId, itemNum) 即捡即用类的道具获得时的效果。实际对应道具图块属性中的itemEffect框。 @@ -1205,8 +1216,9 @@ core.addItem(itemId, itemNum) core.getEquipTypeByName(name) -根据装备位名称来找到一个空的装备孔,适用于多重装备。 +根据装备位名称来找到一个空的装备孔,适用于多重装备,装备位名称可在全塔属性中设置。 如果没有一个装备孔是该装备名称,则返回-1。 +譬如:core.getEquipTypeByName("武器")默认返回全塔属性中武器对应的装备孔号0。 core.getEquipTypeById(equipId) @@ -1219,11 +1231,12 @@ core.canEquip(equipId, hint) core.loadEquip(equipId, callback) -穿上某个装备。 +穿上某个装备,equipId为装备id。 core.unloadEquip(equipType, callback) 脱下某个装备孔的装备。 +譬如core.unloadEquip(0)则为脱下0号装备孔中的装备,默认0号装备孔对应“武器”,1号装备孔对应“盾牌” core.compareEquipment(compareEquipId, beComparedEquipId) @@ -1238,6 +1251,10 @@ core.quickSaveEquip(index) core.quickLoadEquip() 读取当前套装。index为读取的套装编号。 + + +core.getEquippedStatus(name) +获得装备直接增加的属性数据。 ``` ## loader.js @@ -1273,11 +1290,9 @@ core.loadBgm(name) core.freeBgm(name) 释放一个bgm的内存并移出缓存列表。如果该bgm正在播放则也会立刻停止。 +``` - - - ------------------------------------- [maps.js] ------------------------------------ +## map.js maps.js负责一切和地图相关的处理内容,包括如下几个方面: - 地图的初始化,保存和读取,地图数组的生成 @@ -1288,9 +1303,7 @@ maps.js负责一切和地图相关的处理内容,包括如下几个方面: - 移动/跳跃图块,淡入淡出图块 - 全局动画控制,动画的绘制 - - - +```text // ------ 地图的初始化,保存和读取,地图数组的生成 ------ // core.loadFloor(floorId, map) @@ -1299,7 +1312,7 @@ map为存档信息,如果某项在map中不存在则会从core.floors中读取 core.getNumberById(id) -给定一个图块ID,找到对应的数字。 +给定一个图块ID,找到图块对应的图块编号。 core.initBlock(x, y, id, addInfo, eventFloor) @@ -1435,7 +1448,7 @@ toDraw为要绘制到的信息(可为null,或为一个画布名),包括 // ------ 获得某个点的图块信息 ------ // core.noPass(x, y, floorId) -判定某个点是否有noPass的图块。 +判定某个点是否有noPass(不可通行)的图块。 core.npcExists(x, y, floorId) @@ -1443,7 +1456,7 @@ core.npcExists(x, y, floorId) core.terrainExists(x, y, id, floorId) -判定某个点是否有(指定的)地形存在。 +判定某个点是否有(id对应的)地形存在。 如果id为null,则只要存在terrains即为真,否则还会判定对应点的ID。 @@ -1456,7 +1469,7 @@ core.nearStair() core.enemyExists(x, y, id, floorId) -判定某个点是否有(指定的)怪物存在。 +判定某个点是否有(id对应的)怪物存在。 如果id为null,则只要存在怪物即为真,否则还会判定对应点的怪物ID。 请注意,如果需要判定某个楼层是否存在怪物请使用core.hasEnemyLeft()函数。 @@ -1513,14 +1526,17 @@ core.removeBlock(x, y, floorId) core.removeBlockById(index, floorId) +每个楼层的图块存成一个数组,index即为该数组中的索引,每个索引对应该地图中的一个图块 根据索引从地图的block数组中尽可能删除一个图块。floorId可不填或null表示当前楼层。 core.removeBlockByIds(floorId, ids) +ids为由索引组成的数组,如[0,1]等 根据索引数组从地图的block数组中尽可能删除一系列图块。floorId可不填或null表示当前楼层。 core.canRemoveBlock(block, floorId) +block为图块信息,可由core.getBlock获取 判定当前能否完全删除某个图块。floorId可不填或null表示当前楼层。 如果该点存在自定义事件,或者是重生怪,则不可进行删除。 @@ -1564,7 +1580,7 @@ number为要设置到的图块数字,x,y和floorId为目标点坐标和楼层 core.resetMap(floorId) 重置某层或若干层的地图和楼层属性。 -floorId可为某个楼层ID,或者一个楼层数组(同时重置若干层);如果不填则只重置当前楼层。 +floorId可为某个楼层ID,或者一个楼层数组如["MT1","MT2"](同时重置若干层);如果不填则只重置当前楼层。 // ------ 移动/跳跃图块,淡入淡出图块 ------ // @@ -1611,20 +1627,16 @@ core.drawAnimate(name, x, y, callback) core.stopAnimate(id, doCallback) 立刻停止某个动画的播放。id为上面core.drawAnimate的返回值。 如果doCallback为真,则会执行该动画所对应的回调函数。 +``` - - - ------------------------------------- [ui.js] ------------------------------------ +## ui.js ui.js负责一切UI界面的绘制。主要包括三个部分: - 设置某个画布的属性的相关API - 具体的某个UI界面的绘制 - 动态创建画布相关的API - - - +```text // ------ 设置某个画布的属性的相关API ------// 这系列函数的name一般都是画布名,可以是系统画布或动态创建的画布。 但也同时也允许直接传画布的context本身,将返回自身。 @@ -1641,11 +1653,16 @@ core.clearMap(name) 该函数的name也可以是'all',若为'all'则为清空所有系统画布。 -core.fillText(name, text, x, y, style, font) +core.fillText(name, text, x, y, style, font, maxWidth) 在某个画布上绘制一段文字。 text为要绘制的文本,x,y为要绘制的坐标,style可选为绘制的样式,font可选为绘制的字体。(下同) +style可直接使用"red","white"等或用"rgba(255,255,255,1)"或用"#FFFFFF"等方式来获得字体对应的颜色 +font的格式为"20px Verdana"前者为字体大小,后者为字体 +如果maxWidth不为null,则视为文字最大宽度,如果超过此宽度则会自动放缩文字直到自适应为止。 请注意textAlign和textBaseline将决定绘制的左右对齐和上下对齐方式。 具体可详见core.setTextAlign()和core.setTextBaseline()函数。 +譬如:core.fillText("ui", "这是要描绘的文字", 10, 10, "red", "20px Verdana", 100) +即是在ui图层上,以10,10为起始点,描绘20像素大小,Verdana字体的红色字,长度不超过100像素 core.fillBoldText(name, text, x, y, style, font) @@ -1653,7 +1670,7 @@ core.fillBoldText(name, text, x, y, style, font) core.fillRect(name, x, y, width, height, style) -绘制一个矩形。style可选为绘制样式。如果设置将调用core.setFillStyle()。(下同) +绘制一个矩形。width, height为矩形宽高,style可选为绘制样式。如果设置将调用core.setFillStyle()。(下同) core.strokeRect(name, x, y, width, height, style, lineWidth) @@ -1662,11 +1679,11 @@ lineWidth如果设置将调用core.setLineWidth()。(下同) core.drawLine(name, x1, y1, x2, y2, style, lineWidth) -绘制一条线。 +绘制一条线,x1y1为起始点像素,x2y2为终止点像素。 core.drawArrow(name, x1, y1, x2, y2, style, lineWidth) -绘制一个箭头。 +绘制一个箭头,x1y1为起始点像素,x2y2为终止点像素。 core.setFont(name, font) / core.setLineWidth(name, lineWidth) @@ -1688,7 +1705,7 @@ core.setFillStyle(name, style) / core.setStrokeStyle(name, style) core.setTextAlign(name, align) -设置一个画布的文字横向对齐模式,这里的align只能为'left', 'right'和'center'。 +设置一个画布的文字横向对齐模式,这里的align只能为'left', 'right'和'center',分别对应左对齐,右对齐,居中。 默认为'left'。 @@ -1719,6 +1736,13 @@ core.drawImage(name, image, x, y, w, h, x1, y1, w1, h1) http://www.w3school.com.cn/html5/canvas_drawimage.asp 这里的image允许传一个图片,画布。也允许传递图片名,将从你导入的图片中获取图片内容。 + +core.drawIcon(name, id, x, y, w, h) +在一张画布上绘制一个图标。 +id为注册过的图标ID,也可以使用状态栏的图标ID,例如lv, hp, up, save, settings等。 +x和y为绘制的左上角坐标;w和h可选为绘制的宽高,如果不填或null则使用该图标的默认宽高。 + + // ------ 具体的某个UI界面的绘制 ------ // core.closePanel() 结束一切事件和UI绘制,关闭UI窗口,返回游戏。 @@ -1729,11 +1753,16 @@ core.clearUI() 重置UI窗口。此函数将清掉所有的UI帧动画和光标,清空UI画布,并将alpha设为1。 -core.drawTip(text, id) +core.drawTip(text, id, clear) 在左上角以气泡的形式绘制一段提示。 text为文字内容,仅支持${}的表达式计算,不支持换行和变色。 id可选,为同时绘制的图标ID,如果不为null则会同时绘制该图标(仅对32x32的素材有效)。 也可以使用状态栏的图标ID,例如lv, hp, up, save, settings等。 +如果clear为true,则会清空当前所有正在显示的提示。 + + +core.clearTip() +清空当前所有正在显示的提示。 core.drawText(content, callback) @@ -1763,7 +1792,8 @@ posInfo如果不为null则是一个含position, px和py的对象,表示一个 core.drawTextContent(ctx, content, config) 根据配置在某个画布上绘制一段文字。此函数会被core.drawTextBox()所调用。 ctx为画布名或画布本身,如果不设置则会忽略该函数。 -content为要绘制的文字内容,支持所有的文字效果(如\n,${},\r,\\i,\\c,\\d,\\e等),但不支持支持\t和\b的语法。 +content为要绘制的文字内容,支持所有的文字效果(如\n,${},\r,\\i,\\c,\\d,\\e等) + ,但不支持支持\t和\b的语法。 config为绘制的配置项,目前可以包括如下几项: - left, top:在该画布上绘制的左上角像素位置,不设置默认为(0,0)。 > 该函数绘制时会将textBaseline设置为'top',因此只需要考虑第一个字的左上角位置。 @@ -1772,8 +1802,9 @@ config为绘制的配置项,目前可以包括如下几项: - bold:是否粗体。如果不设置默认为false。 - align:文字对齐方式,仅在maxWidth设置时有效,默认为'left'。 - fontSize:字体大小,如果不设置则使用剧情文本设置中的正文字体大小。 - - lineHeight:绘制的行距值,如果不设置则使用fontSize*1.3(即1.3被行距)。 + - lineHeight:绘制的行距值,如果不设置则使用fontSize*1.3(即1.3倍行距)。 - time:打字机效果。若不为0,则会逐个字进行绘制,并设置core.status.event.interval定时器。 + - interval:字符间的间距。值表示绘制每个字符之间间隔的距离,默认为0。 core.drawTextBox(content, showAll) @@ -1798,7 +1829,7 @@ core.textImage(content, lineHeight) core.drawChoices(content, choices) 绘制一个选项框。 -content可选,为选项上方的提示文字,支持所有的文字效果(如\n,${},\r,\\i,\\c,\\d,\\e等),也支持\t效果。 +content可选,为选项上方的提示文字,支持所有的文字效果(如\n,${},\r,\\i,\\c,\\d,\\e等),也支持\t。 choices必选,为要绘制的选项内容,是一个列表。其中的每一项: - 可以是一个字符串,表示选项文字,将使用剧情文本设置中的正文颜色来绘制,仅支持${}表达式计算。 - 或者是一个包含text, color和icon的对象。 @@ -1865,7 +1896,7 @@ z值为创建的纵向高度(关系到画布之间的覆盖),z值高的将 core.ui.relocateCanvas(name, x, y) -重新定位一个自定义画布。x和y为画布的左上角坐标。 +重新定位一个自定义画布。x和y为画布的左上角坐标,name为画布名。 core.ui.resizeCanvas(name, width, height, styleOnly) @@ -1881,21 +1912,22 @@ core.ui.deleteCanvas(name) core.ui.deleteAllCanvas() 删除所有的自定义画布。 +``` - - - ------------------------------------- [utils.js] ------------------------------------ +## utils.js utils.js是一个工具函数库,里面有各个样板中使用到的工具函数。 - - - +```text core.replayText(text, need, times) 将一段文字中的${}(表达式)进行替换。need和time一般可以直接忽略。 +core.replaceValue(value) +对一个表达式中的特殊规则进行替换,如status:xxx等。 +请注意,此项不会对独立开关如switch:A进行替换。 + + core.calValue(value, prefix, need, time) 计算一个表达式的值,支持status:xxx等的计算。 prefix为前缀(switch:xxx的独立开关使用),need和time一般可以直接忽略。 @@ -2058,6 +2090,7 @@ core.matchWildcard(pattern, string) core.encodeBase64(str) / core.decodeBase64(str) 将字符串进行base64加密或解密。 +可用于解压缩录像数据 core.convertBase(str, fromBase, toBase) @@ -2082,6 +2115,7 @@ num如果设置大于0,则生成一个[0, num-1]之间的数;否则生成一 core.readFile(success, error, accept) 读取一个本地文件内容。success和error分别为读取成功或失败的回调函数。 +accept如果设置则控制能选择的文件类型。 iOS平台暂不支持读取文件操作。 @@ -2141,3 +2175,4 @@ mimeType和responseType如果设置将会覆盖默认值。 lzw_encode(s) / lzw_decode(s) LZW压缩算法,来自https://gist.github.com/revolunet/843889 +``` diff --git a/README.md b/README.md index 2345887d..0b5d5987 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,21 @@ HTML5 canvas制作的魔塔样板,支持全平台游戏! ## 更新说明 +### 2019.12.1 HTML5魔塔样板V2.6.5 + +* [x] 事件:设置怪物属性;穿脱装备 +* [x] 新值块:enemy:xxx:atk可获得怪物数据 +* [x] 新值块:blockId:x,y获得某点图块ID +* [x] 部分事件预编译,加快执行速度 +* [x] 在系统设置中可以设置bgm的播放音量 +* [x] 通关事件可以不退出游戏 +* [x] 失败时允许直接读取自动存档 +* [x] NPC48自动注册可以自动绑定faceIds +* [x] 编辑器Alt+1-9存图块,1-9读取图块 +* [x] 编辑器现在可以跨楼层复制粘贴图块了 +* [x] 可以对flags.进行自动补全 +* [x] 部分Bug修复,大量细节优化 + ### 2019.10.29 HTML5魔塔样板V2.6.4 * [x] 自动事件,多事件页 diff --git a/_docs/V2.0.md b/_docs/V2.0.md index 30a38017..8e468781 100644 --- a/_docs/V2.0.md +++ b/_docs/V2.0.md @@ -1,6 +1,6 @@ # V2.0版本介绍 -?> 目前版本**v2.6.3*,上次更新时间:* {docsify-updated} * +?> 目前版本**v2.6.5*,上次更新时间:* {docsify-updated} * 目前样板已经更新到V2.0版本以上,本章将对V2.0的一些内容进行介绍。 diff --git a/_docs/api.md b/_docs/api.md index 735ddd86..4b938e8d 100644 --- a/_docs/api.md +++ b/_docs/api.md @@ -1,6 +1,6 @@ # 附录:API列表 -?> 目前版本**v2.6.3**,上次更新时间:* {docsify-updated} * +?> 目前版本**v2.6.5**,上次更新时间:* {docsify-updated} * 这里将列出所有被转发到core的API,没有被转发的函数此处不会列出,请自行在代码中查看。 @@ -987,10 +987,15 @@ core.getCommonEvent(name) core.recoverEvents(data) 恢复事件现场。一般用于呼出怪物手册、呼出存读档页面等时,恢复事件执行流。 + core.checkAutoEvents() 检测自动事件并执行。 +core.precompile(events) +尝试预编译一段事件。 + + // ------ 点击状态栏图标时执行的一些操作 ------ // core.openBook(fromUserAction) @@ -1918,6 +1923,11 @@ core.replayText(text, need, times) 将一段文字中的${}(表达式)进行替换。need和time一般可以直接忽略。 +core.replaceValue(value) +对一个表达式中的特殊规则进行替换,如status:xxx等。 +请注意,此项不会对独立开关如switch:A进行替换。 + + core.calValue(value, prefix, need, time) 计算一个表达式的值,支持status:xxx等的计算。 prefix为前缀(switch:xxx的独立开关使用),need和time一般可以直接忽略。 diff --git a/_docs/element.md b/_docs/element.md index b7dca11d..f8197b4f 100644 --- a/_docs/element.md +++ b/_docs/element.md @@ -1,6 +1,6 @@ # 元件说明 -?> 目前版本**v2.6.3**,上次更新时间:* {docsify-updated} * +?> 目前版本**v2.6.5**,上次更新时间:* {docsify-updated} * 在本章中,将对样板里的各个元件进行说明。各个元件主要包括道具、门、怪物、楼梯等等。 diff --git a/_docs/event.md b/_docs/event.md index 20a47522..899978e8 100644 --- a/_docs/event.md +++ b/_docs/event.md @@ -1,6 +1,6 @@ # 事件 -?> 目前版本**v2.6.3**,上次更新时间:* {docsify-updated} * +?> 目前版本**v2.6.5**,上次更新时间:* {docsify-updated} * 本章内将对样板所支持的事件进行介绍。 @@ -315,6 +315,8 @@ 从V2.6开始,也可以使用`global:xxx`代表全局存储(和存档无关的存储)。 +从V2.6.5开始,也可以使用`enemy:id:atk`来获得某个怪物的属性,`blockId:x,y`来获得某个点的图块ID,`equip:x`来获得某个装备孔的装备ID。 + ``` js [ "你当前的攻击力是${status:atk}, 防御是${status:def},坐标是(${status:x},${status:y})", @@ -322,15 +324,21 @@ "你的红黄蓝钥匙总数为${item:yellowKey+item:blueKey+item:redKey}", "你访问某个老人的次数为${flag:man_times}", "当前的存档编号是${global:saveIndex}", + "绿色史莱姆的攻击力是${enemy:greenSlime:atk}", + "(2,3)点的图块ID是${blockId:2,3},图块类型是${blockCls:2,3}", + "装备孔0的当前装备ID是${equip:0}", ] ``` -![](img/events/7.jpg) +![](img/events/7.png) - `status:xxx` 获取勇士属性时只能使用如下几个:hp(生命值),atk(攻击力),def(防御力),mdef(魔防值),money(金币),experience(经验),x(勇士的横坐标),y(勇士的纵坐标),direction(勇士的方向)。 - `item:xxx` 中的xxx为道具ID。所有道具的ID定义在items.js中,请自行查看。例如,`item:centerFly` 代表中心对称飞行器的个数。 - `flag:xxx` 中的xxx为一个自定义的变量/Flag(支持中文);如果没有对其进行赋值则默认值为0。 - `global:xxx` 中的xxx为一个全局存储的名称(支持中文);如果没有对其进行赋值则默认值为0。 +- `enemy:xxx:yyy` 中的xxx为怪物ID;yyy为要获得的项,比如hp, atk, def等等 +- `blockId:x,y` 和 `blockCls:x,y` 中的x,y为坐标值 +- `equip:x` 中的x为装备孔编号,从0开始。 ### autoText:自动剧情文本 @@ -478,7 +486,9 @@ value是一个表达式,将通过这个表达式计算出的结果赋值给nam ![](img/events/13.jpg) -另外注意一点的是,如果hp被设置成了0或以下,将触发lose事件,直接死亡。 +从V2.6.5开始,默认`addValue`不会刷新状态栏、地图显伤和自动事件,除非设置了`"refresh": true`。 + +在刷新的情况下,如果hp被设置成了0或以下,将触发lose事件,直接死亡。 ### addValue:增减勇士的某个属性、道具个数,或某个变量/Flag的值 @@ -499,6 +509,7 @@ value是一个表达式,将通过这个表达式计算出的结果赋值给nam ![](img/events/14.jpg) +从V2.6.5开始,默认`addValue`不会刷新状态栏、地图显伤和自动事件,除非设置了`"refresh": true`。 ### setEnemy:设置怪物属性 @@ -1063,9 +1074,9 @@ time为可选的,指定的话将作为楼层切换动画的时间。 ``` js [ - {"type": "changePos", "id": "pickaxe"}, // 尝试使用破 - {"type": "changePos", "id": "bomb"}, // 尝试使用炸 - {"type": "changePos", "id": "centerFly"} // 尝试使用飞 + {"type": "useItem", "id": "pickaxe"}, // 尝试使用破 + {"type": "useItem", "id": "bomb"}, // 尝试使用炸 + {"type": "useItem", "id": "centerFly"} // 尝试使用飞 ] ``` @@ -1077,6 +1088,32 @@ time为可选的,指定的话将作为楼层切换动画的时间。 不可使用“怪物手册”(请使用【呼出怪物手册】事件)或楼层传送器(如果[覆盖楼传事件](personalization#覆盖楼传事件)则可忽视本项)。 +### loadEquip:装上装备 + +使用`{"type": "loadEquip"}`可以装上一个装备。 + +``` js +[ + {"type": "loadEquip", "id": "sword1"}, // 尝试装上铁剑 +] +``` + +id必填,为需要装备的ID。 + +使用装备时仍会检查条件(比如装备是否存在,能否装备等等)。 + +### unloadEquip:卸下装备 + +使用`{"type": "unloadEquip"}`卸下某个装备孔的装备。 + +``` js +[ + {"type": "unloadEquip", "pos": 0}, // 卸下装备孔0的装备 +] +``` + +pos必填,为要卸下的装备孔编号,从0开始。 + ### openShop:打开一个全局商店 使用openShop可以打开一个全局商店。有关全局商店的说明可参见[全局商店](#全局商店)。 diff --git a/_docs/img/events/7.png b/_docs/img/events/7.png new file mode 100644 index 00000000..a2f60686 Binary files /dev/null and b/_docs/img/events/7.png differ diff --git a/_docs/index.md b/_docs/index.md index 74d241d7..e427c4e6 100644 --- a/_docs/index.md +++ b/_docs/index.md @@ -1,6 +1,6 @@ # HTML5 魔塔样板说明文档 -?> 目前版本**v2.6.3**,上次更新时间:* {docsify-updated} * +?> 目前版本**v2.6.5**,上次更新时间:* {docsify-updated} * 众所周知,魔塔的趋势是向移动端发展,贴吧中也常常能见到“求手机魔塔”的帖子。然而现有的工具中,NekoRPG有着比较大的局限性,游戏感较差,更是完全没法在iOS上运行。而一些APP的魔塔虽然可用,但是必须要下载安装,对于Android和iOS还必须开发不同的版本,非常麻烦。 diff --git a/_docs/personalization.md b/_docs/personalization.md index d7faa37f..7b6dd439 100644 --- a/_docs/personalization.md +++ b/_docs/personalization.md @@ -1,6 +1,6 @@ # 个性化 -?> 目前版本**v2.6.3**,上次更新时间:* {docsify-updated} * +?> 目前版本**v2.6.5**,上次更新时间:* {docsify-updated} * 有时候只靠样板本身可能是不够的。我们需要一些个性化、自定义的素材,道具效果,怪物属性,等等。 diff --git a/_docs/script.md b/_docs/script.md index 44e31e2d..a700fd5b 100644 --- a/_docs/script.md +++ b/_docs/script.md @@ -1,6 +1,6 @@ # 脚本 -?> 目前版本**v2.6.3**,上次更新时间:* {docsify-updated} * +?> 目前版本**v2.6.5**,上次更新时间:* {docsify-updated} * 在V2.6版本中,基本对整个项目代码进行了重写,更加方便造塔者的使用和复写函数。 diff --git a/_docs/start.md b/_docs/start.md index 8db27c1c..a49d99ac 100644 --- a/_docs/start.md +++ b/_docs/start.md @@ -1,6 +1,6 @@ # 快速上手 -?> 目前版本**v2.6.3**,上次更新时间:* {docsify-updated} * +?> 目前版本**v2.6.5**,上次更新时间:* {docsify-updated} * 在这一节中,将详细介绍做一部塔的流程。现在,让我们来做一部单层塔! diff --git a/_server/MotaAction.g4 b/_server/MotaAction.g4 index fcde32aa..c309d06d 100644 --- a/_server/MotaAction.g4 +++ b/_server/MotaAction.g4 @@ -359,6 +359,8 @@ action | setViewport_s | moveViewport_s | useItem_s + | loadEquip_s + | unloadEquip_s | openShop_s | disableShop_s | follow_s @@ -587,26 +589,28 @@ return code; */; setValue_s - : '数值操作' ':' '名称' idString_e '值' expression Newline + : '数值操作' ':' '名称' idString_e '值' expression '刷新状态栏和显伤' Bool Newline /* setValue_s tooltip : setValue:设置勇士的某个属性、道具个数, 或某个变量/Flag的值 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=setvalue%EF%BC%9A%E8%AE%BE%E7%BD%AE%E5%8B%87%E5%A3%AB%E7%9A%84%E6%9F%90%E4%B8%AA%E5%B1%9E%E6%80%A7%E3%80%81%E9%81%93%E5%85%B7%E4%B8%AA%E6%95%B0%EF%BC%8C%E6%88%96%E6%9F%90%E4%B8%AA%E5%8F%98%E9%87%8Fflag%E7%9A%84%E5%80%BC colour : this.dataColor -var code = '{"type": "setValue", "name": "'+idString_e_0+'", "value": "'+expression_0+'"},\n'; +Bool_0 = Bool_0 ? ', "refresh": true' : ''; +var code = '{"type": "setValue", "name": "'+idString_e_0+'", "value": "'+expression_0+'"' + Bool_0 + '},\n'; return code; */; addValue_s - : '数值增减' ':' '名称' idString_e '+=' expression Newline + : '数值增减' ':' '名称' idString_e '+=' expression '刷新状态栏和显伤' Bool Newline /* addValue_s tooltip : addValue:增减勇士的某个属性、道具个数, 或某个变量/Flag的值 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=addValue%ef%bc%9a%e5%a2%9e%e5%87%8f%e5%8b%87%e5%a3%ab%e7%9a%84%e6%9f%90%e4%b8%aa%e5%b1%9e%e6%80%a7%e3%80%81%e9%81%93%e5%85%b7%e4%b8%aa%e6%95%b0%ef%bc%8c%e6%88%96%e6%9f%90%e4%b8%aa%e5%8f%98%e9%87%8f%2fFlag%e7%9a%84%e5%80%bc colour : this.dataColor -var code = '{"type": "addValue", "name": "'+idString_e_0+'", "value": "'+expression_0+'"},\n'; +Bool_0 = Bool_0 ? ', "refresh": true' : ''; +var code = '{"type": "addValue", "name": "'+idString_e_0+'", "value": "'+expression_0+'"' + Bool_0 + '},\n'; return code; */; @@ -1244,6 +1248,32 @@ var code = '{"type": "useItem", "id": "'+IdString_0+'"},\n'; return code; */; +loadEquip_s + : '装上装备' IdString Newline + + +/* loadEquip_s +tooltip : loadEquip: 装上装备 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=useItem%ef%bc%9a%e4%bd%bf%e7%94%a8%e9%81%93%e5%85%b7 +colour : this.dataColor +default : ["sword1"] +var code = '{"type": "loadEquip", "id": "'+IdString_0+'"},\n'; +return code; +*/; + +unloadEquip_s + : '卸下装备孔' Int '的装备' Newline + + +/* unloadEquip_s +tooltip : unloadEquip: 卸下装备 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=useItem%ef%bc%9a%e4%bd%bf%e7%94%a8%e9%81%93%e5%85%b7 +colour : this.dataColor +default : [0] +var code = '{"type": "unloadEquip", "pos": '+Int_0+'},\n'; +return code; +*/; + openShop_s : '打开全局商店' IdString Newline @@ -2636,6 +2666,19 @@ return [code, Blockly.JavaScript.ORDER_ATOMIC]; */; +//这一条不会被antlr识别,总是会被归到idString_e +idString_6_e + : '装备孔:' Int + + +/* idString_6_e +colour : this.idstring_eColor +default : [0] +var code = 'equip:'+Int_0; +return [code, Blockly.JavaScript.ORDER_ATOMIC]; +*/; + + evFlag_e : '独立开关' Letter_List @@ -2854,6 +2897,7 @@ this.block('idString_2_e').output='idString_e'; this.block('idString_3_e').output='idString_e'; this.block('idString_4_e').output='idString_e'; this.block('idString_5_e').output='idString_e'; +this.block('idString_6_e').output='idString_e'; this.block('evFlag_e').output='idString_e'; */ @@ -3272,6 +3316,14 @@ ActionParser.prototype.parseAction = function() { this.next = MotaActionBlocks['useItem_s'].xmlText([ data.id,this.next]); break; + case "loadEquip": // 装上装备 + this.next = MotaActionBlocks['loadEquip_s'].xmlText([ + data.id,this.next]); + break; + case "unloadEquip": // 卸下装备 + this.next = MotaActionBlocks['unloadEquip_s'].xmlText([ + data.pos,this.next]); + break; case "openShop": // 打开一个全局商店 this.next = MotaActionBlocks['openShop_s'].xmlText([ data.id,this.next]); @@ -3346,6 +3398,7 @@ ActionParser.prototype.parseAction = function() { this.next = MotaActionBlocks['setValue_s'].xmlText([ this.tryToUseEvFlag_e('idString_e', [data.name]), MotaActionBlocks['evalString_e'].xmlText([data.value]), + data.refresh || false, this.next]); break; case "setValue2": @@ -3353,6 +3406,7 @@ ActionParser.prototype.parseAction = function() { this.next = MotaActionBlocks['addValue_s'].xmlText([ this.tryToUseEvFlag_e('idString_e', [data.name]), MotaActionBlocks['evalString_e'].xmlText([data.value]), + data.refresh || false, this.next]); break; case "setEnemy": @@ -3922,7 +3976,7 @@ MotaActionFunctions.replaceToName = function (str) { return map[c] ? ("怪物:" + b + ":" + map[c]) : c; }).replace(/enemy:/g, "怪物:"); - str = str.replace(/blockId:/g, "图块ID:").replace(/blockCls:/g, "图块类别:"); + str = str.replace(/blockId:/g, "图块ID:").replace(/blockCls:/g, "图块类别:").replace(/equip:/g, "装备孔:"); return str; } @@ -3952,7 +4006,7 @@ MotaActionFunctions.replaceFromName = function (str) { return map[d] ? ("enemy:" + c + ":" + map[d]) : d; }).replace(/怪物[::]/g, "enemy:"); - str = str.replace(/图块I[dD][::]/g, "blockId:").replace(/图块类别[::]/g, "blockCls:"); + str = str.replace(/图块I[dD][::]/g, "blockId:").replace(/图块类别[::]/g, "blockCls:").replace(/装备孔[::]/g, "equip:"); return str; } diff --git a/_server/editor.js b/_server/editor.js index 54b24e35..252b8e4b 100644 --- a/_server/editor.js +++ b/_server/editor.js @@ -608,6 +608,16 @@ editor.prototype.addUsedFlags = function (s) { s.replace(/flag:([a-zA-Z0-9_\u4E00-\u9FCC]+)/g, function (s0, s1) { editor.used_flags[s1] = true; return s0; }); + s.replace(/flags\.([a-zA-Z_]\w*)/g, function (s0, s1) { + editor.used_flags[s1] = true; return s0; + }); + if (window.flags) { + for (var s in editor.used_flags) { + if (!(s in window.flags)) { + window.flags[s] = null; + } + } + } } editor.prototype.listen = function () { diff --git a/_server/editor_blockly.js b/_server/editor_blockly.js index 53907f1c..29630e30 100644 --- a/_server/editor_blockly.js +++ b/_server/editor_blockly.js @@ -100,10 +100,10 @@ editor_blockly = function () { ], '数据相关':[ MotaActionBlocks['addValue_s'].xmlText([ - MotaActionBlocks['idString_1_e'].xmlText(['status','生命']) + MotaActionBlocks['idString_1_e'].xmlText(['status','生命']), '', false ]), MotaActionBlocks['setValue_s'].xmlText([ - MotaActionBlocks['idString_1_e'].xmlText(['status','生命']) + MotaActionBlocks['idString_1_e'].xmlText(['status','生命']), '', false ]), MotaActionBlocks['setEnemy_s'].xmlText(), MotaActionBlocks['setFloor_s'].xmlText(), @@ -120,6 +120,8 @@ editor_blockly = function () { MotaActionBlocks['changePos_1_s'].xmlText(), MotaActionBlocks['battle_s'].xmlText(), MotaActionBlocks['useItem_s'].xmlText(), + MotaActionBlocks['loadEquip_s'].xmlText(), + MotaActionBlocks['unloadEquip_s'].xmlText(), MotaActionBlocks['openShop_s'].xmlText(), MotaActionBlocks['disableShop_s'].xmlText(), MotaActionBlocks['setHeroIcon_s'].xmlText(), @@ -232,6 +234,7 @@ editor_blockly = function () { MotaActionBlocks['idString_3_e'].xmlText(), MotaActionBlocks['idString_4_e'].xmlText(), MotaActionBlocks['idString_5_e'].xmlText(), + MotaActionBlocks['idString_6_e'].xmlText(), MotaActionBlocks['evalString_e'].xmlText(), ], '常见事件模板':[ @@ -684,7 +687,7 @@ function omitedcheckUpdateFunction(event) { var previewBlock = function (b) { var types = [ "previewUI_s", "clearMap_s", "clearMap_1_s", "setAttribute_s", "fillText_s", - "fillBoldText_s", "drawTextContent_s", "fillRect_s", "strokeRect_s", "drawLine_s", + "fillBoldText_s", "fillRect_s", "strokeRect_s", "drawLine_s", "drawArrow_s", "fillPolygon_s", "strokePolygon_s", "fillCircle_s", "strokeCircle_s", "drawImage_s", "drawImage_1_s", "drawIcon_s", "drawBackground_s", "drawSelector_s", "drawSelector_1_s" ]; @@ -744,7 +747,7 @@ function omitedcheckUpdateFunction(event) { 'comment_s', 'show_s', 'hide_s', - 'setValue_s', + 'addValue_s', 'if_s', 'battle_s', 'openDoor_s', @@ -962,6 +965,16 @@ function omitedcheckUpdateFunction(event) { } } + // 提供 flags.xxx 补全 + index = content.lastIndexOf("flags."); + if (index >= 0) { + var token = content.substring(index+6); + return Object.keys(editor.used_flags || {}).filter(function (one) { + return one != token && one.startsWith(token) + && /^[a-zA-Z_]\w*$/.test(one); + }).sort(); + } + return []; } diff --git a/_server/editor_file_unsorted.js b/_server/editor_file_unsorted.js index 42509f14..c11bd4d8 100644 --- a/_server/editor_file_unsorted.js +++ b/_server/editor_file_unsorted.js @@ -146,11 +146,15 @@ editor_file = function (editor, callback) { var templateActions = []; var image = info.images; + var bindFaceIds = false; if (image=='autotile') { callback('不能对自动元件进行自动注册!'); return; } + if (image=='npc48' && confirm("你想绑定npc48的朝向么?\n如果是,则会连续四个一组的对npc48的faceIds进行自动绑定。")) { + bindFaceIds = true; + } var c=image.toUpperCase().charAt(0); // terrains id @@ -162,15 +166,20 @@ editor_file = function (editor, callback) { var allIds = []; editor.ids.forEach(function (v) { if (v.images==image) { - allIds[v.y]=true; + allIds[v.y]=v; } }) var per_height = image.endsWith('48')?48:32; + var faceIds = []; // down, left, right, up + var idnum=300; for (var y=0; y= 49 && keycode <= 57) { var index = keycode - 49; if (index < length) { @@ -1910,11 +1917,14 @@ actions.prototype._keyUpSL = function (keycode) { ////// 系统设置界面时的点击操作 ////// actions.prototype._clickSwitchs = function (x, y) { - if (x < this.CHOICES_LEFT || x > this.CHOICES_RIGHT) return; var choices = core.status.event.ui.choices; var topIndex = this.HSIZE - parseInt((choices.length - 1) / 2) + (core.status.event.ui.offset || 0); - if (y >= topIndex && y < topIndex + choices.length) { - var selection = y - topIndex; + var selection = y - topIndex; + if (x < this.CHOICES_LEFT || x > this.CHOICES_RIGHT) { + if (selection != 2 && selection != 3) return; + if (x != this.HSIZE - 2 && x != this.HSIZE + 2) return; + } + if (selection >= 0 && selection < choices.length) { core.status.event.selection = selection; switch (selection) { case 0: @@ -1922,18 +1932,24 @@ actions.prototype._clickSwitchs = function (x, y) { case 1: return this._clickSwitchs_sound(); case 2: - return this._clickSwitchs_moveSpeed(); + if (x == this.HSIZE - 2) return this._clickSwitchs_userVolume(-1); + if (x == this.HSIZE + 2) return this._clickSwitchs_userVolume(1); + return; case 3: - return this._clickSwitchs_displayEnemyDamage(); + if (x == this.HSIZE - 2) return this._clickSwitchs_moveSpeed(-10); + if (x == this.HSIZE + 2) return this._clickSwitchs_moveSpeed(10); + return; case 4: - return this._clickSwitchs_displayCritical(); + return this._clickSwitchs_displayEnemyDamage(); case 5: - return this._clickSwitchs_displayExtraDamage(); + return this._clickSwitchs_displayCritical(); case 6: - return this._clickSwitchs_localForage(); + return this._clickSwitchs_displayExtraDamage(); case 7: - return this._clickSwitchs_clickMove(); + return this._clickSwitchs_localForage(); case 8: + return this._clickSwitchs_clickMove(); + case 9: core.status.event.selection = 0; core.ui.drawSettings(); break; @@ -1952,14 +1968,20 @@ actions.prototype._clickSwitchs_sound = function () { core.ui.drawSwitchs(); } -actions.prototype._clickSwitchs_moveSpeed = function () { - core.myprompt("请输入行走速度(每走一步的时间,单位毫秒,默认100)", core.values.moveSpeed, function (value) { - value = parseInt(value) || core.values.moveSpeed; - value = core.clamp(value, 10, 500); - core.values.moveSpeed = value; - core.setLocalStorage("moveSpeed", value); - core.ui.drawSwitchs(); - }); +actions.prototype._clickSwitchs_userVolume = function (delta) { + var value = Math.round(Math.sqrt(100 * core.musicStatus.userVolume)); + core.musicStatus.userVolume = core.clamp(Math.pow(value + delta, 2) / 100, 0, 1); + //audioContext 音效 不受designVolume 影响 + if (core.musicStatus.gainNode != null) core.musicStatus.gainNode.gain.value = core.musicStatus.userVolume; + if (core.musicStatus.playingBgm) core.material.bgms[core.musicStatus.playingBgm].volume = core.musicStatus.userVolume * core.musicStatus.designVolume; + core.setLocalStorage('userVolume', core.musicStatus.userVolume); + core.ui.drawSwitchs(); +} + +actions.prototype._clickSwitchs_moveSpeed = function (delta) { + core.values.moveSpeed = core.clamp(core.values.moveSpeed + delta, 50, 200); + core.setLocalStorage("moveSpeed", core.values.moveSpeed); + core.ui.drawSwitchs(); } actions.prototype._clickSwitchs_displayEnemyDamage = function () { diff --git a/libs/control.js b/libs/control.js index 5f7b5e6b..b978711d 100644 --- a/libs/control.js +++ b/libs/control.js @@ -1465,6 +1465,10 @@ control.prototype._replayAction_equip = function (action) { var index = ownEquipment.indexOf(equipId), per = core.__SIZE__-1; if (index<0) return false; core.status.route.push(action); + if (core.material.items[equipId].hideInReplay) { + core.loadEquip(equipId, core.replay); + return true; + } core.status.event.data = {"page":Math.floor(index/per)+1, "selectId":null}; index = index%per+per; core.ui.drawEquipbox(index); @@ -2247,7 +2251,7 @@ control.prototype._playBgm_play = function (bgm, startTime) { // 缓存BGM core.loader.loadBgm(bgm); // 播放当前BGM - core.material.bgms[bgm].volume = core.musicStatus.volume; + core.material.bgms[bgm].volume = core.musicStatus.userVolume * core.musicStatus.designVolume; core.material.bgms[bgm].currentTime = startTime || 0; core.material.bgms[bgm].play(); core.musicStatus.playingBgm = bgm; @@ -2320,7 +2324,7 @@ control.prototype.playSound = function (sound) { core.musicStatus.playingSounds[id] = source; } else { - core.material.sounds[sound].volume = core.musicStatus.volume; + core.material.sounds[sound].volume = core.musicStatus.userVolume; core.material.sounds[sound].play(); } } diff --git a/libs/core.js b/libs/core.js index 0268bb5a..aacb8b92 100644 --- a/libs/core.js +++ b/libs/core.js @@ -61,7 +61,8 @@ function core() { 'lastBgm': null, // 上次播放的bgm 'gainNode': null, 'playingSounds': {}, // 正在播放的SE - 'volume': 1.0, // 音量 + 'userVolume': 1.0, // 用户音量 + 'designVolume': 1.0, //设计音量 'cachedBgms': [], // 缓存BGM内容 'cachedBgmCount': 4, // 缓存的bgm数量 } @@ -250,12 +251,14 @@ core.prototype._init_flags = function () { var locs = loc.split(","), x = parseInt(locs[0]), y = parseInt(locs[1]); for (var index in autoEvents[loc]) { var autoEvent = core.clone(autoEvents[loc][index]); - if (autoEvent && autoEvent.data) { + if (autoEvent && autoEvent.condition && autoEvent.data) { autoEvent.floorId = floorId; autoEvent.x = x; autoEvent.y = y; autoEvent.index = index; autoEvent.symbol = floorId + "@" + x + "@" + y + "@" + index; + autoEvent.condition = core.replaceValue(autoEvent.condition); + autoEvent.data = core.precompile(autoEvent.data); core.initStatus.autoEvents.push(autoEvent); } } @@ -302,6 +305,8 @@ core.prototype._init_platform = function () { } core.musicStatus.bgmStatus = core.getLocalStorage('bgmStatus', true); core.musicStatus.soundStatus = core.getLocalStorage('soundStatus', true); + //新增 userVolume 默认值1.0 + core.musicStatus.userVolume = core.getLocalStorage('userVolume', 1.0); ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"].forEach(function (t) { if (navigator.userAgent.indexOf(t) >= 0) { if (t == 'iPhone' || t == 'iPad' || t == 'iPod') core.platform.isIOS = true; diff --git a/libs/events.js b/libs/events.js index 85758759..8fbbc4e9 100644 --- a/libs/events.js +++ b/libs/events.js @@ -234,7 +234,14 @@ events.prototype._gameOver_askRate = function (ending) { } if (ending == null) { - core.restart(); + core.status.event.selection = 0; + core.ui.drawConfirmBox("你想读取自动存档么?", function () { + core.ui.closePanel(); + core.doSL("autoSave", "load"); + }, function () { + core.ui.closePanel(); + core.restart(); + }); return; } @@ -931,6 +938,8 @@ events.prototype.insertAction = function (action, x, y, callback, addToLast) { } if (!action) return; + action = this.precompile(action); + if (core.status.event.id != 'action') { this.startEvents(action, x, y, callback); } @@ -1039,6 +1048,98 @@ events.prototype.popEventLoc = function () { } } +events.prototype.precompile = function (data) { + var array = this.__precompile_getArray(); + if (typeof data == 'string') { + return this.__precompile_text(data); + } + if (data instanceof Array) { + for (var i = 0; i < data.length; ++i) { + data[i] = this.precompile(data[i]); + } + return data; + } + if (data && data.type) { + if (this["_precompile_" + data.type]) { + data = this["_precompile_" + data.type](data); + } + if (array.texts.indexOf(data.type) >= 0) { + data.text = this.__precompile_text(data.text); + } + if (array.locs.indexOf(data.type) >= 0) { + data.loc = this.__precompile_array(data.loc); + } + if (array.values.indexOf(data.type) >= 0) { + data.value = core.replaceValue(data.value); + } + if (array.uievents.indexOf(data.type) >= 0) { + data.x = core.replaceValue(data.x); + data.y = core.replaceValue(data.y); + data.width = core.replaceValue(data.width); + data.height = core.replaceValue(data.height); + } + if (data.type in array.others) { + array.others[data.type].forEach(function (field) { + data[field] = core.replaceValue(data[field]); + }) + } + } + return data; +} + +events.prototype.__precompile_getArray = function () { + var texts = [ + "text", "autoText", "scrollText", "tip", "textImage", "input", "input2", + "choices", "confirm", "fillText", "fillBoldText", "drawTextContent" + ]; + var locs = [ + "show", "hide", "setBlock", "showFloorImg", "hideFloorImg", "showBgFgMap", + "hideBgFgMap", "setBgFgBlock", "animate", "setViewport", "move", "jumoHero", + "changeFloor", "changePos", "showTextImage", "showGif", "openDoor", + "closeDoor", "battle", "trigger", "insert" + ]; + var values = [ + "setValue", "setValue2", "addValue", "setEnemy", "setFloor", "setGlobalValue", + ]; + var uievents = [ + "clearMap", "fillText", "fillBoldText", "fillRect", "strokeRect", "strokeCircle", + "drawIcon", "drawSelector", "drawBackground", + ]; + var others = { + "strokeCircle": ["r"], + "drawLine": ["x1", "y1", "x2", "y2"], + "drawArrow": ["x1", "y1", "x2", "y2"], + "drawImage": ["x", "y", "w", "h", "x1", "y1", "w1", "h1"], + "drawTextContent": ["left", "top"], + }; + return { + texts: texts, + locs: locs, + values: values, + uievents: uievents, + others: others + }; +} + +events.prototype.__precompile_text = function (text) { + return text.replace(/\${(.*?)}/g, function (word, value) { + return "${" + core.replaceValue(value) + "}"; + }); +} + +events.prototype.__precompile_array = function (value) { + if (typeof value == 'string') { + value = core.replaceValue(value); + return value; + } + if (value instanceof Array) { + for (var i = 0; i < value.length; ++i) { + value[i] = this.__precompile_array(value[i]); + } + } + return value; +} + // ------ 样板提供的的自定义事件 ------ // events.prototype.__action_checkReplaying = function () { @@ -1231,6 +1332,12 @@ events.prototype._action_jump = function (data, x, y, prefix) { this.__action_doAsyncFunc(data.async, core.jumpBlock, from[0], from[1], to[0], to[1], data.time, data.keep); } +events.prototype._precompile_jump = function (data) { + data.from = this.__precompile_array(data.from); + data.to = this.__precompile_array(data.to); + return data; +} + events.prototype._action_jumpHero = function (data, x, y, prefix) { var loc = this.__action_getHeroLoc(data.loc, prefix); this.__action_doAsyncFunc(data.async, core.jumpHero, loc[0], loc[1], data.time); @@ -1258,6 +1365,12 @@ events.prototype._action_showImage = function (data, x, y, prefix) { data.code, data.image, data.sloc, data.loc, data.opacity, data.time); } +events.prototype._precompile_showImage = function (data) { + data.sloc = this.__precompile_array(data.sloc); + data.loc = this.__precompile_array(data.loc); + return data; +} + events.prototype._action_showTextImage = function (data, x, y, prefix) { var loc = this.__action_getLoc(data.loc, 0, 0, prefix); if (core.isReplaying()) data.time = 0; @@ -1281,6 +1394,11 @@ events.prototype._action_moveImage = function (data, x, y, prefix) { this.__action_doAsyncFunc(data.async, core.moveImage, data.code, data.to, data.opacity, data.time); } +events.prototype._precompile_moveImage = function (data) { + data.to = this.__precompile_array(data.to); + return data; +} + events.prototype._action_setFg = function (data, x, y, prefix) { return this._action_setCurtain(data, x, y, prefix); } @@ -1339,6 +1457,16 @@ events.prototype._action_useItem = function (data, x, y, prefix) { } } +events.prototype._action_loadEquip = function (data, x, y, prefix) { + core.loadEquip(data.id); + core.doAction(); +} + +events.prototype._action_unloadEquip = function (data, x, y, prefix) { + core.unloadEquip(data.pos); + core.doAction(); +} + events.prototype._action_openShop = function (data, x, y, prefix) { core.status.shops[data.id].visited = true; this.setEvents([]); @@ -1453,6 +1581,15 @@ events.prototype._action_setVolume = function (data, x, y, prefix) { events.prototype._action_setValue = function (data, x, y, prefix) { this.setValue(data.name, data.value, prefix); + if (data.refresh) { + if (core.status.hero.hp <= 0) { + core.status.hero.hp = 0; + core.updateStatusBar(); + core.events.lose(); + } else { + core.updateStatusBar(); + } + } core.doAction(); } @@ -1462,6 +1599,15 @@ events.prototype._action_setValue2 = function (data, x, y, prefix) { events.prototype._action_addValue = function (data, x, y, prefix) { this.addValue(data.name, data.value, prefix); + if (data.refresh) { + if (core.status.hero.hp <= 0) { + core.status.hero.hp = 0; + core.updateStatusBar(); + core.events.lose(); + } else { + core.updateStatusBar(); + } + } core.doAction(); } @@ -1542,6 +1688,13 @@ events.prototype._action_if = function (data, x, y, prefix) { core.doAction(); } +events.prototype._precompile_if = function (data) { + data.condition = core.replaceValue(data.condition); + data["true"] = this.precompile(data["true"]); + data["false"] = this.precompile(data["false"]); + return data; +} + events.prototype._action_switch = function (data, x, y, prefix) { var key = core.calValue(data.condition, prefix) var list = []; @@ -1557,6 +1710,15 @@ events.prototype._action_switch = function (data, x, y, prefix) { core.doAction(); } +events.prototype._precompile_switch = function (data) { + data.condition = core.replaceValue(data.condition); + for (var i = 0; i < data.caseList.length; i++) { + data.caseList[i]["case"] = core.replaceValue(data.caseList[i]["case"]); + data.caseList[i].action = this.precompile(data.caseList[i].action); + } + return data; +} + events.prototype._action_choices = function (data, x, y, prefix) { data.choices = data.choices.filter(function (x) { if (x.condition == null || x.condition == '') return true; @@ -1583,6 +1745,16 @@ events.prototype._action_choices = function (data, x, y, prefix) { core.ui.drawChoices(data.text, data.choices); } +events.prototype._precompile_choices = function (data) { + if (!(data.choices instanceof Array)) return data; + for (var i = 0; i < data.choices.length; ++i) { + data.choices[i].condition = core.replaceValue(data.choices[i].condition); + data.choices[i].text = this.__precompile_text(data.choices[i].text); + data.choices[i].action = this.precompile(data.choices[i].action); + } + return data; +} + events.prototype._action_confirm = function (data, x, y, prefix) { core.status.event.ui = {"text": data.text, "yes": data.yes, "no": data.no}; if (core.isReplaying()) { @@ -1609,6 +1781,12 @@ events.prototype._action_confirm = function (data, x, y, prefix) { core.ui.drawConfirmBox(data.text); } +events.prototype._precompile_confirm = function (data) { + data.yes = this.precompile(data.yes); + data.no = this.precompile(data.no); + return data; +} + events.prototype._action_while = function (data, x, y, prefix) { if (core.calValue(data.condition, prefix)) { core.unshift(core.status.event.data.list, @@ -1618,6 +1796,12 @@ events.prototype._action_while = function (data, x, y, prefix) { core.doAction(); } +events.prototype._precompile_while = function (data) { + data.condition = core.replaceValue(data.condition); + data.data = this.precompile(data.data); + return data; +} + events.prototype._action_dowhile = function (data, x, y, prefix) { core.unshift(core.status.event.data.list, {"todo": core.clone(data.data), "total": core.clone(data.data), "condition": data.condition} @@ -1625,6 +1809,12 @@ events.prototype._action_dowhile = function (data, x, y, prefix) { core.doAction(); } +events.prototype._precompile_dowhile = function (data) { + data.condition = core.replaceValue(data.condition); + data.data = this.precompile(data.data); + return data; +} + events.prototype._action_break = function (data, x, y, prefix) { core.status.event.data.list.shift(); core.doAction(); @@ -1641,11 +1831,11 @@ events.prototype._action_continue = function (data, x, y, prefix) { } events.prototype._action_win = function (data, x, y, prefix) { - this.win(data.reason, data.norank, data.noexit); + this.win(core.replaceText(data.reason), data.norank, data.noexit); } events.prototype._action_lose = function (data, x, y, prefix) { - this.lose(data.reason); + this.lose(core.replaceText(data.reason)); } events.prototype._action_restart = function (data, x, y, prefix) { @@ -1809,6 +1999,11 @@ events.prototype._action_previewUI = function (data, x, y, prefix) { core.doAction(); } +events.prototype._precompile_previewUI = function (data) { + data.action = this.precompile(data.action); + return data; +} + events.prototype.__action_doUIEvent = function (data) { this.__action_doUIEvent_doOne(data); var current = core.status.event.data.list[0]; @@ -1849,6 +2044,11 @@ events.prototype._action_fillPolygon = function (data, x, y, prefix) { this.__action_doUIEvent(data); } +events.prototype._precompile_fillPolygon = function (data) { + data.nodes = this.__precompile_array(data.nodes); + return data; +} + events.prototype._action_strokeRect = function (data, x, y, prefix) { this.__action_doUIEvent(data); } @@ -1857,6 +2057,11 @@ events.prototype._action_strokePolygon = function (data, x, y, prefix) { this.__action_doUIEvent(data); } +events.prototype._precompile_strokePolygon = function (data) { + data.nodes = this.__precompile_array(data.nodes); + return data; +} + events.prototype._action_fillCircle = function (data, x, y, prefix) { this.__action_doUIEvent(data); } @@ -2099,17 +2304,11 @@ events.prototype.setValue = function (name, value, prefix, add) { this._setValue_setFlag(name, value); this._setValue_setSwitch(name, value, prefix); this._setValue_setGlobal(name, value); - core.updateStatusBar(); } events.prototype._setValue_setStatus = function (name, value) { if (name.indexOf("status:") !== 0) return; core.setStatus(name.substring(7), value); - if (core.status.hero.hp <= 0) { - core.status.hero.hp = 0; - core.updateStatusBar(); - core.events.lose(); - } } events.prototype._setValue_setItem = function (name, value) { @@ -2341,16 +2540,16 @@ events.prototype.showGif = function (name, x, y) { ////// 淡入淡出音乐 ////// events.prototype.setVolume = function (value, time, callback) { var set = function (value) { - core.musicStatus.volume = value; + core.musicStatus.designVolume = value; if (core.musicStatus.playingBgm) - core.material.bgms[core.musicStatus.playingBgm].volume = value; + core.material.bgms[core.musicStatus.playingBgm].volume = core.musicStatus.userVolume * core.musicStatus.designVolume; } if (!time || time < 100) { set(value); if (callback) callback(); return; } - var currVolume = core.musicStatus.volume; + var currVolume = core.musicStatus.designVolume; time /= Math.max(core.status.replay.speed, 1); var per_time = 10, step = 0, steps = parseInt(time / per_time); if (steps <= 0) steps = 1; diff --git a/libs/ui.js b/libs/ui.js index a1b88121..43b0f399 100644 --- a/libs/ui.js +++ b/libs/ui.js @@ -1496,7 +1496,10 @@ ui.prototype.drawSwitchs = function() { var choices = [ "背景音乐: "+(core.musicStatus.bgmStatus ? "[ON]" : "[OFF]"), "背景音效: "+(core.musicStatus.soundStatus ? "[ON]" : "[OFF]"), - "行走速度: "+parseInt(core.values.moveSpeed), + //显示为 0~10 十挡 + " < 音量:" + Math.round(Math.sqrt(100 * core.musicStatus.userVolume)) + " > ", + //数值越大耗时越长 + " < 步时:" + core.values.moveSpeed + " > ", "怪物显伤: "+(core.flags.displayEnemyDamage ? "[ON]" : "[OFF]"), "临界显伤: "+(core.flags.displayCritical ? "[ON]" : "[OFF]"), "领域显伤: "+(core.flags.displayExtraDamage ? "[ON]" : "[OFF]"), diff --git a/libs/utils.js b/libs/utils.js index d8f811c7..059f48d6 100644 --- a/libs/utils.js +++ b/libs/utils.js @@ -66,27 +66,38 @@ utils.prototype.replaceText = function (text, need, times) { }); } +utils.prototype.replaceValue = function (value) { + if (typeof value == "string" && value.indexOf(":") >= 0) { + if (value.indexOf('status:') >= 0) + value = value.replace(/status:([a-zA-Z0-9_]+)/g, "core.getStatus('$1')"); + if (value.indexOf('item:') >= 0) + value = value.replace(/item:([a-zA-Z0-9_]+)/g, "core.itemCount('$1')"); + if (value.indexOf('flag:') >= 0) + value = value.replace(/flag:([a-zA-Z0-9_\u4E00-\u9FCC]+)/g, "core.getFlag('$1', 0)"); + //if (value.indexOf('switch:' >= 0)) + // value = value.replace(/switch:([a-zA-Z0-9_]+)/g, "core.getFlag('" + (prefix || ":f@x@y") + "@$1', 0)"); + if (value.indexOf('global:') >= 0) + value = value.replace(/global:([a-zA-Z0-9_\u4E00-\u9FCC]+)/g, "core.getGlobal('$1', 0)"); + if (value.indexOf('enemy:')>=0) + value = value.replace(/enemy:([a-zA-Z0-9_]+)\.([a-zA-Z0-9_]+)/g, "core.material.enemys['$1'].$2"); + if (value.indexOf('blockId:')>=0) + value = value.replace(/blockId:(\d+),(\d+)/g, "core.getBlockId($1, $2)"); + if (value.indexOf('blockCls:')>=0) + value = value.replace(/blockCls:(\d+),(\d+)/g, "core.getBlockCls($1, $2)"); + if (value.indexOf('equip:')>=0) + value = value.replace(/equip:(\d)/g, "core.getEquip($1)"); + } + return value; +} + ////// 计算表达式的值 ////// utils.prototype.calValue = function (value, prefix, need, times) { if (!core.isset(value)) return null; if (typeof value === 'string') { if (value.indexOf(':') >= 0) { - if (value.indexOf('status:') >= 0) - value = value.replace(/status:([a-zA-Z0-9_]+)/g, "core.getStatus('$1')"); - if (value.indexOf('item:') >= 0) - value = value.replace(/item:([a-zA-Z0-9_]+)/g, "core.itemCount('$1')"); - if (value.indexOf('flag:') >= 0) - value = value.replace(/flag:([a-zA-Z0-9_\u4E00-\u9FCC]+)/g, "core.getFlag('$1', 0)"); if (value.indexOf('switch:' >= 0)) value = value.replace(/switch:([a-zA-Z0-9_]+)/g, "core.getFlag('" + (prefix || ":f@x@y") + "@$1', 0)"); - if (value.indexOf('global:') >= 0) - value = value.replace(/global:([a-zA-Z0-9_\u4E00-\u9FCC]+)/g, "core.getGlobal('$1', 0)"); - if (value.indexOf('enemy:')>=0) - value = value.replace(/enemy:([a-zA-Z0-9_]+)\.([a-zA-Z0-9_]+)/g, "core.material.enemys['$1'].$2"); - if (value.indexOf('blockId:')>=0) - value = value.replace(/blockId:(\d+),(\d+)/g, "core.getBlockId($1, $2)"); - if (value.indexOf('blockCls:')>=0) - value = value.replace(/blockCls:(\d+),(\d+)/g, "core.getBlockCls($1, $2)"); + value = this.replaceValue(value); } return eval(value); } diff --git a/main.js b/main.js index 191e1773..6d435c80 100644 --- a/main.js +++ b/main.js @@ -2,7 +2,7 @@ function main() { //------------------------ 用户修改内容 ------------------------// - this.version = "2.6.4"; // 游戏版本号;如果更改了游戏内容建议修改此version以免造成缓存问题。 + this.version = "2.6.5"; // 游戏版本号;如果更改了游戏内容建议修改此version以免造成缓存问题。 this.useCompress = false; // 是否使用压缩文件 // 当你即将发布你的塔时,请使用“JS代码压缩工具”将所有js代码进行压缩,然后将这里的useCompress改为true。 @@ -189,8 +189,8 @@ function main() { this.floors = {} this.canvas = {}; - this.__VERSION__ = "2.6.4"; - this.__VERSION_CODE__ = 78; + this.__VERSION__ = "2.6.5"; + this.__VERSION_CODE__ = 87; } main.prototype.init = function (mode, callback) { diff --git a/project/data.js b/project/data.js index 629b7a85..9ed376f9 100644 --- a/project/data.js +++ b/project/data.js @@ -78,7 +78,7 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = "firstData": { "title": "魔塔样板", "name": "template", - "version": "Ver 2.6.4", + "version": "Ver 2.6.5", "floorId": "sample0", "hero": { "name": "阳光", diff --git a/project/icons.js b/project/icons.js index e9d0ae7c..4c84391c 100644 --- a/project/icons.js +++ b/project/icons.js @@ -138,8 +138,7 @@ var icons_4665ee12_3a1f_44a4_bea3_0fccba634dc1 = "npc0": 0, "npc1": 1, "npc2": 2, - "npc3": 3, - "npc4": 4 + "npc3": 3 }, "enemys": { "greenSlime": 0, diff --git a/project/images/bg.jpg b/project/images/bg.jpg index 55cf862c..3fbf4d1c 100644 Binary files a/project/images/bg.jpg and b/project/images/bg.jpg differ diff --git a/project/images/npc48.png b/project/images/npc48.png old mode 100644 new mode 100755 index 43c3a376..5b5b0fec Binary files a/project/images/npc48.png and b/project/images/npc48.png differ diff --git a/project/maps.js b/project/maps.js index d631d0ba..fc9bd45f 100644 --- a/project/maps.js +++ b/project/maps.js @@ -98,11 +98,10 @@ var maps_90f36752_8815_4be8_b32b_d7fad1d0542e = "130": {"cls":"npcs","id":"pinkShop"}, "131": {"cls":"npcs","id":"blueShop"}, "132": {"cls":"npcs","id":"princess"}, - "133": {"cls":"npc48","id":"npc0"}, - "134": {"cls":"npc48","id":"npc1"}, - "135": {"cls":"npc48","id":"npc2"}, - "136": {"cls":"npc48","id":"npc3"}, - "137": {"cls":"npc48","id":"npc4"}, + "133": {"cls":"npc48","id":"npc0","faceIds":{"down":"npc0","left":"npc1","right":"npc2","up":"npc3"}}, + "134": {"cls":"npc48","id":"npc1","faceIds":{"down":"npc0","left":"npc1","right":"npc2","up":"npc3"}}, + "135": {"cls":"npc48","id":"npc2","faceIds":{"down":"npc0","left":"npc1","right":"npc2","up":"npc3"}}, + "136": {"cls":"npc48","id":"npc3","faceIds":{"down":"npc0","left":"npc1","right":"npc2","up":"npc3"}}, "151": {"cls":"autotile","id":"autotile1","noPass":true}, "152": {"cls":"autotile","id":"autotile2","noPass":true}, "153": {"cls":"autotile","id":"autotile3","noPass":true}, diff --git a/启动服务.exe b/启动服务.exe index 2f6786f0..43592551 100644 Binary files a/启动服务.exe and b/启动服务.exe differ diff --git a/常用工具/动画编辑器.exe b/常用工具/动画编辑器.exe new file mode 100644 index 00000000..8c4cb315 Binary files /dev/null and b/常用工具/动画编辑器.exe differ diff --git a/常用工具/怪物数据生成机.exe b/常用工具/怪物数据生成机.exe new file mode 100644 index 00000000..ebf34398 Binary files /dev/null and b/常用工具/怪物数据生成机.exe differ diff --git a/更新说明.txt b/更新说明.txt index 8b3e2419..ff227f88 100644 --- a/更新说明.txt +++ b/更新说明.txt @@ -1,4 +1,41 @@ -HTML5魔塔样板V2.6.3 +HTML5魔塔样板V2.6.5 + +事件:设置怪物属性;穿脱装备 +新值块:enemy:xxx:atk可获得怪物数据 +新值块:blockId:x,y获得某点图块ID +部分事件预编译,加快执行速度 +在系统设置中可以设置bgm的播放音量 +通关事件可以不退出游戏 +失败时允许直接读取自动存档 +NPC48自动注册可以自动绑定faceIds +编辑器Alt+1-9存图块,1-9读取图块 +编辑器现在可以跨楼层复制粘贴图块了 +可以对flags.进行自动补全 +部分Bug修复,大量细节优化 + + +----------------------------------------------------------------------- + +HTML5魔塔样板V2.6.4 + +自动事件,多事件页 +增加开场logo动画 +拓展:游戏时动态修改地图和怪物数据 +插件:道具商店,支持买入和卖出道具 +编辑器可以搜索变量出现位置 +变量的中文替换 +可以给图块绑定自定义脚本,碰触时触发 +编辑器右键可以绑定机关门和出生点 +支持多个drawTip同时出现 +闪烁光标同时支持多个同时存在 +插件:镜头平滑移动,默认禁用 +素材的快速追加 +批量导出动画 +部分Bug修复,大量细节优化 + +----------------------------------------------------------------------- + +HTML5魔塔样板V2.6.3 标题界面大幅美化,增加闪烁光标,支持键盘开始游戏 事件编辑器支持自动补全,能对flag和API列表等进行补全