diff --git a/_server/comment.js b/_server/comment.js index 0621926b..dd31f1ab 100644 --- a/_server/comment.js +++ b/_server/comment.js @@ -40,7 +40,7 @@ comment_c456ea59_6018_45ef_8bcc_211a24c627dc = "equip": { "_leaf": true, "_type": "textarea", - "_data": "装备属性设置,仅对cls为equips有效。\n如果此项不为null,需要是一个对象,里面可含\"type\",\"atk\",\"def\",\"mdef\",\"animate\"五项,分别对应装备部位、攻防魔防和动画。\n具体详见文档和已有的几个装备的写法。" + "_data": "装备属性设置,仅对cls为equips有效。\n如果此项不为null,需要是一个对象,里面可含\"type\",\"atk\",\"def\",\"mdef\",\"animate\"五项,分别对应装备部位、攻防魔防和动画。\n具体详见文档(元件说明-装备)和已有的几个装备的写法。" }, } }, diff --git a/docs/api.md b/docs/api.md index c7ced584..e18f44cf 100644 --- a/docs/api.md +++ b/docs/api.md @@ -72,8 +72,17 @@ core.setItem('pickaxe', 10) 将破墙镐个数设置为10个。这里可以写任何道具的ID。 +core.addItem('pickaxe', 2) +将破墙镐的个数增加2个,无任何特效。这里可以写任何道具的ID。 + + core.getItem('pickaxe', 4) -另勇士获得四个破墙镐。这里可以写任何道具的ID。 +令勇士获得4个破墙镐。这里可以写任何道具的ID。 +和addItem相比,使用getItem会播放获得道具的音效,也会在左上角绘制获得提示。 + + +core.removeItem('pickaxe', 3) +删除3个破墙镐。第二项可忽略,默认值为1。 core.itemCount('pickaxe') @@ -84,6 +93,15 @@ core.hasItem('pickaxe') 返回当前是否存在某个道具。等价于 core.itemCount('pickaxe')>0 。 +core.getEquip(0) +获得0号装备类型(武器)的当前装备的itemId。如果不存在则返回null。 +这里可以写任意装备类型,从0开始和全塔属性中的equipName一一对应。 + + +core.hasEquip('sword1') +获得当前某个具体的装备是否处于正在被装备状态。 + + core.setFlag('xyz', 2) 设置某个flag/变量的值为2。这里可以写任何的flag变量名。 @@ -229,12 +247,12 @@ core.canUseItem(itemId) 返回当前能否使用某个道具。 -core.addItem(itemId, number) -将某个道具增加number个。 +core.loadEquip(itemId, callback) +装备上某个装备。itemId为装备的ID,callback为成功或失败后的回调。 -core.removeItem(itemId) -将某个道具个数-1;如果道具个数归0则从道具列表删除。 +core.unloadEquip(equipType, callback) +卸下某个部位的装备。equipType为装备类型,从0开始;callback为成功或失败后的回调。 core.getNextItem() @@ -266,6 +284,11 @@ core.getLocalStorage(key, defaultValue) 从localStorage中获得某个数据(已被parse);如果对应的key不存在则返回defaultValue。 +core.getLocalForage(key, defaultValue, successCallback, errorCallback) +从localForage中获得某个数据(已被parse),如果对应的key不存在则返回defaultValue。 +如果成功则通过successCallback回调,失败则通过errorCallback回调。 + + core.clone(data) 深拷贝某个对象。 @@ -399,6 +422,10 @@ core.events.setHeroIcon(name) items.js将处理和道具相关的内容,比如道具的使用,获取和删除等等。 +core.items.compareEquipment(equipId1, equipId2) +比较两个装备的属性变化值 + + ========== core.loader.XXX 和游戏加载相关的函数 ========== loader.js将主要用来进行资源的加载,比如加载音乐、图片、动画等等。 diff --git a/docs/element.md b/docs/element.md index 882f54f5..fbc5304b 100644 --- a/docs/element.md +++ b/docs/element.md @@ -24,7 +24,58 @@ 如果需要让剑盾等变成装备,可以直接在`data.js`中设置`'equipment': true`即可。 -有关装备更为详细的资料可参见[自定义装备](personalization#自定义装备)的说明。 +从V2.4.1开始,HTML5魔塔样板终于拥有了属于自己的装备页面。 + +### 装备栏的设置,装备类型 + +在全塔属性中,有一个`equipName`项,其定义了本塔的所有可装备的装备栏。 + +其需要是一个不小于1且不大于6的数组,其中每一项为装备栏的名称,**建议是两个汉字**。 + +例如下面这种写法就是定义了四个装备孔,名称分别为武器、防御、首饰和魔杖。 + +``` js +"equipName": ["武器","防具","首饰","魔杖"] +``` + +这么定义好后,装备类型即为每个装备孔的索引(从0开始)。 + +即,武器的装备类型是0,防御的装备类型是1,首饰的装备类型是2,魔杖的装备类型是3。 + +### 设置每个装备的属性 + +如果要将一个道具设置为装备,首先需要将其`cls`设为`equips`。 + +然后在图块属性的`equip`一项中设置装备的具体属性。该项写法如下: +``` js +{"type": 0, "atk": 0, "def": 0, "mdef":0, "animate": "hand"} +``` + +type为该装备的类型,必填,和上面装备栏一一对应。例如,0就是武器,2就是首饰等等。 + +atk/def/mdef为该装备分别增加的攻防魔防数值(支持负数);如果不加也可省略不写。 + +animate为该装备的攻击动画,仅对type为0时有效。具体可参见[动画和天气系统](#动画和天气系统)。 + +下面是几个写法例子。 + +``` js +{"type": 0, "atk": 10} // 装备类型是武器,效果是攻击+10,使用默认的攻击动画 +{"type": 0, "atk": 40, "animate": "sword"} // 装备类型为武器,效果是攻击+10,攻击动画是sword +{"type": 1, "def": 40} // 装备类型是防具,效果是防御+40 +{"type": 1, "def": 100, "mdef": 100} // 装备类型是防具,效果是防御和魔防各+100 +{"type": 3, "atk": -20, "def": 50, "mdef": 50} // 装备类型是魔杖,效果是攻击-20,防御和魔防各+50 +``` + +### 检测是否存在装备 + +可以使用`core.hasEquip(itemId)`来检测是否装上某个装备。 + +使用`core.hasItem(itemId)`来检测是否存在一个未装上的装备。 + +使用`core.getEquip(equipType)`来获得某个装备类型的当前装备。 + +更多相关API详见[附录:API列表](api)。 ## 门 @@ -32,6 +83,8 @@ 开门后可触发该层的`afterOpenDoor`事件,有关事件的详细介绍请参见第四章。 +如果要新增自己的门,请参见[新增门和对应的钥匙](personalization#新增门和对应的钥匙)。 + ## 暗墙 本塔支持暗墙。 @@ -139,16 +192,26 @@ N连击怪物的special是6,且我们可以为它定义n代表实际连击数 领域怪还可以设置`range`选项代表该领域怪的范围,不写则默认为1。 +**将`flag:no_zone`设置为true可以取消领域效果。** + 阻击怪同样需要设置value,代表阻击伤害的数值。如果勇士生命值扣减到0,则直接死亡触发lose事件。 +**将`flag:no_snipe`设置为true可以取消阻击效果。** + !> 阻击怪后退的地点不能有任何事件存在,即使是已经被禁用的自定义事件! 激光怪同样需要设置value,代表激光伤害的数值。 请注意如果吸血、领域、阻击中任何两个同时存在,则value会冲突。**因此请勿将吸血、领域、阻击或激光放置在同一个怪物身上。** +**将`flag:no_laser`设置为true可以免疫激光效果。** + 退化怪需要设置'atkValue'和'defValue'表示退化的数值;也可以不设置默认为0。 +夹击可以通过全塔属性中的`betweenAttackCeil`设为true可以将伤害向上取整。 + +**将`flag:no_betweenAttack`设置为true可以免疫夹击效果。** + 固伤怪则需要设置`damage`选项,代表战前扣血数值。 如有额外需求,可参见[自定义怪物属性](personalization#自定义自定义怪物属性),里面讲了如何设置一个新的怪物属性。 diff --git a/docs/personalization.md b/docs/personalization.md index be460129..d454eb90 100644 --- a/docs/personalization.md +++ b/docs/personalization.md @@ -308,25 +308,13 @@ function (enemy, hero_hp, hero_atk, hero_def, hero_mdef) { } // ... 下略 ``` -3. 免疫领域、夹击、阻击效果:在`control.js`中,找到checkBlock函数,并编辑成如果有神圣盾标记,则将伤害变成0。 +3. 免疫领域、夹击、阻击效果:在2.4.1之后,可以直接将flag:no_zone设为true来免疫领域效果,其他几个同理。 ``` js -// 检查领域、夹击、阻击事件 -control.prototype.checkBlock = function () { - var x=core.getHeroLoc('x'), y=core.getHeroLoc('y'); - var damage = core.status.checkBlock.damage[x+core.bigmap.width*y]; - if (damage>0) { - if (core.hasFlag("shield5")) damage = 0; // 如果存在神圣盾,则将伤害变成0 - core.status.hero.hp -= damage; - - // 检查阻击事件 - var snipe = []; - var scan = { - 'up': {'x': 0, 'y': -1}, - 'left': {'x': -1, 'y': 0}, - 'down': {'x': 0, 'y': 1}, - 'right': {'x': 1, 'y': 0} - } -// ... 下略 +// 同样写在道具的itemEffect中 +core.setFlag("no_zone", true); // 免疫领域 +core.setFlag("no_snipe", true); // 免疫阻击 +core.setFlag("no_laser", true); // 免疫激光 +core.setFlag("no_betweenAttack", true); // 免疫夹击 ``` 4. 如果有更高的需求,例如想让吸血效果变成一半,则还是在上面这些地方进行对应的修改即可。 @@ -375,6 +363,7 @@ control.prototype.useFly = function (need) { ``` 修改时,请先把`null`改成空字符串`""`,然后再双击进行编辑。 + + ## 自定义怪物属性 如果你对现有的怪物不满意,想自行添加怪物属性也是可以的。具体参见脚本编辑-getSpecials。 diff --git a/docs/start.md b/docs/start.md index 46d5346d..6bbceee0 100644 --- a/docs/start.md +++ b/docs/start.md @@ -201,6 +201,8 @@ HTML5的塔都是可以进行控制台调试的。 - `core.getItem('pickaxe', 2)` 令勇士获得两个破墙镐。 - `core.itemCount('pickaxe')` 返回勇士某个道具的个数。 - `core.hasItem('pickaxe')` 返回勇士是否拥有某个道具。等价于`core.itemCount('pickaxe')!=0`。 +- `core.getEquip(0)` 返回0号装备类型(武器)的当前装备的itemId,不存在则返回null +- `core.hasEquip('sword1')` 返回某个装备当前是否处于被装备状态 - `core.setFlag('xxx', 1)` 设置某个flag/自定义变量的值。 - `core.getFlag('xxx', 10)` 获得某个flag/自定义变量的值;如果该项不存在(未被定义),则返回第二个参数的值。 - `core.hasFlag('xxx')` 返回是否存在某个变量且不为0。等价于`core.getFlag('xxx', 0)!=0`。 @@ -210,7 +212,6 @@ HTML5的塔都是可以进行控制台调试的。 - `core.getBlock(3, 5, 'MT1')` 获得当前地图上某一个块的信息。第三个参数为floorId,可省略表示当前楼层。 - `core.getBlockId(3, 5, 'MT1')` 获得当前地图上某一个点的图块ID。第三个参数为floorId,可省略表示当前楼层。 - `core.resetMap()` 重置当前层地图。**当修改地图后再读档,修改的地图不会立刻生效,此时可以使用resetMap来重置当前楼层的地图。** -- `localStorage` 获得所有的存档数据。可以用 `core.getLocalStorage('save1')` 来具体获得某个存档。 - …… 更多API和详细参数介绍可参见[API列表](api)。 diff --git a/libs/actions.js b/libs/actions.js index d060d672..7b259cad 100644 --- a/libs/actions.js +++ b/libs/actions.js @@ -1480,6 +1480,7 @@ actions.prototype.clickEquipboxIndex = function(index) { if (index>=(main.equipName||[]).length) return; if (index==core.status.event.selection && core.isset(core.status.hero.equipment[index])) { core.unloadEquip(index); + core.status.route.push("unEquip:"+index); } } else if (index>=12) { @@ -1487,6 +1488,7 @@ actions.prototype.clickEquipboxIndex = function(index) { if (index==core.status.event.selection) { var equipId = equips[index-12 + (core.status.event.data.page-1)*12]; core.loadEquip(equipId); + core.status.route.push("equip:"+equipId); } } core.ui.drawEquipbox(index); diff --git a/libs/control.js b/libs/control.js index ff4c53d2..2596e872 100644 --- a/libs/control.js +++ b/libs/control.js @@ -1860,6 +1860,7 @@ control.prototype.replay = function () { var equipType = parseInt(action.substring(8)); if (core.isset(equipType)) { core.ui.drawEquipbox(equipType); + core.status.route.push(action); setTimeout(function () { core.ui.closePanel(); core.unloadEquip(equipType, function () { @@ -1874,6 +1875,7 @@ control.prototype.replay = function () { var ownEquipment = Object.keys(core.status.hero.items.equips).sort(); var index = ownEquipment.indexOf(equipId); if (index>=0) { + core.status.route.push(action); core.status.event.data = {"page":Math.floor(index/12)+1, "selectId":null}; index = index%12+12; core.ui.drawEquipbox(index); @@ -2639,8 +2641,6 @@ control.prototype.updateStatusBar = function () { core.statusBar.image.settings.src = core.statusBar.icons.settings.src; } - - core.updateDamage(); } ////// 屏幕分辨率改变后重新自适应 ////// diff --git a/libs/core.js b/libs/core.js index 1c6a8625..f3155dd9 100644 --- a/libs/core.js +++ b/libs/core.js @@ -834,8 +834,13 @@ core.prototype.hasItem = function (itemId) { } ////// 是否装备某件装备 ////// -core.prototype.hasEquip = function (equipId) { - return core.items.hasEquip(equipId); +core.prototype.hasEquip = function (itemId) { + return core.items.hasEquip(itemId); +} + +////// 获得某个装备类型的当前装备 ///// +core.prototype.getEquip = function (equipType) { + return core.items.getEquip(equipType); } ////// 设置某个物品的个数 ////// @@ -844,8 +849,8 @@ core.prototype.setItem = function (itemId, itemNum) { } ////// 删除某个物品 ////// -core.prototype.removeItem = function (itemId) { - return core.items.removeItem(itemId); +core.prototype.removeItem = function (itemId, itemNum) { + return core.items.removeItem(itemId, itemNum); } ////// 使用某个物品 ////// diff --git a/libs/items.js b/libs/items.js index 7203efde..f6bfd29b 100644 --- a/libs/items.js +++ b/libs/items.js @@ -97,17 +97,22 @@ items.prototype.hasItem = function (itemId) { } ////// 是否装备某件装备 ////// -items.prototype.hasEquip = function (equipId) { +items.prototype.hasEquip = function (itemId) { - if (!core.isset(equipId)) return null; - if (!core.isset((core.material.items[equipId]||{}).equip)) return null; + if (!core.isset(itemId)) return null; + if (!core.isset((core.material.items[itemId]||{}).equip)) return null; - var equiptype = core.material.items[equipId].equip.type; - return equipId == (core.status.hero.equipment||[])[equiptype]; + return itemId == this.getEquip(core.material.items[itemId].equip.type); +} + +////// 获得某个装备类型的当前装备 ////// +items.prototype.getEquip = function (equipType) { + return (core.status.hero.equipment||[])[equipType]||null; } ////// 设置某个物品的个数 ////// items.prototype.setItem = function (itemId, itemNum) { + itemNum = itemNum || 1; var itemCls = core.material.items[itemId].cls; if (itemCls == 'items') return; if (!core.isset(core.status.hero.items[itemCls])) { @@ -120,11 +125,12 @@ items.prototype.setItem = function (itemId, itemNum) { } ////// 删除某个物品 ////// -items.prototype.removeItem = function (itemId) { +items.prototype.removeItem = function (itemId, itemNum) { + itemNum = itemNum || 1; if (!core.hasItem(itemId)) return false; var itemCls = core.material.items[itemId].cls; - core.status.hero.items[itemCls][itemId]--; - if (itemCls!='keys' && core.status.hero.items[itemCls][itemId]==0) { + core.status.hero.items[itemCls][itemId]-=itemNum; + if (itemCls!='keys' && core.status.hero.items[itemCls][itemId]<=0) { delete core.status.hero.items[itemCls][itemId]; } core.updateStatusBar(); @@ -178,7 +184,7 @@ items.prototype.loadEquip = function (equipId, callback) { core.updateStatusBar(); // 记录路线 - core.status.route.push("equip:"+equipId); + // core.status.route.push("equip:"+equipId); // 装备更换完毕:删除换上的装备 core.removeItem(equipId); @@ -217,7 +223,7 @@ items.prototype.unloadEquip = function (equipType, callback) { core.updateStatusBar(); // 记录路线 - core.status.route.push("unEquip:"+equipType); + // core.status.route.push("unEquip:"+equipType); // 装备更换完毕:增加卸下的装备 core.addItem(unloadEquipId, 1); diff --git a/libs/ui.js b/libs/ui.js index 9ba566f4..78bf7692 100644 --- a/libs/ui.js +++ b/libs/ui.js @@ -1804,7 +1804,8 @@ ui.prototype.drawEquipbox = function(index) { // 描述 if (core.isset(selectId)) { var equip=core.material.items[selectId]; - var equipType = (equip.equip||{}).type || 0; + if (!core.isset(equip.equip)) equip.equip = {"type": 0}; + var equipType = equip.equip.type; core.fillText('ui', equip.name + "(" + (allEquips[equipType]||"未知部位") + ")", 10, 32, '#FFD700', "bold 20px Verdana") var text = equip.text||"该装备暂无描述。"; diff --git a/project/floors/sample0.js b/project/floors/sample0.js index a442ab3f..51810f8a 100644 --- a/project/floors/sample0.js +++ b/project/floors/sample0.js @@ -32,9 +32,8 @@ main.floors.sample0= ], "events": { "10,9": [ - "\t[老人,man]这些是本样板支持的所有的道具。\n\n道具分为三类:items, constants, tools。\nitems 为即捡即用类道具,例如宝石、血瓶、剑盾等。\nconstants 为永久道具,例如怪物手册、楼层传送器、幸运金币等。\ntools 为消耗类道具,例如破墙镐、炸弹、中心对称飞行器等。\n\n后两类道具在工具栏中可以看到并使用。", + "\t[老人,man]这些是本样板支持的所有的道具。\n\n道具分为四类:items, constants, tools,equips。\nitems 为即捡即用类道具,例如宝石、血瓶、剑盾等。\nconstants 为永久道具,例如怪物手册、楼层传送器、幸运金币等。\ntools 为消耗类道具,例如破墙镐、炸弹、中心对称飞行器等。\nequips 为装备,例如剑盾等。", "\t[老人,man]\b[up]有关道具效果,定义在items.js中。\n目前大多数道具已有默认行为,如有自定义的需求则需在items.js中修改代码。", - "\t[老人,man]constants 和 tools 各最多只允许12种,多了会导致图标溢出。", "\t[老人,man]\b[up]拾取道具结束后可触发 afterGetItem 事件。\n\n有关事件的各种信息在下一层会有更为详细的说明。", { "type": "hide", diff --git a/project/functions.js b/project/functions.js index e397cb30..6f80e240 100644 --- a/project/functions.js +++ b/project/functions.js @@ -477,44 +477,60 @@ functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = core.setStatus('hp', Math.min(core.getStatus('hpmax'), core.getStatus('hp'))); } - // 更新领域、阻击、显伤 - core.updateCheckBlock(); - + // 设置等级奴名称 var lvName = core.getLvName(); core.statusBar.lv.innerHTML = lvName; + // 检测是不是纯数字;如果带中文等需要取消斜体(不然很难看的!) if (/^[+-]?\d+$/.test(lvName)) core.statusBar.lv.style.fontStyle = 'italic'; else core.statusBar.lv.style.fontStyle = 'normal'; + // 设置生命上限、生命值、攻防魔防金币和经验值 var statusList = ['hpmax', 'hp', 'atk', 'def', 'mdef', 'money', 'experience']; statusList.forEach(function (item) { + // 向下取整 if (core.isset(core.status.hero[item])) core.status.hero[item] = Math.floor(core.status.hero[item]); + // 大数据格式化 core.statusBar[item].innerHTML = core.formatBigNumber(core.getStatus(item)); }); + // 可以在这里添加自己额外的状态栏信息,比如想攻击显示 +0.5 可以这么写: + // if (core.hasFlag('halfAtk')) core.statusBar.atk.innerHTML += "+0.5"; + + // 如果是自定义添加的状态栏,也需要在这里进行设置显示的数值 + // 进阶 if (core.flags.enableLevelUp && core.status.hero.lv=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; } @@ -574,6 +595,7 @@ 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;nx0 && x0 && y1) core.status.checkBlock.damage[x+core.bigmap.width*y] += Math.floor((leftHp+(core.flags.betweenAttackCeil?0:1))/2); } @@ -677,7 +704,7 @@ functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = // 在这里写所有需要自定义的函数 // 写法必须是 this.xxx = function (args) { ... // 如果不写this的话,函数将无法被外部所访问 - this.test = function () { + this.test = function () { console.log("插件函数执行测试"); }