idle

挂机无止境的辅助脚本

  1. // ==UserScript==
  2. // @name idle
  3. // @version 1.45
  4. // @namespace ErQi
  5. // @description 挂机无止境的辅助脚本
  6. // @author beside4ever@outlook.com
  7. // @grant GM_addStyle
  8. // @run-at document-start
  9. // @match https://www.idleinfinity.cn/*
  10. // @require https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.1/moment.min.js
  11. // @require https://cdnjs.cloudflare.com/ajax/libs/jquery-url-parser/2.3.1/purl.min.js
  12. // ==/UserScript==
  13.  
  14. const defaultFilterOptions = ['技能', '凹槽(0/2)', '凹槽(0/4)', '取得魔法装备', '攻击速度', '施法速度', '+20 毒素', '+25 毒素'];
  15.  
  16. let config = {
  17. userNumber: 1,
  18. showRequire: true,
  19. fastFilter: true,
  20. fastOptions: defaultFilterOptions.slice(0), // 快速过滤器配置,可自行增删
  21. showSpellColor: true,
  22. showSpeedLevel: true,
  23. showCharDmg: true,
  24. showAccuracy: true,
  25. dropNotification: true,
  26. itemStats: true,
  27. showBattle: true,
  28. mapHack: true,
  29. mapHackType: 'all',
  30. infiniteMap: false,
  31. showSetAttr: true,
  32. showAuctionNote: true,
  33. auctionWatch: true,
  34. oneKeyEquip: true,
  35. oneKeyAgree: true,
  36. oneKeyRune: true,
  37. showRuneTip: true,
  38. showBattleDetail: true,
  39. d3theme: true,
  40. minLevel: null,
  41. // 秘境的石头等级 0 表示普通 1表示魔法 2表示稀有,以此类推 按照下拉列表的排序
  42. level: '',
  43. moveTime: 5000,
  44. failure: 10,
  45. magical: true,
  46. };
  47.  
  48. const configLabel = {
  49. showRequire: '职业专属显示',
  50. fastFilter: '快速过滤选项',
  51. showSpellColor: '法术技能高亮',
  52. showSpeedLevel: '显示速度档位',
  53. showCharDmg: '角色均伤显示',
  54. showAccuracy: '角色命中显示',
  55. dropNotification: '欧皇暗金通知',
  56. itemStats: '欧皇收获统计',
  57. showBattle: '快速秘境战斗',
  58. mapHack: '秘境自动战斗',
  59. infiniteMap: '无限秘境模式',
  60. showSetAttr: '显示套装属性',
  61. showAuctionNote: '显示拍卖备注',
  62. auctionWatch: '拍卖特别关注',
  63. oneKeyEquip: '一键换装功能',
  64. oneKeyAgree: '一键同意功能',
  65. oneKeyRune: '一键转移符文',
  66. showRuneTip: '符文之语提示',
  67. showBattleDetail: '战斗详细分析',
  68. d3theme: '暗黑界面皮肤',
  69. minLevel: '符文序号',
  70. failure: '失败重置次数',
  71. magical: '一件升级蓝色秘境',
  72. };
  73.  
  74. const userConfig = ['dropNotification', 'd3theme'];
  75.  
  76. let localConfig = localStorage.getItem('idle-ui-config');
  77. if (localConfig) {
  78. localConfig = JSON.parse(localConfig);
  79. Object.keys(localConfig).map(key => {
  80. if (config[key] !== undefined) config[key] = localConfig[key];
  81. });
  82. }
  83.  
  84. if (config.d3theme) {
  85. const htmlElement = document.getElementsByTagName('html')[0];
  86. htmlElement.setAttribute('class', 'd3');
  87. }
  88.  
  89. function idleInit() {
  90. // 秘境的石头等级 ''空表示所有秘境 0 表示普通 1表示魔法 2表示稀有,以此类推 按照下拉列表的排序
  91. config.level = '';
  92. // 转移物品间隔时间,单位毫秒,最低不能低于300,会被制裁
  93. config.moveTime = 500;
  94. // 战斗失败重置次数,当同一组怪物失败到达此次数,自动重置当前秘境
  95. config.failure = 25;
  96. // 是否绕着Boss走
  97. config.dodge = false;
  98. // 同意消息间隔时间
  99. config.agreedTime = 800;
  100. var style = document.createElement('style');
  101. style.type = 'text/css';
  102. style.innerHTML = `.eq-weapon { background-color: #700;} .eq-armor {background-color: #007;} .eq-amulet {background-color: #0b0;} .eq-delete {background-color: gray;}
  103. .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;}`;
  104. document.getElementsByTagName('head')[0].appendChild(style);
  105.  
  106. // Extend page width
  107. // $('.container:nth(1)').css('width', '70%');
  108. $('body').css('height', $('body').height() + 500);
  109.  
  110. var equips = $(".panel-filter").parent().prev().find(".equip-content");
  111. var on_gears = $('.equip-container .equip-content');
  112. var i, gear, ps, hits, key, n_name, eqn;
  113. for (i = 0; i < on_gears.length; i++) {
  114. gear = on_gears[i];
  115. ps = gear.getElementsByTagName('p');
  116. if (ps.length > 0) {
  117. hits = gear.innerHTML.match(/彩虹刻面/);
  118. if (hits != null) {
  119. eqn = gear.previousElementSibling.getElementsByClassName('equip-name');
  120. hits = gear.innerHTML.match(/(\d+)陨石/);
  121. if (hits != null) {
  122. eqn[eqn.length - 1].innerHTML += ' <span style="color:red; background-color: black;">火刻 ' + hits[1] + 'slv</span>';
  123. }
  124. hits = gear.innerHTML.match(/(\d+)暴风雪/);
  125. if (hits != null) {
  126. eqn[eqn.length - 1].innerHTML += ' <span style="color:#3ff; background-color: black;">冰刻 ' + hits[1] + 'slv</span>';
  127. }
  128. hits = gear.innerHTML.match(/(\d+)连锁闪电/);
  129. if (hits != null) {
  130. eqn[eqn.length - 1].innerHTML += ' <span style="color:yellow; background-color: black;">电刻 ' + hits[1] + 'slv</span>';
  131. }
  132. hits = gear.innerHTML.match(/(\d+)剧毒新星/);
  133. if (hits != null) {
  134. eqn[eqn.length - 1].innerHTML += ' <span style="color:#00c400; background-color: black;">毒刻 ' + hits[1] + 'slv</span>';
  135. }
  136. hits = gear.innerHTML.match(/(\d+)虚化/);
  137. if (hits != null) {
  138. eqn[eqn.length - 1].innerHTML += ' <span style="color:#B659F5; background-color: black;">魔刻 ' + hits[1] + 'slv</span>';
  139. }
  140. hits = gear.innerHTML.match(/(\d+)伤害加深/);
  141. if (hits != null) {
  142. eqn[eqn.length - 1].innerHTML += ' <span style="color:white; background-color: black;">物刻</span>';
  143. }
  144. hits = gear.innerHTML.match(/(\d+)\% 火焰伤害/);
  145. if (hits != null) {
  146. eqn[eqn.length - 1].innerHTML += ' <span style="color:red; background-color: black;">+' + hits[1] + '</span>';
  147. }
  148. hits = gear.innerHTML.match(/(\d+)\% 冰冷伤害/);
  149. if (hits != null) {
  150. eqn[eqn.length - 1].innerHTML += ' <span style="color:#3ff; background-color: black;">+' + hits[1] + '</span>';
  151. }
  152. hits = gear.innerHTML.match(/(\d+)\% 闪电伤害/);
  153. if (hits != null) {
  154. eqn[eqn.length - 1].innerHTML += ' <span style="color:yellow; background-color: black;">+' + hits[1] + '</span>';
  155. }
  156. hits = gear.innerHTML.match(/(\d+)\% 毒素伤害/);
  157. if (hits != null) {
  158. eqn[eqn.length - 1].innerHTML += ' <span style="color:#00c400; background-color: black;">+' + hits[1] + '</span>';
  159. }
  160. hits = gear.innerHTML.match(/(\d+)\% 魔法伤害/);
  161. if (hits != null) {
  162. eqn[eqn.length - 1].innerHTML += ' <span style="color:#B659F5; background-color: black;">+' + hits[1] + '</span>';
  163. }
  164. hits = gear.innerHTML.match(/(\d+)\% 物理伤害/);
  165. if (hits != null) {
  166. eqn[eqn.length - 1].innerHTML += ' <span style="color:white; background-color: black;">+' + hits[1] + '</span>';
  167. }
  168. hits = gear.innerHTML.match(/(\d+)\% 目标火焰抗性/);
  169. if (hits != null) {
  170. eqn[eqn.length - 1].innerHTML += ' <span style="color:red; background-color: black;">-' + hits[1] + '</span>';
  171. }
  172. hits = gear.innerHTML.match(/(\d+)\% 目标冰冷抗性/);
  173. if (hits != null) {
  174. eqn[eqn.length - 1].innerHTML += ' <span style="color:#3ff; background-color: black;">-' + hits[1] + '</span>';
  175. }
  176. hits = gear.innerHTML.match(/(\d+)\% 目标闪电抗性/);
  177. if (hits != null) {
  178. eqn[eqn.length - 1].innerHTML += ' <span style="color:yellow; background-color: black;">-' + hits[1] + '</span>';
  179. }
  180. hits = gear.innerHTML.match(/(\d+)\% 目标毒素抗性/);
  181. if (hits != null) {
  182. eqn[eqn.length - 1].innerHTML += ' <span style="color:#00c400; background-color: black;">-' + hits[1] + '</span>';
  183. }
  184. }
  185. hits = gear.innerHTML.match(/攻击速度提升 (\d+)\%/);
  186. if (hits != null) {
  187. eqn = gear.previousElementSibling.getElementsByClassName('equip-name');
  188. eqn[eqn.length - 1].innerHTML += ' <span style="color:#ffd700; background-color: black;">' + hits[1] + 'ias </span>';
  189. }
  190. hits = gear.innerHTML.match(/施法速度提升 (\d+)\%/);
  191. if (hits != null) {
  192. eqn = gear.previousElementSibling.getElementsByClassName('equip-name');
  193. eqn[eqn.length - 1].innerHTML += ' <span style="color:#ff8000; background-color: black;">' + hits[1] + 'fcr </span>';
  194. }
  195. hits = gear.innerHTML.match(/\+(\d+)\% 增强伤害/);
  196. if (hits != null) {
  197. eqn = gear.previousElementSibling.getElementsByClassName('equip-name');
  198. eqn[eqn.length - 1].innerHTML += ' <span style="color:#66ccff; background-color: black;">' + hits[1] + 'ed </span>';
  199. }
  200. hits = gear.innerHTML.match(/\+(\d+)\% 暴击几率/);
  201. if (hits != null) {
  202. eqn = gear.previousElementSibling.getElementsByClassName('equip-name');
  203. eqn[eqn.length - 1].innerHTML += ' <span style="color:#CCCC00; background-color: black;">' + hits[1] + 'cri </span>';
  204. }
  205. hits = ps[ps.length - 1].textContent.match(/凹槽(\(\d+\/\d+\))/);
  206. if (hits != null) {
  207. eqn = gear.previousElementSibling.getElementsByClassName('equip-name')
  208. eqn[eqn.length - 1].innerHTML += ' <span>' + hits[1] + ' </span>';
  209. }
  210. hits = gear.innerHTML.match(/\+(\d+)\% 更佳的机会取得魔法装备/);
  211. if (hits != null) {
  212. eqn = gear.previousElementSibling.getElementsByClassName('equip-name');
  213. eqn[eqn.length - 1].innerHTML += ' <span style="color:white; background-color: black;"> ' + hits[1] + 'mf </span>';
  214. }
  215. hits = gear.innerHTML.match(/\+(\d+)\% 额外金币从怪物身上取得/);
  216. if (hits != null) {
  217. eqn = gear.previousElementSibling.getElementsByClassName('equip-name');
  218. eqn[eqn.length - 1].innerHTML += ' <span style="color:gold; background-color: black;"> ' + hits[1] + 'gf </span>';
  219. }
  220. hits = gear.innerHTML.match(/元素抗性 \+(\d+)\%/);
  221. if (hits != null) {
  222. eqn = gear.previousElementSibling.getElementsByClassName('equip-name');
  223. eqn[eqn.length - 1].innerHTML += ' <span style="color:#f90; background-color: black;">' + hits[1] + 'ar </span>';
  224. }
  225. hits = gear.innerHTML.match(/抗火 \+(\d+)\%/);
  226. if (hits != null) {
  227. eqn = gear.previousElementSibling.getElementsByClassName('equip-name');
  228. eqn[eqn.length - 1].innerHTML += ' <span style="color:red; background-color: black;">' + hits[1] + 'f </span>';
  229. }
  230. hits = gear.innerHTML.match(/抗寒 \+(\d+)\%/);
  231. if (hits != null) {
  232. eqn = gear.previousElementSibling.getElementsByClassName('equip-name');
  233. eqn[eqn.length - 1].innerHTML += ' <span style="color:#3ff; background-color: black;">' + hits[1] + 'c </span>';
  234. }
  235. hits = gear.innerHTML.match(/抗闪电 \+(\d+)\%/);
  236. if (hits != null) {
  237. eqn = gear.previousElementSibling.getElementsByClassName('equip-name');
  238. eqn[eqn.length - 1].innerHTML += ' <span style="color:yellow; background-color: black;">' + hits[1] + 'l </span>';
  239. }
  240. hits = gear.innerHTML.match(/抗毒 \+(\d+)\%/);
  241. if (hits != null) {
  242. eqn = gear.previousElementSibling.getElementsByClassName('equip-name');
  243. eqn[eqn.length - 1].innerHTML += ' <span style="color:#00c400; background-color: black;">' + hits[1] + 'p </span>';
  244. }
  245. }
  246. }
  247.  
  248. addConfig();
  249. // 显示限定字符
  250. switchSkin(config.showRequire);
  251. Notification.requestPermission();
  252.  
  253. $('.navbar-nav > li > a').each(function () {
  254. if ($(this).text().indexOf('帮助') >= 0) {
  255. const links = [
  256. {text: '暗金列表', link: '/Help/Content?url=Unique'},
  257. {text: '套装列表', link: '/Help/Content?url=Set'},
  258. // {text: '秘境圣衣', link: '/Help/Content?url=Sacred'},
  259. {text: '神器列表', link: '/Help/Content?url=Artifact'},
  260. {text: '普通物品', link: '/Help/Content?url=BaseEquip'},
  261. {text: '前缀属性', link: '/Help/Content?url=Prefix'},
  262. {text: '后缀属性', link: '/Help/Content?url=Suffix'},
  263. {text: '固定词缀', link: '/Help/Content?url=SpecialAffix'},
  264. {text: '神秘玩具', link: '/Help/specialequip'},
  265. ].map(item => {
  266. return `<li><a class="base" href="${item.link}" target="_blank">${item.text}</a></li>`;
  267. }).join('');
  268. $(this).next().append(links);
  269. }
  270. });
  271.  
  272. function fetchItem(name, callback) {
  273. if (!name) return;
  274. if (quickSearchType === 'Set' || quickSearchType === 'Unique') {
  275. $.get(`/Help/${quickSearchType}`, function (html) {
  276. const dom = $.parseHTML(html);
  277. const type = quickSearchType.toLowerCase();
  278. $(dom).find(`.equip > .${type}`).each(function () {
  279. if ($(this).text().indexOf(name) >= 0) {
  280. callback($(this).parent());
  281. return;
  282. }
  283. });
  284. });
  285. } else {
  286. $.get('/Help/Artifact', function (html) {
  287. const dom = $.parseHTML(html);
  288. $(dom).find('tr').each(function (i) {
  289. if (i > 0) {
  290. const nameLabel = $(this).children().last().find('.artifact');
  291. if (nameLabel.text().indexOf(name) >= 0) {
  292. const ret = [];
  293. ret.push(`<p class="artifact">${nameLabel.text()}</p>`);
  294. $(this).children().first().children('div').each(function () {
  295. ret.push(`<p class="physical">${$(this).text()}</p>`);
  296. });
  297. ret.push('<p class="artifact">神器</p>');
  298. nameLabel.parent().children().each(function (index) {
  299. if (index > 0) ret.push(`<p>${$(this).text()}</p>`);
  300. });
  301. const recipe = [];
  302. $(this).children().eq(1).find('.artifact.equip-name').each(function () {
  303. const id = $(this).text().match(/\d+/g)[0];
  304. recipe.push(`<span class="artifact">${id}#</span>`);
  305. });
  306. ret.push(`<p class="physical">${recipe.join(' + ')}</p>`);
  307. callback($(`<div class="equip">${ret.join('')}</div>`));
  308. return;
  309. }
  310. }
  311. });
  312. });
  313. }
  314. }
  315.  
  316. let quickSearchType = 'Unique';
  317. const itemTypes = `
  318. <div class="btn-group">
  319. <button type="button" class="btn btn-default btn-xs dropdown-toggle" data-toggle="dropdown">
  320. <span id="idle-quick-type">暗金</span><span class="caret" style="margin-left: 5px;"></span>
  321. </button>
  322. <ul class="dropdown-menu">
  323. <li><a class="quick-option unique" data-type="Unique" href="javascript: void(0);">暗金</a></li>
  324. <li><a class="quick-option set" data-type="Set" href="javascript: void(0);">套装</a></li>
  325. <li><a class="quick-option artifact" data-type="Artifact" href="javascript: void(0);">神器</a></li>
  326. </ul>
  327. </div>
  328. `;
  329. 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>`;
  330. $('.navbar-header').append(input);
  331.  
  332. $('.quick-option').click(function (e) {
  333. e.preventDefault();
  334. quickSearchType = $(this).data('type');
  335. $('#idle-quick-type').text($(this).text());
  336. const val = $('#idle-ui-quicksearch > input').val();
  337. if (val) {
  338. const popover = $('#idle-ui-quicksearch > input').next();
  339. popover.hide();
  340. fetchItem(val, function (html) {
  341. popover.children().first().html(html);
  342. popover.show();
  343. });
  344. }
  345. });
  346.  
  347. let quickTimer = null;
  348. $('#idle-ui-quicksearch > input').keyup(function () {
  349. if (quickTimer) {
  350. clearTimeout(quickTimer);
  351. quickTimer = null;
  352. }
  353. const val = $(this).val();
  354. if (!val) $(this).next().hide();
  355. quickTimer = setTimeout(() => {
  356. const popover = $(this).next();
  357. popover.hide();
  358. fetchItem(val, function (html) {
  359. popover.children().first().html(html);
  360. popover.show();
  361. });
  362. }, 500);
  363. });
  364.  
  365. if (config.fastFilter) {
  366. const fastOptions = (['无'].concat(config.fastOptions)).map(function (item) {
  367. return `<li><a href="javascript: void(0);" class="filter-text" style="color: white">${item}</a></li>`;
  368. }).join('');
  369.  
  370. const fastFilter = '<div class="fast-filter btn-group">' +
  371. '<button type="button" class="btn btn-default btn-xs dropdown-toggle" style="margin-left: 10px;" data-toggle="dropdown">快速过滤<span class="caret"/></button>'
  372. + `<ul class="dropdown-menu">${fastOptions}</ul></div>`;
  373. $(fastFilter).insertAfter('.panel-filter');
  374.  
  375. $('.filter-text').click(function () {
  376. const text = $(this).text() === '无' ? '' : $(this).text();
  377. const filter = $(this).parent().parent().parent().prev();
  378. filter.val(text);
  379. filter.trigger('input');
  380. });
  381. }
  382.  
  383. if (config.showSpellColor) {
  384. $('.skill-name').each(function () {
  385. let desc = '';
  386. let label = '';
  387. if ($(this).children().length === 2) {
  388. desc = $(this).next().text();
  389. label = $(this).children().last();
  390. } else {
  391. desc = $(this).parent().next().text();
  392. label = $(this);
  393. }
  394. if (desc.indexOf('法术技能') >= 0) {
  395. label.addClass('skill');
  396. }
  397. });
  398. }
  399.  
  400. function getSpeedLevel(speed, isAttack) {
  401. const levels = isAttack ? [0, -25, -50, -80, -120, -160, -200] : [0, -20, -45, -75, -110, -145, -180];
  402. for (let i = 0; i < levels.length; i++) {
  403. if (speed > levels[i]) {
  404. const next = levels[i];
  405. return [i, next];
  406. }
  407. }
  408. return [levels.length, '已最高'];
  409. }
  410.  
  411. function getAvgDmg(dmgStr) {
  412. const dmgArray = dmgStr.split('~');
  413. const avg = (((dmgArray[0] - 0) + (dmgArray[1] - 0)) / 2);
  414. return avg;
  415. }
  416.  
  417. function getKeySkill() {
  418. let ret = {name: '', accRate: 0, dmgRate: 0};
  419. $('span.label.label-danger').each(function () {
  420. if (!$(this).hasClass('sr-only') && $(this).text().indexOf('K') >= 0) {
  421. ret.name = $(this).prev().text();
  422. const skill = $(this).parent().next().text();
  423. ret.isAttack = skill.indexOf('攻击技能') >= 0;
  424. if (ret.isAttack) {
  425. const accMatch = skill.match(/提升(\d+)%准确率/);
  426. const dmgMatch = skill.match(/(\d+)%基础伤害/);
  427. if (accMatch) ret.accRate = (accMatch[1] - 0) / 100;
  428. if (dmgMatch) ret.dmgRate = (dmgMatch[1] - 0) / 100;
  429. }
  430. }
  431. });
  432. return ret;
  433. }
  434.  
  435. function renderCharLabel(name, value, id) {
  436. const idStr = id ? `id="${id}"` : '';
  437. return `<p><span>${name}:</span><span ${idStr} class="state">${value}</span></p>`;
  438. }
  439.  
  440. if (location.href.indexOf('Character/Detail') >= 0) {
  441. const keySkill = getKeySkill();
  442. let level = 0;
  443. $('.label.label-default').each(function () {
  444. const label = $(this).text();
  445. if (label.indexOf('Lv') >= 0 && level === 0) {
  446. level = label.replace('Lv', '') - 0;
  447. }
  448. if (config.showSpeedLevel) {
  449. if (label === '攻击') {
  450. const attackSpeed = $(this).parent().next().next().next().next().children().last();
  451. const level = getSpeedLevel(attackSpeed.text(), true);
  452. const levelElement = renderCharLabel('攻速档位', level[0]) + renderCharLabel('下档攻速', level[1]);
  453. $(levelElement).insertAfter(attackSpeed.parent());
  454. } else if (label === '法术') {
  455. const spellSpeed = $(this).parent().next().children().last();
  456. const level = getSpeedLevel(spellSpeed.text(), false);
  457. const levelElement = renderCharLabel('速度档位', level[0]) + renderCharLabel('下档速度', level[1]);
  458. $(levelElement).insertAfter(spellSpeed.parent());
  459. }
  460. }
  461. if (config.showCharDmg) {
  462. if (label === '攻击') {
  463. const baseDmg = $(this).parent().next().children().last().text();
  464. const critElement = $(this).parent().next().next().next();
  465. const crit = critElement.children().last().text().replace('%', '') / 100;
  466. const avgDmg = getAvgDmg(baseDmg);
  467. const finalDmg = (avgDmg * (1 + (crit - 0))).toFixed(2) - 0;
  468. let dmgElement = renderCharLabel('普攻均伤', finalDmg);
  469. if (keySkill.isAttack) {
  470. const keyDmg = (keySkill.dmgRate * finalDmg).toFixed(2) - 0;
  471. dmgElement += renderCharLabel(`${keySkill.name}均伤`, keyDmg);
  472. }
  473. $(dmgElement).insertAfter(critElement);
  474. }
  475. }
  476. if (config.showAccuracy) {
  477. if (label === '攻击') {
  478. const accuracy = $(this).parent().next().next().children().last().text() - 0;
  479. const accuracyElement = $(this).parent().next().next();
  480. const accRate = getAccRate(level, level, accuracy);
  481. let accElement = `<p><span>命中怪物等级:</span><span><input type="number" class="form-control hit-input" value="${level}"/></span></p>`;
  482. accElement += renderCharLabel('普攻命中率', `${accRate}%`, 'idle-ui-acc');
  483. if (keySkill.isAttack) {
  484. const keyAcc = accuracy * keySkill.accRate;
  485. const keyAccRate = getAccRate(level, level, keyAcc);
  486. accElement += renderCharLabel(`${keySkill.name}命中率`, `${keyAccRate}%`, 'idle-ui-key-acc');
  487. }
  488. $(accElement).insertAfter(accuracyElement);
  489.  
  490. $('.hit-input').change(function () {
  491. const mlvl = $(this).val();
  492. const def = (mlvl - 0 + 1) * 10;
  493. const curAccRate = getAccRate(level, mlvl, accuracy);
  494. $('#idle-ui-acc').text(`${curAccRate}%`);
  495. if (keySkill.isAttack) {
  496. const curKeyAccRate = getAccRate(level, mlvl, accuracy * keySkill.accRate);
  497. $('#idle-ui-key-acc').text(`${curKeyAccRate}%`);
  498. }
  499. });
  500. }
  501. }
  502. if (config.itemStats) {
  503. if (label == '综合') {
  504. const uniqueNum = $(this).parent().next().next().next().next().children().last().text();
  505. const setNum = $(this).parent().next().next().next().next().next().children().last().text();
  506. const statsData = {uniqueNum: uniqueNum, setNum: setNum};
  507. saveStats({uniqueNum: uniqueNum, setNum: setNum});
  508. }
  509. }
  510. });
  511. }
  512.  
  513. function getAccRate(clvl, mlvl, acc) {
  514. clvl = clvl - 0;
  515. mlvl = mlvl - 0;
  516. acc = acc - 0;
  517. const def = (mlvl - 0 + 1) * 10;
  518. return (2 * (clvl / (clvl + mlvl)) * (acc / (acc + def)) * 100).toFixed(2) - 0;
  519. }
  520.  
  521. function saveStats(statsData) {
  522. const idMatch = location.href.match(/Character\/Detail\?Id=(\d+)/i);
  523. if (!idMatch) return;
  524. const id = idMatch[1];
  525. let stats = localStorage.getItem('idle-ui-stats');
  526. stats = stats ? JSON.parse(stats) : {uniqueNum: 0, setNum: 0};
  527. const lastStatsData = stats[id];
  528. const time = +new Date();
  529. if (lastStatsData && lastStatsData.time) {
  530. const duration = moment.duration(moment(time).diff(moment(lastStatsData.time)));
  531. const timeSpan = duration.asMinutes() > 60 ? (duration.asHours().toFixed(1) - 0) + '小时前' : Math.round(duration.asMinutes()) + '分钟前';
  532. const uniqueChange = statsData.uniqueNum - lastStatsData.uniqueNum;
  533. const setChange = statsData.setNum - lastStatsData.setNum;
  534. displayStats(id, timeSpan, uniqueChange, setChange);
  535. }
  536. statsData.time = time;
  537. stats[id] = statsData;
  538. localStorage.setItem('idle-ui-stats', JSON.stringify(stats));
  539. }
  540.  
  541. function displayStats(id, timeSpan, uniqueChange, setChange) {
  542. 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>`;
  543.  
  544. $('.navbar.navbar-inverse.navbar-fixed-top').next().next().prepend(message);
  545. $('#open-ui-modal').click(function () {
  546. $('#modalUI').modal('show');
  547. });
  548. }
  549.  
  550. // 离线挂机统计记录
  551. if (config.dropNotification && location.href.indexOf('Map/Dungeon') === -1) {
  552. $(document).ready(function () {
  553. // 找到数据添加下拉框
  554. // $("div.panel-heading")
  555.  
  556. // 添加获得焦点事件,在获得焦点时更新下拉列表数据
  557.  
  558. // 处理下拉选中,显示数据
  559.  
  560. // 初始化记载经验数据列表
  561. const userCont = new Map();
  562.  
  563. const dropTypes = {unique: '暗金', set: '套装'};
  564. const oldLog = $.connection.userManagerHub.client.battleLog;
  565. $.connection.userManagerHub.client.battleLog = function (data) {
  566. const ret = JSON.parse(data);
  567. const keys = Object.keys(ret.EquipmentNameList);
  568. if (keys.length > 0) {
  569. keys.forEach(function (type) {
  570. const items = ret.EquipmentNameList[type].join(',');
  571. if (dropTypes[type]) {
  572. const notice = new Notification(
  573. `${ret.CharName} 获得${dropTypes[type]}`,
  574. {
  575. body: items,
  576. icon: 'https://cdn3.iconfinder.com/data/icons/game-play/512/gaming-game-play-multimedia-console-09-512.png'
  577. }
  578. );
  579. }
  580. });
  581. }
  582. if (ret.RuneNameList.length) {
  583. let s = ret.RuneNameList.join(',');
  584. if (parseInt(s.replace(/[^0-9]/ig, "")) >= parseInt(config.minLevel)) {
  585. new Notification(
  586. `${ret.CharName} 获得符文`,
  587. {
  588. body: s,
  589. icon: 'https://cdn0.iconfinder.com/data/icons/geek-4/24/Mortal_Instruments_movie_symbol_logo_rune-512.png'
  590. }
  591. );
  592. }
  593. }
  594.  
  595. if (!userCont.get(ret.CharName)) {
  596. const user = {};
  597. user.name = ret.CharName;
  598. user.time = 0;
  599. user.count = 0;
  600. user.exp = 0;
  601. user.gold = 0;
  602. user.equipment = 0;
  603. userCont.set(ret.CharName, user);
  604. }
  605. let user = userCont.get(ret.CharName);
  606. user.time += Number(ret.CostTime);
  607. user.count += 1;
  608. let exp = Number(ret.Exp);
  609. user.exp += isNaN(exp) ? 0 : exp;
  610. let gold = Number(ret.Gold);
  611. user.gold += isNaN(gold) ? 0 : gold;
  612. userCont.set(ret.CharName, user);
  613. user.equipment += keys.length;
  614. 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));
  615.  
  616. if (oldLog) oldLog(data);
  617. };
  618. $.connection.hub.stop();
  619. $.connection.hub.start();
  620. });
  621. }
  622.  
  623. if (config.showBattle && inBattlePage() && !$('.error').length) {
  624. let waitTime = $('#time');
  625. if (waitTime.length) {
  626. waitTime = waitTime.val();
  627. } else {
  628. $(document).ready(function () {
  629. $(".turn").battle({
  630. interval: 0,
  631. guaji: 0
  632. });
  633. });
  634. }
  635. }
  636.  
  637. function renderConigHtml() {
  638. return Object.keys(config)
  639. .filter(item => userConfig.indexOf(item) >= 0)
  640. .map(key => {
  641. const cfg = config[key];
  642. 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>`
  643. })
  644. .join('');
  645. }
  646.  
  647. function addConfig() {
  648. // $("[name='gold'][id='gold'][type='number']").attr('value', 50000);
  649. const configHtml = renderConigHtml();
  650. const html = `
  651. <div class="modal fade" id="modalUI" style="display: none;">
  652. <div class="modal-dialog modal-large" role="">
  653. <div class="modal-content model-inverse">
  654. <div class="modal-header">
  655. <span class="modal-title">插件设置</span>
  656. </div>
  657. <div class="modal-body">
  658. <div class="idle-ui-title">Idle Infinity UI 增强插件 by 班登</div>
  659. <div class="panel-header state">配置项开关(配置具体含义请参考<a href="https://greasyfork.org/zh-CN/scripts/370841-fight-beibei-everyday" target="_blank">脚本介绍</a>,点击即可启用/禁用,变更后请刷新)</div>
  660. <div class="form row">${configHtml}</div>
  661. <p>按 Alt+T 可快速切换主题皮肤</p>
  662. <div class="panel-header state">自动秘境模式</div>
  663. <div>
  664. <label class="radio-inline">
  665. <input type="radio" class="idle-ui-hack-type" name="maphack-type" id="hack-boss" value="boss"> 只打BOSS
  666. </label>
  667. <label class="radio-inline">
  668. <input type="radio" class="idle-ui-hack-type" name="maphack-type" id="hack-all" value="all"> 小怪全清
  669. </label>
  670. <label class="radio-inline">
  671. <input type="radio" class="idle-ui-hack-type" name="maphack-type" id="hack-mystery" value="mystery"> 秘境扫荡
  672. </label>
  673. </div>
  674. <div class="panel-header state">符文提示过滤</div>
  675. <div>
  676. <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}>
  677. </div>
  678. <div class="panel-header state"></div>
  679. <div class="panel-header state">快速过滤下拉选项(每行一个)</div>
  680. <textarea id="idle-ui-filters" class="form-control panel-textarea" rows="5"></textarea>
  681. <div class="textarea-actions">
  682. <button type="button" class="btn btn-xs btn-success" id="idle-ui-save-filters">保存选项</button>
  683. <button type="button" class="btn btn-xs btn-default" id="idle-ui-reset-filters">恢复默认</button>
  684. </div>
  685. </div>
  686. <div class="modal-footer">
  687. <button type="button" class="btn btn-default btn-xs" data-dismiss="modal">关闭</button>
  688. </div>
  689. </div>
  690. </div>
  691. </div>
  692. `;
  693. $(document.body).append(html);
  694. loadLocalConfig();
  695. }
  696.  
  697. function loadLocalConfig() {
  698. $('.idle-ui-config').each(function () {
  699. const key = $(this).data('key');
  700. $(this).prop('checked', config[key]);
  701. });
  702. $('#idle-ui-filters').val(config.fastOptions.join('\n'));
  703. $(`#hack-${config.mapHackType}`).prop('checked', true);
  704.  
  705. $('#idle-ui-reset-filters').click(function () {
  706. config.fastOptions = defaultFilterOptions;
  707. saveLocalConfig();
  708. loadLocalConfig();
  709. });
  710.  
  711. $('#idle-ui-save-filters').click(function () {
  712. config.fastOptions = $('#idle-ui-filters').val().split('\n');
  713. config.minLevel = $('#idle-ui-rune-filter').val();
  714. saveLocalConfig();
  715. });
  716.  
  717. $('.idle-ui-config').change(function () {
  718. const key = $(this).data('key');
  719. config[key] = $(this).prop('checked');
  720. if (config.d3theme) {
  721. $('html').addClass('d3');
  722. } else {
  723. $('html').removeClass('d3');
  724. }
  725. saveLocalConfig();
  726. });
  727.  
  728. $('.idle-ui-hack-type').change(function () {
  729. if ($(this).prop('checked')) config.mapHackType = $(this).val();
  730. saveLocalConfig();
  731. });
  732.  
  733. // 监听alt+t按键,切换界面
  734. $(document).bind('keyup', function (event) {
  735. if (event.which === 84 && event.altKey) {
  736. $('html').toggleClass('d3');
  737. switchSkin(document.getElementsByClassName('d3').length > 0)
  738. }
  739. });
  740. }
  741.  
  742. function saveLocalConfig() {
  743. localStorage.setItem('idle-ui-config', JSON.stringify(config));
  744. }
  745.  
  746. // 监听过滤条件输入框的改变
  747. $(".panel-filter").on("input propertychange", function () {
  748. $(this).parent().prev().find(".selected").removeClass("selected")
  749.  
  750. // 输入的值
  751. var value = $(this).val();
  752. // 保存到缓存,方便下次使用
  753. window.localStorage.setItem($(this).attr("id"), value);
  754. if (value.length > 0) {
  755. var values = value.split(",");
  756. var equips = $(this).parent().prev().find(".equip-content");
  757.  
  758. // 正则判断是否是数字
  759. const min = /^<[0-9]+.?[0-9]*$/;
  760. const max = /^>[0-9]+.?[0-9]*$/;
  761.  
  762. // 提取装备等级的正则表达式
  763. const level = /\([0-9]*\)/;
  764.  
  765. // 去的当页数据
  766. equips.each(function (i, e) {
  767. var match = 0;
  768. $.each(values, function (j, p) {
  769. let text = $(e).text();
  770. if (min.test(p)) {
  771. // 纯数字,作为掉落等级来判断
  772. let exec = String(level.exec(text));
  773. exec = exec.substring(1, exec.length - 1);
  774. p = p.substring(1, p.length);
  775. if (parseInt(exec) <= parseInt(p)) match++;
  776. } else if (max.test(p)) {
  777. let exec = String(level.exec(text));
  778. exec = exec.substring(1, exec.length - 1);
  779. p = p.substring(1, p.length);
  780. if (parseInt(exec) >= parseInt(p)) match++;
  781. } else if (text.indexOf(p) >= 0) {
  782. // 其他属性
  783. match++;
  784. }
  785. });
  786. if (match == values.length) {
  787. $(e).prev().addClass("selected");
  788. }
  789. });
  790. }
  791. });
  792.  
  793. $(document).ready(function () {
  794. $(".panel-filter").each(function (i, input) {
  795. var value = window.localStorage.getItem($(this).attr("id"));
  796. if (value != null && value.length > 0) {
  797. $(this).val(value);
  798. $(this).trigger("propertychange");
  799. }
  800. });
  801. });
  802.  
  803.  
  804. // 当前是秘境界面
  805. if (config.mapHack && location.href.indexOf('Map/Dungeon') >= 0) {
  806.  
  807. // 爱液的原始点击
  808. $.connection.userManagerHub.client.startDungeon = function (d) {
  809. localStorage.setItem("t", d);
  810. $(".dungeon-container").on("mousedown", ".public", null, function (a, g) {
  811. var f = $(this);
  812. var c = f.parent();
  813. g = f.attr("id");
  814. var k = $("#cid").val();
  815. if (f.hasClass("monster")) window.location.replace("/Battle/InDungeon?id=" + k + "&bid=" + g); else {
  816. $(".dungeon-layer").show();
  817. var e = [];
  818. if (0 < a.pageX && 0 < a.pageY && a.hasOwnProperty("originalEvent") && (a.originalEvent.isTrusted || 1 == a.originalEvent.detail)) {
  819. e = $(c).offset();
  820. var h = $(c).width();
  821. c = $(c).height();
  822. var l = Math.floor(Math.random() * h);
  823. e = [a.pageX, l, a.pageY, e.left, h - l, e.top, h, Math.floor(Math.random() * c), c]
  824. }
  825. a = {
  826. id: k,
  827. bid: g,
  828. m: e,
  829. t: d,
  830. __RequestVerificationToken: $("[name='__RequestVerificationToken']").val()
  831. };
  832. $.ajax({
  833. url: "MoveTo",
  834. type: "post",
  835. data: a,
  836. dataType: "json",
  837. success: function (a) {
  838. $.each(a, function (a, b) {
  839. void 0 == b.id && (b.id = 0);
  840. a = "";
  841. 0 == b.d[0] && (a += " top");
  842. 0 == b.d[1] && (a += " left");
  843. if (1 == b.m)
  844. $("#" + b.id).addClass(a);
  845. else {
  846. a += " public";
  847. var c = "";
  848. 0 < b.mlvl && (c += "Lv" + b.mlvl + " " + b.mname, a = a + " monster " + b.mtype);
  849. $("#" + b.id).removeClass("mask").addClass(a);
  850. "" != c && $("#" + b.id).attr("title", c)
  851. }
  852. });
  853. 0 < a.length && ($("#explore").text(parseInt($("#explore").text()) + a.length),
  854. $("#not-explore").text(parseInt($("#not-explore").text()) - a.length));
  855. $(".current").removeClass("current");
  856. f.addClass("current");
  857. $(".dungeon-layer").hide()
  858. }, error: function (a, c, b) {
  859. alert(a.responseText);
  860. $(".dungeon-layer").hide()
  861. }
  862. })
  863. }
  864. })
  865. };
  866.  
  867. let hacking = false;
  868. const idMatch = location.href.match(/id=(\d+)/i);
  869. if (!idMatch) return;
  870. const id = idMatch[1];
  871. 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>';
  872. $('.dungeon-container').prev().children().last().prepend(btns);
  873.  
  874. if (config.infiniteMap) $('#auto-reset').prop('checked', true);
  875. $('#auto-reset').change(function () {
  876. config.infiniteMap = $(this).prop('checked');
  877. saveLocalConfig();
  878. });
  879.  
  880. let failedBlocks = localStorage.getItem('idle-ui-fail-blocks');
  881. failedBlocks = failedBlocks ? JSON.parse(failedBlocks) : [];
  882.  
  883. let map = localStorage.getItem('idle-ui-maphack');
  884.  
  885. // 是否出现验证码提示
  886. if ($("[role='dialog'][data-code='True']").length) {
  887. // 提示验证码 停止自动秘境
  888. endMove("验证码出现");
  889. return;
  890. }
  891.  
  892. if (map) {
  893. map = JSON.parse(map);
  894.  
  895. if (map[id] && map[id] === 'start') {
  896. const bossLeft = $('.boss-left').text() - 0;
  897. const monster = $('.monster-left').text() - 0;
  898. if (bossLeft === 0 && config.mapHackType === 'boss') {
  899. if (config.infiniteMap) {
  900. setTimeout(() => {
  901. tryReset();
  902. }, 500);
  903. } else {
  904. map = {};
  905. map[id] = 'end';
  906. }
  907. } else if (monster === 0 && config.mapHackType === 'mystery') {
  908. // 秘境扫荡完毕,跳转到装备界面开始继续打石头
  909. // 获得用户的ID
  910. // 秘境的石头等级 0 表示普通 1表示魔法 2表示稀有,以此类推 按照下拉列表的排序
  911. // https://www.idleinfinity.cn/Equipment/Query?id=5671&pt2=2&et2=2147483648&pi=0&pt=1&et=2147483648
  912. // https://www.idleinfinity.cn/Equipment/Query?id=5671&et2=2147483648&pt2=1&pi=0&pt=1&et=2147483648
  913. // https://www.idleinfinity.cn/Equipment/Query?id=5671&pt=2&et=2147483648&pi2=0&pt2=2&et2=2147483648
  914. localStorage.setItem('failure', "0");
  915. const level = config.level;
  916. const userId = $("#cid").val();
  917. location.href = `/Equipment/Query?id=${userId}&pt=5&et=2147483648&pi2=0&pt2=${level}&et2=2147483648`;
  918. // 定位到装备界面
  919. } else {
  920. $('.dungeon-container').prev().children().last().prepend('<button class="btn btn-xs btn-default" style="margin-right: 5px;" id="end-hack">停止自动秘境</button>');
  921. setTimeout(() => {
  922. startHack();
  923. }, 500);
  924. }
  925. }
  926. } else {
  927. map = {};
  928. map[id] = 'end';
  929. }
  930.  
  931. function tryReset() {
  932. const stoneLeft = $('.panel-heading .state').text() - 0;
  933. if (stoneLeft > 0) {
  934. localStorage.setItem('idle-ui-fail-blocks', '[]');
  935. localStorage.setItem('failure', "0");
  936. $("form").attr("action", "DungeonRefresh");
  937. $("form").trigger("submit");
  938. } else {
  939. endMove('秘境之石已用完');
  940. }
  941. }
  942.  
  943. $('#start-hack').click(function (params) {
  944. startHack(true);
  945. });
  946.  
  947. $('#end-hack').click(function (params) {
  948. alert('自动秘境已停止');
  949. endMove();
  950. });
  951.  
  952. function startHack(fromClick) {
  953. if (hacking) return;
  954. hacking = true;
  955. if (!map[id] && typeof map == 'string') {
  956. map = JSON.parse(map);
  957. }
  958. map[id] = 'start';
  959. localStorage.setItem('idle-ui-maphack', JSON.stringify(map));
  960. if (fromClick) {
  961. localStorage.setItem('idle-ui-fail-blocks', '[]');
  962. localStorage.setItem('failure', "0");
  963. }
  964. mapMove();
  965. }
  966.  
  967. function mapMove() {
  968. // if (blockData.num >= 9) {
  969. // endMove('封号打击次数过多,禁止自动秘境');
  970. // return;
  971. // }
  972. if (map[id] !== 'start') return;
  973. // 有boss先打boss
  974. const bossBlock = $('.boss').eq(0);
  975. if(!config.dodge){
  976. if (bossBlock.length && !bossBlock.hasClass('mask')) {
  977. clickBlock(bossBlock);
  978. return;
  979. }
  980. }
  981.  
  982.  
  983. const bossId = bossBlock.attr("id");
  984. const asc = Number(bossId) <= 200;
  985. // Boss在地图上X轴坐标
  986. const boosX = bossId % 20;
  987. // Boss在地图上Y轴坐标
  988. const boosY = bossId / 20;
  989. const blocks = []; // 无敌人的可行区块
  990. const enemyBlocks = []; // 有敌人的可行区块
  991. for (let i = asc ? 0 : 399; asc ? i <= 399 : i >= 0; asc ? i++ : i--) {
  992. const block = $(`#${i}`);
  993. if (canExplore(i)) {
  994. if (block.hasClass('monster')) {
  995. enemyBlocks.push(i);
  996. } else {
  997. blocks.push(i);
  998. }
  999. }
  1000. }
  1001. let nextBlockIndex = null;
  1002. if (blocks.length) {
  1003. nextBlockIndex = blocks[0];
  1004. } else if (enemyBlocks.length) {
  1005. // 和Boss的距离的值,等于X+Y.
  1006. let distance = 39;
  1007. // 计算距离Boss最近的怪
  1008. for (let i = 0; i < enemyBlocks.length; i++) {
  1009. const itemX = enemyBlocks[i] % 20;
  1010. const itemY = enemyBlocks[i] / 20;
  1011. const itemDistance = Math.abs(itemX - boosX) + Math.abs(itemY - boosY);
  1012. // 判断是否有打不过的怪
  1013. if (((config.mapHackType === 'boss') ? (itemDistance < distance) : true) && failedBlocks.indexOf(enemyBlocks[i]) === -1) {
  1014. distance = itemDistance;
  1015. nextBlockIndex = enemyBlocks[i];
  1016. }
  1017. }
  1018. if (nextBlockIndex === null) {
  1019. nextBlockIndex = enemyBlocks[0];
  1020. localStorage.setItem('idle-ui-fail-blocks', '[]');
  1021. let number = parseInt(localStorage.getItem("failure"));
  1022. let failure = (isNaN(number) ? 0 : number) + 1;
  1023. localStorage.setItem('failure', failure);
  1024. if ((failure % 3) === 0) {
  1025. if (failure > 1) new Notification('第' + failure + '轮战斗失败');
  1026. }
  1027. if (failure > config.failure) {
  1028. if (config.mapHackType === 'mystery') {
  1029. const level = config.level;
  1030. const userId = $("#cid").val();
  1031. location.href = `/Equipment/Query?id=${userId}&pt=5&et=2147483648&pi2=0&pt2=${level}&et2=2147483648`;
  1032. return;
  1033. } else if (config.infiniteMap) {
  1034. tryReset();
  1035. return
  1036. }
  1037. }
  1038. }
  1039. } else {
  1040. endMove('', false, config.infiniteMap);
  1041. }
  1042. if (nextBlockIndex !== null) {
  1043. clickBlock($(`#${nextBlockIndex}`));
  1044. }
  1045. }
  1046.  
  1047. function clickBlock(block) {
  1048. const width = block.width();
  1049. const height = block.height();
  1050. const rect = document.getElementById(block.attr('id')).getBoundingClientRect();
  1051. const x = Math.round(rect.left + width / 3 + (width / 4 * Math.random(id))) + $(window).scrollLeft();
  1052. const y = Math.round(rect.top + height / 3 + (height / 4 * Math.random(id))) + $(window).scrollTop();
  1053. ajaxMove(block, {pageX: x, pageY: y, originalEvent: {isTrusted: true}});
  1054. }
  1055.  
  1056. function ajaxMove(block, a) {
  1057. const f = block;
  1058. var c = f.parent();
  1059. const g = f.attr("id");
  1060. const k = $("#cid").val();
  1061. const td = localStorage.getItem("t");
  1062. if (f.hasClass("monster")) {
  1063. location.href = "/Battle/InDungeon?id=" + k + "&bid=" + g;
  1064. } else {
  1065. $(".dungeon-layer").show();
  1066. var e = [];
  1067. if (0 < a.pageX && 0 < a.pageY && a.hasOwnProperty("originalEvent") && (a.originalEvent.isTrusted || 1 == a.originalEvent.detail)) {
  1068. e = $(c).offset();
  1069. const h = $(c).width();
  1070. c = $(c).height();
  1071. const l = Math.floor(Math.random() * h);
  1072. e = [a.pageX, l, a.pageY, e.left, h - l, e.top, h, Math.floor(Math.random() * c), c]
  1073. }
  1074. a = {
  1075. id: k,
  1076. bid: g,
  1077. m: e,
  1078. t: td,
  1079. __RequestVerificationToken: $("[name='__RequestVerificationToken']").val()
  1080. };
  1081. $.ajax({
  1082. url: "MoveTo",
  1083. type: "post",
  1084. data: a,
  1085. dataType: "json",
  1086. success: function (a) {
  1087. $.each(a, function (a, b) {
  1088. void 0 == b.id && (b.id = 0);
  1089. a = "";
  1090. 0 == b.d[0] && (a += " top");
  1091. 0 == b.d[1] && (a += " left");
  1092. if (1 == b.m)
  1093. $("#" + b.id).addClass(a);
  1094. else {
  1095. a += " public";
  1096. var c = "";
  1097. 0 < b.mlvl && (c += "Lv" + b.mlvl + " " + b.mname, a = a + " monster " + b.mtype);
  1098. $("#" + b.id).removeClass("mask").addClass(a);
  1099. "" != c && $("#" + b.id).attr("title", c)
  1100. }
  1101. });
  1102. 0 < a.length && ($("#explore").text(parseInt($("#explore").text()) + a.length),
  1103. $("#not-explore").text(parseInt($("#not-explore").text()) - a.length));
  1104. $(".current").removeClass("current");
  1105. f.addClass("current");
  1106. $(".dungeon-layer").hide();
  1107. setTimeout(() => {
  1108. mapMove();
  1109. }, Math.round(config.userNumber * 300));
  1110. },
  1111. error: function (XMLHttpRequest) {
  1112. const responseText = XMLHttpRequest.responseText;
  1113. if (responseText.indexOf('封号') >= 0) {
  1114. addBlockNum();
  1115. }
  1116. endMove(null, true, true);
  1117. $(".dungeon-layer").hide();
  1118. }
  1119. });
  1120. }
  1121. }
  1122.  
  1123. function endMove(notice, retry, reset) {
  1124. if (!reset) {
  1125. map[id] = 'end';
  1126. localStorage.setItem('idle-ui-maphack', JSON.stringify(map));
  1127. }
  1128.  
  1129. if (notice) new Notification(notice);
  1130.  
  1131. if (retry) {
  1132. // 请求异常情况直接刷新界面,暂时注释原来逻辑
  1133. $('#modalAlert').modal('hide');
  1134. setTimeout(function () {
  1135. const userId = $("#cid").val();
  1136. location.href = `../Map/DungeonForEquip?id=${userId}`
  1137. }, Math.round(300));
  1138. } else if (reset) {
  1139. tryReset();
  1140. }
  1141. }
  1142.  
  1143. // 判断是否可以点击
  1144. function canExplore(i) {
  1145. const size = 20;
  1146. const block = $(`#${i}`);
  1147. if (block.hasClass('mask')) return false;
  1148. if ((config.mapHackType === 'all' || config.mapHackType === 'mystery') && block.hasClass('monster')) return true;
  1149. const left = i % size === 0 ? null : $(`#${i - 1}`);
  1150. const right = i % size === (size - 1) ? null : $(`#${i + 1}`);
  1151. const up = i < size ? null : $(`#${i - size}`);
  1152. const down = i >= ((size * size) - size) ? null : $(`#${i + size}`);
  1153. const canMoveLeft = left && left.hasClass('mask') && !block.hasClass('left');
  1154. const canMoveRight = right && right.hasClass('mask') && !right.hasClass('left');
  1155. const canMoveUp = up && up.hasClass('mask') && !block.hasClass('top');
  1156. const canMoveDown = down && down.hasClass('mask') && !down.hasClass('top');
  1157. return canMoveLeft || canMoveRight || canMoveUp || canMoveDown;
  1158. }
  1159. }
  1160.  
  1161. if (location.href.indexOf('Map/Dungeon') === -1) {
  1162. $.ajaxSetup({
  1163. complete: function (XMLHttpRequest) {
  1164. if (!XMLHttpRequest.responseText) return;
  1165. if (XMLHttpRequest.responseText.indexOf('封号') >= 0) {
  1166. addBlockNum();
  1167. location.reload();
  1168. }
  1169. }
  1170. });
  1171. }
  1172.  
  1173. // 战斗界面
  1174. if (config.mapHack && location.href.indexOf('Battle/InDungeon') >= 0) {
  1175.  
  1176. const id = purl().param().id;
  1177. const bid = purl().param().bid - 0;
  1178. if (!id) return;
  1179. let map = localStorage.getItem('idle-ui-maphack');
  1180. if (map) {
  1181. map = JSON.parse(map);
  1182. if (map[id] && map[id] === 'start') {
  1183. const exception = $('.error').length;
  1184. if (exception) {
  1185. setTimeout(() => {
  1186. location.href = `/Map/Dungeon?id=${id}`;
  1187. }, Math.round(Math.random() * 3000));
  1188. return;
  1189. }
  1190.  
  1191. const stopBtn = renderButton('end-hack', '停止自动秘境', 'default');
  1192. $('.btn.btn-xs').eq(1).before(stopBtn);
  1193. $('#end-hack').click(function () {
  1194. map[id] = 'end';
  1195. localStorage.setItem('idle-ui-maphack', JSON.stringify(map));
  1196. alert('自动秘境已停止');
  1197. });
  1198.  
  1199. let waitTime = $('head').text().match(/waitTime:(\d+)/);
  1200. if (waitTime) {
  1201. waitTime = waitTime[1];
  1202. }
  1203. if (waitTime) {
  1204. setTimeout(() => {
  1205. endFight(id);
  1206. }, (waitTime + 1) * 1000);
  1207. } else {
  1208. endFight(id);
  1209. }
  1210. }
  1211. }
  1212.  
  1213. function endFight(dungeonId) {
  1214. const win = $('.turn').first().text().indexOf('战斗胜利') > 0;
  1215. const turns = $('.turn').length - 1;
  1216. let enemys = {};
  1217. $('.battle-char').each(function () {
  1218. const id = $(this).prop('id').split('_')[1];
  1219. if (id < 0) {
  1220. const type = $(this).children().first().children().last().prop('class');
  1221. if (enemys[type]) {
  1222. enemys[type] += 1;
  1223. } else {
  1224. enemys[type] = 1;
  1225. }
  1226. }
  1227. });
  1228. let drops = [];
  1229. $('.turn').first().find('.equip-name').each(function () {
  1230. const type = $(this).clone().prop('class').replace('equip-name', '').trim();
  1231. const name = $(this).text();
  1232. drops.push({type: type, name: name});
  1233. });
  1234. const isBoss = $('.boss').length > 0;
  1235. const battleLog = {time: +new Date(), win, boss: isBoss, turns, enemys, drops};
  1236. addBattleLog(battleLog);
  1237.  
  1238. const bossWin = isBoss && win;
  1239. if (!win) {
  1240. let failedBlocks = localStorage.getItem('idle-ui-fail-blocks');
  1241. failedBlocks = failedBlocks ? JSON.parse(failedBlocks) : [];
  1242. if (failedBlocks.indexOf(bid) === -1) failedBlocks.push(bid);
  1243. localStorage.setItem('idle-ui-fail-blocks', JSON.stringify(failedBlocks));
  1244. } else {
  1245. localStorage.setItem('failure', '0');
  1246. localStorage.setItem('idle-ui-fail-blocks', '[]');
  1247. }
  1248. let timeout = 5;
  1249. if (turns < 50) {
  1250. timeout = 3
  1251. } else if (turns < 100) {
  1252. timeout = 7;
  1253. } else if (turns < 200) {
  1254. timeout = 10;
  1255. }
  1256. setTimeout(() => {
  1257. location.href = `/Map/Dungeon?id=${dungeonId}`;
  1258. }, timeout * 1000);
  1259. }
  1260.  
  1261. function addBattleLog(battleLog) {
  1262. let log = localStorage.getItem('idle-ui-maplog');
  1263. log = log ? JSON.parse(log) : {};
  1264. if (!log[id]) log[id] = [];
  1265. log[id].unshift(battleLog);
  1266. log[id] = log[id].slice(0, 500);
  1267. localStorage.setItem('idle-ui-maplog', JSON.stringify(log));
  1268. }
  1269. }
  1270.  
  1271. if (config.mapHack && location.href.indexOf('Map/Detail') >= 0) {
  1272. const btn = renderButton('idle-ui-maplog', '自动秘境日志');
  1273. $('.btn.btn-xs').eq(1).before(btn);
  1274. let page = 1;
  1275. let log = {};
  1276. let dataSource = [];
  1277. const id = purl().param().id;
  1278. const pageSize = 10;
  1279. let maxPage = 0;
  1280. const modal = `
  1281. <div class="modal fade" id="modalMapLog" tabindex="-1" role="dialog">
  1282. <div class="modal-dialog modal-lg" role="document">
  1283. <div class="modal-content model-inverse">
  1284. <div class="modal-header">
  1285. <span class="modal-title">自动秘境日志</span>
  1286. </div>
  1287. <div class="modal-body">
  1288. <div class="row">
  1289. <div class="col-md-6 col-xs-12">
  1290. <div class="panel-header state">小怪战斗统计</div>
  1291. <p>
  1292. <span>战斗次数:</span><span class="state mr-10" id="idle-ui-creepnum"></span>
  1293. <span>平均回合:</span><span class="state mr-10" id="idle-ui-avgcreepturns"></span>
  1294. <span>胜率:</span><span class="state" id="idle-ui-creepwinrate"></span>
  1295. </p>
  1296. </div>
  1297. <div class="col-md-6 col-xs-12">
  1298. <div class="panel-header state">Boss战斗统计</div>
  1299. <p>
  1300. <span>战斗次数:</span><span class="state mr-10" id="idle-ui-bossnum"></span>
  1301. <span>平均回合:</span><span class="state mr-10" id="idle-ui-avgbossturns"></span>
  1302. <span>胜率:</span><span class="state" id="idle-ui-bosswinrate"></span>
  1303. </p>
  1304. </div>
  1305. </div>
  1306. <div class="panel-header state">
  1307. <span class="mr-10">战斗日志</span>
  1308. <label class="normal" style="font-weight: normal; cursor: pointer;"><input type="checkbox" id="idle-ui-only-boss"/> 只看Boss</label>
  1309. </div>
  1310. <table class="table table-condensed" style="margin-bottom: 10px;">
  1311. <thead><tr><td width="120">时间</td><td width="50">结果</td><td width="60">回合数</td><td width="200">敌人</td><td>掉落</td></tr></thead>
  1312. <tbody id="idle-ui-log-table" class="table-body"></tbody>
  1313. </table>
  1314. <div class="row">
  1315. <div class="col-md-6 col-xs-12" style="text-align: left;">
  1316. <span>共 <span id="idle-ui-log-length">0</span> 条记录</span>
  1317. </div>
  1318. <div class="col-md-6 col-xs-12" style="text-align: right;">
  1319. <span class="mr-10">第 <span id="idle-ui-page">0</span> 页,共 <span id="idle-ui-max-page">0</span> 页</span>
  1320. </div>
  1321. </div>
  1322. </div>
  1323. <div class="modal-footer">
  1324. <div class="row">
  1325. <div class="col-md-6 col-xs-12" style="text-align: left;">
  1326. <button type="button" id="clear-log" class="btn btn-danger btn-xs" style="float: left;">清空日志</button>
  1327. <button type="button" id="idle-ui-reload" class="btn btn-success btn-xs">刷新数据</button>
  1328. </div>
  1329. <div class="col-md-6 col-xs-12" style="text-align: right;">
  1330. <button type="button" id="page-prev" class="btn btn-default btn-xs">上一页</button>
  1331. <button type="button" id="page-next" class="btn btn-default btn-xs">下一页</button>
  1332. <button type="button" class="btn btn-default btn-xs" data-dismiss="modal">关闭</button>
  1333. </div>
  1334. </div>
  1335. </div>
  1336. </div>
  1337. </div>
  1338. </div>
  1339. `;
  1340. $(document.body).append(modal);
  1341.  
  1342. function getBattleLogStats(battleLog) {
  1343. let creepNum = 0;
  1344. let bossNum = 0;
  1345. let creepWin = 0;
  1346. let bossWin = 0;
  1347. let creepTurns = 0;
  1348. let bossTurns = 0;
  1349. battleLog.forEach(item => {
  1350. if (item.boss) {
  1351. bossNum += 1;
  1352. if (item.win) bossWin += 1;
  1353. bossTurns += item.turns;
  1354. } else {
  1355. creepNum += 1;
  1356. if (item.win) creepWin += 1;
  1357. creepTurns += item.turns;
  1358. }
  1359. });
  1360. const avgCreepTurns = creepNum > 0 ? Math.round(creepTurns / creepNum) : 0;
  1361. const avgBossTurns = bossNum > 0 ? Math.round(bossTurns / bossNum) : 0;
  1362. const creepWinRate = creepNum > 0 ? Math.round(creepWin / creepNum * 100) : 0;
  1363. const bossWinRate = bossNum > 0 ? Math.round(bossWin / bossNum * 100) : 0;
  1364. return {creepNum, bossNum, avgCreepTurns, avgBossTurns, creepWinRate, bossWinRate}
  1365. }
  1366.  
  1367. const enemyTypes = {'normal': '普通', 'rare': '稀有', 'super': '精英', 'boss': 'Boss'};
  1368.  
  1369. function renderRows() {
  1370. const start = (page - 1) * pageSize;
  1371. let data = [];
  1372. if ($('#idle-ui-only-boss').prop('checked')) {
  1373. data = dataSource.filter(item => item.boss).slice(start, start + pageSize);
  1374. } else {
  1375. data = dataSource.slice(start, start + pageSize);
  1376. }
  1377. const rows = data.map(item => {
  1378. const date = moment(item.time).format('MM-DD HH:mm:ss');
  1379. const result = item.win ? '<span class="poison">胜利</span>' : '<span class="fire">失败</span>';
  1380. const enemys = Object.keys(item.enemys).map(type => {
  1381. const count = item.enemys[type];
  1382. return `<span class="${type}">${enemyTypes[type]}</span><span class="normal mr-10"> x ${count}</span>`;
  1383. }).join('');
  1384. const drops = item.drops.map(item => {
  1385. return `<span class="${item.type}">${item.name}</span>`;
  1386. }).join('');
  1387. return `<tr><td>${date}</td><td>${result}</td><td>${item.turns}</td><td>${enemys}</td><td>${drops}</td></tr>`;
  1388. }).join('');
  1389. $('#idle-ui-log-table').html(rows);
  1390. if (page === 1) {
  1391. $('#page-prev').prop('disabled', true);
  1392. } else {
  1393. $('#page-prev').prop('disabled', false);
  1394. }
  1395. if (page === maxPage) {
  1396. $('#page-next').prop('disabled', true);
  1397. } else {
  1398. $('#page-next').prop('disabled', false);
  1399. }
  1400. $('#idle-ui-log-length').text(logLength);
  1401. $('#idle-ui-max-page').text(maxPage);
  1402. $('#idle-ui-page').text(page);
  1403. }
  1404.  
  1405. $('#page-prev').click(function () {
  1406. page = page - 1;
  1407. renderRows();
  1408. });
  1409.  
  1410. $('#page-next').click(function () {
  1411. page = page + 1;
  1412. renderRows();
  1413. });
  1414.  
  1415. $('#idle-ui-only-boss').change(function () {
  1416. page = 1;
  1417. getLengthAndMaxPage();
  1418. renderRows();
  1419. });
  1420.  
  1421. $('#clear-log').click(function () {
  1422. log[id] = [];
  1423. localStorage.setItem('idle-ui-maplog', JSON.stringify(log));
  1424. location.reload();
  1425. });
  1426.  
  1427. function getLengthAndMaxPage() {
  1428. const checked = $('#idle-ui-only-boss').prop('checked');
  1429. logLength = checked ? dataSource.filter(item => item.boss).length : dataSource.length;
  1430. maxPage = Math.ceil(logLength / pageSize);
  1431. }
  1432.  
  1433. function reloadLog() {
  1434. log = localStorage.getItem('idle-ui-maplog');
  1435. log = log ? JSON.parse(log) : {};
  1436. dataSource = log[id] || [];
  1437. getLengthAndMaxPage();
  1438. const stats = getBattleLogStats(dataSource);
  1439. $('#idle-ui-creepnum').text(stats.creepNum);
  1440. $('#idle-ui-avgcreepturns').text(stats.avgCreepTurns);
  1441. $('#idle-ui-creepwinrate').text(`${stats.creepWinRate}%`);
  1442. $('#idle-ui-bossnum').text(stats.bossNum);
  1443. $('#idle-ui-avgbossturns').text(stats.avgBossTurns);
  1444. $('#idle-ui-bosswinrate').text(`${stats.bossWinRate}%`);
  1445. page = 1;
  1446. renderRows();
  1447. }
  1448.  
  1449. $('#idle-ui-reload').click(function () {
  1450. reloadLog();
  1451. });
  1452.  
  1453. $('#idle-ui-maplog').click(function () {
  1454. reloadLog();
  1455. $('#modalMapLog').modal('show');
  1456. });
  1457. }
  1458.  
  1459. if (config.showSetAttr) {
  1460. loadSetAttr();
  1461.  
  1462. function loadSetAttr() {
  1463. if (!$('.equip-content > .equip > .set').length) return;
  1464. const setDB = localStorage.getItem('idle-ui-set-db');
  1465. const newSetDB = localStorage.getItem('idle-ui-set-db-new');
  1466. if (setDB && newSetDB) {
  1467. const JSONSetDB = JSON.parse(setDB);
  1468. const JSONNewSetDB = JSON.parse(newSetDB);
  1469. $('.equip-content > .equip > .set').each(function () {
  1470. const content = $(this).parent();
  1471. const itemName = content.children().first().text().replace(/\(\d+\)/g, '');
  1472. const singleData = JSONSetDB.singleData[itemName];
  1473. const existSingLeNum = content.children('.set').length - 1;
  1474. if (singleData && singleData.length > existSingLeNum) {
  1475. const singleContent = singleData.slice(existSingLeNum).map(item => {
  1476. return `<p class="set idle-ui-set-single">${item}</p>`;
  1477. }).join('');
  1478. content.children('.unique').before(singleContent);
  1479. }
  1480. const fullContent = content.children('.unique');
  1481. const existFullNum = fullContent.children('p[class!="set"][class!="require"]').length - 1;
  1482. const setName = fullContent.children('br').last().next().text().replace(/\(\d+\)/g, '');
  1483. var fullData = JSONSetDB.setData[setName];
  1484. if (!fullData) {
  1485. fullData = JSONNewSetDB.setData[setName];
  1486. }
  1487. let setContent = fullData.slice(existFullNum).map(item => {
  1488. return `<p class="idle-ui-set-full">${item}</p>`;
  1489. }).join('');
  1490. if (fullContent.children('br').length === 1) setContent = '<br>' + setContent;
  1491. fullContent.children('br').last().before(setContent);
  1492. });
  1493. }
  1494. }
  1495.  
  1496. function parseSetHtml(html) {
  1497. $(".footer").before(`<div style="display: none;" id="set-data">${html}</div>`);
  1498. const singleData = {};
  1499. const setData = {};
  1500. $('#set-data .masonry-item .panel-body .equip').each(function () {
  1501. const lines = $(this).children();
  1502. const itemName = lines.first().text().replace(/\(\d+\)/, '');
  1503. const singleLines = [];
  1504. lines.each(function (index) {
  1505. const line = $(this);
  1506. if (index > 0 && line.hasClass('set')) {
  1507. singleLines.push(line.text().replace(/\n/g, ''));
  1508. }
  1509. if (line.hasClass('unique')) {
  1510. const setItems = line.children();
  1511. let stop = false;
  1512. const setLines = [];
  1513. let setName = '';
  1514. setItems.each(function (index) {
  1515. if (index > 0) {
  1516. if ($(this).prop('tagName').toLowerCase() === 'br') {
  1517. stop = true;
  1518. setName = $(this).next().text();
  1519. }
  1520. if (!stop) setLines.push($(this).text().replace(/\n/g, ''));
  1521. }
  1522. });
  1523. if (!setData[setName]) setData[setName] = setLines;
  1524. }
  1525. });
  1526. if (singleLines.length) singleData[itemName] = singleLines;
  1527. });
  1528. return {singleData, setData};
  1529. }
  1530. }
  1531.  
  1532. if (location.href.indexOf('Auction/Query') >= 0 && location.href.indexOf('Auction/QueryBid') === -1) {
  1533. if (config.showAuctionNote) {
  1534. $('.physical.equip-des').each(function () {
  1535. const note = $(this).text();
  1536. const label = $(this).parent().parent().prev().children('.equip-name').last();
  1537. label.after(`<span style="color: #fff;"> ${note}</span>`);
  1538. });
  1539. }
  1540.  
  1541. // if (config.auctionWatch) {
  1542. // let watchList = [];
  1543. //
  1544. // function renderTable(params) {
  1545. // const list = localStorage.getItem('idle-ui-auction');
  1546. // watchList = (list ? JSON.parse(list) : []) || [];
  1547. // const rows = watchList.map((item, index) => {
  1548. // 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>`;
  1549. // });
  1550. // $('#modalAuction .table-body').html(rows);
  1551. // $('.delete-auction').click(function () {
  1552. // const index = $(this).data('index');
  1553. // watchList.splice(index, 1);
  1554. // localStorage.setItem('idle-ui-auction', JSON.stringify(watchList));
  1555. // renderTable();
  1556. // });
  1557. // renderNewItems();
  1558. // }
  1559. //
  1560. // function renderNewItems() {
  1561. // const ids = purl().param().items;
  1562. // if (!ids) return;
  1563. // ids.split(',').map(id => {
  1564. // $(`span[data-id="${id}"`).parent().addClass('idle-ui-new-item');
  1565. // });
  1566. // }
  1567. //
  1568. // const link = '<button id="open-auction-modal" type="button" class="btn btn-xs btn-success" style="margin-right: 10px;">特别关注</button>';
  1569. // $('.btn-group').eq(1).before(link);
  1570. // const categorys = [];
  1571. // $('.panel-heading .btn-group button.dropdown-toggle').each(function () {
  1572. // categorys.push($(this).text().replace('<span class="caret"></span>', '').replace(/\s/g, ''));
  1573. // });
  1574. // const category = categorys.join(' - ');
  1575. //
  1576. // const modal = `
  1577. // <div class="modal fade" id="modalAuction" style="display: none;">
  1578. // <div class="modal-dialog modal-large" role="">
  1579. // <div class="modal-content model-inverse">
  1580. // <div class="modal-header">
  1581. // <span class="modal-title">拍卖行特别关注</span>
  1582. // </div>
  1583. // <div class="modal-body">
  1584. // <div class="panel-header state">已有关注项目</div>
  1585. // <table class="table table-condensed">
  1586. // <thead><tr><td>筛选条件</td><td>装备名称</td><td>操作</td></tr></thead>
  1587. // <tbody class="table-body"></tbody>
  1588. // </table>
  1589. // <div class="panel-header state">添加新项目</div>
  1590. // <div class="form">
  1591. // <div class="form-group">
  1592. // <label>筛选条件</label>
  1593. // <p class="form-control-static" style="color: #fff;">${category}</p>
  1594. // </div>
  1595. // <div class="form-group">
  1596. // <label>装备名称</label>
  1597. // <input type="text" id="auction-name" class="form-control hit-input" style="width: 100%;">
  1598. // </div>
  1599. // <button type="button" class="btn btn-success btn-xs" id="add-auction">新增</button>
  1600. // </div>
  1601. // </div>
  1602. // <div class="modal-footer">
  1603. // <button type="button" class="btn btn-default btn-xs" data-dismiss="modal">关闭</button>
  1604. // </div>
  1605. // </div>
  1606. // </div>
  1607. // </div>
  1608. // `;
  1609. // $(document.body).append(modal);
  1610. // renderTable();
  1611. // $('#open-auction-modal').click(function () {
  1612. // if ($('.equip-name').length) {
  1613. // $('#auction-name').val($('.equip-name').eq(0).text().replace('【', '').replace('】', ''));
  1614. // }
  1615. // $('#modalAuction').modal('show');
  1616. // });
  1617. //
  1618. // $('#add-auction').click(function () {
  1619. // if (watchList.length >= 10) {
  1620. // alert('最多关注10条');
  1621. // return;
  1622. // }
  1623. // const params = purl().param();
  1624. // const et = params.et || '';
  1625. // const pt = params.pt || '';
  1626. // const ei = params.ei || '';
  1627. // const link = `et=${et}&pt=${pt}&ei=${ei}`;
  1628. // const name = $('#auction-name').val();
  1629. // const items = [];
  1630. // $('.equip-name').each(function () {
  1631. // const curName = $(this).text().replace('【', '').replace('】', '');
  1632. // if (curName === name) {
  1633. // const id = $(this).parent().children().last().data('id');
  1634. // items.push(id);
  1635. // }
  1636. // });
  1637. // const data = {
  1638. // category: category,
  1639. // name: $('#auction-name').val(),
  1640. // link: link,
  1641. // items: items
  1642. // };
  1643. // watchList.push(data);
  1644. // localStorage.setItem('idle-ui-auction', JSON.stringify(watchList));
  1645. // renderTable();
  1646. // });
  1647. // }1
  1648. }
  1649.  
  1650. if (config.magical && location.href.indexOf('Equipment/Query') >= 0) {
  1651. let map = localStorage.getItem('idle-ui-maphack');
  1652. if (map) {
  1653. map = JSON.parse(map);
  1654. } else {
  1655. map = {};
  1656. }
  1657. const cid = $("#cid").val();
  1658.  
  1659. const magicalStart = '<button class="btn btn-xs btn-default" id="start-magical">一键升蓝</button>';
  1660. const magicalEnd = '<button class="btn btn-xs btn-default" id="end-magical">停止升蓝</button>';
  1661.  
  1662. // 是否一键升蓝
  1663. const magical = map[`magical${cid}`];
  1664. const panel = $('.panel-footer .btn.btn-xs.btn-warning');
  1665. panel.eq(panel.length - 1).before(magicalStart);
  1666. if ((magical) && magical === 'start') {
  1667. panel.eq(panel.length - 1).before(magicalEnd);
  1668. }
  1669.  
  1670. $('#start-magical').click(function (params) {
  1671. map[`magical${cid}`] = 'start';
  1672. localStorage.setItem('idle-ui-maphack', JSON.stringify(map));
  1673. // startMagical();
  1674. // 重定向到过滤为白色秘境的界面去
  1675. const level = '0';
  1676. const userId = $("#cid").val();
  1677. location.href = `/Equipment/Query?id=${userId}&pt=${level}&et=2147483648&pi2=0&pt2=${level}&et2=2147483648`;
  1678. });
  1679.  
  1680. $('#end-magical').click(function (params) {
  1681. map[`magical${cid}`] = 'end';
  1682. localStorage.setItem('idle-ui-maphack', JSON.stringify(map));
  1683. location.reload();
  1684. });
  1685.  
  1686. // 设置点击对应的点击事件
  1687. function startMagical() {
  1688. const magicalId = $(".base.equip-name").eq(0).data('id');
  1689. if (!magicalId) {
  1690. map[`magical${cid}`] = 'end';
  1691. localStorage.setItem('idle-ui-maphack', JSON.stringify(map));
  1692. alert('没有普通秘境,已停止自动升级');
  1693. return;
  1694. }
  1695. map[`magical${cid}`] = 'start';
  1696. a = {
  1697. id: cid,
  1698. cid: cid,
  1699. eid: magicalId,
  1700. type: '0',
  1701. __RequestVerificationToken: $("[name='__RequestVerificationToken']").val(),
  1702. };
  1703.  
  1704. $.ajax({
  1705. //几个参数需要注意一下
  1706. type: "POST",//方法类型
  1707. dataType: "html",//预期服务器返回的数据类型
  1708. url: "EquipReform",//url
  1709. data: a,
  1710. success: function (result) {
  1711. location.reload()
  1712. },
  1713. error: function (XMLHttpRequest, textStatus) {
  1714. map[`magical${cid}`] = 'end';
  1715. alert("发生错误,请检查是否材料不够,或者不够改造等级")
  1716. }
  1717. });
  1718. }
  1719.  
  1720. if (magical && magical === 'start') {
  1721. setTimeout(() => {
  1722. if ((magical) && magical === 'start') {
  1723. startMagical()
  1724. }
  1725. }, config.moveTime);
  1726. }
  1727. }
  1728.  
  1729. if (config.oneKeyEquip && location.href.indexOf('Equipment/Query') >= 0) {
  1730. const btn = '<button type="button" class="btn btn-xs btn-success mr-10" id="show-one-key-equip">一键换装</button>';
  1731. const cname = '<input style="height: 22px;background: black; border: solid 1px #322a20; width: 180px; text-indent: 3px" class="move-name" placeholder="转移ID"/>';
  1732. const startMetastasis = '<button class="btn btn-xs btn-default" id="start-metastasis">一键转移</button>';
  1733. const stopMetastasis = '<button class="btn btn-xs btn-default" id="end-metastasis">停止转移</button>';
  1734.  
  1735. const start = '<button class="btn btn-xs btn-default" id="start-mystery">开始扫荡秘境</button>';
  1736. const end = '<button class="btn btn-xs btn-default" id="end-mystery">停止扫荡</button>';
  1737. $('.panel-heading .btn').eq(0).before(btn);
  1738. $('.panel-heading .btn').eq(0).before(cname);
  1739. let map = localStorage.getItem('idle-ui-maphack');
  1740. if (map) {
  1741. map = JSON.parse(map);
  1742. } else {
  1743. map = {};
  1744. }
  1745. const cid = $("#cid").val();
  1746. var mysteryIndex = 5;
  1747.  
  1748. // 是否一键转移
  1749. const metastasis = map[`metastasis${cid}`];
  1750. // 要转移人的姓名
  1751. const name = map[`cname${cid}`];
  1752.  
  1753. if (name) {
  1754. $('.move-name').val(name);
  1755. }
  1756. if ((metastasis) && metastasis === 'start') {
  1757. $('.panel-heading .btn').eq(0).before(stopMetastasis);
  1758. mysteryIndex = 6;
  1759. }
  1760.  
  1761. $('#end-metastasis').click(function (params) {
  1762. map[`metastasis${cid}`] = 'end';
  1763. map[`cname${cid}`] = "";
  1764. localStorage.setItem('idle-ui-maphack', JSON.stringify(map));
  1765. location.reload();
  1766. });
  1767.  
  1768. $('.panel-heading .btn').eq(0).before(startMetastasis);
  1769. $('#start-metastasis').click(function (params) {
  1770. map[`metastasis${cid}`] = 'start';
  1771. map[`cname${cid}`] = $('.move-name').val();
  1772. localStorage.setItem('idle-ui-maphack', JSON.stringify(map));
  1773. moveMystery();
  1774. });
  1775.  
  1776. function moveMystery() {
  1777. const mysteryId = $(".selected").children(":first").next().next().next().data('id');
  1778. if (!mysteryId) {
  1779. map[`metastasis${cid}`] = 'end';
  1780. localStorage.setItem('idle-ui-maphack', JSON.stringify(map));
  1781. alert('没有物品被选中,已停止');
  1782. return;
  1783. }
  1784. a = {
  1785. cid: cid,
  1786. eid: mysteryId,
  1787. cname: map[`cname${cid}`],
  1788. __RequestVerificationToken: $("[name='__RequestVerificationToken']").val(),
  1789. };
  1790.  
  1791. $.ajax({
  1792. //几个参数需要注意一下
  1793. type: "POST",//方法类型
  1794. dataType: "html",//预期服务器返回的数据类型
  1795. url: 'EquipTrade',//url
  1796. data: a,
  1797. success: function (result) {
  1798. location.reload()
  1799. },
  1800. error: function (result) {
  1801. alert(result)
  1802. }
  1803. });
  1804. }
  1805.  
  1806. if (metastasis && metastasis === 'start') {
  1807. setTimeout(() => {
  1808. if ((metastasis) && metastasis === 'start') {
  1809. moveMystery()
  1810. }
  1811. }, config.moveTime);
  1812. }
  1813.  
  1814.  
  1815. // 开始扫荡秘境了,就显示停止扫荡按钮
  1816. const mystery = map[`mystery${cid}`];
  1817. if ((mystery) && mystery === 'start') {
  1818. $('.panel-heading .btn').eq(mysteryIndex).before(end);
  1819. $('#end-mystery').click(function (params) {
  1820. alert('已停止扫荡秘境');
  1821. map[`mystery${cid}`] = 'end';
  1822. localStorage.setItem('idle-ui-maphack', JSON.stringify(map));
  1823. });
  1824. }
  1825. $('.panel-heading .btn').eq(mysteryIndex).before(start);
  1826.  
  1827. $('#start-mystery').click(function (params) {
  1828. map[`mystery${cid}`] = 'start';
  1829. localStorage.setItem('idle-ui-maphack', JSON.stringify(map));
  1830. startMystery();
  1831. });
  1832.  
  1833. function startMystery() {
  1834. const mysteryId = $(".selected").children(":first").next().next().next().data('id');
  1835. if (!mysteryId) {
  1836. map[cid] = 'end';
  1837. localStorage.setItem('idle-ui-maphack', JSON.stringify(map));
  1838. alert('没有物品被选中,或使用等级不够,已停止');
  1839. return;
  1840. }
  1841. map[cid] = 'start';
  1842. a = {
  1843. id: cid,
  1844. cid: cid,
  1845. eid: mysteryId,
  1846. __RequestVerificationToken: $("[name='__RequestVerificationToken']").val(),
  1847. };
  1848.  
  1849. $.ajax({
  1850. //几个参数需要注意一下
  1851. type: "POST",//方法类型
  1852. dataType: "html",//预期服务器返回的数据类型
  1853. url: "EquipDungeon",//url
  1854. data: a,
  1855. success: function (result) {
  1856. // 请求成功,返回网页,自动跳转到秘境界面
  1857. location.href = `../Map/DungeonForEquip?id=${userId}`
  1858. },
  1859. error: function (XMLHttpRequest, textStatus) {
  1860. alert(XMLHttpRequest)
  1861. }
  1862. });
  1863. }
  1864.  
  1865. if (mystery && mystery === 'start') {
  1866. setTimeout(() => {
  1867. if ((mystery) && mystery === 'start') {
  1868. startMystery()
  1869. }
  1870. }, 15000);
  1871. }
  1872.  
  1873. const equipList = ['主手', '副手', '头盔', '护符', '项链', '戒指', '戒指', '衣服', '腰带', '手套', '靴子'];
  1874. let buildMap = {};
  1875. let buildData = [];
  1876. const userId = purl().param().id;
  1877. const equipItems = getEquipItems();
  1878.  
  1879. function loadEquipBuild() {
  1880. buildMap = JSON.parse(localStorage.getItem('idle-ui-equip-build') || '{}');
  1881. buildData = buildMap[userId] || [];
  1882. }
  1883.  
  1884. function saveEquipBuild(data) {
  1885. localStorage.setItem('idle-ui-equip-build', JSON.stringify(data));
  1886. loadEquipBuild();
  1887. renderEquip();
  1888. }
  1889.  
  1890. function renderEquip(buildIndex) {
  1891. if (!buildIndex && buildData.length) buildIndex = 0;
  1892. const data = buildData[buildIndex] || {};
  1893. const equipContent = equipList.map((item, index) => {
  1894. const equipItem = data.items ? data.items[index] : {};
  1895. return `<p><span>${item}</span><span class="${equipItem.type || ''}">${equipItem.name || ''}</span></p>`;
  1896. });
  1897. const firstCol = equipContent.slice(0, 4).join('');
  1898. const secondCol = equipContent.slice(4, 7).join('');
  1899. const thirdCol = equipContent.slice(7).join('');
  1900. 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>`;
  1901. $('#equip-build-content').html(content);
  1902.  
  1903. // 一键换装
  1904. const buildTags = buildData.map((item, index) => {
  1905. return `<li><a class="physical equip-build-option" href="#" data-index="${index}">${item.name}</a></li>`;
  1906. }).join('');
  1907. $('#equip-build-tags').html(buildTags);
  1908. $('#selected-build-name').text(data.name || '选择方案');
  1909. if (buildIndex !== undefined) {
  1910. $('#use-equip-build').data('index', buildIndex);
  1911. $('#del-equip-build').data('index', buildIndex);
  1912. } else {
  1913. $('#use-equip-build').data('index', -1);
  1914. $('#del-equip-build').data('index', -1);
  1915. }
  1916. $('.equip-build-option').click(function (e) {
  1917. e.preventDefault();
  1918. const index = $(this).data('index');
  1919. renderEquip(index);
  1920. });
  1921. }
  1922.  
  1923. const modal = `
  1924. <div class="modal fade" id="modalEquipBuild" style="display: none;">
  1925. <div class="modal-dialog modal-large" role="" style="width: 800px;">
  1926. <div class="modal-content model-inverse">
  1927. <div class="modal-header">
  1928. <span class="modal-title">一键换装</span>
  1929. </div>
  1930. <div class="modal-body">
  1931. <div class="panel-header state">
  1932. <span>已有装备方案:</span>
  1933. <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>
  1934. </div>
  1935. <div class="row" id="equip-build-content"></div>
  1936. <button type="button" class="btn btn-success btn-xs mr-10" id="use-equip-build">使用本方案</button>
  1937. <button type="button" class="btn btn-danger btn-xs" id="del-equip-build">删除本方案</button>
  1938. <div id="processing" style="display:none; margin-top: 10px;"><i class="glyphicon glyphicon-refresh"></i> 处理中...</div>
  1939. <div class="panel-header state" style="margin-top: 10px;">保存当前装备到新方案</div>
  1940. <div class="form">
  1941. <div class="form-group">
  1942. <label>方案名称</label>
  1943. <input type="text" id="equip-build-name" class="form-control hit-input" style="width: 100%;">
  1944. </div>
  1945. <button type="button" class="btn btn-success btn-xs" id="add-equip-build">保存</button>
  1946. </div>
  1947. </div>
  1948. <div class="modal-footer">
  1949. <button type="button" class="btn btn-default btn-xs" data-dismiss="modal">关闭</button>
  1950. </div>
  1951. </div>
  1952. </div>
  1953. </div>
  1954. `;
  1955. $(document.body).append(modal);
  1956. loadEquipBuild();
  1957. renderEquip();
  1958. $('#show-one-key-equip').click(function () {
  1959. $('#modalEquipBuild').modal('show');
  1960. });
  1961.  
  1962. let processing = false;
  1963.  
  1964. function doEquip(buildIndex, itemIndex) {
  1965. if (blockData.num >= 9) {
  1966. alert('封号打击次数过多,禁止一键换装');
  1967. location.reload();
  1968. }
  1969. if (itemIndex > equipItems.length - 1) {
  1970. setTimeout(() => {
  1971. processing = false;
  1972. $('#processing').hide();
  1973. location.reload();
  1974. }, 500);
  1975. return;
  1976. }
  1977. const list = $('#form').serializeArray();
  1978. const params = {};
  1979. list.forEach(item => {
  1980. params[item.name] = item.value;
  1981. });
  1982. params.eid = buildData[buildIndex].items[itemIndex].id;
  1983. params.cid = userId;
  1984. // 判断当前要替换的装备是否已经装备
  1985. const itemAlreadyEquiped = equipItems.some(item => item.id === params.eid);
  1986. if (!params.eid || !params.cid) return;
  1987. const name = buildData[buildIndex].items[itemIndex].name;
  1988.  
  1989. if (itemAlreadyEquiped) {
  1990. // 已经装备,进入下一件装备
  1991. doEquip(buildIndex, itemIndex + 1);
  1992. } else {
  1993. // 没有装备,还是进行替换
  1994. $.post('/Equipment/EquipOn', params, function (data) {
  1995. setTimeout(function () {
  1996. doEquip(buildIndex, itemIndex + 1);
  1997. }, 1000);
  1998. }).fail(function (data) {
  1999. setTimeout(function () {
  2000. doEquip(buildIndex, itemIndex + 1);
  2001. }, 1000);
  2002. });
  2003. }
  2004. }
  2005.  
  2006. $('#use-equip-build').click(function () {
  2007. if (processing) return;
  2008. const index = $(this).data('index');
  2009. if (index >= 0) {
  2010. processing = true;
  2011. $('#processing').show();
  2012. doEquip(index, 0);
  2013. } else {
  2014. alert('请先选择一个方案');
  2015. }
  2016. });
  2017.  
  2018. $('#del-equip-build').click(function () {
  2019. const index = $(this).data('index');
  2020. if (index >= 0) {
  2021. buildData.splice(index, 1);
  2022. buildMap[userId] = buildData;
  2023. saveEquipBuild(buildMap);
  2024. } else {
  2025. alert('请先选择一个方案');
  2026. }
  2027. });
  2028.  
  2029. function getEquipItems() {
  2030. const items = [];
  2031. $('.panel-body').eq(0).find('.equip-content').each(function () {
  2032. const label = $(this).prev().children('.equip-name').eq(0);
  2033. if (label.length) {
  2034. const name = label.text();
  2035. const type = label.prop('class').replace('equip-name', '').trim();
  2036. const id = label.parent().children().last().data('id');
  2037. items.push({name: name, type: type, id: id});
  2038. } else {
  2039. items.push({name: '', type: '', id: 0});
  2040. }
  2041. });
  2042. return items;
  2043. }
  2044.  
  2045. $('#add-equip-build').click(function () {
  2046. if (buildData.length >= 5) {
  2047. alert('同一角色最多保存5套方案');
  2048. return;
  2049. }
  2050. const name = $('#equip-build-name').val();
  2051. if (!name) {
  2052. alert('方案必须有一个名称');
  2053. return;
  2054. }
  2055. const newBuild = {
  2056. name: name,
  2057. items: equipItems
  2058. };
  2059. buildData.push(newBuild);
  2060. buildMap[userId] = buildData;
  2061. saveEquipBuild(buildMap);
  2062. });
  2063. }
  2064.  
  2065. if (config.oneKeyAgree && location.href.indexOf('Notice/Query') >= 0) {
  2066. let map = localStorage.getItem('idle-ui-maphack');
  2067. if (map) {
  2068. map = JSON.parse(map);
  2069. } else {
  2070. map = {};
  2071. }
  2072. // 所有消息的数量
  2073. const allCount = $('.badge').eq(0).text();
  2074.  
  2075. let processing = false;
  2076. const agreeList = [];
  2077. $('.notice-yes').each(function () {
  2078. agreeList.push($(this).data('id'));
  2079. });
  2080.  
  2081. function doAgree(index) {
  2082. if (blockData.num >= 9) {
  2083. alert('封号打击次数过多,禁止一键同意');
  2084. location.reload();
  2085. }
  2086. if (index > agreeList.length - 1) {
  2087. $('#processing').hide();
  2088. processing = false;
  2089.  
  2090. if ( map[`agree${cid}`] && map[`agree${cid}`] === 'start' && allCount > 0) {
  2091. // 获得当前页面的第几页数据,然后+1
  2092. var number = getUrlParam('pi');
  2093. if (number > 0) {
  2094. number = Number(number) + 1;
  2095. } else {
  2096. number = 1;
  2097. }
  2098. // 跳转到下一页
  2099. location.href = `/Notice/Query?pi=${number}&pi2=0`;
  2100. return;
  2101. } else {
  2102. map[`agree${cid}`] = 'end';
  2103. localStorage.setItem('idle-ui-maphack', JSON.stringify(map));
  2104. location.reload();
  2105. return;
  2106. }
  2107. }
  2108. const id = agreeList[index];
  2109. const list = $('#form').serializeArray();
  2110. const params = {
  2111. contentType: false,
  2112. processData: false,
  2113. };
  2114. list.forEach(item => {
  2115. params[item.name] = item.value;
  2116. });
  2117. params.nid = id;
  2118. $.post('/Notice/NoticeYes', params, function () {
  2119. setTimeout(function () {
  2120. location.reload();
  2121. }, config.agreedTime );
  2122. }).fail(function (data) {
  2123. alert("发生异常");
  2124. setTimeout(function () {
  2125. location.reload();
  2126. }, config.agreedTime);
  2127. });
  2128. }
  2129.  
  2130. function getUrlParam(paraName) {
  2131. const url = document.location.toString();
  2132. const arrObj = url.split("?");
  2133.  
  2134. if (arrObj.length > 1) {
  2135. const arrPara = arrObj[1].split("&");
  2136. var arr;
  2137.  
  2138. for (var i = 0; i < arrPara.length; i++) {
  2139. arr = arrPara[i].split("=");
  2140. if (arr != null && arr[0] == paraName) {
  2141. return arr[1];
  2142. }
  2143. }
  2144. return "";
  2145. }
  2146. else {
  2147. return "";
  2148. }
  2149. }
  2150.  
  2151. const def = $('a.btn.btn-xs.btn-default');
  2152. let all = renderProcessing();
  2153. all += renderButton('idle-ui-agree-all', '同意所有');
  2154. def.eq(0).before(all);
  2155. $('#idle-ui-agree-all').click(function () {
  2156. // 终止转移
  2157. map[`agree${cid}`] = 'start';
  2158. localStorage.setItem('idle-ui-maphack', JSON.stringify(map));
  2159. agreeMessage();
  2160. });
  2161.  
  2162. if ( map[`agree${cid}`] && map[`agree${cid}`] === 'start') {
  2163. let stop = renderProcessing();
  2164. stop += renderButton('idle-ui-agree-stop', '停止同意');
  2165. def.eq(0).before(stop);
  2166.  
  2167. $('#idle-ui-agree-stop').click(function () {
  2168. // 终止转移
  2169. map[`agree${cid}`] = 'stop';
  2170. localStorage.setItem('idle-ui-maphack', JSON.stringify(map));
  2171. location.reload();
  2172. });
  2173. if (allCount > 0) {
  2174. setTimeout(function () {
  2175. agreeMessage();
  2176. }, 500);
  2177. } else {
  2178. // 终止转移
  2179. map[`agree${cid}`] = 'end';
  2180. localStorage.setItem('idle-ui-maphack', JSON.stringify(map));
  2181. }
  2182. }
  2183.  
  2184. function agreeMessage() {
  2185. if (processing) return;
  2186. if (agreeList.length || allCount > 0) {
  2187. $('#processing').show();
  2188. processing = true;
  2189. doAgree(0);
  2190. } else {
  2191. alert('没有可处理的消息');
  2192. }
  2193. }
  2194. }
  2195.  
  2196. if (config.oneKeyRune && location.href.indexOf('Equipment/Material') >= 0) {
  2197. let processing = false;
  2198. const runeList = [];
  2199. $('.artifact.equip-name').each(function () {
  2200. const count = $(this).next().next().text() - 0;
  2201. if (count > 0) {
  2202. const rune = {
  2203. id: $(this).next().next().next().data('id') - 0,
  2204. count: count
  2205. };
  2206. runeList.push(rune);
  2207. }
  2208. });
  2209.  
  2210. $('.equip-name').each(function () {
  2211. const count = $(this).next().next().text() - 0;
  2212. if (count > 0) {
  2213. const rune = {
  2214. id: $(this).next().next().next().data('id') - 0,
  2215. count: count
  2216. };
  2217. runeList.push(rune);
  2218. }
  2219. });
  2220.  
  2221. function doMoveRune(index, cname) {
  2222. if (blockData.num >= 9) {
  2223. alert('封号打击次数过多,禁止一键符文转移');
  2224. location.reload();
  2225. }
  2226. if (index > runeList.length - 1) {
  2227. $('#processing').hide();
  2228. processing = false;
  2229. location.reload();
  2230. return;
  2231. }
  2232. const rune = runeList[index];
  2233. const list = $('#form').serializeArray();
  2234. const params = {};
  2235. list.forEach(item => {
  2236. params[item.name] = item.value;
  2237. });
  2238. params.cname = cname;
  2239. params.count = rune.count;
  2240. params.rune = rune.id;
  2241. $.post('/Equipment/RuneTrade', params, function () {
  2242. setTimeout(function () {
  2243. doMoveRune(index + 1, cname);
  2244. }, 300);
  2245. }).fail(function (data) {
  2246. alert("发生异常,请检查角色名是否正确");
  2247. location.reload();
  2248. });
  2249. }
  2250.  
  2251. $('.btn.btn-xs.btn-default').eq(1).before(renderButton('idle-ui-show-rune', '转移全部符文'));
  2252. $('#idle-ui-show-rune').click(function () {
  2253. $('#modalMoveRune').modal('show');
  2254. });
  2255. const spinner = renderProcessing();
  2256. const modal = `
  2257. <div class="modal fade" id="modalMoveRune" tabindex="-1" role="dialog">
  2258. <div class="modal-dialog modal-sm" role="document">
  2259. <div class="modal-content model-inverse">
  2260. <div class="modal-header">
  2261. <span class="modal-title">转移全部符文</span>
  2262. </div>
  2263. <div class="modal-body">
  2264. <div class="form-group">
  2265. <label for="charName" class="control-label">交易角色:</label>
  2266. <input type="text" class="form-control" id="idle-ui-cname" name="charName" placeholder="请输入角色名称">
  2267. </div>
  2268. </div>
  2269. <div class="modal-footer">
  2270. ${spinner}
  2271. <button type="button" class="btn btn-primary btn-xs" id="idle-ui-move-rune">提交</button>
  2272. <button type="button" class="btn btn-default btn-xs" data-dismiss="modal">关闭</button>
  2273. </div>
  2274. </div>
  2275. </div>
  2276. </div>
  2277. `;
  2278. $(document.body).append(modal);
  2279. $('#idle-ui-move-rune').click(function () {
  2280. if (processing) return;
  2281. if (runeList.length) {
  2282. const cname = $('#idle-ui-cname').val();
  2283. if (!cname) {
  2284. alert('请输入角色名称');
  2285. } else {
  2286. processing = true;
  2287. $('#processing').show();
  2288. doMoveRune(0, cname);
  2289. }
  2290. } else {
  2291. alert('没有转移的符文');
  2292. }
  2293. });
  2294. }
  2295.  
  2296. if (config.showRuneTip) {
  2297. let runeList = [];
  2298. const runeData = localStorage.getItem('idle-ui-rune-db');
  2299. if (runeData) {
  2300. runeList = JSON.parse(runeData);
  2301. } else {
  2302. fetchRuneTip();
  2303. }
  2304.  
  2305. if (location.href.indexOf('Equipment/Inlay') >= 0) {
  2306. const footer = `
  2307. <div class="panel-footer">
  2308. <input class="panel-filter hidden-xs filter-input" id="panel-filter-runeword" placeholder="搜索符文之语">
  2309. <span id="runeword-content"></span>
  2310. </div>
  2311. `;
  2312. $('.panel').eq(0).append(footer);
  2313. let timer = null;
  2314. $('#panel-filter-runeword').keyup(function () {
  2315. if (timer) {
  2316. clearTimeout(timer);
  2317. timer = null;
  2318. }
  2319. timer = setTimeout(() => {
  2320. const name = $(this).val();
  2321. const filtered = name ? runeList.filter(item => item.name.indexOf(name) >= 0) : [];
  2322. let ret = '';
  2323. if (filtered.length) {
  2324. const item = filtered[0];
  2325. const recipe = item.recipe.map(item => {
  2326. return `<span class="artifact">${item}</span>`
  2327. }).join(' + ');
  2328. ret = `<span><span class="artifact equip-name">【${item.name}】</span>:<span>${recipe}</span></span>`;
  2329. const requireContent = item.require.map(item => {
  2330. return `<p><span class="equip-label">${item}</span></p>`;
  2331. }).join('');
  2332. const attrContent = item.attr.map(item => {
  2333. return `<p>${item}</p>`;
  2334. }).join('');
  2335. const tip = `<div class="equip-content"><div class="equip"><p class="artifact">${item.name}</p>${requireContent}${attrContent}</div></div>`;
  2336. ret += tip;
  2337. }
  2338. $('#runeword-content').html(ret);
  2339. $.initPopup();
  2340. }, 300);
  2341. });
  2342.  
  2343. $('.equip').eq(0).children().last().prop('id', 'big-slot');
  2344.  
  2345. const link = '<a href="/Help/Content?url=Artifact" target="_blank" class="btn btn-xs btn-success mr-10">神器列表</a>';
  2346. $('.btn.btn-xs').eq(0).before(link);
  2347. }
  2348.  
  2349. if (location.href.indexOf('Help/Content?url=Artifact') >= 0) {
  2350. const filter = '<div class="container" style="margin-bottom: 20px;"><input class="form-control" id="panel-filter" placeholder="输入神器名称或符文序号" /></div>';
  2351. $('.navbar').next().after(filter);
  2352. let timer = null;
  2353. $('#panel-filter').keyup(function () {
  2354. if (timer) {
  2355. clearTimeout(timer);
  2356. timer = null;
  2357. }
  2358. timer = setTimeout(() => {
  2359. const val = $(this).val();
  2360. if (val) {
  2361. if (/^\d+$/.test(val)) {
  2362. $('tbody tr').each(function (i) {
  2363. const recipe = [];
  2364. $(this).children().eq(1).find('.artifact.equip-name').each(function () {
  2365. recipe.push($(this).text().match(/\d+/g)[0]);
  2366. });
  2367. if (recipe.indexOf(val) >= 0) {
  2368. $(this).show();
  2369. } else {
  2370. $(this).hide();
  2371. }
  2372. });
  2373. } else {
  2374. $('tbody tr').each(function (i) {
  2375. const name = $(this).children().last().find('.artifact').text();
  2376. if (name.indexOf(val) >= 0) {
  2377. $(this).show();
  2378. } else {
  2379. $(this).hide();
  2380. }
  2381. });
  2382. }
  2383. } else {
  2384. $('tbody tr').show();
  2385. }
  2386. }, 300);
  2387. });
  2388. }
  2389.  
  2390. function fetchRuneTip() {
  2391. $.get('/Help/Artifact', function (html) {
  2392. const dom = $.parseHTML(html);
  2393. $(dom).find('tr').each(function (i) {
  2394. if (i > 0) {
  2395. const nameLabel = $(this).children().last().find('.artifact');
  2396. const rune = {name: nameLabel.text(), attr: [], recipe: [], require: []};
  2397. nameLabel.parent().children().each(function (index) {
  2398. if (index > 0) rune.attr.push($(this).text());
  2399. });
  2400. $(this).children().eq(1).find('.artifact.equip-name').each(function () {
  2401. rune.recipe.push($(this).text());
  2402. });
  2403. $(this).children().eq(0).find('.equip-label').each(function () {
  2404. rune.require.push($(this).text());
  2405. });
  2406. runeList.push(rune);
  2407. }
  2408. });
  2409. localStorage.setItem('idle-ui-rune-db', JSON.stringify(runeList));
  2410. });
  2411. }
  2412. }
  2413.  
  2414. if (config.showBattleDetail && inBattlePage()) {
  2415. const battleResult = {};
  2416. const addedDamageTypes = ['溅射', '触发了技能', '对方受到'];
  2417.  
  2418. function getDamageType(plainText) {
  2419. let ret = -1;
  2420. addedDamageTypes.forEach((item, i) => {
  2421. if (plainText.indexOf(item) >= 0) ret = i;
  2422. });
  2423. return ret;
  2424. }
  2425.  
  2426. $('.turn').each(function (index) {
  2427. if (index > 0) {
  2428. const line = $(this).children().eq(1);
  2429. const hpData = $(this).children().first().data('hp');
  2430. const id = line.children()[0].innerHTML;
  2431. if (!hpData[1]) return;
  2432. const firstTargetId = hpData[1].id;
  2433. const skillLabel = line.children('.skill-name');
  2434. const skill = skillLabel.length ? skillLabel.eq(0).text() : '普通攻击';
  2435. const damageLabel = line.children('.damage');
  2436.  
  2437. let damage = 0;
  2438. let damageDetail = {base: 0};
  2439. if (firstTargetId < 0) {
  2440. damage = damageLabel.length ? damageLabel.eq(0).text() - 0 : 0;
  2441. damageDetail = {base: damage};
  2442. $(this).children().each(function (i) {
  2443. if (i > 1) {
  2444. const plainText = getPlainText($(this));
  2445. if (getDamageType(plainText) >= 0) {
  2446. const addedDamage = $(this).children('.damage').eq(0).text() - 0;
  2447. const damageType = getDamageType(plainText);
  2448. damage += addedDamage;
  2449. const lastDamage = damageDetail[damageType];
  2450. damageDetail[damageType] = lastDamage ? lastDamage + addedDamage : addedDamage;
  2451. }
  2452. }
  2453. });
  2454. }
  2455. if (!battleResult[id]) battleResult[id] = {};
  2456. if (!battleResult[id][skill]) battleResult[id][skill] = {
  2457. turn: 0,
  2458. damage: 0,
  2459. damageDetail: {}
  2460. };
  2461.  
  2462. const skillData = battleResult[id][skill];
  2463. skillData.turn += 1;
  2464. skillData.damage += damage;
  2465. Object.keys(damageDetail).forEach(type => {
  2466. if (skillData.damageDetail[type]) {
  2467. skillData.damageDetail[type] += damageDetail[type];
  2468. } else {
  2469. skillData.damageDetail[type] = damageDetail[type];
  2470. }
  2471. });
  2472. }
  2473. });
  2474.  
  2475. const totalTurns = $('.turn').length - 1;
  2476. let partyTotalDamage = 0;
  2477. $('.battle-data tbody tr').each(function (index) {
  2478. if (getCharId(index) > 0) {
  2479. const dmg = $(this).children().eq(2).text() - 0;
  2480. partyTotalDamage += dmg;
  2481. }
  2482. });
  2483.  
  2484. $('.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>');
  2485. $('.battle-data tbody tr').each(function (index) {
  2486. const id = getCharId(index);
  2487. const actor = $(this).children().first().text();
  2488. const turns = getActorTurns(actor);
  2489. const turnsPercent = (turns / totalTurns * 100).toFixed(1) - 0;
  2490. const damage = $(this).children().eq(2).text() - 0;
  2491. const damagePercent = id > 0 ? `${(damage / partyTotalDamage * 100).toFixed(1) - 0}%` : '-';
  2492. const avgDamage = turns > 0 ? Math.round(damage / turns) : '-';
  2493. const link = battleResult[actor] ? `<a href="javascript: void(0);" class="link-detail" data-id="${actor}" data-actor="${actor}">查看</a>` : '-';
  2494. 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>`;
  2495. $(this).children().eq(2).after(content);
  2496. });
  2497.  
  2498. $('.battle-data').css('overflow', 'auto');
  2499.  
  2500. const modal = `
  2501. <div class="modal fade" id="modalBattleDetail" tabindex="-1" role="dialog">
  2502. <div class="modal-dialog modal-lg" role="document">
  2503. <div class="modal-content model-inverse">
  2504. <div class="modal-header">
  2505. <span class="modal-title"><span id="idle-ui-char"></span> - 伤害详情</span>
  2506. </div>
  2507. <div class="modal-body">
  2508. <table class="table table-condensed">
  2509. <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>
  2510. <tbody id="idle-ui-battle-rows"></tbody>
  2511. </table>
  2512. <ul>
  2513. <li>直接伤害:技能造成的实际直接伤害</li>
  2514. <li>溅射:因溅射,对非主目标造成的溅射伤害之和</li>
  2515. <li>触发技能:【装备自带技能】或【被击中触发】的技能等被触发后造成的伤害</li>
  2516. <li>持续伤害及其他:技能造成的持续伤害,以及其他伤害 </li>
  2517. </ul>
  2518. </div>
  2519. <div class="modal-footer">
  2520. <button type="button" class="btn btn-default btn-xs" data-dismiss="modal">关闭</button>
  2521. </div>
  2522. </div>
  2523. </div>
  2524. </div>
  2525. `;
  2526.  
  2527. $(document.body).append(modal);
  2528.  
  2529. $('.link-detail').click(function () {
  2530. const id = $(this).data('id');
  2531. const data = battleResult[id];
  2532. const actor = $(this).data('actor');
  2533. $('#idle-ui-char').text(actor);
  2534. let actorTotalTurns = 0;
  2535. let actorTotalDamage = 0;
  2536. Object.keys(data).forEach(skill => {
  2537. actorTotalTurns += data[skill].turn;
  2538. actorTotalDamage += data[skill].damage;
  2539. });
  2540.  
  2541. const content = Object.keys(data).map(skill => {
  2542. const skillData = data[skill];
  2543. const percent = (skillData.turn / actorTotalTurns * 100).toFixed(1) - 0;
  2544. const damagePercent = (skillData.damage / actorTotalDamage * 100).toFixed(1) - 0;
  2545. const avgDamage = skillData.turn > 0 ? Math.round(skillData.damage / skillData.turn) : '-';
  2546. 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>`;
  2547. }).join('');
  2548. $('#idle-ui-battle-rows').html(content);
  2549. $('#modalBattleDetail').modal('show');
  2550. });
  2551.  
  2552. function getCharId(index) {
  2553. const ary = $('.battle-char').eq(index).prop('id').split('_');
  2554. return ary[ary.length - 1];
  2555. }
  2556.  
  2557. function getActorTurns(id) {
  2558. let ret = 0;
  2559. if (battleResult[id]) {
  2560. Object.keys(battleResult[id]).forEach(skill => {
  2561. ret += battleResult[id][skill].turn;
  2562. });
  2563. }
  2564. return ret;
  2565. }
  2566.  
  2567. function getPlainText(element) {
  2568. return element.clone() //clone the element
  2569. .children() //select all the children
  2570. .remove() //remove all the children
  2571. .end() //again go back to selected element
  2572. .text();
  2573. }
  2574. }
  2575.  
  2576. function switchSkin(showRequire) {
  2577. $('.equip-content > .equip').each(function (item) {
  2578. const type = $(this).children().first().attr('class');
  2579.  
  2580. let classLabel = '';
  2581. const requireIndex = $(this).text().indexOf('限');
  2582. if (requireIndex >= 0) {
  2583. const requireClass = $(this).text().substring(requireIndex + 1, requireIndex + 2);
  2584. classLabel = '<span style="color: #a99877" class="mr-10">' + requireClass + '</span>';
  2585. }
  2586.  
  2587. const label = location.href.indexOf('Auction/QueryBid') >= 0 ? $(this).parent().prev().find('.equip-name').first() : $(this).parent().prev().find('.equip-name').last();
  2588. if (classLabel) {
  2589. showRequire ? label.after(classLabel) : label.next().remove();
  2590. }
  2591. });
  2592. }
  2593.  
  2594. function inBattlePage() {
  2595. const battePages = ['Battle/Simulate', 'Battle/InDungeon', 'Battle/WithChar'];
  2596. return battePages.some(path => location.href.indexOf(path) >= 0);
  2597. }
  2598.  
  2599. function renderProcessing() {
  2600. return '<span id="processing" class="mr-10" style="display:none;"><i class="glyphicon glyphicon-refresh"></i> 处理中...</span>';
  2601. }
  2602.  
  2603. function renderButton(id, text, type) {
  2604. if (!type) type = 'success';
  2605. return `<button type="button" class="btn btn-xs btn-${type} mr-10" id="${id}">${text}</button>`;
  2606. }
  2607.  
  2608. let uid = purl().param().id || purl().param().Id;
  2609.  
  2610. let blockMap = localStorage.getItem('idle-ui-block');
  2611. if (blockMap) {
  2612. blockMap = JSON.parse(blockMap);
  2613. } else {
  2614. blockMap = {};
  2615. }
  2616. if (!blockMap[uid]) blockMap[uid] = {num: 0, time: +new Date()};
  2617. let blockData = blockMap[uid];
  2618.  
  2619. if (location.href.indexOf('Character/Detail') >= 0) {
  2620. checkBlockNum();
  2621. $('.col-sm-6 .panel-body').eq(0).children().last().append(`<p>封号打击次数(仅供参考):<span class="physical">${blockData.num}</span></p>`);
  2622. }
  2623.  
  2624. function addBlockNum() {
  2625. checkBlockNum();
  2626. if (!blockData.num) blockData.num = 0;
  2627. blockData.num += 1;
  2628. blockData.time = +new Date();
  2629. localStorage.setItem('idle-ui-block', JSON.stringify(blockMap));
  2630. new Notification(`当前封号打击为${blockData.num}次,请注意`);
  2631. }
  2632.  
  2633. function checkBlockNum() {
  2634. const curTime = +new Date();
  2635. const hours = Math.floor((curTime - blockData.time) / (3600 * 1000));
  2636. if (hours > 0) {
  2637. blockData.num = blockData.num > hours ? blockData.num - hours : 0;
  2638. blockData.time = blockData.time + (hours * 3600 * 1000);
  2639. localStorage.setItem('idle-ui-block', JSON.stringify(blockMap));
  2640. }
  2641. }
  2642. };
  2643.  
  2644. window.addEventListener('load', idleInit, false);
  2645.  
  2646. const borderColor = '#6f5a40';
  2647. GM_addStyle(`
  2648. .panel-top {
  2649. margin-bottom: 20px;
  2650. text-align: center;
  2651. }
  2652. .idle-ui-title {
  2653. font-size: 18px;
  2654. color: #fff;
  2655. margin-bottom: 6px;
  2656. }
  2657. .panel-header {
  2658. margin: 8px 0;
  2659. }
  2660. .panel-textarea {
  2661. background-color: rgba(255,255,255,0.1);
  2662. color: #a99877;
  2663. margin-bottom: 8px;
  2664. }
  2665. .block-visited {
  2666. background-color: #3f51b5 !important;
  2667. }
  2668. .hit-input {
  2669. display: inline-block;
  2670. color: #fff;
  2671. width: 60px;
  2672. padding: 0 8px;
  2673. border-radius: 0;
  2674. background-color: transparent;
  2675. }
  2676. .idle-ui-set-single, .idle-ui-set-full {
  2677. opacity: 0.5;
  2678. }
  2679. .idle-ui-new-item {
  2680. border: 1px dashed #888 !important;
  2681. }
  2682. .mr-10 {
  2683. margin-right: 10px;
  2684. }
  2685. .ml-10 {
  2686. margin-left: 10px;
  2687. }
  2688. @-webkit-keyframes rotate {
  2689. from {
  2690. -webkit-transform: rotate(0deg);
  2691. -o-transform: rotate(0deg);
  2692. transform: rotate(0deg);
  2693. }
  2694. to {
  2695. -webkit-transform: rotate(360deg);
  2696. -o-transform: rotate(360deg);
  2697. transform: rotate(360deg);
  2698. }
  2699. }
  2700. #processing i {
  2701. animation: rotate 1s ease-in-out infinite;
  2702. }
  2703. .filter-input {
  2704. width: 150px !important;
  2705. }
  2706. #big-slot {
  2707. font-size: 24px;
  2708. margin-top: 10px !important;
  2709. color: #fff;
  2710. }
  2711. #idle-ui-quicksearch {
  2712. position: relative;
  2713. float: left;
  2714. margin-top: 14px;
  2715. }
  2716. #idle-ui-quicksearch > input {
  2717. width: 150px;
  2718. display: inline-block;
  2719. height: 24px;
  2720. line-height: 24px;
  2721. border-radius: 3px;
  2722. }
  2723. .equip-container > p:hover {
  2724. white-space: nowrap;
  2725. }
  2726. .equip-container > p:hover .sr-only {
  2727. z-index: 1;
  2728. position: relative;
  2729. }
  2730. html.d3 body {
  2731. color: #a99877;
  2732. font-family: "Consolas", Arial, sans-serif;
  2733. }
  2734. html.d3 .panel {
  2735. background-color: #171614;
  2736. border-color: ${borderColor};
  2737. }
  2738. html.d3 .panel-inverse > .panel-heading {
  2739. background-color: #101010;
  2740. border-color: ${borderColor};
  2741. font: normal 16px "Exocet Blizzard Light","Palatino Linotype", "Times", serif;
  2742. color: #F3E6D0;
  2743. line-height: 26px;
  2744. }
  2745. html.d3 .panel-inverse > .panel-heading .label {
  2746. font-size: 12px;
  2747. font-family: "Consolas", Arial, sans-serif;
  2748. }
  2749. html.d3 .btn {
  2750. background-color: transparent;
  2751. border: 1px solid ${borderColor};
  2752. vertical-align: top;
  2753. color: #ad835a;
  2754. font: normal 14px/1.5 Arial, sans-serif;
  2755. line-height: normal;
  2756. }
  2757. html.d3 .btn:hover {
  2758. color: #fff !important;
  2759. }
  2760. html.d3 .btn:active {
  2761. background-color: transparent;
  2762. }
  2763. html.d3 .label {
  2764. line-height: normal;
  2765. font-weight: normal;
  2766. border-radius: 2px;
  2767. padding: 3px 4px 1px;
  2768. border: 1px solid #5f3d11;
  2769. box-shadow: 0 0 2px #000;
  2770. background-color: #000;
  2771. color: #ad835a;
  2772. }
  2773. html.d3 .label.label-info {
  2774. color: #6969ff;
  2775. }
  2776. html.d3 .label.label-warning {
  2777. color: #ffff00;
  2778. }
  2779. html.d3 .label.label-danger {
  2780. color: #e60101;
  2781. }
  2782. html.d3 .label.label-success {
  2783. color: #00c400;
  2784. }
  2785. html.d3 .physical {
  2786. color: #f3e6d0 !important;
  2787. }
  2788. html.d3 .navbar-inverse.navbar-fixed-top {
  2789. border-bottom: 1px solid #322a20;
  2790. background-color: #171614;
  2791. }
  2792. html.d3 .navbar-inverse .navbar-brand {
  2793. color: #f3e6d0;
  2794. font-family: "Exocet Blizzard Light","Palatino Linotype", "Times", serif;
  2795. }
  2796. html.d3 a, html.d3 .navbar-inverse .navbar-nav>li>a {
  2797. color: #ad835a;
  2798. }
  2799. html.d3 .magical, html.d3 .skill, html.d3 .cold {
  2800. color: #6969ff !important;
  2801. }
  2802. html.d3 .hit-input {
  2803. border-color: ${borderColor};
  2804. }
  2805. html.d3 .progress {
  2806. border: 1px solid #513f2e;
  2807. border-radius: 0;
  2808. box-shadow: 0 0 5px #000;
  2809. background-color: #101010;
  2810. color: #f3e6d0;
  2811. height: 22px;
  2812. }
  2813. html.d3 .progress-bar {
  2814. border: 1px solid #101010;
  2815. line-height: 20px;
  2816. }
  2817. html.d3 .progress-bar-exp {
  2818. background-color: rgb(251,131,44);
  2819. }
  2820. html.d3 .progress-bar-life {
  2821. background: rgb(235,21,28);
  2822. }
  2823. html.d3 .footer {
  2824. border-top: 1px solid #322a20;
  2825. background-color: #171614;
  2826. }
  2827. html.d3 .btn.btn-success {
  2828. color: #00c400;
  2829. }
  2830. html.d3 .btn.btn-danger {
  2831. color: #e60101;
  2832. }
  2833. html.d3 .img-thumbnail {
  2834. border-color: #d59c52;
  2835. }
  2836. html.d3 .popover {
  2837. background: #1d180e;
  2838. padding: 1px;
  2839. border: 1px solid #322a20;
  2840. border-radius: 2px;
  2841. box-shadow: 0 0 10px #000;
  2842. max-width: 271px;
  2843. font-family: "Consolas", Arial, sans-serif;
  2844. }
  2845. html.d3 .popover-content .equip p:first-child {
  2846. height: 30px;
  2847. width: 263px;
  2848. padding: 0;
  2849. margin: 0 -10px 10px -10px !important;
  2850. background: url(http://images.targetedu.cn/d3/tooltip-title.jpg) no-repeat;
  2851. text-align: center;
  2852. line-height: 28px;
  2853. font-size: 16px;
  2854. font-family: "Exocet Blizzard Light","Palatino Linotype", "Times", serif;
  2855. }
  2856. html.d3 .popover-content .equip p.unique:first-child {
  2857. background-position: 0 -120px;
  2858. }
  2859. html.d3 .popover-content .equip p.set:first-child {
  2860. background-position: 0 -180px;
  2861. }
  2862. html.d3 .popover-content .equip p.rare:first-child {
  2863. background-position: 0 -90px;
  2864. }
  2865. html.d3 .popover-content .equip p.artifact:first-child {
  2866. background-position: 0 -150px;
  2867. }
  2868. html.d3 .popover-content .equip p.magical:first-child {
  2869. background-position: 0 -60px;
  2870. }
  2871. html.d3 .popover-content .equip p.base:first-child {
  2872. background-position: 0 -30px;
  2873. }
  2874. html.d3 .popover-content .equip p.slot:first-child {
  2875. background-position: 0 -30px;
  2876. }
  2877. html.d3 .popover-content {
  2878. background-color: #000;
  2879. padding: 2px 12px;
  2880. }
  2881. html.d3 hr {
  2882. border-color: ${borderColor};
  2883. }
  2884. html.d3 .panel-inverse > .panel-footer {
  2885. background-color: #101010;
  2886. border-color: ${borderColor};
  2887. }
  2888. html.d3 .modal-dialog {
  2889. box-shadow: 0 0 10px #000;
  2890. }
  2891. html.d3 .modal-content {
  2892. background-color: #171614;
  2893. border-color: ${borderColor};
  2894. }
  2895. html.d3 .model-inverse > .modal-header, html.d3 .model-inverse > .modal-footer {
  2896. background-color: #101010;
  2897. border-color: ${borderColor};
  2898. }
  2899. html.d3 .model-inverse > .modal-header span {
  2900. line-height: normal;
  2901. }
  2902. html.d3 .panel-textarea {
  2903. border-color: ${borderColor};
  2904. }
  2905. html.d3 .panel-footer .panel-filter {
  2906. border-color: #2a241c;
  2907. }
  2908. html.d3 .btn-default:active:focus,
  2909. html.d3 .open>.dropdown-toggle.btn-default:focus,
  2910. html.d3 .btn-default.active, .btn-default:active,
  2911. html.d3 .open>.dropdown-toggle.btn-default {
  2912. background-color: transparent;
  2913. color: #a99877;
  2914. }
  2915. html.d3 .dropdown-menu {
  2916. background-color: #101010;
  2917. border-color: ${borderColor};
  2918. box-shadow: 0 0 10px #000;
  2919. font-family: "Consolas", Arial, sans-serif;
  2920. }
  2921. html.d3 .equip-container .selected {
  2922. border: 1px solid ${borderColor};
  2923. background-color: transparent;
  2924. }
  2925. html.d3 .table > tbody > tr > td,
  2926. html.d3 .table > tbody > tr > th,
  2927. html.d3 .table > tfoot > tr > td,
  2928. html.d3 .table > tfoot > tr > th,
  2929. html.d3 .table > thead > tr > td,
  2930. html.d3 .table > thead > tr > th {
  2931. border-color: ${borderColor};
  2932. }
  2933. html.d3 .equip .divider {
  2934. background-color: ${borderColor};
  2935. }
  2936. html.d3 .panel-heading .btn-group, html.d3 .panel-heading .btn {
  2937. vertical-align: top;
  2938. }
  2939. html.d3 .form-control{
  2940. border-color: ${borderColor};
  2941. background-color: #101010;
  2942. color: #a99877;
  2943. }
  2944. html.d3 .form-validation .form-control {
  2945. width: 198px;
  2946. }
  2947. html.d3 .popover.bottom>.arrow:after {
  2948. border-bottom-color: #322a20;
  2949. }
  2950. html.d3 .super, html.d3 .unique {
  2951. color: rgb(255,128,0) !important;
  2952. }
  2953. html.d3 .artifact {
  2954. color: rgb(182,89,245) !important;
  2955. }
  2956. html.d3 .equip > p {
  2957. color: #6969ff;
  2958. }
  2959. `);