diff --git a/libs/ui.js b/libs/ui.js index 126824d4..02bbf3a4 100644 --- a/libs/ui.js +++ b/libs/ui.js @@ -1375,60 +1375,96 @@ ui.prototype.drawBook = function (index) { ////// 绘制怪物属性的详细信息 ////// ui.prototype.drawBookDetail = function (index) { + var info = this._drawBookDetail_getInfo(index), enemy = info[0]; + var content = info[1].join("\n"); + core.status.event.id = 'book-detail'; + clearInterval(core.interval.tipAnimate); + core.clearMap('data'); + + var left = 10, width = this.PIXEL - 2 * left, right = left + width; + var content_left = left + 25, validWidth = right - content_left - 13; + var contents = core.splitLines("data", content, validWidth, this._buildFont(16, false)); + var height = Math.max(24 * contents.length + 55, 80), top = (this.PIXEL - height) / 2, bottom = top + height; + + core.setAlpha('data', 0.9); + core.fillRect('data', left, top, width, height, '#000000'); + core.setAlpha('data', 1); + core.strokeRect('data', left - 1, top - 1, width + 1, height + 1, + core.status.globalAttribute.borderColor, 2); + + this._drawBookDetail_drawContent(enemy, contents, {top: top, content_left: content_left, bottom: bottom}); +} + +ui.prototype._drawBookDetail_getInfo = function (index) { var floorId = core.floorIds[(core.status.event.ui||{}).index] || core.status.floorId; var enemys = core.enemys.getCurrentEnemys(floorId); - if (enemys.length==0) return; - if (index<0) index=0; - if (index>=enemys.length) index=enemys.length-1; - + index = core.clamp(index, 0, enemys.length - 1); var enemy = enemys[index], enemyId = enemy.id; - var hints=core.enemys.getSpecialHint(enemyId); + var texts=core.enemys.getSpecialHint(enemyId); var damageInfo = core.enemys.getDamageInfo(enemy, null, null, null, floorId); + if (texts.length == 0) texts.push("该怪物无特殊属性。"); + texts.push(""); + this._drawBookDetail_getTexts(enemy, floorId, texts); + return [enemy, texts]; +} - if (hints.length==0) - hints.push("该怪物无特殊属性。"); +ui.prototype._drawBookDetail_getTexts = function (enemy, floorId, texts) { + // --- 模仿临界计算器 + this._drawBookDetail_mofang(enemy, texts); + // --- 吸血怪最低生命值 + this._drawBookDetail_vampire(enemy, texts); + // --- 仇恨伤害 + this._drawBookDetail_hatred(enemy, texts); + // --- 战斗回合数,临界表 + this._drawBookDetail_turnAndCriticals(enemy, floorId, texts); +} +ui.prototype._drawBookDetail_mofang = function (enemy, texts) { // 模仿临界计算器 if (core.enemys.hasSpecial(enemy.special, 10)) { var hp = enemy.hp; var delta = core.status.hero.atk - core.status.hero.def; if (delta0) { - hints.push(""); - hints.push("模仿临界计算器:(当前攻防差"+core.formatBigNumber(delta)+")"); - var arr = []; - (function () { - var last=0, start=0; - for (var i=1;i=0) { var x1 = text.substring(0, index+1); - core.fillText('data', x1, content_left, content_top, '#FF6A6A', 'bold 16px '+globalFont); + core.fillText('data', x1, pos.content_left, content_top, '#FF6A6A', this._buildFont(16, true)); var len=core.calWidth('data', x1); - core.fillText('data', text.substring(index+1), content_left+len, content_top, '#FFFFFF', '16px '+globalFont); + core.fillText('data', text.substring(index+1), pos.content_left+len, content_top, '#FFFFFF', this._buildFont(16, false)); } else { - core.fillText('data', contents[i], content_left, content_top, '#FFFFFF', '16px '+globalFont); + core.fillText('data', contents[i], pos.content_left, content_top, '#FFFFFF', this._buildFont(16, false)); } content_top+=24; } - - core.fillText('data', '<点击任意位置继续>', 270, top+height-13, '#CCCCCC', '13px '+globalFont); } ////// 绘制楼层传送器 ////// @@ -2193,177 +2207,21 @@ ui.prototype.drawStatusBar = function () { } ////// 绘制“数据统计”界面 ////// -ui.prototype.drawStatistics = function () { - - // 数据统计要统计如下方面: - // 1. 当前全塔剩余下的怪物数量,总金币数,总经验数,总加点数 - // 2. 当前全塔剩余的黄蓝红铁门数量,和对应的钥匙数量 - // 3. 当前全塔剩余的三种宝石数量,血瓶数量,装备数量;总共增加的攻防生命值 - // 4. 当前层的上述信息 - // 5. 当前已走的步数;瞬间移动的步数,瞬间移动的次数(和少走的步数);游戏时长 - // 6. 当前已恢复的生命值;当前总伤害、战斗伤害、阻激夹域血网伤害、中毒伤害。 - - var ori = this.uidata.drawStatistics(); - var ids = ori.filter(function (e) { - return e.endsWith("Door") || core.isset(core.material.items[e]); +ui.prototype.drawStatistics = function (floorIds) { + var obj = this._drawStatistics_buildObj(); + if (typeof floorIds == 'string') floorIds = [floorIds]; + (floorIds || core.floorIds).forEach(function (floorId) { + core.ui._drawStatistics_floorId(floorId, obj); }); - var obj = {}; - var cls = {}; - ids.forEach(function (e) { - if (e.endsWith("Door")) cls[e] = "doors"; - else cls[e] = core.material.items[e].cls; - obj[e] = 0; - }) - var order = ["doors", "keys", "items", "tools", "constants", "equips"]; - ids.sort(function (a, b) { - var c1 = order.indexOf(cls[a]), c2 = order.indexOf(cls[b]); - if (c1==c2) return ori.indexOf(a)-ori.indexOf(b); - return c1-c2; - }); - var ext = {}; - - var total = { - 'monster': { - 'count': 0, 'money': 0, 'experience': 0, 'point': 0, - }, - 'count': obj, - 'add': { - 'hp': 0, 'atk': 0, 'def': 0, 'mdef': 0 - } - }; - var current = core.clone(total); - - core.floorIds.forEach(function (floorId) { - var floor=core.status.maps[floorId]||core.floors[floorId]; - var blocks=core.status.maps[floorId].blocks; - // 隐藏层不给看 - if (floor.cannotViewMap && floorId!=core.status.floorId) return; - - blocks.forEach(function (block) { - if (block.disable) return; - var event = block.event; - if (event.cls.indexOf("enemy")==0) { - var enemyId = event.id, enemy = core.material.enemys[enemyId]; - total.monster.money+=enemy.money||0; - total.monster.experience+=enemy.experience||0; - total.monster.point+=enemy.point||0; - total.monster.count++; - if (floorId==core.status.floorId) { - current.monster.money+=enemy.money||0; - current.monster.experience+=enemy.experience||0; - current.monster.point+=enemy.point||0; - current.monster.count++; - } - } - else { - var id = event.id; - - if (core.isset(total.count[id])) { - var hp=0, atk=0, def=0, mdef=0; - - if (cls[id]=='items' && id!='superPotion') { - var temp = core.clone(core.status.hero); - core.setFlag("__statistics__", true); - var ratio = floor.item_ratio||1; - if (core.isset(core.items.itemEffect[id])) { - try { - // 需要检查是否是测试状态... - eval(core.items.itemEffect[id]); - } - catch (e) {} - } - hp = core.status.hero.hp - temp.hp; - atk = core.status.hero.atk - temp.atk; - def = core.status.hero.def - temp.def; - mdef = core.status.hero.mdef - temp.mdef; - core.status.hero = temp; - } - else { - // 装备 - if (cls[id]=='equips') { - var values = core.material.items[id].equip||{}; - atk = values.atk||0; - def = values.def||0; - mdef = values.mdef||0; - } - } - - if (id.indexOf('sword')==0 || id.indexOf('shield')==0 || cls[id]=='equips') { - var t = ""; - if (atk>0) t+=atk+"攻"; - if (def>0) t+=def+"防"; - if (mdef>0) t+=mdef+"魔防"; - if (t!="") ext[id]=t; - } - - total.count[id]++; - total.add.hp+=hp; - total.add.atk+=atk; - total.add.def+=def; - total.add.mdef+=mdef; - if (floorId==core.status.floorId) { - current.count[id]++; - current.add.hp+=hp; - current.add.atk+=atk; - current.add.def+=def; - current.add.mdef+=mdef; - } - } - } - }) - }) - - var getText = function (type, data) { - var text = type+"地图中:\n"; - text += "共有怪物"+data.monster.count+"个"; - if (core.flags.enableMoney) text+=",总金币数"+data.monster.money; - if (core.flags.enableExperience) text+=",总经验数"+data.monster.experience; - if (core.flags.enableAddPoint) text+=",总加点数"+data.monster.point; - text+="。\n"; - - var prev = ""; - ids.forEach(function (key) { - var value = data.count[key]; - if (value==0) return; - var c = cls[key]; - if (c!=prev) { - if (prev != "") text += "。"; - text += "\n"; - } - else - text += ","; - prev = c; - var name = null; - if (key=='yellowDoor') name="黄门"; - else if (key=='blueDoor') name="蓝门"; - else if (key=='redDoor') name="红门"; - else if (key=='greenDoor') name="绿门"; - else if (key=='steelDoor') name="铁门"; - else name=core.material.items[key].name; - text+=name+value+"个"; - if (core.isset(ext[key])) - text+="("+ext[key]+")"; - }) - - if (prev!="") text+="。"; - text+="\n\n"; - text+="共加生命值"+core.formatBigNumber(data.add.hp)+"点,攻击" - +core.formatBigNumber(data.add.atk)+"点,防御" - +core.formatBigNumber(data.add.def)+"点,魔防" - +core.formatBigNumber(data.add.mdef)+"点。"; - return text; - } - var formatTime = function (time) { return core.setTwoDigits(parseInt(time/3600000)) +":"+core.setTwoDigits(parseInt(time/60000)%60) +":"+core.setTwoDigits(parseInt(time/1000)%60); } - var statistics = core.status.hero.statistics; core.drawText([ - getText("全塔", total), - getText("当前", current), + this._drawStatistics_generateText(obj, "全塔", obj.total), + this._drawStatistics_generateText(obj, "当前", obj.current), "当前总步数:"+core.status.hero.steps+",当前游戏时长:"+formatTime(statistics.currTime) +",总游戏时长"+formatTime(statistics.totalTime) +"。\n瞬间移动次数:"+statistics.moveDirectly+",共计少走"+statistics.ignoreSteps+"步。" @@ -2375,10 +2233,148 @@ ui.prototype.drawStatistics = function () { +",领域/夹击/阻击/血网伤害"+core.formatBigNumber(statistics.extraDamage)+"点。", "\t[说明]1. 地图数据统计的效果仅模拟当前立刻获得该道具的效果。\n2. 不会计算“不可被浏览地图”的隐藏层的数据。\n" + "3. 不会计算任何通过事件得到的道具(显示事件、改变图块、或直接增加道具等)。\n"+ - "4. 在自定义道具(例如其他宝石)后,需在ui.js的drawStatistics中注册,不然不会进行统计。\n"+ + "4. 在自定义道具(例如其他宝石)后,需在脚本编辑的drawStatistics中注册,不然不会进行统计。\n"+ "5. 所有统计信息仅供参考,如有错误,概不负责。" ]) +} +ui.prototype._drawStatistics_buildObj = function () { + // 数据统计要统计如下方面: + // 1. 当前全塔剩余下的怪物数量,总金币数,总经验数,总加点数 + // 2. 当前全塔剩余的黄蓝红铁门数量,和对应的钥匙数量 + // 3. 当前全塔剩余的三种宝石数量,血瓶数量,装备数量;总共增加的攻防生命值 + // 4. 当前层的上述信息 + // 5. 当前已走的步数;瞬间移动的步数,瞬间移动的次数(和少走的步数);游戏时长 + // 6. 当前已恢复的生命值;当前总伤害、战斗伤害、阻激夹域血网伤害、中毒伤害。 + var ori = this.uidata.drawStatistics(); + var ids = ori.filter(function (e) { + return e.endsWith("Door") || core.material.items[e]; + }); + var cnt = {}, cls = {}, ext = {}; + ids.forEach(function (e) { + if (e.endsWith("Door")) cls[e] = "doors"; + else cls[e] = core.material.items[e].cls; + cnt[e] = 0; + }) + var order = ["doors", "keys", "items", "tools", "constants", "equips"]; + ids.sort(function (a, b) { + var c1 = order.indexOf(cls[a]), c2 = order.indexOf(cls[b]); + if (c1==c2) return ori.indexOf(a)-ori.indexOf(b); + return c1-c2; + }); + var obj = { + 'monster': { + 'count': 0, 'money': 0, 'experience': 0, 'point': 0, + }, + 'count': cnt, + 'add': { + 'hp': 0, 'atk': 0, 'def': 0, 'mdef': 0 + } + }; + return {ids: ids, cls: cls, ext: ext, total: core.clone(obj), current: core.clone(obj)}; +} + +ui.prototype._drawStatistics_add = function (floorId, obj, x1, x2, value) { + obj.total[x1][x2] += value || 0; + if (floorId == core.status.floorId) + obj.current[x1][x2] += value || 0; +} + +ui.prototype._drawStatistics_floorId = function (floorId, obj) { + var floor = core.status.maps[floorId], blocks = floor.blocks; + // 隐藏层不给看 + if (floor.cannotViewMap && floorId!=core.status.floorId) return; + blocks.forEach(function (block) { + if (block.disable) return; + var event = block.event; + if (event.cls.indexOf("enemy")==0) { + core.ui._drawStatistics_enemy(floorId, event.id, obj); + } + else { + var id = event.id; + if (obj.total.count[id] != null) + core.ui._drawStatistics_items(floorId, floor, id, obj); + } + }) +} + +ui.prototype._drawStatistics_enemy = function (floorId, id, obj) { + var enemy = core.material.enemys[id]; + this._drawStatistics_add(floorId, obj, 'monster', 'money', enemy.money); + this._drawStatistics_add(floorId, obj, 'monster', 'experience', enemy.experience); + this._drawStatistics_add(floorId, obj, 'monster', 'point', enemy.point); + this._drawStatistics_add(floorId, obj, 'monster', 'count', 1); +} + +ui.prototype._drawStatistics_items = function (floorId, floor, id, obj) { + var hp=0, atk=0, def=0, mdef=0; + if (obj.cls[id]=='items' && id!='superPotion') { + var temp = core.clone(core.status.hero); + core.setFlag("__statistics__", true); + var ratio = floor.item_ratio||1; + try { eval(core.items.itemEffect[id]); } + catch (e) {} + hp = core.status.hero.hp - temp.hp; + atk = core.status.hero.atk - temp.atk; + def = core.status.hero.def - temp.def; + mdef = core.status.hero.mdef - temp.mdef; + core.status.hero = temp; + } + else if (obj.cls[id]=='equips') { + var values = core.material.items[id].equip || {}; + atk = values.atk || 0; + def = values.def || 0; + mdef = values.mdef || 0; + } + if (id.indexOf('sword')==0 || id.indexOf('shield')==0 || obj.cls[id]=='equips') { + var t = ""; + if (atk > 0) t += atk + "攻"; + if (def > 0) t += def + "防"; + if (mdef > 0) t += mdef + "魔防"; + if (t != "") obj.ext[id] = t; + } + this._drawStatistics_add(floorId, obj, 'count', id, 1); + this._drawStatistics_add(floorId, obj, 'add', 'hp', hp); + this._drawStatistics_add(floorId, obj, 'add', 'atk', atk); + this._drawStatistics_add(floorId, obj, 'add', 'def', def); + this._drawStatistics_add(floorId, obj, 'add', 'mdef', mdef); +} + +ui.prototype._drawStatistics_generateText = function (obj, type, data) { + var text = type+"地图中:\n"; + text += "共有怪物"+data.monster.count+"个"; + if (core.flags.enableMoney) text+=",总金币数"+data.monster.money; + if (core.flags.enableExperience) text+=",总经验数"+data.monster.experience; + if (core.flags.enableAddPoint) text+=",总加点数"+data.monster.point; + text+="。\n"; + + var prev = ""; + obj.ids.forEach(function (key) { + var value = data.count[key]; + if (value==0) return; + if (obj.cls[key] != prev) { + if (prev != "") text += "。"; + text += "\n"; + } + else text += ","; + prev = obj.cls[key]; + text+=core.ui._drawStatistics_getName(key)+value+"个"; + if (obj.ext[key]) + text+="("+obj.ext[key]+")"; + }) + if (prev!="") text+="。"; + + text+="\n\n"; + text+="共加生命值"+core.formatBigNumber(data.add.hp)+"点,攻击" + +core.formatBigNumber(data.add.atk)+"点,防御" + +core.formatBigNumber(data.add.def)+"点,魔防" + +core.formatBigNumber(data.add.mdef)+"点。"; + return text; +} + +ui.prototype._drawStatistics_getName = function (key) { + return {"yellowDoor": "黄门", "blueDoor": "蓝门", "redDoor": "红门", "greenDoor": "绿门", + "steelDoor": "铁门"}[key] || core.material.items[key].name; } ////// 绘制“关于”界面 ////// @@ -2434,7 +2430,8 @@ ui.prototype.drawHelp = function () { core.status.event.id = 'help'; core.lockControl(); core.setAlpha('ui', 1); - core.drawImage('ui', core.material.images.keyboard, 0, 0); + core.fillRect('ui', 0, 0, this.PIXEL, this.PIXEL, '#FFFFFF'); + core.drawImage('ui', core.material.images.keyboard, 32 * (this.HSIZE - 6), 32 * (this.HSIZE - 6)); } else { core.drawText([