Greasy Fork is available in English.
挂机无止境的辅助脚本
// ==UserScript== // @name idle // @version 1.45 // @namespace ErQi // @description 挂机无止境的辅助脚本 // @author [email protected] // @grant GM_addStyle // @run-at document-start // @match https://www.idleinfinity.cn/* // @require https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.1/moment.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/jquery-url-parser/2.3.1/purl.min.js // ==/UserScript== const defaultFilterOptions = ['技能', '凹槽(0/2)', '凹槽(0/4)', '取得魔法装备', '攻击速度', '施法速度', '+20 毒素', '+25 毒素']; let config = { userNumber: 1, showRequire: true, fastFilter: true, fastOptions: defaultFilterOptions.slice(0), // 快速过滤器配置,可自行增删 showSpellColor: true, showSpeedLevel: true, showCharDmg: true, showAccuracy: true, dropNotification: true, itemStats: true, showBattle: true, mapHack: true, mapHackType: 'all', infiniteMap: false, showSetAttr: true, showAuctionNote: true, auctionWatch: true, oneKeyEquip: true, oneKeyAgree: true, oneKeyRune: true, showRuneTip: true, showBattleDetail: true, d3theme: true, minLevel: null, // 秘境的石头等级 0 表示普通 1表示魔法 2表示稀有,以此类推 按照下拉列表的排序 level: '', moveTime: 5000, failure: 10, magical: true, }; const configLabel = { showRequire: '职业专属显示', fastFilter: '快速过滤选项', showSpellColor: '法术技能高亮', showSpeedLevel: '显示速度档位', showCharDmg: '角色均伤显示', showAccuracy: '角色命中显示', dropNotification: '欧皇暗金通知', itemStats: '欧皇收获统计', showBattle: '快速秘境战斗', mapHack: '秘境自动战斗', infiniteMap: '无限秘境模式', showSetAttr: '显示套装属性', showAuctionNote: '显示拍卖备注', auctionWatch: '拍卖特别关注', oneKeyEquip: '一键换装功能', oneKeyAgree: '一键同意功能', oneKeyRune: '一键转移符文', showRuneTip: '符文之语提示', showBattleDetail: '战斗详细分析', d3theme: '暗黑界面皮肤', minLevel: '符文序号', failure: '失败重置次数', magical: '一件升级蓝色秘境', }; const userConfig = ['dropNotification', 'd3theme']; let localConfig = localStorage.getItem('idle-ui-config'); if (localConfig) { localConfig = JSON.parse(localConfig); Object.keys(localConfig).map(key => { if (config[key] !== undefined) config[key] = localConfig[key]; }); } if (config.d3theme) { const htmlElement = document.getElementsByTagName('html')[0]; htmlElement.setAttribute('class', 'd3'); } function idleInit() { // 秘境的石头等级 ''空表示所有秘境 0 表示普通 1表示魔法 2表示稀有,以此类推 按照下拉列表的排序 config.level = ''; // 转移物品间隔时间,单位毫秒,最低不能低于300,会被制裁 config.moveTime = 500; // 战斗失败重置次数,当同一组怪物失败到达此次数,自动重置当前秘境 config.failure = 25; // 是否绕着Boss走 config.dodge = false; // 同意消息间隔时间 config.agreedTime = 800; var style = document.createElement('style'); style.type = 'text/css'; style.innerHTML = `.eq-weapon { background-color: #700;} .eq-armor {background-color: #007;} .eq-amulet {background-color: #0b0;} .eq-delete {background-color: gray;} .eq-jewel {background-color: #808a87;} .selected-b {border: 1px solid #66ccff!important;} .selected-r {border: 1px solid #f00!important;} .selected-d {border: 1px solid #fff!important;}`; document.getElementsByTagName('head')[0].appendChild(style); // Extend page width // $('.container:nth(1)').css('width', '70%'); $('body').css('height', $('body').height() + 500); var equips = $(".panel-filter").parent().prev().find(".equip-content"); var on_gears = $('.equip-container .equip-content'); var i, gear, ps, hits, key, n_name, eqn; for (i = 0; i < on_gears.length; i++) { gear = on_gears[i]; ps = gear.getElementsByTagName('p'); if (ps.length > 0) { hits = gear.innerHTML.match(/彩虹刻面/); if (hits != null) { eqn = gear.previousElementSibling.getElementsByClassName('equip-name'); hits = gear.innerHTML.match(/(\d+)陨石/); if (hits != null) { eqn[eqn.length - 1].innerHTML += ' <span style="color:red; background-color: black;">火刻 ' + hits[1] + 'slv</span>'; } hits = gear.innerHTML.match(/(\d+)暴风雪/); if (hits != null) { eqn[eqn.length - 1].innerHTML += ' <span style="color:#3ff; background-color: black;">冰刻 ' + hits[1] + 'slv</span>'; } hits = gear.innerHTML.match(/(\d+)连锁闪电/); if (hits != null) { eqn[eqn.length - 1].innerHTML += ' <span style="color:yellow; background-color: black;">电刻 ' + hits[1] + 'slv</span>'; } hits = gear.innerHTML.match(/(\d+)剧毒新星/); if (hits != null) { eqn[eqn.length - 1].innerHTML += ' <span style="color:#00c400; background-color: black;">毒刻 ' + hits[1] + 'slv</span>'; } hits = gear.innerHTML.match(/(\d+)虚化/); if (hits != null) { eqn[eqn.length - 1].innerHTML += ' <span style="color:#B659F5; background-color: black;">魔刻 ' + hits[1] + 'slv</span>'; } hits = gear.innerHTML.match(/(\d+)伤害加深/); if (hits != null) { eqn[eqn.length - 1].innerHTML += ' <span style="color:white; background-color: black;">物刻</span>'; } hits = gear.innerHTML.match(/(\d+)\% 火焰伤害/); if (hits != null) { eqn[eqn.length - 1].innerHTML += ' <span style="color:red; background-color: black;">+' + hits[1] + '</span>'; } hits = gear.innerHTML.match(/(\d+)\% 冰冷伤害/); if (hits != null) { eqn[eqn.length - 1].innerHTML += ' <span style="color:#3ff; background-color: black;">+' + hits[1] + '</span>'; } hits = gear.innerHTML.match(/(\d+)\% 闪电伤害/); if (hits != null) { eqn[eqn.length - 1].innerHTML += ' <span style="color:yellow; background-color: black;">+' + hits[1] + '</span>'; } hits = gear.innerHTML.match(/(\d+)\% 毒素伤害/); if (hits != null) { eqn[eqn.length - 1].innerHTML += ' <span style="color:#00c400; background-color: black;">+' + hits[1] + '</span>'; } hits = gear.innerHTML.match(/(\d+)\% 魔法伤害/); if (hits != null) { eqn[eqn.length - 1].innerHTML += ' <span style="color:#B659F5; background-color: black;">+' + hits[1] + '</span>'; } hits = gear.innerHTML.match(/(\d+)\% 物理伤害/); if (hits != null) { eqn[eqn.length - 1].innerHTML += ' <span style="color:white; background-color: black;">+' + hits[1] + '</span>'; } hits = gear.innerHTML.match(/(\d+)\% 目标火焰抗性/); if (hits != null) { eqn[eqn.length - 1].innerHTML += ' <span style="color:red; background-color: black;">-' + hits[1] + '</span>'; } hits = gear.innerHTML.match(/(\d+)\% 目标冰冷抗性/); if (hits != null) { eqn[eqn.length - 1].innerHTML += ' <span style="color:#3ff; background-color: black;">-' + hits[1] + '</span>'; } hits = gear.innerHTML.match(/(\d+)\% 目标闪电抗性/); if (hits != null) { eqn[eqn.length - 1].innerHTML += ' <span style="color:yellow; background-color: black;">-' + hits[1] + '</span>'; } hits = gear.innerHTML.match(/(\d+)\% 目标毒素抗性/); if (hits != null) { eqn[eqn.length - 1].innerHTML += ' <span style="color:#00c400; background-color: black;">-' + hits[1] + '</span>'; } } hits = gear.innerHTML.match(/攻击速度提升 (\d+)\%/); if (hits != null) { eqn = gear.previousElementSibling.getElementsByClassName('equip-name'); eqn[eqn.length - 1].innerHTML += ' <span style="color:#ffd700; background-color: black;">' + hits[1] + 'ias </span>'; } hits = gear.innerHTML.match(/施法速度提升 (\d+)\%/); if (hits != null) { eqn = gear.previousElementSibling.getElementsByClassName('equip-name'); eqn[eqn.length - 1].innerHTML += ' <span style="color:#ff8000; background-color: black;">' + hits[1] + 'fcr </span>'; } hits = gear.innerHTML.match(/\+(\d+)\% 增强伤害/); if (hits != null) { eqn = gear.previousElementSibling.getElementsByClassName('equip-name'); eqn[eqn.length - 1].innerHTML += ' <span style="color:#66ccff; background-color: black;">' + hits[1] + 'ed </span>'; } hits = gear.innerHTML.match(/\+(\d+)\% 暴击几率/); if (hits != null) { eqn = gear.previousElementSibling.getElementsByClassName('equip-name'); eqn[eqn.length - 1].innerHTML += ' <span style="color:#CCCC00; background-color: black;">' + hits[1] + 'cri </span>'; } hits = ps[ps.length - 1].textContent.match(/凹槽(\(\d+\/\d+\))/); if (hits != null) { eqn = gear.previousElementSibling.getElementsByClassName('equip-name') eqn[eqn.length - 1].innerHTML += ' <span>' + hits[1] + ' </span>'; } hits = gear.innerHTML.match(/\+(\d+)\% 更佳的机会取得魔法装备/); if (hits != null) { eqn = gear.previousElementSibling.getElementsByClassName('equip-name'); eqn[eqn.length - 1].innerHTML += ' <span style="color:white; background-color: black;"> ' + hits[1] + 'mf </span>'; } hits = gear.innerHTML.match(/\+(\d+)\% 额外金币从怪物身上取得/); if (hits != null) { eqn = gear.previousElementSibling.getElementsByClassName('equip-name'); eqn[eqn.length - 1].innerHTML += ' <span style="color:gold; background-color: black;"> ' + hits[1] + 'gf </span>'; } hits = gear.innerHTML.match(/元素抗性 \+(\d+)\%/); if (hits != null) { eqn = gear.previousElementSibling.getElementsByClassName('equip-name'); eqn[eqn.length - 1].innerHTML += ' <span style="color:#f90; background-color: black;">' + hits[1] + 'ar </span>'; } hits = gear.innerHTML.match(/抗火 \+(\d+)\%/); if (hits != null) { eqn = gear.previousElementSibling.getElementsByClassName('equip-name'); eqn[eqn.length - 1].innerHTML += ' <span style="color:red; background-color: black;">' + hits[1] + 'f </span>'; } hits = gear.innerHTML.match(/抗寒 \+(\d+)\%/); if (hits != null) { eqn = gear.previousElementSibling.getElementsByClassName('equip-name'); eqn[eqn.length - 1].innerHTML += ' <span style="color:#3ff; background-color: black;">' + hits[1] + 'c </span>'; } hits = gear.innerHTML.match(/抗闪电 \+(\d+)\%/); if (hits != null) { eqn = gear.previousElementSibling.getElementsByClassName('equip-name'); eqn[eqn.length - 1].innerHTML += ' <span style="color:yellow; background-color: black;">' + hits[1] + 'l </span>'; } hits = gear.innerHTML.match(/抗毒 \+(\d+)\%/); if (hits != null) { eqn = gear.previousElementSibling.getElementsByClassName('equip-name'); eqn[eqn.length - 1].innerHTML += ' <span style="color:#00c400; background-color: black;">' + hits[1] + 'p </span>'; } } } addConfig(); // 显示限定字符 switchSkin(config.showRequire); Notification.requestPermission(); $('.navbar-nav > li > a').each(function () { if ($(this).text().indexOf('帮助') >= 0) { const links = [ {text: '暗金列表', link: '/Help/Content?url=Unique'}, {text: '套装列表', link: '/Help/Content?url=Set'}, // {text: '秘境圣衣', link: '/Help/Content?url=Sacred'}, {text: '神器列表', link: '/Help/Content?url=Artifact'}, {text: '普通物品', link: '/Help/Content?url=BaseEquip'}, {text: '前缀属性', link: '/Help/Content?url=Prefix'}, {text: '后缀属性', link: '/Help/Content?url=Suffix'}, {text: '固定词缀', link: '/Help/Content?url=SpecialAffix'}, {text: '神秘玩具', link: '/Help/specialequip'}, ].map(item => { return `<li><a class="base" href="${item.link}" target="_blank">${item.text}</a></li>`; }).join(''); $(this).next().append(links); } }); function fetchItem(name, callback) { if (!name) return; if (quickSearchType === 'Set' || quickSearchType === 'Unique') { $.get(`/Help/${quickSearchType}`, function (html) { const dom = $.parseHTML(html); const type = quickSearchType.toLowerCase(); $(dom).find(`.equip > .${type}`).each(function () { if ($(this).text().indexOf(name) >= 0) { callback($(this).parent()); return; } }); }); } else { $.get('/Help/Artifact', function (html) { const dom = $.parseHTML(html); $(dom).find('tr').each(function (i) { if (i > 0) { const nameLabel = $(this).children().last().find('.artifact'); if (nameLabel.text().indexOf(name) >= 0) { const ret = []; ret.push(`<p class="artifact">${nameLabel.text()}</p>`); $(this).children().first().children('div').each(function () { ret.push(`<p class="physical">${$(this).text()}</p>`); }); ret.push('<p class="artifact">神器</p>'); nameLabel.parent().children().each(function (index) { if (index > 0) ret.push(`<p>${$(this).text()}</p>`); }); const recipe = []; $(this).children().eq(1).find('.artifact.equip-name').each(function () { const id = $(this).text().match(/\d+/g)[0]; recipe.push(`<span class="artifact">${id}#</span>`); }); ret.push(`<p class="physical">${recipe.join(' + ')}</p>`); callback($(`<div class="equip">${ret.join('')}</div>`)); return; } } }); }); } } let quickSearchType = 'Unique'; const itemTypes = ` <div class="btn-group"> <button type="button" class="btn btn-default btn-xs dropdown-toggle" data-toggle="dropdown"> <span id="idle-quick-type">暗金</span><span class="caret" style="margin-left: 5px;"></span> </button> <ul class="dropdown-menu"> <li><a class="quick-option unique" data-type="Unique" href="javascript: void(0);">暗金</a></li> <li><a class="quick-option set" data-type="Set" href="javascript: void(0);">套装</a></li> <li><a class="quick-option artifact" data-type="Artifact" href="javascript: void(0);">神器</a></li> </ul> </div> `; const input = `<div id="idle-ui-quicksearch">${itemTypes}<input placeholder="搜索..." class="form-control"/><div class="popover" style="display: none; left: 60px; top: 28px;"><div class="popover-content"></div></div></div>`; $('.navbar-header').append(input); $('.quick-option').click(function (e) { e.preventDefault(); quickSearchType = $(this).data('type'); $('#idle-quick-type').text($(this).text()); const val = $('#idle-ui-quicksearch > input').val(); if (val) { const popover = $('#idle-ui-quicksearch > input').next(); popover.hide(); fetchItem(val, function (html) { popover.children().first().html(html); popover.show(); }); } }); let quickTimer = null; $('#idle-ui-quicksearch > input').keyup(function () { if (quickTimer) { clearTimeout(quickTimer); quickTimer = null; } const val = $(this).val(); if (!val) $(this).next().hide(); quickTimer = setTimeout(() => { const popover = $(this).next(); popover.hide(); fetchItem(val, function (html) { popover.children().first().html(html); popover.show(); }); }, 500); }); if (config.fastFilter) { const fastOptions = (['无'].concat(config.fastOptions)).map(function (item) { return `<li><a href="javascript: void(0);" class="filter-text" style="color: white">${item}</a></li>`; }).join(''); const fastFilter = '<div class="fast-filter btn-group">' + '<button type="button" class="btn btn-default btn-xs dropdown-toggle" style="margin-left: 10px;" data-toggle="dropdown">快速过滤<span class="caret"/></button>' + `<ul class="dropdown-menu">${fastOptions}</ul></div>`; $(fastFilter).insertAfter('.panel-filter'); $('.filter-text').click(function () { const text = $(this).text() === '无' ? '' : $(this).text(); const filter = $(this).parent().parent().parent().prev(); filter.val(text); filter.trigger('input'); }); } if (config.showSpellColor) { $('.skill-name').each(function () { let desc = ''; let label = ''; if ($(this).children().length === 2) { desc = $(this).next().text(); label = $(this).children().last(); } else { desc = $(this).parent().next().text(); label = $(this); } if (desc.indexOf('法术技能') >= 0) { label.addClass('skill'); } }); } function getSpeedLevel(speed, isAttack) { const levels = isAttack ? [0, -25, -50, -80, -120, -160, -200] : [0, -20, -45, -75, -110, -145, -180]; for (let i = 0; i < levels.length; i++) { if (speed > levels[i]) { const next = levels[i]; return [i, next]; } } return [levels.length, '已最高']; } function getAvgDmg(dmgStr) { const dmgArray = dmgStr.split('~'); const avg = (((dmgArray[0] - 0) + (dmgArray[1] - 0)) / 2); return avg; } function getKeySkill() { let ret = {name: '', accRate: 0, dmgRate: 0}; $('span.label.label-danger').each(function () { if (!$(this).hasClass('sr-only') && $(this).text().indexOf('K') >= 0) { ret.name = $(this).prev().text(); const skill = $(this).parent().next().text(); ret.isAttack = skill.indexOf('攻击技能') >= 0; if (ret.isAttack) { const accMatch = skill.match(/提升(\d+)%准确率/); const dmgMatch = skill.match(/(\d+)%基础伤害/); if (accMatch) ret.accRate = (accMatch[1] - 0) / 100; if (dmgMatch) ret.dmgRate = (dmgMatch[1] - 0) / 100; } } }); return ret; } function renderCharLabel(name, value, id) { const idStr = id ? `id="${id}"` : ''; return `<p><span>${name}:</span><span ${idStr} class="state">${value}</span></p>`; } if (location.href.indexOf('Character/Detail') >= 0) { const keySkill = getKeySkill(); let level = 0; $('.label.label-default').each(function () { const label = $(this).text(); if (label.indexOf('Lv') >= 0 && level === 0) { level = label.replace('Lv', '') - 0; } if (config.showSpeedLevel) { if (label === '攻击') { const attackSpeed = $(this).parent().next().next().next().next().children().last(); const level = getSpeedLevel(attackSpeed.text(), true); const levelElement = renderCharLabel('攻速档位', level[0]) + renderCharLabel('下档攻速', level[1]); $(levelElement).insertAfter(attackSpeed.parent()); } else if (label === '法术') { const spellSpeed = $(this).parent().next().children().last(); const level = getSpeedLevel(spellSpeed.text(), false); const levelElement = renderCharLabel('速度档位', level[0]) + renderCharLabel('下档速度', level[1]); $(levelElement).insertAfter(spellSpeed.parent()); } } if (config.showCharDmg) { if (label === '攻击') { const baseDmg = $(this).parent().next().children().last().text(); const critElement = $(this).parent().next().next().next(); const crit = critElement.children().last().text().replace('%', '') / 100; const avgDmg = getAvgDmg(baseDmg); const finalDmg = (avgDmg * (1 + (crit - 0))).toFixed(2) - 0; let dmgElement = renderCharLabel('普攻均伤', finalDmg); if (keySkill.isAttack) { const keyDmg = (keySkill.dmgRate * finalDmg).toFixed(2) - 0; dmgElement += renderCharLabel(`${keySkill.name}均伤`, keyDmg); } $(dmgElement).insertAfter(critElement); } } if (config.showAccuracy) { if (label === '攻击') { const accuracy = $(this).parent().next().next().children().last().text() - 0; const accuracyElement = $(this).parent().next().next(); const accRate = getAccRate(level, level, accuracy); let accElement = `<p><span>命中怪物等级:</span><span><input type="number" class="form-control hit-input" value="${level}"/></span></p>`; accElement += renderCharLabel('普攻命中率', `${accRate}%`, 'idle-ui-acc'); if (keySkill.isAttack) { const keyAcc = accuracy * keySkill.accRate; const keyAccRate = getAccRate(level, level, keyAcc); accElement += renderCharLabel(`${keySkill.name}命中率`, `${keyAccRate}%`, 'idle-ui-key-acc'); } $(accElement).insertAfter(accuracyElement); $('.hit-input').change(function () { const mlvl = $(this).val(); const def = (mlvl - 0 + 1) * 10; const curAccRate = getAccRate(level, mlvl, accuracy); $('#idle-ui-acc').text(`${curAccRate}%`); if (keySkill.isAttack) { const curKeyAccRate = getAccRate(level, mlvl, accuracy * keySkill.accRate); $('#idle-ui-key-acc').text(`${curKeyAccRate}%`); } }); } } if (config.itemStats) { if (label == '综合') { const uniqueNum = $(this).parent().next().next().next().next().children().last().text(); const setNum = $(this).parent().next().next().next().next().next().children().last().text(); const statsData = {uniqueNum: uniqueNum, setNum: setNum}; saveStats({uniqueNum: uniqueNum, setNum: setNum}); } } }); } function getAccRate(clvl, mlvl, acc) { clvl = clvl - 0; mlvl = mlvl - 0; acc = acc - 0; const def = (mlvl - 0 + 1) * 10; return (2 * (clvl / (clvl + mlvl)) * (acc / (acc + def)) * 100).toFixed(2) - 0; } function saveStats(statsData) { const idMatch = location.href.match(/Character\/Detail\?Id=(\d+)/i); if (!idMatch) return; const id = idMatch[1]; let stats = localStorage.getItem('idle-ui-stats'); stats = stats ? JSON.parse(stats) : {uniqueNum: 0, setNum: 0}; const lastStatsData = stats[id]; const time = +new Date(); if (lastStatsData && lastStatsData.time) { const duration = moment.duration(moment(time).diff(moment(lastStatsData.time))); const timeSpan = duration.asMinutes() > 60 ? (duration.asHours().toFixed(1) - 0) + '小时前' : Math.round(duration.asMinutes()) + '分钟前'; const uniqueChange = statsData.uniqueNum - lastStatsData.uniqueNum; const setChange = statsData.setNum - lastStatsData.setNum; displayStats(id, timeSpan, uniqueChange, setChange); } statsData.time = time; stats[id] = statsData; localStorage.setItem('idle-ui-stats', JSON.stringify(stats)); } function displayStats(id, timeSpan, uniqueChange, setChange) { const message = `<div class="panel panel-inverse panel-top"><div class="panel-body">上次访问是${timeSpan},这段时间内你获得了 <span class="unique">${uniqueChange}</span> 件暗金,<span class="set">${setChange}</span> 件套装。<a href="javascript: void(0);" id="open-ui-modal" class="btn btn-xs btn-default ml-10">插件设置</a></div></div>`; $('.navbar.navbar-inverse.navbar-fixed-top').next().next().prepend(message); $('#open-ui-modal').click(function () { $('#modalUI').modal('show'); }); } // 离线挂机统计记录 if (config.dropNotification && location.href.indexOf('Map/Dungeon') === -1) { $(document).ready(function () { // 找到数据添加下拉框 // $("div.panel-heading") // 添加获得焦点事件,在获得焦点时更新下拉列表数据 // 处理下拉选中,显示数据 // 初始化记载经验数据列表 const userCont = new Map(); const dropTypes = {unique: '暗金', set: '套装'}; const oldLog = $.connection.userManagerHub.client.battleLog; $.connection.userManagerHub.client.battleLog = function (data) { const ret = JSON.parse(data); const keys = Object.keys(ret.EquipmentNameList); if (keys.length > 0) { keys.forEach(function (type) { const items = ret.EquipmentNameList[type].join(','); if (dropTypes[type]) { const notice = new Notification( `${ret.CharName} 获得${dropTypes[type]}`, { body: items, icon: 'https://cdn3.iconfinder.com/data/icons/game-play/512/gaming-game-play-multimedia-console-09-512.png' } ); } }); } if (ret.RuneNameList.length) { let s = ret.RuneNameList.join(','); if (parseInt(s.replace(/[^0-9]/ig, "")) >= parseInt(config.minLevel)) { new Notification( `${ret.CharName} 获得符文`, { body: s, icon: 'https://cdn0.iconfinder.com/data/icons/geek-4/24/Mortal_Instruments_movie_symbol_logo_rune-512.png' } ); } } if (!userCont.get(ret.CharName)) { const user = {}; user.name = ret.CharName; user.time = 0; user.count = 0; user.exp = 0; user.gold = 0; user.equipment = 0; userCont.set(ret.CharName, user); } let user = userCont.get(ret.CharName); user.time += Number(ret.CostTime); user.count += 1; let exp = Number(ret.Exp); user.exp += isNaN(exp) ? 0 : exp; let gold = Number(ret.Gold); user.gold += isNaN(gold) ? 0 : gold; userCont.set(ret.CharName, user); user.equipment += keys.length; console.log(user.name + "\t" + (user.time / user.count).toFixed(2) + "\t" + ((user.exp / user.time) * 60).toFixed(2) + "\t" + ((user.equipment / user.time * 3600)).toFixed(0)); if (oldLog) oldLog(data); }; $.connection.hub.stop(); $.connection.hub.start(); }); } if (config.showBattle && inBattlePage() && !$('.error').length) { let waitTime = $('#time'); if (waitTime.length) { waitTime = waitTime.val(); } else { $(document).ready(function () { $(".turn").battle({ interval: 0, guaji: 0 }); }); } } function renderConigHtml() { return Object.keys(config) .filter(item => userConfig.indexOf(item) >= 0) .map(key => { const cfg = config[key]; return `<div class="col-sm-4"><div class="checkbox" style="margin: 2px 0;"><label><input class=" idle-ui-config" type="checkbox" data-key="${key}"> ${configLabel[key]}</label></div></div>` }) .join(''); } function addConfig() { // $("[name='gold'][id='gold'][type='number']").attr('value', 50000); const configHtml = renderConigHtml(); const html = ` <div class="modal fade" id="modalUI" style="display: none;"> <div class="modal-dialog modal-large" role=""> <div class="modal-content model-inverse"> <div class="modal-header"> <span class="modal-title">插件设置</span> </div> <div class="modal-body"> <div class="idle-ui-title">Idle Infinity UI 增强插件 by 班登</div> <div class="panel-header state">配置项开关(配置具体含义请参考<a href="https://greasyfork.org/zh-CN/scripts/370841-fight-beibei-everyday" target="_blank">脚本介绍</a>,点击即可启用/禁用,变更后请刷新)</div> <div class="form row">${configHtml}</div> <p>按 Alt+T 可快速切换主题皮肤</p> <div class="panel-header state">自动秘境模式</div> <div> <label class="radio-inline"> <input type="radio" class="idle-ui-hack-type" name="maphack-type" id="hack-boss" value="boss"> 只打BOSS </label> <label class="radio-inline"> <input type="radio" class="idle-ui-hack-type" name="maphack-type" id="hack-all" value="all"> 小怪全清 </label> <label class="radio-inline"> <input type="radio" class="idle-ui-hack-type" name="maphack-type" id="hack-mystery" value="mystery"> 秘境扫荡 </label> </div> <div class="panel-header state">符文提示过滤</div> <div> <input id="idle-ui-rune-filter" type="number" name="points" min="1" max="33" step="1" style="padding: 0 0 0 10px; width: 20%;" placeholder=${configLabel.minLevel} value=${config.minLevel}> </div> <div class="panel-header state"></div> <div class="panel-header state">快速过滤下拉选项(每行一个)</div> <textarea id="idle-ui-filters" class="form-control panel-textarea" rows="5"></textarea> <div class="textarea-actions"> <button type="button" class="btn btn-xs btn-success" id="idle-ui-save-filters">保存选项</button> <button type="button" class="btn btn-xs btn-default" id="idle-ui-reset-filters">恢复默认</button> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-default btn-xs" data-dismiss="modal">关闭</button> </div> </div> </div> </div> `; $(document.body).append(html); loadLocalConfig(); } function loadLocalConfig() { $('.idle-ui-config').each(function () { const key = $(this).data('key'); $(this).prop('checked', config[key]); }); $('#idle-ui-filters').val(config.fastOptions.join('\n')); $(`#hack-${config.mapHackType}`).prop('checked', true); $('#idle-ui-reset-filters').click(function () { config.fastOptions = defaultFilterOptions; saveLocalConfig(); loadLocalConfig(); }); $('#idle-ui-save-filters').click(function () { config.fastOptions = $('#idle-ui-filters').val().split('\n'); config.minLevel = $('#idle-ui-rune-filter').val(); saveLocalConfig(); }); $('.idle-ui-config').change(function () { const key = $(this).data('key'); config[key] = $(this).prop('checked'); if (config.d3theme) { $('html').addClass('d3'); } else { $('html').removeClass('d3'); } saveLocalConfig(); }); $('.idle-ui-hack-type').change(function () { if ($(this).prop('checked')) config.mapHackType = $(this).val(); saveLocalConfig(); }); // 监听alt+t按键,切换界面 $(document).bind('keyup', function (event) { if (event.which === 84 && event.altKey) { $('html').toggleClass('d3'); switchSkin(document.getElementsByClassName('d3').length > 0) } }); } function saveLocalConfig() { localStorage.setItem('idle-ui-config', JSON.stringify(config)); } // 监听过滤条件输入框的改变 $(".panel-filter").on("input propertychange", function () { $(this).parent().prev().find(".selected").removeClass("selected") // 输入的值 var value = $(this).val(); // 保存到缓存,方便下次使用 window.localStorage.setItem($(this).attr("id"), value); if (value.length > 0) { var values = value.split(","); var equips = $(this).parent().prev().find(".equip-content"); // 正则判断是否是数字 const min = /^<[0-9]+.?[0-9]*$/; const max = /^>[0-9]+.?[0-9]*$/; // 提取装备等级的正则表达式 const level = /\([0-9]*\)/; // 去的当页数据 equips.each(function (i, e) { var match = 0; $.each(values, function (j, p) { let text = $(e).text(); if (min.test(p)) { // 纯数字,作为掉落等级来判断 let exec = String(level.exec(text)); exec = exec.substring(1, exec.length - 1); p = p.substring(1, p.length); if (parseInt(exec) <= parseInt(p)) match++; } else if (max.test(p)) { let exec = String(level.exec(text)); exec = exec.substring(1, exec.length - 1); p = p.substring(1, p.length); if (parseInt(exec) >= parseInt(p)) match++; } else if (text.indexOf(p) >= 0) { // 其他属性 match++; } }); if (match == values.length) { $(e).prev().addClass("selected"); } }); } }); $(document).ready(function () { $(".panel-filter").each(function (i, input) { var value = window.localStorage.getItem($(this).attr("id")); if (value != null && value.length > 0) { $(this).val(value); $(this).trigger("propertychange"); } }); }); // 当前是秘境界面 if (config.mapHack && location.href.indexOf('Map/Dungeon') >= 0) { // 爱液的原始点击 $.connection.userManagerHub.client.startDungeon = function (d) { localStorage.setItem("t", d); $(".dungeon-container").on("mousedown", ".public", null, function (a, g) { var f = $(this); var c = f.parent(); g = f.attr("id"); var k = $("#cid").val(); if (f.hasClass("monster")) window.location.replace("/Battle/InDungeon?id=" + k + "&bid=" + g); else { $(".dungeon-layer").show(); var e = []; if (0 < a.pageX && 0 < a.pageY && a.hasOwnProperty("originalEvent") && (a.originalEvent.isTrusted || 1 == a.originalEvent.detail)) { e = $(c).offset(); var h = $(c).width(); c = $(c).height(); var l = Math.floor(Math.random() * h); e = [a.pageX, l, a.pageY, e.left, h - l, e.top, h, Math.floor(Math.random() * c), c] } a = { id: k, bid: g, m: e, t: d, __RequestVerificationToken: $("[name='__RequestVerificationToken']").val() }; $.ajax({ url: "MoveTo", type: "post", data: a, dataType: "json", success: function (a) { $.each(a, function (a, b) { void 0 == b.id && (b.id = 0); a = ""; 0 == b.d[0] && (a += " top"); 0 == b.d[1] && (a += " left"); if (1 == b.m) $("#" + b.id).addClass(a); else { a += " public"; var c = ""; 0 < b.mlvl && (c += "Lv" + b.mlvl + " " + b.mname, a = a + " monster " + b.mtype); $("#" + b.id).removeClass("mask").addClass(a); "" != c && $("#" + b.id).attr("title", c) } }); 0 < a.length && ($("#explore").text(parseInt($("#explore").text()) + a.length), $("#not-explore").text(parseInt($("#not-explore").text()) - a.length)); $(".current").removeClass("current"); f.addClass("current"); $(".dungeon-layer").hide() }, error: function (a, c, b) { alert(a.responseText); $(".dungeon-layer").hide() } }) } }) }; let hacking = false; const idMatch = location.href.match(/id=(\d+)/i); if (!idMatch) return; const id = idMatch[1]; const btns = '<button class="btn btn-xs btn-success mr-10" id="start-hack">开始自动秘境</button><label class="mr-10"><input id="auto-reset" type="checkbox"/> 自动重置</label>'; $('.dungeon-container').prev().children().last().prepend(btns); if (config.infiniteMap) $('#auto-reset').prop('checked', true); $('#auto-reset').change(function () { config.infiniteMap = $(this).prop('checked'); saveLocalConfig(); }); let failedBlocks = localStorage.getItem('idle-ui-fail-blocks'); failedBlocks = failedBlocks ? JSON.parse(failedBlocks) : []; let map = localStorage.getItem('idle-ui-maphack'); // 是否出现验证码提示 if ($("[role='dialog'][data-code='True']").length) { // 提示验证码 停止自动秘境 endMove("验证码出现"); return; } if (map) { map = JSON.parse(map); if (map[id] && map[id] === 'start') { const bossLeft = $('.boss-left').text() - 0; const monster = $('.monster-left').text() - 0; if (bossLeft === 0 && config.mapHackType === 'boss') { if (config.infiniteMap) { setTimeout(() => { tryReset(); }, 500); } else { map = {}; map[id] = 'end'; } } else if (monster === 0 && config.mapHackType === 'mystery') { // 秘境扫荡完毕,跳转到装备界面开始继续打石头 // 获得用户的ID // 秘境的石头等级 0 表示普通 1表示魔法 2表示稀有,以此类推 按照下拉列表的排序 // https://www.idleinfinity.cn/Equipment/Query?id=5671&pt2=2&et2=2147483648&pi=0&pt=1&et=2147483648 // https://www.idleinfinity.cn/Equipment/Query?id=5671&et2=2147483648&pt2=1&pi=0&pt=1&et=2147483648 // https://www.idleinfinity.cn/Equipment/Query?id=5671&pt=2&et=2147483648&pi2=0&pt2=2&et2=2147483648 localStorage.setItem('failure', "0"); const level = config.level; const userId = $("#cid").val(); location.href = `/Equipment/Query?id=${userId}&pt=5&et=2147483648&pi2=0&pt2=${level}&et2=2147483648`; // 定位到装备界面 } else { $('.dungeon-container').prev().children().last().prepend('<button class="btn btn-xs btn-default" style="margin-right: 5px;" id="end-hack">停止自动秘境</button>'); setTimeout(() => { startHack(); }, 500); } } } else { map = {}; map[id] = 'end'; } function tryReset() { const stoneLeft = $('.panel-heading .state').text() - 0; if (stoneLeft > 0) { localStorage.setItem('idle-ui-fail-blocks', '[]'); localStorage.setItem('failure', "0"); $("form").attr("action", "DungeonRefresh"); $("form").trigger("submit"); } else { endMove('秘境之石已用完'); } } $('#start-hack').click(function (params) { startHack(true); }); $('#end-hack').click(function (params) { alert('自动秘境已停止'); endMove(); }); function startHack(fromClick) { if (hacking) return; hacking = true; if (!map[id] && typeof map == 'string') { map = JSON.parse(map); } map[id] = 'start'; localStorage.setItem('idle-ui-maphack', JSON.stringify(map)); if (fromClick) { localStorage.setItem('idle-ui-fail-blocks', '[]'); localStorage.setItem('failure', "0"); } mapMove(); } function mapMove() { // if (blockData.num >= 9) { // endMove('封号打击次数过多,禁止自动秘境'); // return; // } if (map[id] !== 'start') return; // 有boss先打boss const bossBlock = $('.boss').eq(0); if(!config.dodge){ if (bossBlock.length && !bossBlock.hasClass('mask')) { clickBlock(bossBlock); return; } } const bossId = bossBlock.attr("id"); const asc = Number(bossId) <= 200; // Boss在地图上X轴坐标 const boosX = bossId % 20; // Boss在地图上Y轴坐标 const boosY = bossId / 20; const blocks = []; // 无敌人的可行区块 const enemyBlocks = []; // 有敌人的可行区块 for (let i = asc ? 0 : 399; asc ? i <= 399 : i >= 0; asc ? i++ : i--) { const block = $(`#${i}`); if (canExplore(i)) { if (block.hasClass('monster')) { enemyBlocks.push(i); } else { blocks.push(i); } } } let nextBlockIndex = null; if (blocks.length) { nextBlockIndex = blocks[0]; } else if (enemyBlocks.length) { // 和Boss的距离的值,等于X+Y. let distance = 39; // 计算距离Boss最近的怪 for (let i = 0; i < enemyBlocks.length; i++) { const itemX = enemyBlocks[i] % 20; const itemY = enemyBlocks[i] / 20; const itemDistance = Math.abs(itemX - boosX) + Math.abs(itemY - boosY); // 判断是否有打不过的怪 if (((config.mapHackType === 'boss') ? (itemDistance < distance) : true) && failedBlocks.indexOf(enemyBlocks[i]) === -1) { distance = itemDistance; nextBlockIndex = enemyBlocks[i]; } } if (nextBlockIndex === null) { nextBlockIndex = enemyBlocks[0]; localStorage.setItem('idle-ui-fail-blocks', '[]'); let number = parseInt(localStorage.getItem("failure")); let failure = (isNaN(number) ? 0 : number) + 1; localStorage.setItem('failure', failure); if ((failure % 3) === 0) { if (failure > 1) new Notification('第' + failure + '轮战斗失败'); } if (failure > config.failure) { if (config.mapHackType === 'mystery') { const level = config.level; const userId = $("#cid").val(); location.href = `/Equipment/Query?id=${userId}&pt=5&et=2147483648&pi2=0&pt2=${level}&et2=2147483648`; return; } else if (config.infiniteMap) { tryReset(); return } } } } else { endMove('', false, config.infiniteMap); } if (nextBlockIndex !== null) { clickBlock($(`#${nextBlockIndex}`)); } } function clickBlock(block) { const width = block.width(); const height = block.height(); const rect = document.getElementById(block.attr('id')).getBoundingClientRect(); const x = Math.round(rect.left + width / 3 + (width / 4 * Math.random(id))) + $(window).scrollLeft(); const y = Math.round(rect.top + height / 3 + (height / 4 * Math.random(id))) + $(window).scrollTop(); ajaxMove(block, {pageX: x, pageY: y, originalEvent: {isTrusted: true}}); } function ajaxMove(block, a) { const f = block; var c = f.parent(); const g = f.attr("id"); const k = $("#cid").val(); const td = localStorage.getItem("t"); if (f.hasClass("monster")) { location.href = "/Battle/InDungeon?id=" + k + "&bid=" + g; } else { $(".dungeon-layer").show(); var e = []; if (0 < a.pageX && 0 < a.pageY && a.hasOwnProperty("originalEvent") && (a.originalEvent.isTrusted || 1 == a.originalEvent.detail)) { e = $(c).offset(); const h = $(c).width(); c = $(c).height(); const l = Math.floor(Math.random() * h); e = [a.pageX, l, a.pageY, e.left, h - l, e.top, h, Math.floor(Math.random() * c), c] } a = { id: k, bid: g, m: e, t: td, __RequestVerificationToken: $("[name='__RequestVerificationToken']").val() }; $.ajax({ url: "MoveTo", type: "post", data: a, dataType: "json", success: function (a) { $.each(a, function (a, b) { void 0 == b.id && (b.id = 0); a = ""; 0 == b.d[0] && (a += " top"); 0 == b.d[1] && (a += " left"); if (1 == b.m) $("#" + b.id).addClass(a); else { a += " public"; var c = ""; 0 < b.mlvl && (c += "Lv" + b.mlvl + " " + b.mname, a = a + " monster " + b.mtype); $("#" + b.id).removeClass("mask").addClass(a); "" != c && $("#" + b.id).attr("title", c) } }); 0 < a.length && ($("#explore").text(parseInt($("#explore").text()) + a.length), $("#not-explore").text(parseInt($("#not-explore").text()) - a.length)); $(".current").removeClass("current"); f.addClass("current"); $(".dungeon-layer").hide(); setTimeout(() => { mapMove(); }, Math.round(config.userNumber * 300)); }, error: function (XMLHttpRequest) { const responseText = XMLHttpRequest.responseText; if (responseText.indexOf('封号') >= 0) { addBlockNum(); } endMove(null, true, true); $(".dungeon-layer").hide(); } }); } } function endMove(notice, retry, reset) { if (!reset) { map[id] = 'end'; localStorage.setItem('idle-ui-maphack', JSON.stringify(map)); } if (notice) new Notification(notice); if (retry) { // 请求异常情况直接刷新界面,暂时注释原来逻辑 $('#modalAlert').modal('hide'); setTimeout(function () { const userId = $("#cid").val(); location.href = `../Map/DungeonForEquip?id=${userId}` }, Math.round(300)); } else if (reset) { tryReset(); } } // 判断是否可以点击 function canExplore(i) { const size = 20; const block = $(`#${i}`); if (block.hasClass('mask')) return false; if ((config.mapHackType === 'all' || config.mapHackType === 'mystery') && block.hasClass('monster')) return true; const left = i % size === 0 ? null : $(`#${i - 1}`); const right = i % size === (size - 1) ? null : $(`#${i + 1}`); const up = i < size ? null : $(`#${i - size}`); const down = i >= ((size * size) - size) ? null : $(`#${i + size}`); const canMoveLeft = left && left.hasClass('mask') && !block.hasClass('left'); const canMoveRight = right && right.hasClass('mask') && !right.hasClass('left'); const canMoveUp = up && up.hasClass('mask') && !block.hasClass('top'); const canMoveDown = down && down.hasClass('mask') && !down.hasClass('top'); return canMoveLeft || canMoveRight || canMoveUp || canMoveDown; } } if (location.href.indexOf('Map/Dungeon') === -1) { $.ajaxSetup({ complete: function (XMLHttpRequest) { if (!XMLHttpRequest.responseText) return; if (XMLHttpRequest.responseText.indexOf('封号') >= 0) { addBlockNum(); location.reload(); } } }); } // 战斗界面 if (config.mapHack && location.href.indexOf('Battle/InDungeon') >= 0) { const id = purl().param().id; const bid = purl().param().bid - 0; if (!id) return; let map = localStorage.getItem('idle-ui-maphack'); if (map) { map = JSON.parse(map); if (map[id] && map[id] === 'start') { const exception = $('.error').length; if (exception) { setTimeout(() => { location.href = `/Map/Dungeon?id=${id}`; }, Math.round(Math.random() * 3000)); return; } const stopBtn = renderButton('end-hack', '停止自动秘境', 'default'); $('.btn.btn-xs').eq(1).before(stopBtn); $('#end-hack').click(function () { map[id] = 'end'; localStorage.setItem('idle-ui-maphack', JSON.stringify(map)); alert('自动秘境已停止'); }); let waitTime = $('head').text().match(/waitTime:(\d+)/); if (waitTime) { waitTime = waitTime[1]; } if (waitTime) { setTimeout(() => { endFight(id); }, (waitTime + 1) * 1000); } else { endFight(id); } } } function endFight(dungeonId) { const win = $('.turn').first().text().indexOf('战斗胜利') > 0; const turns = $('.turn').length - 1; let enemys = {}; $('.battle-char').each(function () { const id = $(this).prop('id').split('_')[1]; if (id < 0) { const type = $(this).children().first().children().last().prop('class'); if (enemys[type]) { enemys[type] += 1; } else { enemys[type] = 1; } } }); let drops = []; $('.turn').first().find('.equip-name').each(function () { const type = $(this).clone().prop('class').replace('equip-name', '').trim(); const name = $(this).text(); drops.push({type: type, name: name}); }); const isBoss = $('.boss').length > 0; const battleLog = {time: +new Date(), win, boss: isBoss, turns, enemys, drops}; addBattleLog(battleLog); const bossWin = isBoss && win; if (!win) { let failedBlocks = localStorage.getItem('idle-ui-fail-blocks'); failedBlocks = failedBlocks ? JSON.parse(failedBlocks) : []; if (failedBlocks.indexOf(bid) === -1) failedBlocks.push(bid); localStorage.setItem('idle-ui-fail-blocks', JSON.stringify(failedBlocks)); } else { localStorage.setItem('failure', '0'); localStorage.setItem('idle-ui-fail-blocks', '[]'); } let timeout = 5; if (turns < 50) { timeout = 3 } else if (turns < 100) { timeout = 7; } else if (turns < 200) { timeout = 10; } setTimeout(() => { location.href = `/Map/Dungeon?id=${dungeonId}`; }, timeout * 1000); } function addBattleLog(battleLog) { let log = localStorage.getItem('idle-ui-maplog'); log = log ? JSON.parse(log) : {}; if (!log[id]) log[id] = []; log[id].unshift(battleLog); log[id] = log[id].slice(0, 500); localStorage.setItem('idle-ui-maplog', JSON.stringify(log)); } } if (config.mapHack && location.href.indexOf('Map/Detail') >= 0) { const btn = renderButton('idle-ui-maplog', '自动秘境日志'); $('.btn.btn-xs').eq(1).before(btn); let page = 1; let log = {}; let dataSource = []; const id = purl().param().id; const pageSize = 10; let maxPage = 0; const modal = ` <div class="modal fade" id="modalMapLog" tabindex="-1" role="dialog"> <div class="modal-dialog modal-lg" role="document"> <div class="modal-content model-inverse"> <div class="modal-header"> <span class="modal-title">自动秘境日志</span> </div> <div class="modal-body"> <div class="row"> <div class="col-md-6 col-xs-12"> <div class="panel-header state">小怪战斗统计</div> <p> <span>战斗次数:</span><span class="state mr-10" id="idle-ui-creepnum"></span> <span>平均回合:</span><span class="state mr-10" id="idle-ui-avgcreepturns"></span> <span>胜率:</span><span class="state" id="idle-ui-creepwinrate"></span> </p> </div> <div class="col-md-6 col-xs-12"> <div class="panel-header state">Boss战斗统计</div> <p> <span>战斗次数:</span><span class="state mr-10" id="idle-ui-bossnum"></span> <span>平均回合:</span><span class="state mr-10" id="idle-ui-avgbossturns"></span> <span>胜率:</span><span class="state" id="idle-ui-bosswinrate"></span> </p> </div> </div> <div class="panel-header state"> <span class="mr-10">战斗日志</span> <label class="normal" style="font-weight: normal; cursor: pointer;"><input type="checkbox" id="idle-ui-only-boss"/> 只看Boss</label> </div> <table class="table table-condensed" style="margin-bottom: 10px;"> <thead><tr><td width="120">时间</td><td width="50">结果</td><td width="60">回合数</td><td width="200">敌人</td><td>掉落</td></tr></thead> <tbody id="idle-ui-log-table" class="table-body"></tbody> </table> <div class="row"> <div class="col-md-6 col-xs-12" style="text-align: left;"> <span>共 <span id="idle-ui-log-length">0</span> 条记录</span> </div> <div class="col-md-6 col-xs-12" style="text-align: right;"> <span class="mr-10">第 <span id="idle-ui-page">0</span> 页,共 <span id="idle-ui-max-page">0</span> 页</span> </div> </div> </div> <div class="modal-footer"> <div class="row"> <div class="col-md-6 col-xs-12" style="text-align: left;"> <button type="button" id="clear-log" class="btn btn-danger btn-xs" style="float: left;">清空日志</button> <button type="button" id="idle-ui-reload" class="btn btn-success btn-xs">刷新数据</button> </div> <div class="col-md-6 col-xs-12" style="text-align: right;"> <button type="button" id="page-prev" class="btn btn-default btn-xs">上一页</button> <button type="button" id="page-next" class="btn btn-default btn-xs">下一页</button> <button type="button" class="btn btn-default btn-xs" data-dismiss="modal">关闭</button> </div> </div> </div> </div> </div> </div> `; $(document.body).append(modal); function getBattleLogStats(battleLog) { let creepNum = 0; let bossNum = 0; let creepWin = 0; let bossWin = 0; let creepTurns = 0; let bossTurns = 0; battleLog.forEach(item => { if (item.boss) { bossNum += 1; if (item.win) bossWin += 1; bossTurns += item.turns; } else { creepNum += 1; if (item.win) creepWin += 1; creepTurns += item.turns; } }); const avgCreepTurns = creepNum > 0 ? Math.round(creepTurns / creepNum) : 0; const avgBossTurns = bossNum > 0 ? Math.round(bossTurns / bossNum) : 0; const creepWinRate = creepNum > 0 ? Math.round(creepWin / creepNum * 100) : 0; const bossWinRate = bossNum > 0 ? Math.round(bossWin / bossNum * 100) : 0; return {creepNum, bossNum, avgCreepTurns, avgBossTurns, creepWinRate, bossWinRate} } const enemyTypes = {'normal': '普通', 'rare': '稀有', 'super': '精英', 'boss': 'Boss'}; function renderRows() { const start = (page - 1) * pageSize; let data = []; if ($('#idle-ui-only-boss').prop('checked')) { data = dataSource.filter(item => item.boss).slice(start, start + pageSize); } else { data = dataSource.slice(start, start + pageSize); } const rows = data.map(item => { const date = moment(item.time).format('MM-DD HH:mm:ss'); const result = item.win ? '<span class="poison">胜利</span>' : '<span class="fire">失败</span>'; const enemys = Object.keys(item.enemys).map(type => { const count = item.enemys[type]; return `<span class="${type}">${enemyTypes[type]}</span><span class="normal mr-10"> x ${count}</span>`; }).join(''); const drops = item.drops.map(item => { return `<span class="${item.type}">${item.name}</span>`; }).join(''); return `<tr><td>${date}</td><td>${result}</td><td>${item.turns}</td><td>${enemys}</td><td>${drops}</td></tr>`; }).join(''); $('#idle-ui-log-table').html(rows); if (page === 1) { $('#page-prev').prop('disabled', true); } else { $('#page-prev').prop('disabled', false); } if (page === maxPage) { $('#page-next').prop('disabled', true); } else { $('#page-next').prop('disabled', false); } $('#idle-ui-log-length').text(logLength); $('#idle-ui-max-page').text(maxPage); $('#idle-ui-page').text(page); } $('#page-prev').click(function () { page = page - 1; renderRows(); }); $('#page-next').click(function () { page = page + 1; renderRows(); }); $('#idle-ui-only-boss').change(function () { page = 1; getLengthAndMaxPage(); renderRows(); }); $('#clear-log').click(function () { log[id] = []; localStorage.setItem('idle-ui-maplog', JSON.stringify(log)); location.reload(); }); function getLengthAndMaxPage() { const checked = $('#idle-ui-only-boss').prop('checked'); logLength = checked ? dataSource.filter(item => item.boss).length : dataSource.length; maxPage = Math.ceil(logLength / pageSize); } function reloadLog() { log = localStorage.getItem('idle-ui-maplog'); log = log ? JSON.parse(log) : {}; dataSource = log[id] || []; getLengthAndMaxPage(); const stats = getBattleLogStats(dataSource); $('#idle-ui-creepnum').text(stats.creepNum); $('#idle-ui-avgcreepturns').text(stats.avgCreepTurns); $('#idle-ui-creepwinrate').text(`${stats.creepWinRate}%`); $('#idle-ui-bossnum').text(stats.bossNum); $('#idle-ui-avgbossturns').text(stats.avgBossTurns); $('#idle-ui-bosswinrate').text(`${stats.bossWinRate}%`); page = 1; renderRows(); } $('#idle-ui-reload').click(function () { reloadLog(); }); $('#idle-ui-maplog').click(function () { reloadLog(); $('#modalMapLog').modal('show'); }); } if (config.showSetAttr) { loadSetAttr(); function loadSetAttr() { if (!$('.equip-content > .equip > .set').length) return; const setDB = localStorage.getItem('idle-ui-set-db'); const newSetDB = localStorage.getItem('idle-ui-set-db-new'); if (setDB && newSetDB) { const JSONSetDB = JSON.parse(setDB); const JSONNewSetDB = JSON.parse(newSetDB); $('.equip-content > .equip > .set').each(function () { const content = $(this).parent(); const itemName = content.children().first().text().replace(/\(\d+\)/g, ''); const singleData = JSONSetDB.singleData[itemName]; const existSingLeNum = content.children('.set').length - 1; if (singleData && singleData.length > existSingLeNum) { const singleContent = singleData.slice(existSingLeNum).map(item => { return `<p class="set idle-ui-set-single">${item}</p>`; }).join(''); content.children('.unique').before(singleContent); } const fullContent = content.children('.unique'); const existFullNum = fullContent.children('p[class!="set"][class!="require"]').length - 1; const setName = fullContent.children('br').last().next().text().replace(/\(\d+\)/g, ''); var fullData = JSONSetDB.setData[setName]; if (!fullData) { fullData = JSONNewSetDB.setData[setName]; } let setContent = fullData.slice(existFullNum).map(item => { return `<p class="idle-ui-set-full">${item}</p>`; }).join(''); if (fullContent.children('br').length === 1) setContent = '<br>' + setContent; fullContent.children('br').last().before(setContent); }); } } function parseSetHtml(html) { $(".footer").before(`<div style="display: none;" id="set-data">${html}</div>`); const singleData = {}; const setData = {}; $('#set-data .masonry-item .panel-body .equip').each(function () { const lines = $(this).children(); const itemName = lines.first().text().replace(/\(\d+\)/, ''); const singleLines = []; lines.each(function (index) { const line = $(this); if (index > 0 && line.hasClass('set')) { singleLines.push(line.text().replace(/\n/g, '')); } if (line.hasClass('unique')) { const setItems = line.children(); let stop = false; const setLines = []; let setName = ''; setItems.each(function (index) { if (index > 0) { if ($(this).prop('tagName').toLowerCase() === 'br') { stop = true; setName = $(this).next().text(); } if (!stop) setLines.push($(this).text().replace(/\n/g, '')); } }); if (!setData[setName]) setData[setName] = setLines; } }); if (singleLines.length) singleData[itemName] = singleLines; }); return {singleData, setData}; } } if (location.href.indexOf('Auction/Query') >= 0 && location.href.indexOf('Auction/QueryBid') === -1) { if (config.showAuctionNote) { $('.physical.equip-des').each(function () { const note = $(this).text(); const label = $(this).parent().parent().prev().children('.equip-name').last(); label.after(`<span style="color: #fff;"> ${note}</span>`); }); } // if (config.auctionWatch) { // let watchList = []; // // function renderTable(params) { // const list = localStorage.getItem('idle-ui-auction'); // watchList = (list ? JSON.parse(list) : []) || []; // const rows = watchList.map((item, index) => { // return `<tr><td>${item.category}</td><td>${item.name}</td><td><a href="Query?id=&${item.link}" class="btn btn-xs btn-default" style="margin-right: 12px;">查看</a><button data-index="${index}" type="button" class="delete-auction btn btn-xs btn-danger">取消关注</button></td></tr>`; // }); // $('#modalAuction .table-body').html(rows); // $('.delete-auction').click(function () { // const index = $(this).data('index'); // watchList.splice(index, 1); // localStorage.setItem('idle-ui-auction', JSON.stringify(watchList)); // renderTable(); // }); // renderNewItems(); // } // // function renderNewItems() { // const ids = purl().param().items; // if (!ids) return; // ids.split(',').map(id => { // $(`span[data-id="${id}"`).parent().addClass('idle-ui-new-item'); // }); // } // // const link = '<button id="open-auction-modal" type="button" class="btn btn-xs btn-success" style="margin-right: 10px;">特别关注</button>'; // $('.btn-group').eq(1).before(link); // const categorys = []; // $('.panel-heading .btn-group button.dropdown-toggle').each(function () { // categorys.push($(this).text().replace('<span class="caret"></span>', '').replace(/\s/g, '')); // }); // const category = categorys.join(' - '); // // const modal = ` // <div class="modal fade" id="modalAuction" style="display: none;"> // <div class="modal-dialog modal-large" role=""> // <div class="modal-content model-inverse"> // <div class="modal-header"> // <span class="modal-title">拍卖行特别关注</span> // </div> // <div class="modal-body"> // <div class="panel-header state">已有关注项目</div> // <table class="table table-condensed"> // <thead><tr><td>筛选条件</td><td>装备名称</td><td>操作</td></tr></thead> // <tbody class="table-body"></tbody> // </table> // <div class="panel-header state">添加新项目</div> // <div class="form"> // <div class="form-group"> // <label>筛选条件</label> // <p class="form-control-static" style="color: #fff;">${category}</p> // </div> // <div class="form-group"> // <label>装备名称</label> // <input type="text" id="auction-name" class="form-control hit-input" style="width: 100%;"> // </div> // <button type="button" class="btn btn-success btn-xs" id="add-auction">新增</button> // </div> // </div> // <div class="modal-footer"> // <button type="button" class="btn btn-default btn-xs" data-dismiss="modal">关闭</button> // </div> // </div> // </div> // </div> // `; // $(document.body).append(modal); // renderTable(); // $('#open-auction-modal').click(function () { // if ($('.equip-name').length) { // $('#auction-name').val($('.equip-name').eq(0).text().replace('【', '').replace('】', '')); // } // $('#modalAuction').modal('show'); // }); // // $('#add-auction').click(function () { // if (watchList.length >= 10) { // alert('最多关注10条'); // return; // } // const params = purl().param(); // const et = params.et || ''; // const pt = params.pt || ''; // const ei = params.ei || ''; // const link = `et=${et}&pt=${pt}&ei=${ei}`; // const name = $('#auction-name').val(); // const items = []; // $('.equip-name').each(function () { // const curName = $(this).text().replace('【', '').replace('】', ''); // if (curName === name) { // const id = $(this).parent().children().last().data('id'); // items.push(id); // } // }); // const data = { // category: category, // name: $('#auction-name').val(), // link: link, // items: items // }; // watchList.push(data); // localStorage.setItem('idle-ui-auction', JSON.stringify(watchList)); // renderTable(); // }); // }1 } if (config.magical && location.href.indexOf('Equipment/Query') >= 0) { let map = localStorage.getItem('idle-ui-maphack'); if (map) { map = JSON.parse(map); } else { map = {}; } const cid = $("#cid").val(); const magicalStart = '<button class="btn btn-xs btn-default" id="start-magical">一键升蓝</button>'; const magicalEnd = '<button class="btn btn-xs btn-default" id="end-magical">停止升蓝</button>'; // 是否一键升蓝 const magical = map[`magical${cid}`]; const panel = $('.panel-footer .btn.btn-xs.btn-warning'); panel.eq(panel.length - 1).before(magicalStart); if ((magical) && magical === 'start') { panel.eq(panel.length - 1).before(magicalEnd); } $('#start-magical').click(function (params) { map[`magical${cid}`] = 'start'; localStorage.setItem('idle-ui-maphack', JSON.stringify(map)); // startMagical(); // 重定向到过滤为白色秘境的界面去 const level = '0'; const userId = $("#cid").val(); location.href = `/Equipment/Query?id=${userId}&pt=${level}&et=2147483648&pi2=0&pt2=${level}&et2=2147483648`; }); $('#end-magical').click(function (params) { map[`magical${cid}`] = 'end'; localStorage.setItem('idle-ui-maphack', JSON.stringify(map)); location.reload(); }); // 设置点击对应的点击事件 function startMagical() { const magicalId = $(".base.equip-name").eq(0).data('id'); if (!magicalId) { map[`magical${cid}`] = 'end'; localStorage.setItem('idle-ui-maphack', JSON.stringify(map)); alert('没有普通秘境,已停止自动升级'); return; } map[`magical${cid}`] = 'start'; a = { id: cid, cid: cid, eid: magicalId, type: '0', __RequestVerificationToken: $("[name='__RequestVerificationToken']").val(), }; $.ajax({ //几个参数需要注意一下 type: "POST",//方法类型 dataType: "html",//预期服务器返回的数据类型 url: "EquipReform",//url data: a, success: function (result) { location.reload() }, error: function (XMLHttpRequest, textStatus) { map[`magical${cid}`] = 'end'; alert("发生错误,请检查是否材料不够,或者不够改造等级") } }); } if (magical && magical === 'start') { setTimeout(() => { if ((magical) && magical === 'start') { startMagical() } }, config.moveTime); } } if (config.oneKeyEquip && location.href.indexOf('Equipment/Query') >= 0) { const btn = '<button type="button" class="btn btn-xs btn-success mr-10" id="show-one-key-equip">一键换装</button>'; const cname = '<input style="height: 22px;background: black; border: solid 1px #322a20; width: 180px; text-indent: 3px" class="move-name" placeholder="转移ID"/>'; const startMetastasis = '<button class="btn btn-xs btn-default" id="start-metastasis">一键转移</button>'; const stopMetastasis = '<button class="btn btn-xs btn-default" id="end-metastasis">停止转移</button>'; const start = '<button class="btn btn-xs btn-default" id="start-mystery">开始扫荡秘境</button>'; const end = '<button class="btn btn-xs btn-default" id="end-mystery">停止扫荡</button>'; $('.panel-heading .btn').eq(0).before(btn); $('.panel-heading .btn').eq(0).before(cname); let map = localStorage.getItem('idle-ui-maphack'); if (map) { map = JSON.parse(map); } else { map = {}; } const cid = $("#cid").val(); var mysteryIndex = 5; // 是否一键转移 const metastasis = map[`metastasis${cid}`]; // 要转移人的姓名 const name = map[`cname${cid}`]; if (name) { $('.move-name').val(name); } if ((metastasis) && metastasis === 'start') { $('.panel-heading .btn').eq(0).before(stopMetastasis); mysteryIndex = 6; } $('#end-metastasis').click(function (params) { map[`metastasis${cid}`] = 'end'; map[`cname${cid}`] = ""; localStorage.setItem('idle-ui-maphack', JSON.stringify(map)); location.reload(); }); $('.panel-heading .btn').eq(0).before(startMetastasis); $('#start-metastasis').click(function (params) { map[`metastasis${cid}`] = 'start'; map[`cname${cid}`] = $('.move-name').val(); localStorage.setItem('idle-ui-maphack', JSON.stringify(map)); moveMystery(); }); function moveMystery() { const mysteryId = $(".selected").children(":first").next().next().next().data('id'); if (!mysteryId) { map[`metastasis${cid}`] = 'end'; localStorage.setItem('idle-ui-maphack', JSON.stringify(map)); alert('没有物品被选中,已停止'); return; } a = { cid: cid, eid: mysteryId, cname: map[`cname${cid}`], __RequestVerificationToken: $("[name='__RequestVerificationToken']").val(), }; $.ajax({ //几个参数需要注意一下 type: "POST",//方法类型 dataType: "html",//预期服务器返回的数据类型 url: 'EquipTrade',//url data: a, success: function (result) { location.reload() }, error: function (result) { alert(result) } }); } if (metastasis && metastasis === 'start') { setTimeout(() => { if ((metastasis) && metastasis === 'start') { moveMystery() } }, config.moveTime); } // 开始扫荡秘境了,就显示停止扫荡按钮 const mystery = map[`mystery${cid}`]; if ((mystery) && mystery === 'start') { $('.panel-heading .btn').eq(mysteryIndex).before(end); $('#end-mystery').click(function (params) { alert('已停止扫荡秘境'); map[`mystery${cid}`] = 'end'; localStorage.setItem('idle-ui-maphack', JSON.stringify(map)); }); } $('.panel-heading .btn').eq(mysteryIndex).before(start); $('#start-mystery').click(function (params) { map[`mystery${cid}`] = 'start'; localStorage.setItem('idle-ui-maphack', JSON.stringify(map)); startMystery(); }); function startMystery() { const mysteryId = $(".selected").children(":first").next().next().next().data('id'); if (!mysteryId) { map[cid] = 'end'; localStorage.setItem('idle-ui-maphack', JSON.stringify(map)); alert('没有物品被选中,或使用等级不够,已停止'); return; } map[cid] = 'start'; a = { id: cid, cid: cid, eid: mysteryId, __RequestVerificationToken: $("[name='__RequestVerificationToken']").val(), }; $.ajax({ //几个参数需要注意一下 type: "POST",//方法类型 dataType: "html",//预期服务器返回的数据类型 url: "EquipDungeon",//url data: a, success: function (result) { // 请求成功,返回网页,自动跳转到秘境界面 location.href = `../Map/DungeonForEquip?id=${userId}` }, error: function (XMLHttpRequest, textStatus) { alert(XMLHttpRequest) } }); } if (mystery && mystery === 'start') { setTimeout(() => { if ((mystery) && mystery === 'start') { startMystery() } }, 15000); } const equipList = ['主手', '副手', '头盔', '护符', '项链', '戒指', '戒指', '衣服', '腰带', '手套', '靴子']; let buildMap = {}; let buildData = []; const userId = purl().param().id; const equipItems = getEquipItems(); function loadEquipBuild() { buildMap = JSON.parse(localStorage.getItem('idle-ui-equip-build') || '{}'); buildData = buildMap[userId] || []; } function saveEquipBuild(data) { localStorage.setItem('idle-ui-equip-build', JSON.stringify(data)); loadEquipBuild(); renderEquip(); } function renderEquip(buildIndex) { if (!buildIndex && buildData.length) buildIndex = 0; const data = buildData[buildIndex] || {}; const equipContent = equipList.map((item, index) => { const equipItem = data.items ? data.items[index] : {}; return `<p><span>${item}</span><span class="${equipItem.type || ''}">${equipItem.name || ''}</span></p>`; }); const firstCol = equipContent.slice(0, 4).join(''); const secondCol = equipContent.slice(4, 7).join(''); const thirdCol = equipContent.slice(7).join(''); const content = `<div class="col-sm-6 col-md-4">${firstCol}</div><div class="col-sm-6 col-md-4">${secondCol}</div><div class="col-sm-6 col-md-4">${thirdCol}</div>`; $('#equip-build-content').html(content); // 一键换装 const buildTags = buildData.map((item, index) => { return `<li><a class="physical equip-build-option" href="#" data-index="${index}">${item.name}</a></li>`; }).join(''); $('#equip-build-tags').html(buildTags); $('#selected-build-name').text(data.name || '选择方案'); if (buildIndex !== undefined) { $('#use-equip-build').data('index', buildIndex); $('#del-equip-build').data('index', buildIndex); } else { $('#use-equip-build').data('index', -1); $('#del-equip-build').data('index', -1); } $('.equip-build-option').click(function (e) { e.preventDefault(); const index = $(this).data('index'); renderEquip(index); }); } const modal = ` <div class="modal fade" id="modalEquipBuild" style="display: none;"> <div class="modal-dialog modal-large" role="" style="width: 800px;"> <div class="modal-content model-inverse"> <div class="modal-header"> <span class="modal-title">一键换装</span> </div> <div class="modal-body"> <div class="panel-header state"> <span>已有装备方案:</span> <div class="btn-group"><button type="button" class="btn btn-default btn-xs dropdown-toggle" data-toggle="dropdown"><span id="selected-build-name">选择方案</span><span class="caret" style="margin-left: 5px;"></span></button><ul class="dropdown-menu" id="equip-build-tags"></ul></div> </div> <div class="row" id="equip-build-content"></div> <button type="button" class="btn btn-success btn-xs mr-10" id="use-equip-build">使用本方案</button> <button type="button" class="btn btn-danger btn-xs" id="del-equip-build">删除本方案</button> <div id="processing" style="display:none; margin-top: 10px;"><i class="glyphicon glyphicon-refresh"></i> 处理中...</div> <div class="panel-header state" style="margin-top: 10px;">保存当前装备到新方案</div> <div class="form"> <div class="form-group"> <label>方案名称</label> <input type="text" id="equip-build-name" class="form-control hit-input" style="width: 100%;"> </div> <button type="button" class="btn btn-success btn-xs" id="add-equip-build">保存</button> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-default btn-xs" data-dismiss="modal">关闭</button> </div> </div> </div> </div> `; $(document.body).append(modal); loadEquipBuild(); renderEquip(); $('#show-one-key-equip').click(function () { $('#modalEquipBuild').modal('show'); }); let processing = false; function doEquip(buildIndex, itemIndex) { if (blockData.num >= 9) { alert('封号打击次数过多,禁止一键换装'); location.reload(); } if (itemIndex > equipItems.length - 1) { setTimeout(() => { processing = false; $('#processing').hide(); location.reload(); }, 500); return; } const list = $('#form').serializeArray(); const params = {}; list.forEach(item => { params[item.name] = item.value; }); params.eid = buildData[buildIndex].items[itemIndex].id; params.cid = userId; // 判断当前要替换的装备是否已经装备 const itemAlreadyEquiped = equipItems.some(item => item.id === params.eid); if (!params.eid || !params.cid) return; const name = buildData[buildIndex].items[itemIndex].name; if (itemAlreadyEquiped) { // 已经装备,进入下一件装备 doEquip(buildIndex, itemIndex + 1); } else { // 没有装备,还是进行替换 $.post('/Equipment/EquipOn', params, function (data) { setTimeout(function () { doEquip(buildIndex, itemIndex + 1); }, 1000); }).fail(function (data) { setTimeout(function () { doEquip(buildIndex, itemIndex + 1); }, 1000); }); } } $('#use-equip-build').click(function () { if (processing) return; const index = $(this).data('index'); if (index >= 0) { processing = true; $('#processing').show(); doEquip(index, 0); } else { alert('请先选择一个方案'); } }); $('#del-equip-build').click(function () { const index = $(this).data('index'); if (index >= 0) { buildData.splice(index, 1); buildMap[userId] = buildData; saveEquipBuild(buildMap); } else { alert('请先选择一个方案'); } }); function getEquipItems() { const items = []; $('.panel-body').eq(0).find('.equip-content').each(function () { const label = $(this).prev().children('.equip-name').eq(0); if (label.length) { const name = label.text(); const type = label.prop('class').replace('equip-name', '').trim(); const id = label.parent().children().last().data('id'); items.push({name: name, type: type, id: id}); } else { items.push({name: '', type: '', id: 0}); } }); return items; } $('#add-equip-build').click(function () { if (buildData.length >= 5) { alert('同一角色最多保存5套方案'); return; } const name = $('#equip-build-name').val(); if (!name) { alert('方案必须有一个名称'); return; } const newBuild = { name: name, items: equipItems }; buildData.push(newBuild); buildMap[userId] = buildData; saveEquipBuild(buildMap); }); } if (config.oneKeyAgree && location.href.indexOf('Notice/Query') >= 0) { let map = localStorage.getItem('idle-ui-maphack'); if (map) { map = JSON.parse(map); } else { map = {}; } // 所有消息的数量 const allCount = $('.badge').eq(0).text(); let processing = false; const agreeList = []; $('.notice-yes').each(function () { agreeList.push($(this).data('id')); }); function doAgree(index) { if (blockData.num >= 9) { alert('封号打击次数过多,禁止一键同意'); location.reload(); } if (index > agreeList.length - 1) { $('#processing').hide(); processing = false; if ( map[`agree${cid}`] && map[`agree${cid}`] === 'start' && allCount > 0) { // 获得当前页面的第几页数据,然后+1 var number = getUrlParam('pi'); if (number > 0) { number = Number(number) + 1; } else { number = 1; } // 跳转到下一页 location.href = `/Notice/Query?pi=${number}&pi2=0`; return; } else { map[`agree${cid}`] = 'end'; localStorage.setItem('idle-ui-maphack', JSON.stringify(map)); location.reload(); return; } } const id = agreeList[index]; const list = $('#form').serializeArray(); const params = { contentType: false, processData: false, }; list.forEach(item => { params[item.name] = item.value; }); params.nid = id; $.post('/Notice/NoticeYes', params, function () { setTimeout(function () { location.reload(); }, config.agreedTime ); }).fail(function (data) { alert("发生异常"); setTimeout(function () { location.reload(); }, config.agreedTime); }); } function getUrlParam(paraName) { const url = document.location.toString(); const arrObj = url.split("?"); if (arrObj.length > 1) { const arrPara = arrObj[1].split("&"); var arr; for (var i = 0; i < arrPara.length; i++) { arr = arrPara[i].split("="); if (arr != null && arr[0] == paraName) { return arr[1]; } } return ""; } else { return ""; } } const def = $('a.btn.btn-xs.btn-default'); let all = renderProcessing(); all += renderButton('idle-ui-agree-all', '同意所有'); def.eq(0).before(all); $('#idle-ui-agree-all').click(function () { // 终止转移 map[`agree${cid}`] = 'start'; localStorage.setItem('idle-ui-maphack', JSON.stringify(map)); agreeMessage(); }); if ( map[`agree${cid}`] && map[`agree${cid}`] === 'start') { let stop = renderProcessing(); stop += renderButton('idle-ui-agree-stop', '停止同意'); def.eq(0).before(stop); $('#idle-ui-agree-stop').click(function () { // 终止转移 map[`agree${cid}`] = 'stop'; localStorage.setItem('idle-ui-maphack', JSON.stringify(map)); location.reload(); }); if (allCount > 0) { setTimeout(function () { agreeMessage(); }, 500); } else { // 终止转移 map[`agree${cid}`] = 'end'; localStorage.setItem('idle-ui-maphack', JSON.stringify(map)); } } function agreeMessage() { if (processing) return; if (agreeList.length || allCount > 0) { $('#processing').show(); processing = true; doAgree(0); } else { alert('没有可处理的消息'); } } } if (config.oneKeyRune && location.href.indexOf('Equipment/Material') >= 0) { let processing = false; const runeList = []; $('.artifact.equip-name').each(function () { const count = $(this).next().next().text() - 0; if (count > 0) { const rune = { id: $(this).next().next().next().data('id') - 0, count: count }; runeList.push(rune); } }); $('.equip-name').each(function () { const count = $(this).next().next().text() - 0; if (count > 0) { const rune = { id: $(this).next().next().next().data('id') - 0, count: count }; runeList.push(rune); } }); function doMoveRune(index, cname) { if (blockData.num >= 9) { alert('封号打击次数过多,禁止一键符文转移'); location.reload(); } if (index > runeList.length - 1) { $('#processing').hide(); processing = false; location.reload(); return; } const rune = runeList[index]; const list = $('#form').serializeArray(); const params = {}; list.forEach(item => { params[item.name] = item.value; }); params.cname = cname; params.count = rune.count; params.rune = rune.id; $.post('/Equipment/RuneTrade', params, function () { setTimeout(function () { doMoveRune(index + 1, cname); }, 300); }).fail(function (data) { alert("发生异常,请检查角色名是否正确"); location.reload(); }); } $('.btn.btn-xs.btn-default').eq(1).before(renderButton('idle-ui-show-rune', '转移全部符文')); $('#idle-ui-show-rune').click(function () { $('#modalMoveRune').modal('show'); }); const spinner = renderProcessing(); const modal = ` <div class="modal fade" id="modalMoveRune" tabindex="-1" role="dialog"> <div class="modal-dialog modal-sm" role="document"> <div class="modal-content model-inverse"> <div class="modal-header"> <span class="modal-title">转移全部符文</span> </div> <div class="modal-body"> <div class="form-group"> <label for="charName" class="control-label">交易角色:</label> <input type="text" class="form-control" id="idle-ui-cname" name="charName" placeholder="请输入角色名称"> </div> </div> <div class="modal-footer"> ${spinner} <button type="button" class="btn btn-primary btn-xs" id="idle-ui-move-rune">提交</button> <button type="button" class="btn btn-default btn-xs" data-dismiss="modal">关闭</button> </div> </div> </div> </div> `; $(document.body).append(modal); $('#idle-ui-move-rune').click(function () { if (processing) return; if (runeList.length) { const cname = $('#idle-ui-cname').val(); if (!cname) { alert('请输入角色名称'); } else { processing = true; $('#processing').show(); doMoveRune(0, cname); } } else { alert('没有转移的符文'); } }); } if (config.showRuneTip) { let runeList = []; const runeData = localStorage.getItem('idle-ui-rune-db'); if (runeData) { runeList = JSON.parse(runeData); } else { fetchRuneTip(); } if (location.href.indexOf('Equipment/Inlay') >= 0) { const footer = ` <div class="panel-footer"> <input class="panel-filter hidden-xs filter-input" id="panel-filter-runeword" placeholder="搜索符文之语"> <span id="runeword-content"></span> </div> `; $('.panel').eq(0).append(footer); let timer = null; $('#panel-filter-runeword').keyup(function () { if (timer) { clearTimeout(timer); timer = null; } timer = setTimeout(() => { const name = $(this).val(); const filtered = name ? runeList.filter(item => item.name.indexOf(name) >= 0) : []; let ret = ''; if (filtered.length) { const item = filtered[0]; const recipe = item.recipe.map(item => { return `<span class="artifact">${item}</span>` }).join(' + '); ret = `<span><span class="artifact equip-name">【${item.name}】</span>:<span>${recipe}</span></span>`; const requireContent = item.require.map(item => { return `<p><span class="equip-label">${item}</span></p>`; }).join(''); const attrContent = item.attr.map(item => { return `<p>${item}</p>`; }).join(''); const tip = `<div class="equip-content"><div class="equip"><p class="artifact">${item.name}</p>${requireContent}${attrContent}</div></div>`; ret += tip; } $('#runeword-content').html(ret); $.initPopup(); }, 300); }); $('.equip').eq(0).children().last().prop('id', 'big-slot'); const link = '<a href="/Help/Content?url=Artifact" target="_blank" class="btn btn-xs btn-success mr-10">神器列表</a>'; $('.btn.btn-xs').eq(0).before(link); } if (location.href.indexOf('Help/Content?url=Artifact') >= 0) { const filter = '<div class="container" style="margin-bottom: 20px;"><input class="form-control" id="panel-filter" placeholder="输入神器名称或符文序号" /></div>'; $('.navbar').next().after(filter); let timer = null; $('#panel-filter').keyup(function () { if (timer) { clearTimeout(timer); timer = null; } timer = setTimeout(() => { const val = $(this).val(); if (val) { if (/^\d+$/.test(val)) { $('tbody tr').each(function (i) { const recipe = []; $(this).children().eq(1).find('.artifact.equip-name').each(function () { recipe.push($(this).text().match(/\d+/g)[0]); }); if (recipe.indexOf(val) >= 0) { $(this).show(); } else { $(this).hide(); } }); } else { $('tbody tr').each(function (i) { const name = $(this).children().last().find('.artifact').text(); if (name.indexOf(val) >= 0) { $(this).show(); } else { $(this).hide(); } }); } } else { $('tbody tr').show(); } }, 300); }); } function fetchRuneTip() { $.get('/Help/Artifact', function (html) { const dom = $.parseHTML(html); $(dom).find('tr').each(function (i) { if (i > 0) { const nameLabel = $(this).children().last().find('.artifact'); const rune = {name: nameLabel.text(), attr: [], recipe: [], require: []}; nameLabel.parent().children().each(function (index) { if (index > 0) rune.attr.push($(this).text()); }); $(this).children().eq(1).find('.artifact.equip-name').each(function () { rune.recipe.push($(this).text()); }); $(this).children().eq(0).find('.equip-label').each(function () { rune.require.push($(this).text()); }); runeList.push(rune); } }); localStorage.setItem('idle-ui-rune-db', JSON.stringify(runeList)); }); } } if (config.showBattleDetail && inBattlePage()) { const battleResult = {}; const addedDamageTypes = ['溅射', '触发了技能', '对方受到']; function getDamageType(plainText) { let ret = -1; addedDamageTypes.forEach((item, i) => { if (plainText.indexOf(item) >= 0) ret = i; }); return ret; } $('.turn').each(function (index) { if (index > 0) { const line = $(this).children().eq(1); const hpData = $(this).children().first().data('hp'); const id = line.children()[0].innerHTML; if (!hpData[1]) return; const firstTargetId = hpData[1].id; const skillLabel = line.children('.skill-name'); const skill = skillLabel.length ? skillLabel.eq(0).text() : '普通攻击'; const damageLabel = line.children('.damage'); let damage = 0; let damageDetail = {base: 0}; if (firstTargetId < 0) { damage = damageLabel.length ? damageLabel.eq(0).text() - 0 : 0; damageDetail = {base: damage}; $(this).children().each(function (i) { if (i > 1) { const plainText = getPlainText($(this)); if (getDamageType(plainText) >= 0) { const addedDamage = $(this).children('.damage').eq(0).text() - 0; const damageType = getDamageType(plainText); damage += addedDamage; const lastDamage = damageDetail[damageType]; damageDetail[damageType] = lastDamage ? lastDamage + addedDamage : addedDamage; } } }); } if (!battleResult[id]) battleResult[id] = {}; if (!battleResult[id][skill]) battleResult[id][skill] = { turn: 0, damage: 0, damageDetail: {} }; const skillData = battleResult[id][skill]; skillData.turn += 1; skillData.damage += damage; Object.keys(damageDetail).forEach(type => { if (skillData.damageDetail[type]) { skillData.damageDetail[type] += damageDetail[type]; } else { skillData.damageDetail[type] = damageDetail[type]; } }); } }); const totalTurns = $('.turn').length - 1; let partyTotalDamage = 0; $('.battle-data tbody tr').each(function (index) { if (getCharId(index) > 0) { const dmg = $(this).children().eq(2).text() - 0; partyTotalDamage += dmg; } }); $('.battle-data thead td').eq(2).after('<td class="text-center">友方伤害占比</td><td class="text-center">详情</td><td class="text-center">出手次数</td><td class="text-center">出手占比</td><td class="text-center">每回合伤害</td>'); $('.battle-data tbody tr').each(function (index) { const id = getCharId(index); const actor = $(this).children().first().text(); const turns = getActorTurns(actor); const turnsPercent = (turns / totalTurns * 100).toFixed(1) - 0; const damage = $(this).children().eq(2).text() - 0; const damagePercent = id > 0 ? `${(damage / partyTotalDamage * 100).toFixed(1) - 0}%` : '-'; const avgDamage = turns > 0 ? Math.round(damage / turns) : '-'; const link = battleResult[actor] ? `<a href="javascript: void(0);" class="link-detail" data-id="${actor}" data-actor="${actor}">查看</a>` : '-'; const content = `<td class="text-center poison">${damagePercent}</td><td class="text-center">${link}</td><td class="text-center physical ddd">${turns}</td><td class="text-center poison">${turnsPercent}%</td><td class="text-center fire ee">${avgDamage}</td>`; $(this).children().eq(2).after(content); }); $('.battle-data').css('overflow', 'auto'); const modal = ` <div class="modal fade" id="modalBattleDetail" tabindex="-1" role="dialog"> <div class="modal-dialog modal-lg" role="document"> <div class="modal-content model-inverse"> <div class="modal-header"> <span class="modal-title"><span id="idle-ui-char"></span> - 伤害详情</span> </div> <div class="modal-body"> <table class="table table-condensed"> <thead><tr><th class="text-center">技能</th><th class="text-center">总伤害</th><th class="text-center">伤害占比</th><th class="text-center">出手次数</th><th class="text-center">出手占比</th><th class="text-center">每回合伤害</th><th class="text-center">直接伤害</th><th class="text-center">溅射</th><th class="text-center">触发技能</th><th class="text-center">持续伤害及其他</th></tr></thead> <tbody id="idle-ui-battle-rows"></tbody> </table> <ul> <li>直接伤害:技能造成的实际直接伤害</li> <li>溅射:因溅射,对非主目标造成的溅射伤害之和</li> <li>触发技能:【装备自带技能】或【被击中触发】的技能等被触发后造成的伤害</li> <li>持续伤害及其他:技能造成的持续伤害,以及其他伤害 </li> </ul> </div> <div class="modal-footer"> <button type="button" class="btn btn-default btn-xs" data-dismiss="modal">关闭</button> </div> </div> </div> </div> `; $(document.body).append(modal); $('.link-detail').click(function () { const id = $(this).data('id'); const data = battleResult[id]; const actor = $(this).data('actor'); $('#idle-ui-char').text(actor); let actorTotalTurns = 0; let actorTotalDamage = 0; Object.keys(data).forEach(skill => { actorTotalTurns += data[skill].turn; actorTotalDamage += data[skill].damage; }); const content = Object.keys(data).map(skill => { const skillData = data[skill]; const percent = (skillData.turn / actorTotalTurns * 100).toFixed(1) - 0; const damagePercent = (skillData.damage / actorTotalDamage * 100).toFixed(1) - 0; const avgDamage = skillData.turn > 0 ? Math.round(skillData.damage / skillData.turn) : '-'; return `<tr><td class="text-center skill">${skill}</td><td class="text-center fire">${skillData.damage}</td><td class="text-center poison">${damagePercent}%</td><td class="text-center physical">${skillData.turn}</td><td class="text-center poison">${percent}%</td><td class="text-center fire">${avgDamage}</td><td class="text-center fire">${skillData.damageDetail.base}</td><td class="text-center fire">${skillData.damageDetail['0'] || 0}</td><td class="text-center fire">${skillData.damageDetail['1'] || 0}</td><td class="text-center fire">${skillData.damageDetail['2'] || 0}</td></tr>`; }).join(''); $('#idle-ui-battle-rows').html(content); $('#modalBattleDetail').modal('show'); }); function getCharId(index) { const ary = $('.battle-char').eq(index).prop('id').split('_'); return ary[ary.length - 1]; } function getActorTurns(id) { let ret = 0; if (battleResult[id]) { Object.keys(battleResult[id]).forEach(skill => { ret += battleResult[id][skill].turn; }); } return ret; } function getPlainText(element) { return element.clone() //clone the element .children() //select all the children .remove() //remove all the children .end() //again go back to selected element .text(); } } function switchSkin(showRequire) { $('.equip-content > .equip').each(function (item) { const type = $(this).children().first().attr('class'); let classLabel = ''; const requireIndex = $(this).text().indexOf('限'); if (requireIndex >= 0) { const requireClass = $(this).text().substring(requireIndex + 1, requireIndex + 2); classLabel = '<span style="color: #a99877" class="mr-10">' + requireClass + '</span>'; } const label = location.href.indexOf('Auction/QueryBid') >= 0 ? $(this).parent().prev().find('.equip-name').first() : $(this).parent().prev().find('.equip-name').last(); if (classLabel) { showRequire ? label.after(classLabel) : label.next().remove(); } }); } function inBattlePage() { const battePages = ['Battle/Simulate', 'Battle/InDungeon', 'Battle/WithChar']; return battePages.some(path => location.href.indexOf(path) >= 0); } function renderProcessing() { return '<span id="processing" class="mr-10" style="display:none;"><i class="glyphicon glyphicon-refresh"></i> 处理中...</span>'; } function renderButton(id, text, type) { if (!type) type = 'success'; return `<button type="button" class="btn btn-xs btn-${type} mr-10" id="${id}">${text}</button>`; } let uid = purl().param().id || purl().param().Id; let blockMap = localStorage.getItem('idle-ui-block'); if (blockMap) { blockMap = JSON.parse(blockMap); } else { blockMap = {}; } if (!blockMap[uid]) blockMap[uid] = {num: 0, time: +new Date()}; let blockData = blockMap[uid]; if (location.href.indexOf('Character/Detail') >= 0) { checkBlockNum(); $('.col-sm-6 .panel-body').eq(0).children().last().append(`<p>封号打击次数(仅供参考):<span class="physical">${blockData.num}</span></p>`); } function addBlockNum() { checkBlockNum(); if (!blockData.num) blockData.num = 0; blockData.num += 1; blockData.time = +new Date(); localStorage.setItem('idle-ui-block', JSON.stringify(blockMap)); new Notification(`当前封号打击为${blockData.num}次,请注意`); } function checkBlockNum() { const curTime = +new Date(); const hours = Math.floor((curTime - blockData.time) / (3600 * 1000)); if (hours > 0) { blockData.num = blockData.num > hours ? blockData.num - hours : 0; blockData.time = blockData.time + (hours * 3600 * 1000); localStorage.setItem('idle-ui-block', JSON.stringify(blockMap)); } } }; window.addEventListener('load', idleInit, false); const borderColor = '#6f5a40'; GM_addStyle(` .panel-top { margin-bottom: 20px; text-align: center; } .idle-ui-title { font-size: 18px; color: #fff; margin-bottom: 6px; } .panel-header { margin: 8px 0; } .panel-textarea { background-color: rgba(255,255,255,0.1); color: #a99877; margin-bottom: 8px; } .block-visited { background-color: #3f51b5 !important; } .hit-input { display: inline-block; color: #fff; width: 60px; padding: 0 8px; border-radius: 0; background-color: transparent; } .idle-ui-set-single, .idle-ui-set-full { opacity: 0.5; } .idle-ui-new-item { border: 1px dashed #888 !important; } .mr-10 { margin-right: 10px; } .ml-10 { margin-left: 10px; } @-webkit-keyframes rotate { from { -webkit-transform: rotate(0deg); -o-transform: rotate(0deg); transform: rotate(0deg); } to { -webkit-transform: rotate(360deg); -o-transform: rotate(360deg); transform: rotate(360deg); } } #processing i { animation: rotate 1s ease-in-out infinite; } .filter-input { width: 150px !important; } #big-slot { font-size: 24px; margin-top: 10px !important; color: #fff; } #idle-ui-quicksearch { position: relative; float: left; margin-top: 14px; } #idle-ui-quicksearch > input { width: 150px; display: inline-block; height: 24px; line-height: 24px; border-radius: 3px; } .equip-container > p:hover { white-space: nowrap; } .equip-container > p:hover .sr-only { z-index: 1; position: relative; } html.d3 body { color: #a99877; font-family: "Consolas", Arial, sans-serif; } html.d3 .panel { background-color: #171614; border-color: ${borderColor}; } html.d3 .panel-inverse > .panel-heading { background-color: #101010; border-color: ${borderColor}; font: normal 16px "Exocet Blizzard Light","Palatino Linotype", "Times", serif; color: #F3E6D0; line-height: 26px; } html.d3 .panel-inverse > .panel-heading .label { font-size: 12px; font-family: "Consolas", Arial, sans-serif; } html.d3 .btn { background-color: transparent; border: 1px solid ${borderColor}; vertical-align: top; color: #ad835a; font: normal 14px/1.5 Arial, sans-serif; line-height: normal; } html.d3 .btn:hover { color: #fff !important; } html.d3 .btn:active { background-color: transparent; } html.d3 .label { line-height: normal; font-weight: normal; border-radius: 2px; padding: 3px 4px 1px; border: 1px solid #5f3d11; box-shadow: 0 0 2px #000; background-color: #000; color: #ad835a; } html.d3 .label.label-info { color: #6969ff; } html.d3 .label.label-warning { color: #ffff00; } html.d3 .label.label-danger { color: #e60101; } html.d3 .label.label-success { color: #00c400; } html.d3 .physical { color: #f3e6d0 !important; } html.d3 .navbar-inverse.navbar-fixed-top { border-bottom: 1px solid #322a20; background-color: #171614; } html.d3 .navbar-inverse .navbar-brand { color: #f3e6d0; font-family: "Exocet Blizzard Light","Palatino Linotype", "Times", serif; } html.d3 a, html.d3 .navbar-inverse .navbar-nav>li>a { color: #ad835a; } html.d3 .magical, html.d3 .skill, html.d3 .cold { color: #6969ff !important; } html.d3 .hit-input { border-color: ${borderColor}; } html.d3 .progress { border: 1px solid #513f2e; border-radius: 0; box-shadow: 0 0 5px #000; background-color: #101010; color: #f3e6d0; height: 22px; } html.d3 .progress-bar { border: 1px solid #101010; line-height: 20px; } html.d3 .progress-bar-exp { background-color: rgb(251,131,44); } html.d3 .progress-bar-life { background: rgb(235,21,28); } html.d3 .footer { border-top: 1px solid #322a20; background-color: #171614; } html.d3 .btn.btn-success { color: #00c400; } html.d3 .btn.btn-danger { color: #e60101; } html.d3 .img-thumbnail { border-color: #d59c52; } html.d3 .popover { background: #1d180e; padding: 1px; border: 1px solid #322a20; border-radius: 2px; box-shadow: 0 0 10px #000; max-width: 271px; font-family: "Consolas", Arial, sans-serif; } html.d3 .popover-content .equip p:first-child { height: 30px; width: 263px; padding: 0; margin: 0 -10px 10px -10px !important; background: url(http://images.targetedu.cn/d3/tooltip-title.jpg) no-repeat; text-align: center; line-height: 28px; font-size: 16px; font-family: "Exocet Blizzard Light","Palatino Linotype", "Times", serif; } html.d3 .popover-content .equip p.unique:first-child { background-position: 0 -120px; } html.d3 .popover-content .equip p.set:first-child { background-position: 0 -180px; } html.d3 .popover-content .equip p.rare:first-child { background-position: 0 -90px; } html.d3 .popover-content .equip p.artifact:first-child { background-position: 0 -150px; } html.d3 .popover-content .equip p.magical:first-child { background-position: 0 -60px; } html.d3 .popover-content .equip p.base:first-child { background-position: 0 -30px; } html.d3 .popover-content .equip p.slot:first-child { background-position: 0 -30px; } html.d3 .popover-content { background-color: #000; padding: 2px 12px; } html.d3 hr { border-color: ${borderColor}; } html.d3 .panel-inverse > .panel-footer { background-color: #101010; border-color: ${borderColor}; } html.d3 .modal-dialog { box-shadow: 0 0 10px #000; } html.d3 .modal-content { background-color: #171614; border-color: ${borderColor}; } html.d3 .model-inverse > .modal-header, html.d3 .model-inverse > .modal-footer { background-color: #101010; border-color: ${borderColor}; } html.d3 .model-inverse > .modal-header span { line-height: normal; } html.d3 .panel-textarea { border-color: ${borderColor}; } html.d3 .panel-footer .panel-filter { border-color: #2a241c; } html.d3 .btn-default:active:focus, html.d3 .open>.dropdown-toggle.btn-default:focus, html.d3 .btn-default.active, .btn-default:active, html.d3 .open>.dropdown-toggle.btn-default { background-color: transparent; color: #a99877; } html.d3 .dropdown-menu { background-color: #101010; border-color: ${borderColor}; box-shadow: 0 0 10px #000; font-family: "Consolas", Arial, sans-serif; } html.d3 .equip-container .selected { border: 1px solid ${borderColor}; background-color: transparent; } html.d3 .table > tbody > tr > td, html.d3 .table > tbody > tr > th, html.d3 .table > tfoot > tr > td, html.d3 .table > tfoot > tr > th, html.d3 .table > thead > tr > td, html.d3 .table > thead > tr > th { border-color: ${borderColor}; } html.d3 .equip .divider { background-color: ${borderColor}; } html.d3 .panel-heading .btn-group, html.d3 .panel-heading .btn { vertical-align: top; } html.d3 .form-control{ border-color: ${borderColor}; background-color: #101010; color: #a99877; } html.d3 .form-validation .form-control { width: 198px; } html.d3 .popover.bottom>.arrow:after { border-bottom-color: #322a20; } html.d3 .super, html.d3 .unique { color: rgb(255,128,0) !important; } html.d3 .artifact { color: rgb(182,89,245) !important; } html.d3 .equip > p { color: #6969ff; } `);