pad.skyozora.com-Multiplay-Helper

show stamina and fast add stage

当前为 2017-10-05 提交的版本,查看 最新版本

  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.5
  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 && location.pathname == "/multiplay/register/")
  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. if(location.pathname == "/multiplay/register/") 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. //紧急活动地下城表格
  526. var JinJiEvent = PageDOM.querySelector("#container>.item:nth-of-type(1)>table:nth-of-type(2)");
  527. //今天的降临
  528. if (JinJiEvent.rows[2] == undefined || JinJiEvent.rows[2].cells[1] == undefined) {alert("?未发现今日数据,是不是主页格式有问题?"); return;}
  529. config.todayStage.length = 0; //先清空
  530.  
  531. var JiangLin = JinJiEvent.rows[2].cells[1].getElementsByTagName("a");
  532. for (var ai=0;ai<JiangLin.length;ai++)
  533. {
  534. var link = JiangLin[ai];
  535. if (new RegExp(stageTestReg,"igm").test(link.getAttribute("href")))
  536. {
  537. config.todayStage.push(link.title);
  538. }
  539. }
  540. //今天的紧急
  541. for (var ri=1;ri<JinJiEvent.rows[2].cells[0].rowSpan;ri++)
  542. {
  543. var link = JinJiEvent.rows[2+ri].cells[0].querySelector("a");
  544. if (new RegExp(stageTestReg,"igm").test(link.getAttribute("href")))
  545. {
  546. config.todayStage.push(link.title);
  547. }
  548. }
  549. //长期活动地下城表格
  550. var ChangQiEvent = PageDOM.querySelector("#container>.item:nth-of-type(2)>table:nth-of-type(2)");
  551. for (var ri=1;ri<ChangQiEvent.rows.length;ri++)
  552. {
  553. var imgs = ChangQiEvent.rows[ri].getElementsByTagName("img");
  554. var typeStr = ""; //储存地下城类型说明
  555. var typeSpan = ChangQiEvent.rows[ri].cells[2].querySelector("span");
  556. if (typeSpan != undefined)
  557. {
  558. typeStr = typeSpan.textContent;
  559. }
  560. var endTime = "";
  561. var endTimeTd = ChangQiEvent.rows[ri].cells[3];
  562. if (endTimeTd != undefined)
  563. {
  564. endTime = endTimeTd.childNodes[1].nodeValue;
  565. }
  566. for (var ii=0;ii<imgs.length;ii++)
  567. {
  568. var link = imgs[ii].parentElement;
  569. if (new RegExp(stageTestReg,"igm").test(link.getAttribute("href")) //是场景
  570. && !/coin\.png/igm.test(imgs[ii].getAttribute("src")) //不是金币地下城
  571. && !/一次通關限定/igm.test(typeStr) //不是一次通关限定
  572. && !/排名地下城/igm.test(typeStr) //不是排名地下城
  573. && !/每天一場/igm.test(typeStr) //不是每天一场限定
  574. && !/後開始/igm.test(endTime) //不是还没有开始的
  575. )
  576. {
  577. config.todayStage.push(link.title);
  578. }
  579. }
  580. }
  581. config.updateDate = new Date().getTime();
  582. log("今日有" + config.todayStage.length + "个地下城");
  583. //console.log("今日地下城获取完毕",config);
  584. callback();
  585. }
  586. }
  587. //关卡大家都有的部分,类
  588. function minStage(name,iconUrl)
  589. {
  590. this.name = name;
  591. this.iconUrl = iconUrl;
  592. }
  593. //单个难度地下城关卡,类
  594. function Stage(name,iconUrl,stamina,battles)
  595. {
  596. var obj = new minStage(name,iconUrl);
  597. obj.stamina = stamina; //体力
  598. obj.battles = battles; //层数
  599. return obj;
  600. }
  601. //多个难度的地下城关卡,类
  602. function mainStage(name,iconUrl)
  603. {
  604. var obj = new minStage(name,iconUrl);
  605. obj.name = name;
  606. obj.iconUrl = iconUrl;
  607. obj.subStage = [];
  608. obj.checkSubStage = function(callback)
  609. {
  610. GM_xmlhttpRequest({
  611. method: "GET",
  612. url: "stage/" + this.name,
  613. onload: function(response){ //获取成功
  614. var PageDOM = new DOMParser().parseFromString(response.responseText, "text/html");
  615. var subStageList = PageDOM.querySelector("#wrapper>table:nth-of-type(3) ul"); //子关卡的列表ul
  616. var subStage = subStageList.getElementsByTagName("li"); //所有的li
  617.  
  618. obj.subStage.length = 0; //去掉所有的旧数据
  619. for (var si=0;si<subStage.length;si++)
  620. {
  621. var link = subStage[si].querySelector("div a"); //图标链接
  622. var iconUrl = link.querySelector("img").getAttribute("data-original");
  623. var detailTd = subStage[si].querySelector("div:nth-of-type(2)"); //介绍格
  624. if (detailTd == undefined)
  625. { //目前不知道到底是谁错了
  626. console.error("没有介绍格",subStage[si]);
  627. }
  628. var name = detailTd.querySelector("a").textContent.replace(/\s*關卡資料.*$/igm,"");
  629. var stamina = 0;var battles = 0;
  630. for (var ci=0;ci<detailTd.childNodes.length;ci++)
  631. {
  632. var cld = detailTd.childNodes[ci];
  633. if (cld.nodeName == "SPAN" && /體力/igm.test(cld.previousSibling.nodeValue))
  634. var stamina = parseInt(cld.textContent);
  635. if (cld.nodeName == "SPAN" && /層數/igm.test(cld.previousSibling.nodeValue))
  636. var battles = parseInt(cld.textContent);
  637. }
  638. var stage = new Stage(name,iconUrl,stamina,battles);
  639. obj.subStage.push(stage);
  640. }
  641. callback();
  642. },
  643. onerror: function(response) {
  644. log("获取 " + obj.name + " 详情失败");
  645. console.error("获取 " + obj.name + " 详情失败",response);
  646. },
  647. });
  648. }
  649. return obj;
  650. }
  651. function checkAllStageList(resetAll = false)
  652. {
  653. GM_xmlhttpRequest({
  654. method: "GET",
  655. url: "stage",
  656. onload: dealStageList,
  657. onerror: function(response) {
  658. log("获取全部地下城列表失败");
  659. console.error("获取全部地下城列表失败",response);
  660. },
  661. });
  662.  
  663. function dealStageList(response)
  664. {
  665. var PageDOM = new DOMParser().parseFromString(response.responseText, "text/html");
  666. if (resetAll) stageList.length = 0; //先清空
  667. //所有地下城表格
  668. var stageTd = PageDOM.querySelector("#wrapper>table:nth-of-type(3) td");
  669. var stages = stageTd.getElementsByClassName("tooltip"); //获取所有的链接
  670.  
  671.  
  672. //检查是否已经存在,否则添加新的
  673. function checkExistAdd(newStage,resetAll = false)
  674. {
  675. var oldStage = stageList.filter(function(item){ //查找以前有没有这个地图
  676. return item.name == link.title;
  677. })[0];
  678. if (!resetAll && oldStage != undefined)
  679. {
  680. oldStage.name = newStage.name;
  681. oldStage.iconUrl = newStage.iconUrl;
  682. }else
  683. { //没有就添加新的
  684. newStages.push(newStage);
  685. }
  686. }
  687.  
  688. var newStages = [];
  689. //所有地下城
  690. for (var si=1,si_l=stages.length;si<si_l;si++)
  691. {
  692. var link = stages[si];
  693. if (new RegExp(stageTestReg,"igm").test(link.getAttribute("href")))
  694. {
  695. imgUrl = link.querySelector("img").getAttribute("data-original");
  696. checkExistAdd(new mainStage(link.title,imgUrl),resetAll);
  697. }
  698. }
  699. //▼添加暂时没有的特殊图
  700. //checkExistAdd(new mainStage("闇の戦武龍","http://i1296.photobucket.com/albums/ag18/skyozora/pets_icon/3839_zpsinupxf0j.png"),resetAll);
  701. //▲添加暂时没有的特殊图
  702.  
  703. //var stageArr = stageList.slice(398,400); //debug用
  704. getStageDetail(newStages,newStages.length,function(){
  705. stageList = stageList.concat(newStages);
  706. log("所有地下城获取完毕");
  707. //console.log("所有地下城获取完毕",config);
  708. saveConfig(2);
  709. });
  710. }
  711. function getStageDetail(stgArr,max,callback)
  712. {
  713. if (stgArr.length < 1)
  714. {
  715. callback();
  716. return;
  717. }
  718. var newStgArr = stgArr.concat();
  719. var thisStg = newStgArr.shift(); //删除新数组的第一个元素
  720.  
  721. thisStg.checkSubStage(function(){
  722. log("已获取" + (max-newStgArr.length) + "/" + max);
  723. console.log("已获取" + (max-newStgArr.length) + "/" + max);
  724. getStageDetail(newStgArr,max,callback);
  725. });
  726. }
  727. }
  728.  
  729. /*
  730. * 协力列表页面
  731. *
  732. */
  733. function multiplayPage()
  734. {
  735. var table = document.querySelector("#wrapper>table:nth-of-type(3) table"); //协力请求表格
  736. if (table == undefined) //如果没找到,试试手机版
  737. {
  738. table = document.querySelector(".content>table");
  739. if (table!=undefined)
  740. {
  741. mobile = true;
  742. }else
  743. {
  744. alert("?未找到协力列表");
  745. }
  746. }
  747. var cellMaxLength = 0;
  748. for (var ci=0;ci<table.rows[0].cells.length;ci++)
  749. {
  750. cellMaxLength += table.rows[0].cells[ci].colSpan; //计算宽度
  751. }
  752. for (var ri=table.rows.length-1;ri>0;ri--)
  753. {
  754. if (table.rows[ri].cells[0].colSpan >= cellMaxLength)
  755. {
  756. table.rows[ri].remove(); //去除广告
  757. }
  758. }
  759. if (!mobile) table.rows[0].cells[0].colSpan += 1; //标题添加一格合并
  760. for (var ri=(mobile?0:1);ri<table.rows.length;(mobile?ri+=nextRow+1:ri++))
  761. {
  762. var stageNameCell = table.rows[ri].cells[1]; //获取名字的格
  763. if (mobile)
  764. {
  765. var nextRow = table.rows[ri].cells[0].rowSpan++; //增加一跨行
  766. var newRow = table.insertRow(ri+nextRow);
  767. var newCell = newRow.insertCell(0); //添加新格
  768. }else
  769. {
  770. var newCell = table.rows[ri].insertCell(2); //添加新格
  771. }
  772.  
  773. var link1 = stageNameCell.querySelector("a");
  774. var link2 = stageNameCell.querySelector("a:nth-of-type(2)");
  775. var stage1 = stageList.filter(function(item){
  776. return item.name == link1.textContent;
  777. })[0];
  778. if (stage1 == undefined) //如果发现没有数据的图,跳过
  779. {
  780. console.error("没有主关卡数据",link1.textContent)
  781. continue;
  782. }
  783. var stage2 = stage1.subStage.filter(function(item){
  784. return item.name == link2.textContent;
  785. })[0];
  786. if (stage2 == undefined) //如果发现没有数据的图,跳过
  787. {
  788. console.error("没有子关卡数据",link2.textContent)
  789. continue;
  790. }
  791. //newCell.appendChild(document.createTextNode(stage2.stamina + "体"));
  792. //newCell.appendChild(document.createElement("br"));
  793. newCell.appendChild(document.createTextNode("协力" + Math.round(stage2.stamina/2) + "体"));
  794. if (!mobile) newCell.appendChild(document.createElement("br")); else newCell.appendChild(document.createTextNode(","));
  795. newCell.appendChild(document.createTextNode(stage2.battles + "层"));
  796. }
  797. }
  798.  
  799.  
  800. function ioConfigDialog()
  801. {
  802. var box = document.querySelector("#io-config-dialog");
  803. if (box != undefined) return box;
  804.  
  805. var box = document.createElement("div");
  806. box.id = box.className = "io-config-dialog";
  807. box.className = "display-none";
  808.  
  809. var txtBox = document.createElement("div");box.appendChild(txtBox);
  810. var divConfig = document.createElement("div");txtBox.appendChild(divConfig);
  811. divConfig.className = "text-box";
  812. var lblConfig = document.createElement("label");divConfig.appendChild(lblConfig);
  813. lblConfig.appendChild(document.createTextNode("设置:"));
  814. lblConfig.appendChild(document.createElement("br"));
  815. var txtConfig = document.createElement("textarea");lblConfig.appendChild(txtConfig);
  816. txtConfig.id = txtConfig.className = "text-config";
  817. txtConfig.value = "";
  818. box.configText = txtConfig;
  819.  
  820. var divStageList = document.createElement("div");txtBox.appendChild(divStageList);
  821. divStageList.className = "text-box";
  822. var lblStageList = document.createElement("label");divStageList.appendChild(lblStageList);
  823. lblStageList.appendChild(document.createTextNode("地下城列表:"));
  824. lblStageList.appendChild(document.createElement("br"));
  825. var txtStageList = document.createElement("textarea");lblStageList.appendChild(txtStageList);
  826. txtStageList.id = txtStageList.className = "text-stage-list";
  827. txtStageList.value = "";
  828. box.stageListText = txtStageList;
  829.  
  830. var btnBox = document.createElement("div");box.appendChild(btnBox);
  831. btnBox.className = "botton-box";
  832. var btnIpt = document.createElement("input");btnBox.appendChild(btnIpt);
  833. btnIpt.type = "button";
  834. btnIpt.id = btnIpt.className = "input-config";
  835. btnIpt.value = "导入设置";
  836. btnIpt.onclick = function(){
  837. var bk = loadConfig(txtConfig.value,txtStageList.value,true);
  838. if (bk[0] && bk[1])
  839. {
  840. saveConfig();
  841. alert("?导入成功");
  842. }else
  843. {
  844. if(!bk[0])alert("?该设置信息格式不正确");
  845. if(!bk[1])alert("?该地下城列表信息格式不正确");
  846. }
  847. }
  848.  
  849. var btnCls = document.createElement("input");btnBox.appendChild(btnCls);
  850. btnCls.type = "button";
  851. btnCls.id = btnCls.className = "close-dialog";
  852. btnCls.value = "关闭";
  853. btnCls.onclick = function(){box.classList.add("display-none");}
  854.  
  855. return box;
  856. }