pad.skyozora.com-Multiplay-Helper

show stamina and fast add stage

目前为 2017-11-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?v6
  10. // @version 1.1.24
  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. function getLocalTime(i)
  121. {
  122. //参数i为时区值数字,比如北京为东八区则输进8,西5输入-5
  123. if (typeof i !== 'number') return;
  124. var d = new Date();
  125. //得到1970年一月一日到现在的秒数
  126. var len = d.getTime();
  127. //本地时间与GMT时间的时间偏移差
  128. var offset = d.getTimezoneOffset() * 60000;
  129. //得到现在的格林尼治时间
  130. var utcTime = len + offset;
  131. return new Date(utcTime + 3600000 * i);
  132. }
  133.  
  134. var config={
  135. version:1, //储存当前设置结构版本
  136. updateDate:0, //储存今日开放地图上次更新时间
  137. todayStage:[
  138. {name:"每日降临",detail:"每天都会更换一次的降临神,保持24小时。",stages:[]},
  139. {name:"紧急降临",detail:"每天分组出现的紧急本,每个组一小时。",stages:[]},
  140. {name:"耀日本",detail:"每周分星期几固定出现的本",stages:[]},
  141. {name:"活动本",detail:"各种活动的本",stages:[]}
  142. ], //储存当前开放的地图
  143. starStage:[], //储存收藏的地图
  144. message:[],
  145. };
  146. var stageList=[]; //储存全部地图的数据
  147. var mobile = false; //是否为手机版
  148. var stageTestReg = "^/?s(?:tage)?/"; //用来测试href是不是地下城的
  149.  
  150. if(typeof(GM_getResourceText) != "undefined") //用了GM插件
  151. {
  152. var styleDom = document.createElement("style");
  153. styleDom.type = "text/css";
  154. styleDom.appendChild(document.createTextNode(GM_getResourceText('style')));
  155. document.head.appendChild(styleDom);
  156. }
  157.  
  158. if (GM_getValue("helper-config") == undefined && location.pathname == "/multiplay/register/")
  159. {
  160. saveConfig();
  161. alert("?欢迎使用!\n请先导入地下城列表数据\n然后检查今日开放地下城。");
  162. console.log("配置不存在,储存默认配置");
  163. }else
  164. {
  165. loadConfig(GM_getValue("helper-config"),GM_getValue("helper-stage-list"));
  166. //console.log("配置存在",config);
  167.  
  168. var now = getLocalTime(9);var last = new Date(config.updateDate);
  169. if (now > last && now.getDate() != last.getDate())
  170. {
  171. console.log("今天的开放地图还没检查");
  172. if(location.pathname == "/multiplay/register/") alert("?又是新的一天了!\n请检查今天开放的地下城。");
  173. config.todayStage.length = 0; //清空昨天的
  174. }else
  175. {
  176. console.log("已经是今天的开放地图");
  177. }
  178. }
  179. function loadConfig(configStr,stageListStr,reset = false)
  180. {
  181. var bk = [true,true];
  182. var saConfig = JSON.parse(configStr);
  183. console.log("设置",saConfig)
  184. var saStageList = JSON.parse(stageListStr);
  185. console.log("地图数据",saStageList)
  186.  
  187. if (saConfig != null && typeof(saConfig) == "object")
  188. {
  189. if (reset)
  190. {
  191. config = saConfig;
  192. }
  193. else
  194. config = Object.assign(config, saConfig);
  195. }
  196. else
  197. {
  198. console.error("配置损坏,使用默认配置");
  199. bk[0] = false;
  200. }
  201. if (saStageList != null && typeof(saStageList) == "object")
  202. stageList = saStageList.concat();
  203. else
  204. {
  205. console.error("完整地下城数据丢失,使用空配置");
  206. bk[1] = false;
  207. }
  208. return bk;
  209. }
  210. function saveConfig(type)
  211. {
  212. if (type == undefined) type = 255;
  213. if (1 == (type & 1))
  214. {
  215. var configStr = JSON.stringify(config);
  216. GM_setValue("helper-config", configStr);
  217. }
  218. if (2 == (type & 2))
  219. {
  220. var stageListStr = JSON.stringify(stageList);
  221. GM_setValue("helper-stage-list", stageListStr);
  222. }
  223. }
  224.  
  225.  
  226. if(location.pathname == "/multiplay/register/") //注册页面
  227. {
  228. registerPage();
  229. }else if(location.pathname == "/multiplay/") //列表页面
  230. {
  231. multiplayPage();
  232. }
  233.  
  234. function registerPage()
  235. {
  236. var form = document.querySelector("#wrapper>table:nth-last-of-type(2) form"); //主要版面的表单
  237. if (form == undefined) //如果没找到,试试手机版
  238. {
  239. form = document.querySelector(".content>form");
  240. if (form!=undefined)
  241. {
  242. mobile = true;
  243. }else
  244. {
  245. alert("?未找到协力登陆窗口");
  246. }
  247. }
  248. if (!mobile) form.querySelector("p:nth-last-of-type(1)").remove() //去除最后面那个无用的东西
  249. var box = document.createElement("div");form.parentElement.appendChild(box);
  250. box.id = box.className = "mlt-helper";
  251.  
  252.  
  253. function typeClick(){refreshStageList1(this.value)};
  254.  
  255. var stgBox = document.createElement("div");box.appendChild(stgBox);
  256. stgBox.className = "main-stg-box";
  257.  
  258. var stg1Box = document.createElement("div");stgBox.appendChild(stg1Box);
  259. stg1Box.className = "stg-box stg-box-1";
  260. var stg1Ul = document.createElement("ul");stg1Box.appendChild(stg1Ul);
  261. function refresTypeList()
  262. {
  263. for (var ci = stg1Ul.childNodes.length-1;ci>=0;ci--) //清空主图列表
  264. {
  265. stg1Ul.childNodes[ci].remove();
  266. }
  267. //添加每日类型
  268. config.todayStage.forEach(function(stgs,index){
  269. var stg1UlLi1 = document.createElement("li");stg1Ul.appendChild(stg1UlLi1);
  270. if (typeof(stgs) != "object") return;
  271. var stgType1 = new LabelInput(stgs.name, "stg-type","stg-type","radio",index,stgs.name.detail);
  272. //if (index == 0) stgType1.input.checked = true;
  273. stgType1.input.onclick = typeClick;
  274. stg1UlLi1.appendChild(stgType1);
  275. })
  276.  
  277. //添加收藏类型
  278. var stg1UlLi2 = document.createElement("li");stg1Ul.appendChild(stg1UlLi2);
  279. var stgType2 = new LabelInput("我的收藏", "stg-type","stg-type","radio",100,"我收藏的地下城");
  280. stgType2.input.onclick = typeClick;
  281. stg1UlLi2.appendChild(stgType2);
  282. }
  283.  
  284.  
  285. var stg2Box = document.createElement("div");stgBox.appendChild(stg2Box);
  286. stg2Box.className = "stg-box stg-box-2";
  287. var stg2Ul = document.createElement("ul");stg2Box.appendChild(stg2Ul);
  288.  
  289. //征求文本信息
  290. var req = form.querySelector("[name=req]");
  291. var msgBox = document.createElement("select");stgBox.appendChild(msgBox);
  292. msgBox.size = 5;
  293. msgBox.className = "stg-box msg-box";
  294. msgBox.onclick = function(){
  295. var msg = config.message[this.value];
  296. if (msg !== undefined)
  297. insertText(req,msg);
  298. //req.value += msg;
  299. }
  300.  
  301. function refreshMessageList()
  302. {
  303. while(msgBox.options.length>0) //清空原来的短语列表
  304. {
  305. msgBox.remove(0);
  306. }
  307. config.message.forEach(function(item,index){
  308. var opt = new Option(item, index);
  309. msgBox.add(opt);
  310. })
  311. }
  312. function insertText(obj,str) {
  313. if (document.selection) {
  314. var sel = document.selection.createRange();
  315. sel.text = str;
  316. } else if (typeof obj.selectionStart === 'number' && typeof obj.selectionEnd === 'number') {
  317. var startPos = obj.selectionStart,
  318. endPos = obj.selectionEnd,
  319. cursorPos = startPos,
  320. tmpStr = obj.value;
  321. obj.value = tmpStr.substring(0, startPos) + str + tmpStr.substring(endPos, tmpStr.length);
  322. cursorPos += str.length;
  323. obj.selectionStart = obj.selectionEnd = cursorPos;
  324. } else {
  325. obj.value += str;
  326. }
  327. }
  328.  
  329. var msgBoxCtl = document.createElement("div");stgBox.appendChild(msgBoxCtl);
  330. msgBoxCtl.className = "msg-box-control";
  331. var msgAdd = document.createElement("input");msgBoxCtl.appendChild(msgAdd);
  332. msgAdd.type = "button";
  333. msgAdd.id = msgAdd.className = "message-add";
  334. msgAdd.value = "+";
  335. msgAdd.onclick = function(){
  336. var str = prompt("请输入需要保存的短语");
  337. if (str == null) return;
  338. config.message.push(str);
  339. saveConfig(1);
  340. refreshMessageList();
  341. };
  342. var msgRmv = document.createElement("input");msgBoxCtl.appendChild(msgRmv);
  343. msgRmv.type = "button";
  344. msgRmv.id = msgRmv.className = "message-remove";
  345. msgRmv.value = "-";
  346. msgRmv.onclick = function(){
  347. config.message.splice(msgBox.selectedIndex,1);
  348. saveConfig(1);
  349. refreshMessageList();
  350. };
  351.  
  352. //刷新地下城列表类型
  353. function refreshStageList1(type)
  354. {
  355. if (type == undefined)type = 0;
  356. for (var ci = stg2Ul.childNodes.length-1;ci>=0;ci--) //清空主图列表
  357. {
  358. stg2Ul.childNodes[ci].remove();
  359. }
  360. var stages; //需要处理的数组
  361. if (type == 100)
  362. {
  363. stages = config.starStage;
  364. }else if (type >=0 )
  365. {
  366. if (config.todayStage[type] == undefined) return;
  367. stages = config.todayStage[type].stages;
  368. }else
  369. {
  370. console.error("未知的地下城类型",type,stages);
  371. return;
  372. }
  373.  
  374. if (typeof(stages) != "object") return;
  375. stages.forEach(function(stgName)
  376. {
  377. var _stgName = stgName;
  378. var li = document.createElement("li");stg2Ul.appendChild(li);
  379. var stgLbl = new LabelInput(null, "stg-list","stg-list","radio",_stgName,"地下城大关卡:" + _stgName);
  380. li.appendChild(stgLbl);
  381. stgLbl.input.onclick = refreshStageList2;
  382.  
  383. var icon = document.createElement("div"); stgLbl.appendChild(icon);
  384. icon.className = "stage-icon";
  385. var thisStage = stageList.filter(function(stg){return stg.name == _stgName;})[0]
  386. if (thisStage) icon.style.backgroundImage = "url(" + thisStage.iconUrl + ")";
  387. var detail = document.createElement("div"); stgLbl.appendChild(detail);
  388. detail.className = "stage-detail";
  389. detail.appendChild(document.createTextNode(_stgName));
  390. })
  391. }
  392.  
  393. function refreshStageList2()
  394. {
  395. if (!this.checked) return; //如果并不是自身被选中,那么就没反应
  396. var _stgName = this.value;
  397. var thisStage = stageList.filter(function(stg){return stg.name == _stgName;})[0]
  398. if (thisStage == undefined)
  399. {
  400. alert("?数据库里没有这个地下城");
  401. return;
  402. }
  403.  
  404. stage0.selectedIndex = stage0.options.length - 1; //选中“上次登录的关卡”
  405.  
  406. while(stage1.options.length>0) //清空原来的主地下城列表
  407. {
  408. stage1.remove(0);
  409. }
  410. while(stage2.options.length>0) //清空原来的子地下城列表
  411. {
  412. stage2.remove(0);
  413. }
  414.  
  415. var opt = new Option(thisStage.name, thisStage.name);
  416. stage1.add(opt);
  417. stage1.selectedIndex = stage1.options.length - 1;
  418.  
  419. thisStage.subStage.forEach(function(stg){
  420. var opt = new Option(stg.name, stg.name);
  421. stage2.add(opt);
  422. })
  423. stage2.selectedIndex = 0;
  424. }
  425.  
  426. function addStarStage(name)
  427. {
  428. if (config.starStage.indexOf(name)<0)
  429. {
  430. if (!stageList.some(function(item){ //查找以前有没有这个地图
  431. return item.name == name;
  432. }))
  433. alert("?数据库里没有这个地下城");
  434. else{
  435. config.starStage.push(name);
  436. saveConfig(1);
  437. stg1Ul.querySelector("input[value='100']").click(); //点击刷新
  438. //alert("?“"+ name +"”收藏成功");
  439. }
  440. }else
  441. {
  442. alert("?“"+ name +"”已经收藏过了");
  443. }
  444. }
  445. function removeStarStage(name)
  446. {
  447. if (name == undefined)
  448. {
  449. config.starStage.length = 0; //如果没有输入,直接清空
  450. saveConfig(1);
  451. stg1Ul.querySelector("input[value='100']").click(); //点击刷新
  452. //alert("收藏清空了");
  453. return;
  454. }
  455. var index = config.starStage.indexOf(name);
  456. if (index<0)
  457. {
  458. alert("?你并没有收藏过“"+ name +"”");
  459. }else
  460. {
  461. config.starStage.splice(index,1)
  462. saveConfig(1);
  463. stg1Ul.querySelector("input[value='100']").click(); //点击刷新
  464. //alert("“"+ name +"”被删掉了");
  465. }
  466. }
  467. var btnBox1 = document.createElement("div");box.appendChild(btnBox1);
  468. var btnAddStg = document.createElement("input");btnBox1.appendChild(btnAddStg);
  469. btnAddStg.type = "button";
  470. btnAddStg.id = btnAddStg.className = "add-stage-string";
  471. btnAddStg.value = "输入地下城收藏";
  472. btnAddStg.onclick = function(){
  473. addStarStage(prompt("请输入地下城名称"));
  474. };
  475. var btnRemoveStg = document.createElement("input");btnBox1.appendChild(btnRemoveStg);
  476. btnRemoveStg.type = "button";
  477. btnRemoveStg.id = btnRemoveStg.className = "remove-stage";
  478. btnRemoveStg.value = "删除选中地下城收藏";
  479. btnRemoveStg.onclick = function(){
  480. var radios = document.getElementsByName("stg-list");
  481. for (var ri=0;ri<radios.length;ri++)
  482. {
  483. if (radios[ri].checked)
  484. {
  485. removeStarStage(radios[ri].value);
  486. }
  487. }
  488. };
  489. var btnRemoveAllStg = document.createElement("input");btnBox1.appendChild(btnRemoveAllStg);
  490. btnRemoveAllStg.type = "button";
  491. btnRemoveAllStg.id = btnRemoveAllStg.className = "remove-stage";
  492. btnRemoveAllStg.value = "清空我的收藏";
  493. btnRemoveAllStg.onclick = function(){
  494. removeStarStage();
  495. };
  496.  
  497. var btnBox2 = document.createElement("div");box.appendChild(btnBox2);
  498. var chkUpt = document.createElement("input");btnBox2.appendChild(chkUpt);
  499. chkUpt.type = "button";
  500. chkUpt.id = chkUpt.className = "checkUpdate";
  501. chkUpt.value = "检查今日开放地下城";
  502. chkUpt.onclick = function(){
  503. checkTodayUpdate(function(){
  504. refresTypeList();
  505. saveConfig(1);
  506. refreshStageList1(0);
  507. })
  508. }
  509.  
  510. var chkStgLst = document.createElement("input");btnBox2.appendChild(chkStgLst);
  511. chkStgLst.type = "button";
  512. chkStgLst.id = chkUpt.className = "check-stage-list";
  513. chkStgLst.value = "获取完整地下城数据";
  514. chkStgLst.onclick = function(){
  515. checkAllStageList();
  516. }
  517.  
  518. var ioCfg = document.createElement("input");btnBox2.appendChild(ioCfg);
  519. ioCfg.type = "button";
  520. ioCfg.id = chkUpt.className = "input-output-config";
  521. ioCfg.value = "导入/导出设置&地下城列表";
  522. ioCfg.onclick = function(){
  523. var dlg = ioConfigDialog();
  524. form.parentElement.appendChild(dlg);
  525. dlg.classList.remove("display-none");
  526. dlg.configText.value = JSON.stringify(config);
  527. dlg.stageListText.value = JSON.stringify(stageList);
  528. };
  529.  
  530. //收藏按钮
  531. var stage0 = form.querySelector("[name=column1]");
  532. var stage1 = form.querySelector("#stage");
  533. var stage2 = form.querySelector("#stage2"); stage2.onchange = null;
  534. var starStg = document.createElement("input");form.insertBefore(starStg,stage2.nextSibling);
  535. starStg.type = "button";
  536. starStg.id = starStg.className = "star-stage";
  537. starStg.value = "⭐️";
  538. starStg.onclick = function(){
  539. addStarStage(stage1.value);
  540. };
  541.  
  542. var infoBox = document.createElement("div");box.appendChild(infoBox);
  543. infoBox.id = infoBox.className = "info-box";
  544. refresTypeList();
  545. refreshStageList1(0); //先刷新地下城吧
  546. refreshMessageList(); //刷新文本列表
  547. }
  548. function checkTodayUpdate(callback)
  549. {
  550. log("开始检查今日地下城");
  551. GM_xmlhttpRequest({
  552. method: "GET",
  553. url: "desktop/", //主页
  554. onload: dealMainPage,
  555. onerror: function(response) {
  556. log("获取主页地下城活动失败");
  557. console.error("获取主页地下城活动失败",response);
  558. }
  559. });
  560.  
  561. function dealMainPage(response)
  562. {
  563. var PageDOM = new DOMParser().parseFromString(response.responseText, "text/html");
  564. //紧急活动地下城表格
  565. var JinJiEvent = PageDOM.querySelector("#container>.item:nth-of-type(1)>table:nth-of-type(2)");
  566. //今天的降临
  567. if (JinJiEvent.rows[2] == undefined || JinJiEvent.rows[2].cells[1] == undefined) {alert("?未发现今日数据,是不是主页格式有问题?"); return;}
  568. config.todayStage.length = 0; //先清空
  569.  
  570. var JiangLin = JinJiEvent.rows[2].cells[1].getElementsByTagName("a");
  571. var stgs1 = {name:"每日降临",detail:"每天都会更换一次的降临神,保持24小时。",stages:[]};
  572. for (var ai=0;ai<JiangLin.length;ai++)
  573. {
  574. var link = JiangLin[ai];
  575. if (new RegExp(stageTestReg,"igm").test(link.getAttribute("href")) && stgs1.stages.indexOf(link.title)<0)
  576. {
  577. stgs1.stages.push(link.title);
  578. }
  579. }
  580. config.todayStage.push(stgs1);
  581. //今天的紧急
  582. var stgs2 = {name:"紧急降临",detail:"每天分组出现的紧急本,每个组一小时。",stages:[]};
  583. for (var ri=1;ri<JinJiEvent.rows[2].cells[0].rowSpan;ri++)
  584. {
  585. var link = JinJiEvent.rows[2+ri].cells[0].querySelector("a");
  586. if (new RegExp(stageTestReg,"igm").test(link.getAttribute("href")) && stgs2.stages.indexOf(link.title)<0)
  587. {
  588. stgs2.stages.push(link.title);
  589. }
  590. }
  591. config.todayStage.push(stgs2);
  592. //长期活动地下城表格
  593. //第一行周回本
  594. var ChangQiEvent = PageDOM.querySelector("#container>.item:nth-of-type(2)>table:nth-last-of-type(1)");
  595. var stgs3 = {name:"耀日本",detail:"每周分星期几固定出现的本",stages:[]};
  596. var imgs = ChangQiEvent.rows[1].getElementsByTagName("img");
  597. for (var ii=0;ii<imgs.length;ii++)
  598. {
  599. var link = imgs[ii].parentElement;
  600. if (new RegExp(stageTestReg,"igm").test(link.getAttribute("href")) //是场景
  601. && stgs3.stages.indexOf(link.title)<0
  602. )
  603. {
  604. stgs3.stages.push(link.title);
  605. }
  606. }
  607. config.todayStage.push(stgs3);
  608.  
  609. //后面的活动
  610. var stgs4 = {name:"长期活动",detail:"各种活动的本",stages:[]};
  611. for (var ri=4;ri<ChangQiEvent.rows.length;ri++)
  612. {
  613. var imgs = ChangQiEvent.rows[ri].getElementsByTagName("img");
  614. var typeStr = ""; //储存地下城类型说明
  615. var typeSpan = ChangQiEvent.rows[ri].cells[2].querySelector("span");
  616. if (typeSpan != undefined)
  617. {
  618. typeStr = typeSpan.textContent;
  619. }
  620. var endTime = "";
  621. var endTimeTd = ChangQiEvent.rows[ri].cells[3];
  622. if (endTimeTd != undefined)
  623. {
  624. endTime = endTimeTd.childNodes[1].nodeValue;
  625. }
  626. for (var ii=0;ii<imgs.length;ii++)
  627. {
  628. var link = imgs[ii].parentElement;
  629. var href = link.getAttribute("href");
  630. if (new RegExp(stageTestReg,"igm").test(href) //是场景
  631. && !/coin\.png/igm.test(imgs[ii].getAttribute("src")) //不是金币地下城
  632. && !/一次通關限定/igm.test(typeStr) //不是一次通关限定
  633. && !/排名地下城/igm.test(typeStr) //不是排名地下城
  634. && !/每天一場/igm.test(typeStr) //不是每天一场限定
  635. && !/後開始/igm.test(endTime) //不是还没有开始的
  636. && stgs4.stages.indexOf(link.title)<0
  637. )
  638. {
  639. var realName = link.title.replace(/【.*】/igm,"");
  640. if (href.indexOf(realName)>=0)
  641. {
  642. //console.log(link.title,realName);
  643. stgs4.stages.push(realName);
  644. }else //那些活动title和场景stage名字不符
  645. {
  646. var subStageReg = "^/?s(?:tage)?/([^/]+)/[^/]+"; //用来测试href是不是有子地下城的
  647. if (new RegExp(subStageReg,"igm").test(href))
  648. {
  649. var stgV = new RegExp(subStageReg,"igm").exec(href);
  650. stgs4.stages.push(stgV[1]);
  651. }
  652. }
  653. }
  654. }
  655. }
  656. config.todayStage.push(stgs4);
  657.  
  658. config.updateDate = getLocalTime(9).getTime();
  659. log("今日有" + config.todayStage.reduce(function(previous, current){return previous + current.stages.length},0) + "个地下城");
  660. //console.log("今日地下城获取完毕",config);
  661. callback();
  662. }
  663. }
  664. //关卡大家都有的部分,类
  665. function minStage(name,iconUrl)
  666. {
  667. this.name = name;
  668. this.iconUrl = iconUrl;
  669. }
  670. //单个难度地下城关卡,类
  671. function Stage(name,iconUrl,stamina,battles)
  672. {
  673. var obj = new minStage(name,iconUrl);
  674. obj.stamina = stamina; //体力
  675. obj.battles = battles; //层数
  676. return obj;
  677. }
  678. //多个难度的地下城关卡,类
  679. function mainStage(name,iconUrl)
  680. {
  681. var obj = new minStage(name,iconUrl);
  682. obj.name = name;
  683. obj.iconUrl = iconUrl;
  684. obj.subStage = [];
  685. obj.checkSubStage = function(callback)
  686. {
  687. GM_xmlhttpRequest({
  688. method: "GET",
  689. url: "stage/" + this.name,
  690. onload: function(response){ //获取成功
  691. var PageDOM = new DOMParser().parseFromString(response.responseText, "text/html");
  692. var subStageList = PageDOM.querySelector("#wrapper>table:nth-last-of-type(2) ul"); //子关卡的列表ul
  693. if (subStageList == undefined) //如果没找到,试试手机版
  694. {
  695. subStageList = PageDOM.querySelector(".content>ul");
  696. if (subStageList!=undefined)
  697. {
  698. mobile = true;
  699. }else
  700. {
  701. alert("? " + name + " 页面未找到關卡資料");
  702. }
  703. }
  704.  
  705. var subStage = subStageList.getElementsByTagName("li"); //所有的li
  706.  
  707. obj.subStage.length = 0; //去掉所有的旧数据
  708. for (var si=0;si<subStage.length;si++)
  709. {
  710. var link = subStage[si].querySelector("div a"); //图标链接
  711. var iconUrl = link.querySelector("img").getAttribute("data-original");
  712. var detailTd = subStage[si].querySelector("div:nth-of-type(2)"); //介绍格
  713. if (detailTd == undefined)
  714. { //目前不知道到底是谁错了
  715. console.error("没有介绍格",subStage[si]);
  716. }
  717. var name = detailTd.querySelector("a").textContent.replace(/\s*關卡資料.*$/igm,"");
  718. var stamina = 0;var battles = 0;
  719. for (var ci=0;ci<detailTd.childNodes.length;ci++)
  720. {
  721. var cld = detailTd.childNodes[ci];
  722. if (cld.nodeName == "SPAN" && /體力/igm.test(cld.previousSibling.nodeValue))
  723. var stamina = parseInt(cld.textContent);
  724. if (cld.nodeName == "SPAN" && /層數/igm.test(cld.previousSibling.nodeValue))
  725. var battles = parseInt(cld.textContent);
  726. }
  727. var stage = new Stage(name,iconUrl,stamina,battles);
  728. obj.subStage.push(stage);
  729. }
  730. callback();
  731. },
  732. onerror: function(response) {
  733. log("获取 " + obj.name + " 详情失败");
  734. console.error("获取 " + obj.name + " 详情失败",response);
  735. },
  736. });
  737. }
  738. return obj;
  739. }
  740. function checkAllStageList(resetAll = false)
  741. {
  742. GM_xmlhttpRequest({
  743. method: "GET",
  744. url: "stage",
  745. onload: dealStageList,
  746. onerror: function(response) {
  747. log("获取全部地下城列表失败");
  748. console.error("获取全部地下城列表失败",response);
  749. },
  750. });
  751.  
  752. function dealStageList(response)
  753. {
  754. var PageDOM = new DOMParser().parseFromString(response.responseText, "text/html");
  755. if (resetAll) stageList.length = 0; //先清空
  756. //所有地下城表格
  757. var stageTd = PageDOM.querySelector("#wrapper>table:nth-last-of-type(2) td");
  758. if (stageTd == undefined) //如果没找到,试试手机版
  759. {
  760. stageTd = PageDOM.querySelector(".content");
  761. if (stageTd!=undefined)
  762. {
  763. mobile = true;
  764. }else
  765. {
  766. alert("?未找到地下城列表");
  767. }
  768. }
  769. var stages = stageTd.getElementsByClassName("tooltip"); //获取所有的链接
  770. if(mobile)
  771. {
  772. stages = stageTd.getElementsByTagName("a"); //获取所有的链接
  773. }
  774. stages = Array.prototype.slice.call(stages); //将类数组转换为数组
  775. stages = stages.filter(function(item){ //清除没有图标的链接和不是地下城的链接
  776. return new RegExp(stageTestReg,"igm").test(item.getAttribute("href")) //是地下城链接
  777. && item.querySelector("img") != undefined; //有图标
  778. })
  779.  
  780. //检查是否已经存在,否则添加新的
  781. function checkExistAdd(newStage,resetAll = false)
  782. {
  783. var oldStage = stageList.filter(function(item){ //查找以前有没有这个地图
  784. return item.name == newStage.name;
  785. })[0];
  786. if (resetAll || oldStage == undefined)
  787. { //没有就添加新的
  788. newStages.push(newStage);
  789. }else
  790. { //有的话就什么也不改变
  791. //oldStage.name = newStage.name;
  792. //oldStage.iconUrl = newStage.iconUrl;
  793. }
  794. }
  795.  
  796. var newStages = [];
  797. //所有地下城
  798. stages.forEach(function(item) {
  799. var img= item.querySelector("img");
  800. imgUrl = img.getAttribute("data-original");
  801. checkExistAdd(new mainStage(mobile?img.alt:item.title,imgUrl),resetAll);
  802. });
  803. //▼添加暂时没有的特殊图
  804. //checkExistAdd(new mainStage("闇の戦武龍","http://i1296.photobucket.com/albums/ag18/skyozora/pets_icon/3839_zpsinupxf0j.png"),resetAll);
  805. //▲添加暂时没有的特殊图
  806.  
  807. //var stageArr = stageList.slice(398,400); //debug用
  808. getStageDetail(newStages,newStages.length,function(){
  809. stageList = stageList.concat(newStages);
  810. log("所有地下城获取完毕");
  811. //console.log("所有地下城获取完毕",config);
  812. saveConfig(2);
  813. });
  814. }
  815. function getStageDetail(stgArr,max,callback)
  816. {
  817. if (stgArr.length < 1)
  818. {
  819. callback();
  820. return;
  821. }
  822. var newStgArr = stgArr.concat();
  823. var thisStg = newStgArr.shift(); //删除新数组的第一个元素
  824.  
  825. thisStg.checkSubStage(function(){
  826. log("已获取" + (max-newStgArr.length) + "/" + max);
  827. console.log("已获取" + (max-newStgArr.length) + "/" + max);
  828. getStageDetail(newStgArr,max,callback);
  829. });
  830. }
  831. }
  832.  
  833. /*
  834. * 协力列表页面
  835. *
  836. */
  837. function multiplayPage()
  838. {
  839. var table = document.querySelector("#wrapper>table:nth-last-of-type(2) table"); //协力请求表格
  840. if (table == undefined) //如果没找到,试试手机版
  841. {
  842. table = document.querySelector(".content>table");
  843. if (table!=undefined)
  844. {
  845. mobile = true;
  846. }else
  847. {
  848. alert("?未找到协力列表");
  849. }
  850. }
  851. var cellMaxLength = 0;
  852. for (var ci=0;ci<table.rows[0].cells.length;ci++)
  853. {
  854. cellMaxLength += table.rows[0].cells[ci].colSpan; //计算宽度
  855. }
  856. for (var ri=table.rows.length-1;ri>0;ri--)
  857. {
  858. if (table.rows[ri].cells[0].colSpan >= cellMaxLength)
  859. {
  860. table.rows[ri].remove(); //去除广告
  861. }
  862. }
  863. if (!mobile) table.rows[0].cells[0].colSpan += 1; //标题添加一格合并
  864. for (var ri=(mobile?0:1);ri<table.rows.length;(mobile?ri+=nextRow+1:ri++))
  865. {
  866. var stageNameCell = table.rows[ri].cells[1]; //获取名字的格
  867. if (mobile)
  868. {
  869. var nextRow = table.rows[ri].cells[0].rowSpan++; //增加一跨行
  870. var newRow = table.insertRow(ri+nextRow);
  871. newRow.bgColor = table.rows[ri].bgColor;
  872. var newCell = newRow.insertCell(0); //添加新格
  873. }else
  874. {
  875. var newCell = table.rows[ri].insertCell(2); //添加新格
  876. }
  877.  
  878. var link1 = stageNameCell.querySelector("a");
  879. var link2 = stageNameCell.querySelector("a:nth-of-type(2)");
  880. var stage1 = stageList.filter(function(item){
  881. return item.name == link1.textContent;
  882. })[0];
  883. if (stage1 == undefined) //如果发现没有数据的图,跳过
  884. {
  885. console.error("没有主关卡数据",link1.textContent)
  886. continue;
  887. }
  888. var stage2 = stage1.subStage.filter(function(item){
  889. return item.name == link2.textContent;
  890. })[0];
  891. if (stage2 == undefined) //如果发现没有数据的图,跳过
  892. {
  893. console.error("没有子关卡数据",link2.textContent)
  894. continue;
  895. }
  896. //newCell.appendChild(document.createTextNode(stage2.stamina + "体"));
  897. //newCell.appendChild(document.createElement("br"));
  898. newCell.appendChild(document.createTextNode("协力" + Math.round(stage2.stamina/2) + "体"));
  899. if (!mobile) newCell.appendChild(document.createElement("br")); else newCell.appendChild(document.createTextNode(","));
  900. newCell.appendChild(document.createTextNode(stage2.battles + "层"));
  901. }
  902. }
  903.  
  904.  
  905. function ioConfigDialog()
  906. {
  907. var box = document.querySelector("#io-config-dialog");
  908. if (box != undefined) return box;
  909.  
  910. var box = document.createElement("div");
  911. box.id = box.className = "io-config-dialog";
  912. box.className = "display-none";
  913.  
  914. var txtBox = document.createElement("div");box.appendChild(txtBox);
  915. txtBox.className = "text-box";
  916. var divConfig = document.createElement("div");txtBox.appendChild(divConfig);
  917. divConfig.className = "text-lbl-box";
  918. var lblConfig = document.createElement("label");divConfig.appendChild(lblConfig);
  919. lblConfig.appendChild(document.createTextNode("设置:"));
  920. lblConfig.appendChild(document.createElement("br"));
  921. var txtConfig = document.createElement("textarea");lblConfig.appendChild(txtConfig);
  922. txtConfig.id = txtConfig.className = "text-config";
  923. txtConfig.value = "";
  924. box.configText = txtConfig;
  925.  
  926. var divStageList = document.createElement("div");txtBox.appendChild(divStageList);
  927. divStageList.className = "text-lbl-box";
  928. var lblStageList = document.createElement("label");divStageList.appendChild(lblStageList);
  929. lblStageList.appendChild(document.createTextNode("地下城列表:"));
  930. lblStageList.appendChild(document.createElement("br"));
  931. var txtStageList = document.createElement("textarea");lblStageList.appendChild(txtStageList);
  932. txtStageList.id = txtStageList.className = "text-stage-list";
  933. txtStageList.value = "";
  934. box.stageListText = txtStageList;
  935.  
  936. var btnBox = document.createElement("div");box.appendChild(btnBox);
  937. btnBox.className = "botton-box";
  938. var btnIpt = document.createElement("input");btnBox.appendChild(btnIpt);
  939. btnIpt.type = "button";
  940. btnIpt.id = btnIpt.className = "input-config";
  941. btnIpt.value = "导入设置";
  942. btnIpt.onclick = function(){
  943. var bk = loadConfig(txtConfig.value,txtStageList.value,true);
  944. if (bk[0] && bk[1])
  945. {
  946. saveConfig();
  947. alert("?导入成功");
  948. }else
  949. {
  950. if(!bk[0])alert("?该设置信息格式不正确");
  951. if(!bk[1])alert("?该地下城列表信息格式不正确");
  952. }
  953. }
  954.  
  955. var btnCls = document.createElement("input");btnBox.appendChild(btnCls);
  956. btnCls.type = "button";
  957. btnCls.id = btnCls.className = "close-dialog";
  958. btnCls.value = "关闭";
  959. btnCls.onclick = function(){box.classList.add("display-none");}
  960.  
  961. return box;
  962. }