diff --git a/docs/event.md b/docs/event.md index 0ccdc36c..061b97e6 100644 --- a/docs/event.md +++ b/docs/event.md @@ -1869,8 +1869,8 @@ if (core.getFlag("door",0)==2) { {"text": "攻击+4", "effect": "status:atk+=4"}, {"text": "防御+4", "effect": "status:def+=4"}, {"text": "魔防+10", "effect": "status:mdef+=10"} - // effect只能对status和item进行操作,不能修改flag值。 - // 必须是X+=Y的形式,其中Y可以是一个表达式,以status:xxx或item:xxx为参数 + // effect可以对status,item和flag进行操作。 + // 必须是X+=Y的形式,其中Y可以是一个表达式,以status:xxx, item:xxx或flag:xxx为参数 // 其他effect样例: // "item:yellowKey+=1" 黄钥匙+1 // "item:pickaxe+=3" 破墙镐+3 @@ -1912,7 +1912,7 @@ if (core.getFlag("door",0)==2) { - text 为商店所说的话。可以用${need}表示需要的数值。 - choices 为商店的各个选项,是一个list,每一项是一个选项 - text为显示文字。请注意这里不支持 ${} 的表达式计算。 - - effect 为该选项的效果;effect只能对status或items进行操作,且必须是 `status:xxx+=yyy` 或 `item:xxx+=yyy`的形式。即中间必须是+=符号。 + - effect 为该选项的效果;effect必须是 `status:xxx+=yyy`, `item:xxx+=yyy`或`flag:xxx+=yyy`的形式。即中间必须是+=符号。 - 如有多个effect(例如升级全属性提升),使用分号分开,参见经验商店的写法。 像这样定义了全局商店后,即可在快捷栏中看到。 diff --git a/docs/personalization.md b/docs/personalization.md index 22271bbe..f88c49a2 100644 --- a/docs/personalization.md +++ b/docs/personalization.md @@ -779,6 +779,65 @@ if (core.flags.enableSkill) { 通过上述这几种方式,我们就能成功的让H5支持技能啦! +## 成就系统 + +我们还可以给HTML5魔塔增加成就系统。注意到成就是和游戏相关,因此需要使用getLocalStorage而不是getFlag判定。 + +可将下面的代码粘贴到脚本编辑 - 插件编写中。 + +``` js +// 所有成就项的定义 +this.achievements = [ + // 每行一个,分别定义flag、名称、描述、是否存在提示、成就点数 + {"flag": "a1", "name": "成就1", "text": "成就1的达成描述", "hint": false, "point": 1}, + // 可以继续往后新增其他的。 +]; + +// 达成成就;如 core.plugin.achieve("a1") 即达成a1对应的成就 +this.achieve = function (flag) { + // 获得已达成的成就;如果跟存档而不是跟游戏则改成getFlag + var achieved = core.getLocalStorage("achievements", []); + var point = core.getLocalStorage("achievePoint", 0); + // 已经获得该成就 + if (achieved.indexOf(flag)>=0) return; + // 尝试达成成就;找到对应的成就项 + this.achievements.forEach(function (one) { + if (one.flag == flag) { + // 执行达成成就的操作;也可以自行在上面加上达成成就后的事件 + core.insertAction("\t[达成成就:"+one.name+"]"+one.text); + point += one.point || 0; + } + }); + achieved.push(flag); + // 存入localStorage中;如果跟存档走则使用setFlag + core.setLocalStorage("achievements", achieved); + core.setLocalStorage("achievePoint", point); +} + +// 获得所有成就说明;这里简单使用两个insertAction,你也可以修改成自己的实现 +// 简单一点的可以使用insertAction+剧情文本;稍微复杂一点的可以使用图片化文本等;更复杂的可以自绘UI。 +this.getAchievements = function () { + var achieved = core.getLocalStorage("achievements", []); + var yes = [], no = []; + // 对所有成就进行遍历 + this.achievements.forEach(function (one) { + // 检测是否达成 + if (achieved.indexOf(one.flag)>=0) { + yes.push(one.name+":"+one.text); + } + else { + no.push(one.name+":"+(one.hint?one.text:"达成条件请自行探索")); + } + }); + core.insertAction([ + "\t[已达成的成就]"+(yes.length==0?"暂无":yes.join("\n")), + "\t[尚未达成的成就]"+(no.length==0?"暂无":no.join("\n")) + ]); +} +``` + + + ## 多角色的支持 其实,我们的样板还能支持多角色的制作。比如《黑·白·间》之类的塔也是完全可以刻的。 @@ -787,7 +846,7 @@ if (core.flags.enableSkill) { 1. 每个角色弄一张行走图。相关信息参见[自定义事件:setHeroIcon](event#setHeroIcon:更改角色行走图)。 2. [覆盖楼传事件](#覆盖楼传事件),这样可以通过点工具栏的楼层传送按钮来切换角色。当然你也完全可以自己写一个道具,或[自定义快捷键](#自定义快捷键)来进行绑定。 -3. 将下述代码直接贴入脚本编辑 - 插件编写中。(写在`var _useEquipment = ...`之前。) +3. 将下述代码直接贴入脚本编辑 - 插件编写中。 ``` js // 所有需要保存的内容;这些保存的内容不会多角色共用,在切换时会进行恢复。 // 你也可以自行新增或删除,比如不共用金币则可以加上"money"的初始化,不共用道具则可以加上"items"的初始化, diff --git a/libs/actions.js b/libs/actions.js index d50443b8..f41f52dc 100644 --- a/libs/actions.js +++ b/libs/actions.js @@ -1080,13 +1080,13 @@ actions.prototype.clickShop = function(x,y) { core.status.event.selection=y-topIndex; var money = core.getStatus('money'), experience = core.getStatus('experience'); - var times = shop.times, need = eval(shop.need); + var times = shop.times, need = core.calValue(shop.need, null, times); var use = shop.use; var use_text = use=='money'?"金币":"经验"; var choice = choices[y-topIndex]; if (core.isset(choice.need)) - need = eval(choice.need); + need = core.calValue(choice.need, null, times); if (need > eval(use)) { core.drawTip("你的"+use_text+"不足"); @@ -1101,7 +1101,7 @@ actions.prototype.clickShop = function(x,y) { // 更新属性 choice.effect.split(";").forEach(function (t) { - core.doEffect(t); + core.doEffect(t, need, times); }); core.updateStatusBar(); shop.times++; diff --git a/libs/control.js b/libs/control.js index 3d8f41f2..25bcd17b 100644 --- a/libs/control.js +++ b/libs/control.js @@ -1639,11 +1639,11 @@ control.prototype.updateDamage = function (floorId, canvas) { } ////// 执行一个表达式的effect操作 ////// -control.prototype.doEffect = function (effect) { +control.prototype.doEffect = function (effect, need, times) { effect.split(";").forEach(function (expression) { var arr = expression.split("+="); if (arr.length!=2) return; - var name=arr[0], value=core.calValue(arr[1]); + var name=arr[0], value=core.calValue(arr[1], need, times); if (name.indexOf("status:")==0) { var status=name.substring(7); core.setStatus(status, core.getStatus(status)+value); @@ -1652,6 +1652,10 @@ control.prototype.doEffect = function (effect) { var itemId=name.substring(5); core.setItem(itemId, core.itemCount(itemId)+value); } + else if (name.indexOf("flag:")==0) { + var flag=name.substring(5); + core.setFlag(flag, core.getFlag(flag, 0)+value); + } }); } diff --git a/libs/core.js b/libs/core.js index 76dc3052..5c9871d1 100644 --- a/libs/core.js +++ b/libs/core.js @@ -999,18 +999,18 @@ core.prototype.drawText = function (contents, callback) { /////////// 系统机制 /////////// ////// 将文字中的${和}(表达式)进行替换 ////// -core.prototype.replaceText = function (text) { - return core.utils.replaceText(text); +core.prototype.replaceText = function (text, need, times) { + return core.utils.replaceText(text, need, times); } ////// 计算表达式的值 ////// -core.prototype.calValue = function (value) { - return core.utils.calValue(value); +core.prototype.calValue = function (value, need, times) { + return core.utils.calValue(value, need, times); } ////// 执行一个表达式的effect操作 ////// -core.prototype.doEffect = function (expression) { - core.control.doEffect(expression); +core.prototype.doEffect = function (expression, need, times) { + core.control.doEffect(expression, need, times); } ////// 字符串自动换行的分割 ////// diff --git a/libs/events.js b/libs/events.js index 6ca2dfdd..518a5c25 100644 --- a/libs/events.js +++ b/libs/events.js @@ -1849,20 +1849,18 @@ events.prototype.openShop = function(shopId, needVisited) { // 拼词 var content = "\t["+shop.name+","+shop.icon+"]"; - var times = shop.times, need=eval(shop.need); + var times = shop.times, need=core.calValue(shop.need, null, times); - content = content + shop.text.replace(/\${([^}]+)}/g, function (word, value) { - return eval(value); - }); + content += core.replaceText(shop.text, need, times); var use = shop.use=='experience'?'经验':'金币'; var choices = []; for (var i=0;i=core.firstData.levelUp.length) return; - // 计算下一个所需要的数值 - var next = (core.firstData.levelUp[core.status.hero.lv]||{}); - var need = core.calValue(next.need); - if (!core.isset(need)) return; - if (core.status.hero.experience>=need) { - // 升级 - core.status.hero.lv++; - if (next.clear) core.status.hero.experience -= need; - core.insertAction(next.action); - this.checkLvUp(); + var check = function () { + if (!core.flags.enableLevelUp || !core.isset(core.firstData.levelUp) + || core.status.hero.lv>=core.firstData.levelUp.length) return null; + // 计算下一个所需要的数值 + var next = (core.firstData.levelUp[core.status.hero.lv]||{}); + var need = core.calValue(next.need); + if (!core.isset(need)) return null; + if (core.status.hero.experience>=need) { + // 升级 + core.status.hero.lv++; + if (next.clear) core.status.hero.experience -= need; + return next.action||[]; + } + return null; } + var actions = []; + while (true) { + var next = check(); + if (next == null) break; + actions = actions.concat(next); + } + if (actions.length>0) core.insertAction(actions); } ////// 尝试使用道具 ////// diff --git a/libs/ui.js b/libs/ui.js index e747cb6d..dc030742 100644 --- a/libs/ui.js +++ b/libs/ui.js @@ -1371,20 +1371,38 @@ ui.prototype.drawWaiting = function(text) { core.status.event.id = 'waiting'; core.clearLastEvent(); - core.setFillStyle('ui', core.material.groundPattern); + + var background = core.status.textAttribute.background; + var isWindowSkin = false; + if (typeof background == 'string') { + background = core.material.images.images[background]; + if (core.isset(background) && background.width==192 && background.height==128) isWindowSkin = true; + else background = core.initStatus.textAttribute.background; + } + if (!isWindowSkin) background = core.arrayToRGBA(background); + var borderColor = core.status.globalAttribute.borderColor; + var textColor = core.arrayToRGBA(core.status.textAttribute.text); var globalFont = core.status.globalAttribute.font; - core.setFont('ui', 'bold 17px '+globalFont); + core.setFont('ui', "bold 19px "+globalFont); var text_length = core.canvas.ui.measureText(text).width; var right = Math.max(text_length+50, 220); var left = 208-parseInt(right/2), top = 208 - 32 - 16, bottom = 416 - 2 * top; - core.fillRect('ui', left, top, right, bottom); - core.strokeRect('ui', left - 1, top - 1, right + 1, bottom + 1, '#FFFFFF', 2); + core.clearMap('ui'); + if (isWindowSkin) { + core.setAlpha('ui', 0.85); + this.drawWindowSkin(background,'ui',left,top,right,bottom); + } + else { + core.fillRect('ui', left, top, right, bottom, background); + core.strokeRect('ui', left - 1, top - 1, right + 1, bottom + 1, borderColor, 2); + } + core.setAlpha('ui', 1); core.canvas.ui.textAlign = "center"; - core.fillText('ui', text, 208, top + 56, '#FFFFFF'); + core.fillText('ui', text, 208, top + 56, textColor); } diff --git a/libs/utils.js b/libs/utils.js index 8cb58dce..5a356344 100644 --- a/libs/utils.js +++ b/libs/utils.js @@ -39,14 +39,14 @@ utils.prototype.init = function () { } ////// 将文字中的${和}(表达式)进行替换 ////// -utils.prototype.replaceText = function (text) { +utils.prototype.replaceText = function (text, need, times) { return text.replace(/\${(.*?)}/g, function (word, value) { - return core.calValue(value); + return core.calValue(value, need, times); }); } ////// 计算表达式的值 ////// -utils.prototype.calValue = function (value) { +utils.prototype.calValue = function (value, need, times) { if (!core.isset(value)) return value; if (typeof value == 'number') { return value;