pad.skyozora.com-Multiplay-Helper

show stamina and fast add stage

当前为 2017-09-30 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name pad.skyozora.com-Multiplay-Helper
  3. // @name:zh-CN 智龙迷城战友系统及资讯网协力页面辅助器
  4. // @namespace http://www.mapaler.com/
  5. // @description show stamina and fast add stage
  6. // @description:zh-CN 智龙迷城战友系统及资讯网,协力页面,显示体力,登陆页面可快速添加今日地图
  7. // @include http://pad.skyozora.com/multiplay/register/
  8. // @include http://pad.skyozora.com/multiplay/
  9. // @resource style https://raw.githubusercontent.com/Mapaler/pad.skyozora.com-Multiplay-Helper/master/style.css?v4
  10. // @version 1.0.4
  11. // @copyright 2017+, Mapaler <mapaler@163.com>
  12. // @grant GM_getResourceText
  13. // ==/UserScript==
  14.  
  15.  
  16. //仿GM_xmlhttpRequest函数v1.3
  17. if (typeof(GM_xmlhttpRequest) == "undefined")
  18. {
  19. var GM_xmlhttpRequest = function(GM_param) {
  20.  
  21. var xhr = new XMLHttpRequest(); //创建XMLHttpRequest对象
  22. xhr.open(GM_param.method, GM_param.url, true);
  23. if (GM_param.responseType) xhr.responseType = GM_param.responseType;
  24. if (GM_param.overrideMimeType) xhr.overrideMimeType(GM_param.overrideMimeType);
  25. xhr.onreadystatechange = function() //设置回调函数
  26. {
  27. if (xhr.readyState === xhr.DONE) {
  28. if (xhr.status === 200 && GM_param.onload)
  29. GM_param.onload(xhr);
  30. if (xhr.status !== 200 && GM_param.onerror)
  31. GM_param.onerror(xhr);
  32. }
  33. }
  34.  
  35. for (var header in GM_param.headers) {
  36. xhr.setRequestHeader(header, GM_param.headers[header]);
  37. }
  38.  
  39. xhr.send(GM_param.data ? GM_param.data : null);
  40. }
  41. }
  42. //仿GM_getValue函数v1.0
  43. if(typeof(GM_getValue) == "undefined")
  44. {
  45. var GM_getValue = function(name, type){
  46. var value = localStorage.getItem(name);
  47. if (value == undefined) return value;
  48. if ((/^(?:true|false)$/i.test(value) && type == undefined) || type == "boolean")
  49. {
  50. if (/^true$/i.test(value))
  51. return true;
  52. else if (/^false$/i.test(value))
  53. return false;
  54. else
  55. return Boolean(value);
  56. }
  57. else if((/^\-?[\d\.]+$/i.test(value) && type == undefined) || type == "number")
  58. return Number(value);
  59. else
  60. return value;
  61. }
  62. }
  63. //仿GM_setValue函数v1.0
  64. if(typeof(GM_setValue) == "undefined")
  65. {
  66. var GM_setValue = function(name, value){
  67. localStorage.setItem(name, value);
  68. }
  69. }
  70. //仿GM_deleteValue函数v1.0
  71. if(typeof(GM_deleteValue) == "undefined")
  72. {
  73. var GM_deleteValue = function(name){
  74. localStorage.removeItem(name);
  75. }
  76. }
  77. //仿GM_listValues函数v1.0
  78. if(typeof(GM_listValues) == "undefined")
  79. {
  80. var GM_listValues = function(){
  81. var keys = [];
  82. for (var ki=0, kilen=localStorage.length; ki<kilen; ki++)
  83. {
  84. keys.push(localStorage.key(ki));
  85. }
  86. return keys;
  87. }
  88. }
  89. //创建带Label的Input类
  90. var LabelInput = function(text, classname, name, type, value, title = "", beforeText = true) {
  91. var label = document.createElement("label");
  92. if (text != undefined) label.appendChild(document.createTextNode(text));
  93. label.className = classname;
  94. if (typeof(title) != "undefined")
  95. label.title = title;
  96.  
  97. var ipt = document.createElement("input");
  98. ipt.name = name;
  99. ipt.id = ipt.name;
  100. ipt.type = type;
  101. ipt.value = value;
  102.  
  103. label.input = ipt;
  104. if (beforeText)
  105. label.insertBefore(ipt, label.firstChild);
  106. else
  107. label.appendChild(ipt);
  108. return label;
  109. };
  110. function log(str) //在信息框显示内容的
  111. {
  112. var infoBox = document.querySelector("#info-box");
  113. for (var ci = infoBox.childNodes.length-1;ci>=0;ci--) //清空主图列表
  114. {
  115. infoBox.childNodes[ci].remove();
  116. }
  117. infoBox.appendChild(document.createTextNode(str));
  118. }
  119.  
  120.  
  121. var config={
  122. version:1, //储存当前设置结构版本
  123. updateDate:0, //储存今日开放地图上次更新时间
  124. todayStage:[], //储存当前开放的地图
  125. starStage:[], //储存收藏的地图
  126. message:[],
  127. };
  128. var stageList=[]; //储存全部地图的数据
  129. var mobile = false; //是否为手机版
  130. var stageTestReg = "^/?s(?:tage)?/"; //用来测试href是不是地下城的
  131.  
  132. if(typeof(GM_getResourceText) != "undefined") //用了GM插件
  133. {
  134. var styleDom = document.createElement("style");
  135. styleDom.type = "text/css";
  136. styleDom.appendChild(document.createTextNode(GM_getResourceText('style')));
  137. document.head.appendChild(styleDom);
  138. }
  139.  
  140. if (GM_getValue("helper-config")==undefined)
  141. {
  142. saveConfig();
  143. alert("?欢迎使用!\n请先导入地下城列表数据\n然后检查今日开放地下城。");
  144. console.log("配置不存在,储存默认配置");
  145. }else
  146. {
  147. loadConfig(GM_getValue("helper-config"),GM_getValue("helper-stage-list"));
  148. //console.log("配置存在",config);
  149.  
  150. var now = new Date();var last = new Date(config.updateDate);
  151. if (now > last && now.getDate() != last.getDate())
  152. {
  153. console.log("今天的开放地图还没检查");
  154. alert("?又是新的一天了!\n请检查今天开放的地下城。");
  155. config.todayStage.length = 0; //清空昨天的
  156. }else
  157. {
  158. console.log("已经是今天的开放地图");
  159. }
  160. }
  161. function loadConfig(configStr,stageListStr,reset = false)
  162. {
  163. var bk = [true,true];
  164. var saConfig = JSON.parse(configStr);
  165. console.log(saConfig)
  166. var saStageList = JSON.parse(stageListStr);
  167. console.log(saStageList)
  168.  
  169. if (saConfig != null && typeof(saConfig) == "object")
  170. {
  171. if (reset)
  172. {
  173. config = saConfig;
  174. }
  175. else
  176. config = Object.assign(config, saConfig);
  177. }
  178. else
  179. {
  180. console.error("配置损坏,使用默认配置");
  181. bk[0] = false;
  182. }
  183. console.log(typeof(saStageList),saStageList)
  184. if (saStageList != null && typeof(saStageList) == "object")
  185. stageList = saStageList.concat();
  186. else
  187. {
  188. console.error("完整地下城数据丢失,使用空配置");
  189. bk[1] = false;
  190. }
  191. return bk;
  192. }
  193. function saveConfig(type)
  194. {
  195. if (type == undefined) type = 255;
  196. if (1 == (type & 1))
  197. {
  198. var configStr = JSON.stringify(config);
  199. GM_setValue("helper-config", configStr);
  200. }
  201. if (2 == (type & 2))
  202. {
  203. var stageListStr = JSON.stringify(stageList);
  204. GM_setValue("helper-stage-list", stageListStr);
  205. }
  206. }
  207.  
  208.  
  209. if(location.pathname == "/multiplay/register/") //注册页面
  210. {
  211. registerPage();
  212. }else if(location.pathname == "/multiplay/") //列表页面
  213. {
  214. multiplayPage();
  215. }
  216.  
  217. function registerPage()
  218. {
  219. var form = document.querySelector("#wrapper>table:nth-of-type(3) form"); //主要版面的表单
  220. form.querySelector("p:nth-last-of-type(1)").remove() //去除最后面那个无用的东西
  221. //new Date().getDate()
  222. var box = document.createElement("div");form.parentElement.appendChild(box);
  223. box.id = box.className = "mlt-helper";
  224.  
  225.  
  226. function typeClick(){refreshStageList1(this.value)};
  227.  
  228. var stgBox = document.createElement("div");box.appendChild(stgBox);
  229. stgBox.className = "main-stg-box";
  230.  
  231. var stg1Box = document.createElement("div");stgBox.appendChild(stg1Box);
  232. stg1Box.className = "stg-box stg-box-1";
  233. var stg1Ul = document.createElement("ul");stg1Box.appendChild(stg1Ul);
  234. var stg1UlLi1 = document.createElement("li");stg1Ul.appendChild(stg1UlLi1);
  235. var stgType1 = new LabelInput("今日地下城", "stg-type","stg-type","radio","0","今天开放的降临地下城与活动地下城");
  236. stgType1.input.checked = true;
  237. stgType1.input.onclick = typeClick;
  238. stg1UlLi1.appendChild(stgType1);
  239. var stg1UlLi2 = document.createElement("li");stg1Ul.appendChild(stg1UlLi2);
  240. var stgType2 = new LabelInput("我的收藏", "stg-type","stg-type","radio","1","我收藏的地下城");
  241. stgType2.input.onclick = typeClick;
  242. stg1UlLi2.appendChild(stgType2);
  243.  
  244. var stg2Box = document.createElement("div");stgBox.appendChild(stg2Box);
  245. stg2Box.className = "stg-box stg-box-2";
  246. var stg2Ul = document.createElement("ul");stg2Box.appendChild(stg2Ul);
  247.  
  248. //征求文本信息
  249. var req = form.querySelector("[name=req]");
  250. var msgBox = document.createElement("select");stgBox.appendChild(msgBox);
  251. msgBox.size = 5;
  252. msgBox.className = "stg-box msg-box";
  253. msgBox.onclick = function(){
  254. if (config.message[this.value] !== undefined)
  255. req.value += config.message[this.value];
  256. }
  257.  
  258. function refreshMessageList()
  259. {
  260. while(msgBox.options.length>0) //清空原来的短语列表
  261. {
  262. msgBox.remove(0);
  263. }
  264. config.message.forEach(function(item,index){
  265. var opt = new Option(item, index);
  266. msgBox.add(opt);
  267. })
  268. }
  269. var msgBoxCtl = document.createElement("div");stgBox.appendChild(msgBoxCtl);
  270. msgBoxCtl.className = "msg-box-control";
  271. var msgAdd = document.createElement("input");msgBoxCtl.appendChild(msgAdd);
  272. msgAdd.type = "button";
  273. msgAdd.id = msgAdd.className = "message-add";
  274. msgAdd.value = "+";
  275. msgAdd.onclick = function(){
  276. var str = prompt("请输入需要保存的短语");
  277. if (str == null) return;
  278. config.message.push(str);
  279. saveConfig(1);
  280. refreshMessageList();
  281. };
  282. var msgAdd = document.createElement("input");msgBoxCtl.appendChild(msgAdd);
  283. msgAdd.type = "button";
  284. msgAdd.id = msgAdd.className = "message-remove";
  285. msgAdd.value = "-";
  286. msgAdd.onclick = function(){
  287. config.message.splice(msgBox.selectedIndex,1);
  288. saveConfig(1);
  289. refreshMessageList();
  290. };
  291.  
  292.  
  293. //刷新地下城列表类型
  294. function refreshStageList1(type)
  295. {
  296. if (type == undefined)type = 0;
  297. for (var ci = stg2Ul.childNodes.length-1;ci>=0;ci--) //清空主图列表
  298. {
  299. stg2Ul.childNodes[ci].remove();
  300. }
  301. var stages; //需要处理的数组
  302. if (type == 0)
  303. {
  304. stages = config.todayStage
  305. }else if (type == 1)
  306. {
  307. stages = config.starStage
  308. }else
  309. {
  310. console.error("未知的地下城类型");
  311. return;
  312. }
  313.  
  314. stages.forEach(function(stgName)
  315. {
  316. var _stgName = stgName;
  317. var li = document.createElement("li");stg2Ul.appendChild(li);
  318. var stgLbl = new LabelInput(null, "stg-list","stg-list","radio",_stgName,"地下城大关卡:" + _stgName);
  319. li.appendChild(stgLbl);
  320. stgLbl.input.onclick = refreshStageList2;
  321.  
  322. var icon = document.createElement("div"); stgLbl.appendChild(icon);
  323. icon.className = "stage-icon";
  324. var thisStage = stageList.filter(function(stg){return stg.name == _stgName;})[0]
  325. if (thisStage) icon.style.backgroundImage = "url(" + thisStage.iconUrl + ")";
  326. var detail = document.createElement("div"); stgLbl.appendChild(detail);
  327. detail.className = "stage-detail";
  328. detail.appendChild(document.createTextNode(_stgName));
  329. })
  330. }
  331. function refreshStageList2()
  332. {
  333. if (!this.checked) return; //如果并不是自身被选中,那么就没反应
  334. var _stgName = this.value;
  335. var thisStage = stageList.filter(function(stg){return stg.name == _stgName;})[0]
  336. if (thisStage == undefined)
  337. {
  338. alert("?数据库里没有这个地下城");
  339. return;
  340. }
  341. /*
  342. //添加脚本的地下城类型
  343. function checkOptionValue(select,value)
  344. {
  345. var otps = select.options;
  346. for (var oi=0,oi_l = otps.length;oi<oi_l;oi++)
  347. {
  348. if (otps[oi].value == value)
  349. {
  350. return oi;
  351. }
  352. }
  353. return -1;
  354. }
  355. var newTypeName = "脚本选中>>";
  356. var typeIdx = checkOptionValue(stage0,newTypeName);
  357. if (typeIdx>=0)
  358. {
  359. stage0.selectedIndex = typeIdx;
  360. }else
  361. {
  362. var opt = new Option(newTypeName, newTypeName);
  363. stage0.add(opt);
  364. stage0.selectedIndex = stage0.options.length - 1;
  365. }
  366. */
  367. stage0.selectedIndex = stage0.options.length - 1; //选中“上次登录的关卡”
  368.  
  369. while(stage1.options.length>0) //清空原来的主地下城列表
  370. {
  371. stage1.remove(0);
  372. }
  373. while(stage2.options.length>0) //清空原来的子地下城列表
  374. {
  375. stage2.remove(0);
  376. }
  377.  
  378. var opt = new Option(thisStage.name, thisStage.name);
  379. stage1.add(opt);
  380. stage1.selectedIndex = stage1.options.length - 1;
  381.  
  382. thisStage.subStage.forEach(function(stg){
  383. var opt = new Option(stg.name, stg.name);
  384. stage2.add(opt);
  385. })
  386. stage2.selectedIndex = 0;
  387. }
  388.  
  389. function addStarStage(name)
  390. {
  391. if (config.starStage.indexOf(name)<0)
  392. {
  393. if (!stageList.some(function(item){ //查找以前有没有这个地图
  394. return item.name == name;
  395. }))
  396. alert("?数据库里没有这个地下城");
  397. else{
  398. config.starStage.push(name);
  399. saveConfig(1);
  400. stgType2.input.click(); //点击刷新
  401. //alert("?“"+ name +"”收藏成功");
  402. }
  403. }else
  404. {
  405. alert("?“"+ name +"”已经收藏过了");
  406. }
  407. }
  408. function removeStarStage(name)
  409. {
  410. if (name == undefined)
  411. {
  412. config.starStage.length = 0; //如果没有输入,直接清空
  413. saveConfig(1);
  414. stgType2.input.click(); //点击刷新
  415. //alert("收藏清空了");
  416. return;
  417. }
  418. var index = config.starStage.indexOf(name);
  419. if (index<0)
  420. {
  421. alert("?你并没有收藏过“"+ name +"”");
  422. }else
  423. {
  424. config.starStage.splice(index,1)
  425. saveConfig(1);
  426. stgType2.input.click(); //点击刷新
  427. //alert("“"+ name +"”被删掉了");
  428. }
  429. }
  430. var btnBox1 = document.createElement("div");box.appendChild(btnBox1);
  431. var btnAddStg = document.createElement("input");btnBox1.appendChild(btnAddStg);
  432. btnAddStg.type = "button";
  433. btnAddStg.id = btnAddStg.className = "add-stage-string";
  434. btnAddStg.value = "输入地下城收藏";
  435. btnAddStg.onclick = function(){
  436. addStarStage(prompt("请输入地下城名称"));
  437. };
  438. var btnRemoveStg = document.createElement("input");btnBox1.appendChild(btnRemoveStg);
  439. btnRemoveStg.type = "button";
  440. btnRemoveStg.id = btnRemoveStg.className = "remove-stage";
  441. btnRemoveStg.value = "删除选中地下城收藏";
  442. btnRemoveStg.onclick = function(){
  443. var radios = document.getElementsByName("stg-list");
  444. for (var ri=0;ri<radios.length;ri++)
  445. {
  446. if (radios[ri].checked)
  447. {
  448. removeStarStage(radios[ri].value);
  449. }
  450. }
  451. };
  452. var btnRemoveAllStg = document.createElement("input");btnBox1.appendChild(btnRemoveAllStg);
  453. btnRemoveAllStg.type = "button";
  454. btnRemoveAllStg.id = btnRemoveAllStg.className = "remove-stage";
  455. btnRemoveAllStg.value = "清空我的收藏";
  456. btnRemoveAllStg.onclick = function(){
  457. removeStarStage();
  458. };
  459.  
  460. var btnBox2 = document.createElement("div");box.appendChild(btnBox2);
  461. var chkUpt = document.createElement("input");btnBox2.appendChild(chkUpt);
  462. chkUpt.type = "button";
  463. chkUpt.id = chkUpt.className = "checkUpdate";
  464. chkUpt.value = "检查今日开放地下城";
  465. chkUpt.onclick = function(){
  466. checkTodayUpdate(function(){
  467. saveConfig(1);
  468. refreshStageList1(0);
  469. })
  470. }
  471.  
  472. var chkStgLst = document.createElement("input");btnBox2.appendChild(chkStgLst);
  473. chkStgLst.type = "button";
  474. chkStgLst.id = chkUpt.className = "check-stage-list";
  475. chkStgLst.value = "获取完整地下城数据";
  476. chkStgLst.onclick = function(){
  477. checkAllStageList();
  478. }
  479.  
  480. var ioCfg = document.createElement("input");btnBox2.appendChild(ioCfg);
  481. ioCfg.type = "button";
  482. ioCfg.id = chkUpt.className = "input-output-config";
  483. ioCfg.value = "导入/导出设置&地下城列表";
  484. ioCfg.onclick = function(){
  485. var dlg = ioConfigDialog();
  486. document.body.appendChild(dlg);
  487. dlg.classList.remove("display-none");
  488. dlg.configText.value = JSON.stringify(config);
  489. dlg.stageListText.value = JSON.stringify(stageList);
  490. };
  491.  
  492. //收藏按钮
  493. var stage0 = form.querySelector("[name=column1]");
  494. var stage1 = form.querySelector("#stage");
  495. var stage2 = form.querySelector("#stage2"); stage2.onchange = null;
  496. var starStg = document.createElement("input");form.insertBefore(starStg,stage2.nextSibling);
  497. starStg.type = "button";
  498. starStg.id = starStg.className = "star-stage";
  499. starStg.value = "⭐️";
  500. starStg.onclick = function(){
  501. addStarStage(stage1.value);
  502. };
  503.  
  504. var infoBox = document.createElement("div");box.appendChild(infoBox);
  505. infoBox.id = infoBox.className = "info-box";
  506. refreshStageList1(0); //先刷新地下城吧
  507. refreshMessageList(); //刷新文本列表
  508. }
  509. function checkTodayUpdate(callback)
  510. {
  511. log("开始检查今日地下城");
  512. GM_xmlhttpRequest({
  513. method: "GET",
  514. url: location.origin, //主页
  515. onload: dealMainPage,
  516. onerror: function(response) {
  517. log("获取主页地下城活动失败");
  518. console.error("获取主页地下城活动失败",response);
  519. }
  520. });
  521.  
  522. function dealMainPage(response)
  523. {
  524. var PageDOM = new DOMParser().parseFromString(response.responseText, "text/html");
  525. config.todayStage.length = 0; //先清空
  526. //紧急活动地下城表格
  527. var JinJiEvent = PageDOM.querySelector("#container>.item:nth-of-type(1)>table:nth-of-type(2)");
  528. //今天的降临
  529. var JiangLin = JinJiEvent.rows[2].cells[1].getElementsByTagName("a");
  530. for (var ai=0;ai<JiangLin.length;ai++)
  531. {
  532. var link = JiangLin[ai];
  533. if (new RegExp(stageTestReg,"igm").test(link.getAttribute("href")))
  534. {
  535. config.todayStage.push(link.title);
  536. }
  537. }
  538. //今天的紧急
  539. for (var ri=1;ri<JinJiEvent.rows[2].cells[0].rowSpan;ri++)
  540. {
  541. var link = JinJiEvent.rows[2+ri].cells[0].querySelector("a");
  542. if (new RegExp(stageTestReg,"igm").test(link.getAttribute("href")))
  543. {
  544. config.todayStage.push(link.title);
  545. }
  546. }
  547. //长期活动地下城表格
  548. var ChangQiEvent = PageDOM.querySelector("#container>.item:nth-of-type(2)>table:nth-of-type(2)");
  549. for (var ri=1;ri<ChangQiEvent.rows.length;ri++)
  550. {
  551. var imgs = ChangQiEvent.rows[ri].getElementsByTagName("img");
  552. var typeStr = ""; //储存地下城类型说明
  553. var typeSpan = ChangQiEvent.rows[ri].cells[2].querySelector("span");
  554. if (typeSpan != undefined)
  555. {
  556. typeStr = typeSpan.textContent;
  557. }
  558. var endTime = "";
  559. var endTimeTd = ChangQiEvent.rows[ri].cells[3];
  560. if (endTimeTd != undefined)
  561. {
  562. endTime = endTimeTd.childNodes[1].nodeValue;
  563. }
  564. for (var ii=0;ii<imgs.length;ii++)
  565. {
  566. var link = imgs[ii].parentElement;
  567. if (new RegExp(stageTestReg,"igm").test(link.getAttribute("href")) //是场景
  568. && !/coin\.png/igm.test(imgs[ii].getAttribute("src")) //不是金币地下城
  569. && !/一次通關限定/igm.test(typeStr) //不是一次通关限定
  570. && !/每天一場/igm.test(typeStr) //不是每天一场限定
  571. && !/後開始/igm.test(endTime) //不是还没有开始的
  572. )
  573. {
  574. config.todayStage.push(link.title);
  575. }
  576. }
  577. }
  578. config.updateDate = new Date().getTime();
  579. log("今日有" + config.todayStage.length + "个地下城");
  580. //console.log("今日地下城获取完毕",config);
  581. callback();
  582. }
  583. }
  584. //关卡大家都有的部分,类
  585. function minStage(name,iconUrl)
  586. {
  587. this.name = name;
  588. this.iconUrl = iconUrl;
  589. }
  590. //单个难度地下城关卡,类
  591. function Stage(name,iconUrl,stamina,battles)
  592. {
  593. var obj = new minStage(name,iconUrl);
  594. obj.stamina = stamina; //体力
  595. obj.battles = battles; //层数
  596. return obj;
  597. }
  598. //多个难度的地下城关卡,类
  599. function mainStage(name,iconUrl)
  600. {
  601. var obj = new minStage(name,iconUrl);
  602. obj.name = name;
  603. obj.iconUrl = iconUrl;
  604. obj.subStage = [];
  605. obj.checkSubStage = function(callback)
  606. {
  607. GM_xmlhttpRequest({
  608. method: "GET",
  609. url: "stage/" + this.name,
  610. onload: function(response){ //获取成功
  611. var PageDOM = new DOMParser().parseFromString(response.responseText, "text/html");
  612. var subStageList = PageDOM.querySelector("#wrapper>table:nth-of-type(3) ul"); //子关卡的列表ul
  613. var subStage = subStageList.getElementsByTagName("li"); //所有的li
  614.  
  615. obj.subStage.length = 0; //去掉所有的旧数据
  616. for (var si=0;si<subStage.length;si++)
  617. {
  618. var link = subStage[si].querySelector("div a"); //图标链接
  619. var iconUrl = link.querySelector("img").getAttribute("data-original");
  620. var detailTd = subStage[si].querySelector("div:nth-of-type(2)"); //介绍格
  621. if (detailTd == undefined)
  622. { //目前不知道到底是谁错了
  623. console.error("没有介绍格",subStage[si]);
  624. }
  625. var name = detailTd.querySelector("a").textContent.replace(/\s*關卡資料.*$/igm,"");
  626. var stamina = 0;var battles = 0;
  627. for (var ci=0;ci<detailTd.childNodes.length;ci++)
  628. {
  629. var cld = detailTd.childNodes[ci];
  630. if (cld.nodeName == "SPAN" && /體力/igm.test(cld.previousSibling.nodeValue))
  631. var stamina = parseInt(cld.textContent);
  632. if (cld.nodeName == "SPAN" && /層數/igm.test(cld.previousSibling.nodeValue))
  633. var battles = parseInt(cld.textContent);
  634. }
  635. var stage = new Stage(name,iconUrl,stamina,battles);
  636. obj.subStage.push(stage);
  637. }
  638. callback();
  639. },
  640. onerror: function(response) {
  641. log("获取 " + obj.name + " 详情失败");
  642. console.error("获取 " + obj.name + " 详情失败",response);
  643. },
  644. });
  645. }
  646. return obj;
  647. }
  648. function checkAllStageList(resetAll = false)
  649. {
  650. GM_xmlhttpRequest({
  651. method: "GET",
  652. url: "stage",
  653. onload: dealStageList,
  654. onerror: function(response) {
  655. log("获取全部地下城列表失败");
  656. console.error("获取全部地下城列表失败",response);
  657. },
  658. });
  659.  
  660. function dealStageList(response)
  661. {
  662. var PageDOM = new DOMParser().parseFromString(response.responseText, "text/html");
  663. if (resetAll) stageList.length = 0; //先清空
  664. //所有地下城表格
  665. var stageTd = PageDOM.querySelector("#wrapper>table:nth-of-type(3) td");
  666. var stages = stageTd.getElementsByClassName("tooltip"); //获取所有的链接
  667.  
  668.  
  669. //检查是否已经存在,否则添加新的
  670. function checkExistAdd(newStage,resetAll = false)
  671. {
  672. var oldStage = stageList.filter(function(item){ //查找以前有没有这个地图
  673. return item.name == link.title;
  674. })[0];
  675. if (!resetAll && oldStage != undefined)
  676. {
  677. oldStage.name = newStage.name;
  678. oldStage.iconUrl = newStage.iconUrl;
  679. }else
  680. { //没有就添加新的
  681. newStages.push(newStage);
  682. }
  683. }
  684.  
  685. var newStages = [];
  686. //所有地下城
  687. for (var si=1,si_l=stages.length;si<si_l;si++)
  688. {
  689. var link = stages[si];
  690. if (new RegExp(stageTestReg,"igm").test(link.getAttribute("href")))
  691. {
  692. imgUrl = link.querySelector("img").getAttribute("data-original");
  693. checkExistAdd(new mainStage(link.title,imgUrl),resetAll);
  694. }
  695. }
  696. //▼添加暂时没有的特殊图
  697. //checkExistAdd(new mainStage("闇の戦武龍","http://i1296.photobucket.com/albums/ag18/skyozora/pets_icon/3839_zpsinupxf0j.png"),resetAll);
  698. //▲添加暂时没有的特殊图
  699.  
  700. //var stageArr = stageList.slice(398,400); //debug用
  701. getStageDetail(newStages,newStages.length,function(){
  702. stageList = stageList.concat(newStages);
  703. log("所有地下城获取完毕");
  704. //console.log("所有地下城获取完毕",config);
  705. saveConfig(2);
  706. });
  707. }
  708. function getStageDetail(stgArr,max,callback)
  709. {
  710. if (stgArr.length < 1)
  711. {
  712. callback();
  713. return;
  714. }
  715. var newStgArr = stgArr.concat();
  716. var thisStg = newStgArr.shift(); //删除新数组的第一个元素
  717.  
  718. thisStg.checkSubStage(function(){
  719. log("已获取" + (max-newStgArr.length) + "/" + max);
  720. console.log("已获取" + (max-newStgArr.length) + "/" + max);
  721. getStageDetail(newStgArr,max,callback);
  722. });
  723. }
  724. }
  725.  
  726. /*
  727. * 协力列表页面
  728. *
  729. */
  730. function multiplayPage()
  731. {
  732. var table = document.querySelector("#wrapper>table:nth-of-type(3) table"); //协力请求表格
  733. if (table == undefined) //如果没找到,试试手机版
  734. {
  735. table = document.querySelector(".content>table");
  736. if (table!=undefined)
  737. {
  738. mobile = true;
  739. }else
  740. {
  741. alert("?未找到协力列表");
  742. }
  743. }
  744. var cellMaxLength = 0;
  745. for (var ci=0;ci<table.rows[0].cells.length;ci++)
  746. {
  747. cellMaxLength += table.rows[0].cells[ci].colSpan; //计算宽度
  748. }
  749. for (var ri=table.rows.length-1;ri>0;ri--)
  750. {
  751. if (table.rows[ri].cells[0].colSpan >= cellMaxLength)
  752. {
  753. table.rows[ri].remove(); //去除广告
  754. }
  755. }
  756. if (!mobile) table.rows[0].cells[0].colSpan += 1; //标题添加一格合并
  757. for (var ri=(mobile?0:1);ri<table.rows.length;(mobile?ri+=nextRow+1:ri++))
  758. {
  759. var stageNameCell = table.rows[ri].cells[1]; //获取名字的格
  760. if (mobile)
  761. {
  762. var nextRow = table.rows[ri].cells[0].rowSpan++; //增加一跨行
  763. var newRow = table.insertRow(ri+nextRow);
  764. var newCell = newRow.insertCell(0); //添加新格
  765. }else
  766. {
  767. var newCell = table.rows[ri].insertCell(2); //添加新格
  768. }
  769.  
  770. var link1 = stageNameCell.querySelector("a");
  771. var link2 = stageNameCell.querySelector("a:nth-of-type(2)");
  772. var stage1 = stageList.filter(function(item){
  773. return item.name == link1.textContent;
  774. })[0];
  775. if (stage1 == undefined) //如果发现没有数据的图,跳过
  776. {
  777. console.error("没有主关卡数据",link1.textContent)
  778. continue;
  779. }
  780. var stage2 = stage1.subStage.filter(function(item){
  781. return item.name == link2.textContent;
  782. })[0];
  783. if (stage2 == undefined) //如果发现没有数据的图,跳过
  784. {
  785. console.error("没有子关卡数据",link2.textContent)
  786. continue;
  787. }
  788. //newCell.appendChild(document.createTextNode(stage2.stamina + "体"));
  789. //newCell.appendChild(document.createElement("br"));
  790. newCell.appendChild(document.createTextNode("协力" + Math.round(stage2.stamina/2) + "体"));
  791. if (!mobile) newCell.appendChild(document.createElement("br")); else newCell.appendChild(document.createTextNode(","));
  792. newCell.appendChild(document.createTextNode(stage2.battles + "层"));
  793. }
  794. }
  795.  
  796.  
  797. function ioConfigDialog()
  798. {
  799. var box = document.querySelector("#io-config-dialog");
  800. if (box != undefined) return box;
  801.  
  802. var box = document.createElement("div");
  803. box.id = box.className = "io-config-dialog";
  804. box.className = "display-none";
  805.  
  806. var txtBox = document.createElement("div");box.appendChild(txtBox);
  807. var divConfig = document.createElement("div");txtBox.appendChild(divConfig);
  808. divConfig.className = "text-box";
  809. var lblConfig = document.createElement("label");divConfig.appendChild(lblConfig);
  810. lblConfig.appendChild(document.createTextNode("设置:"));
  811. lblConfig.appendChild(document.createElement("br"));
  812. var txtConfig = document.createElement("textarea");lblConfig.appendChild(txtConfig);
  813. txtConfig.id = txtConfig.className = "text-config";
  814. txtConfig.value = "";
  815. box.configText = txtConfig;
  816.  
  817. var divStageList = document.createElement("div");txtBox.appendChild(divStageList);
  818. divStageList.className = "text-box";
  819. var lblStageList = document.createElement("label");divStageList.appendChild(lblStageList);
  820. lblStageList.appendChild(document.createTextNode("地下城列表:"));
  821. lblStageList.appendChild(document.createElement("br"));
  822. var txtStageList = document.createElement("textarea");lblStageList.appendChild(txtStageList);
  823. txtStageList.id = txtStageList.className = "text-stage-list";
  824. txtStageList.value = "";
  825. box.stageListText = txtStageList;
  826.  
  827. var btnBox = document.createElement("div");box.appendChild(btnBox);
  828. btnBox.className = "botton-box";
  829. var btnIpt = document.createElement("input");btnBox.appendChild(btnIpt);
  830. btnIpt.type = "button";
  831. btnIpt.id = btnIpt.className = "input-config";
  832. btnIpt.value = "导入设置";
  833. btnIpt.onclick = function(){
  834. var bk = loadConfig(txtConfig.value,txtStageList.value,true);
  835. if (bk[0] && bk[1])
  836. {
  837. saveConfig();
  838. alert("?导入成功");
  839. }else
  840. {
  841. if(!bk[0])alert("?该设置信息格式不正确");
  842. if(!bk[1])alert("?该地下城列表信息格式不正确");
  843. }
  844. }
  845.  
  846. var btnCls = document.createElement("input");btnBox.appendChild(btnCls);
  847. btnCls.type = "button";
  848. btnCls.id = btnCls.className = "close-dialog";
  849. btnCls.value = "关闭";
  850. btnCls.onclick = function(){box.classList.add("display-none");}
  851.  
  852. return box;
  853. }