您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
用来在英雄-》属性页面添加一个按钮,点击后生成文本格式的可复制的人物卡,便于群众交流
// ==UserScript== // @name WoD 人物卡 // @icon http://info.world-of-dungeons.org/wod/css/WOD.gif // @namespace WOD_Tools_(fork) by_hildolfr@aino // @description 用来在英雄-》属性页面添加一个按钮,点击后生成文本格式的可复制的人物卡,便于群众交流 // @include http*://*.world-of-dungeons.org/wod/spiel/hero/attributes.php* // @license MIT License // @modifier Christophero // @version 2023.05.15.1 // ==/UserScript== var mini=(function(){var b=/(?:[\w\-\\.#]+)+(?:\[\w+?=([\'"])?(?:\\\1|.)+?\1\])?|\*|>/ig,g=/^(?:[\w\-_]+)?\.([\w\-_]+)/,f=/^(?:[\w\-_]+)?#([\w\-_]+)/,j=/^([\w\*\-_]+)/,h=[null,null];function d(o,m){m=m||document;var k=/^[\w\-_#]+$/.test(o);if(!k&&m.querySelectorAll){return c(m.querySelectorAll(o))}if(o.indexOf(",")>-1){var v=o.split(/,/g),t=[],s=0,r=v.length;for(;s<r;++s){t=t.concat(d(v[s],m))}return e(t)}var p=o.match(b),n=p.pop(),l=(n.match(f)||h)[1],u=!l&&(n.match(g)||h)[1],w=!l&&(n.match(j)||h)[1],q;if(u&&!w&&m.getElementsByClassName){q=c(m.getElementsByClassName(u))}else{q=!l&&c(m.getElementsByTagName(w||"*"));if(u){q=i(q,"className",RegExp("(^|\\s)"+u+"(\\s|$)"))}if(l){var x=m.getElementById(l);return x?[x]:[]}}return p[0]&&q[0]?a(p,q):q}function c(o){try{return Array.prototype.slice.call(o)}catch(n){var l=[],m=0,k=o.length;for(;m<k;++m){l[m]=o[m]}return l}}function a(w,p,n){var q=w.pop();if(q===">"){return a(w,p,true)}var s=[],k=-1,l=(q.match(f)||h)[1],t=!l&&(q.match(g)||h)[1],v=!l&&(q.match(j)||h)[1],u=-1,m,x,o;v=v&&v.toLowerCase();while((m=p[++u])){x=m.parentNode;do{o=!v||v==="*"||v===x.nodeName.toLowerCase();o=o&&(!l||x.id===l);o=o&&(!t||RegExp("(^|\\s)"+t+"(\\s|$)").test(x.className));if(n||o){break}}while((x=x.parentNode));if(o){s[++k]=m}}return w[0]&&s[0]?a(w,s):s}var e=(function(){var k=+new Date();var l=(function(){var m=1;return function(p){var o=p[k],n=m++;if(!o){p[k]=n;return true}return false}})();return function(m){var s=m.length,n=[],q=-1,o=0,p;for(;o<s;++o){p=m[o];if(l(p)){n[++q]=p}}k+=1;return n}})();function i(q,k,p){var m=-1,o,n=-1,l=[];while((o=q[++m])){if(p.test(o[k])){l[++n]=o}}return l}return d})(); Function.prototype.method = function ( name, func ) { this.prototype[name] = func; return this; }; String.method( 'txt', function () { return this.replace( /<.*?>|\s+|\s+|\n|\r|!/g, '' ); }); // 1 need reset point to unequip // 2 item name // 3 = 4+5+6+7 // 4 empty space // 5 uses // 6 empty space // 7 group mark //var rObj = new RegExp( '^(.+?)(!)?([ ])?([\(][0-9]+[\/][0-9]+[\)])?$' ); //var rObj = /^(!! )?(.+?)((!)?([ ])?(\([0-9]+\/[0-9]+\))?)$/; var rObj = /^(!! )?(.+?)(([ ])?(\([0-9]+\/[0-9]+\))?([ ])?(!)?)$/; var pattern_graft = /^\/wod\/css\/icons\/WOD\/gems\/gem_(.)\.png$/ ; // used to separate item name, group mark, and number of uses String.method( 'item_txt', function () { var result = []; var item = this.replace( /<.*?>|\n|\r/g, '' ); var item_list = rObj.exec(item); result.push( (item_list[1])?item_list[1]:'' ); result.push(item_list[2]); result.push( (item_list[3])?item_list[3]:'' ); return result }); String.method( 'sindexOf', function ( subs ) { var i = -1; while ( (sub = subs[++i]) ) { if ( this.indexOf( sub ) != -1 ) { return this.indexOf( sub ); } } return ( -1 ); }); var WoDTool = { attrs : [], skills : [], items : [], busy : 0, root : location.protocol + '//' + location.host + '/', done_func : function () {}, done : function ( func ) { WoDTool.done_func = func || WoDTool.done_func; if (WoDTool.busy == 0) { WoDTool.done_func(); } return this; }, walker : function ( selector, func, context ) { var i = -1, node; context = context || document; var collection = mini( selector, context ); while ( (node = collection[++i]) ) { if (func( node ) ) break; } return this; }, loader : function ( url, func, i ) { WoDTool.busy++; if ( url.indexOf( 'http' ) == -1 ) { url = WoDTool.root + url; } var req = new XMLHttpRequest(); req.onreadystatechange = function () { if ( ( req.readyState == 4 ) && ( req.status == 200 ) ) { var dummy = document.createElement( 'div' ); dummy.innerHTML = req.responseText; func( dummy, i ); WoDTool.busy--; WoDTool.done(); } }; req.open( 'GET', url, true); req.send(); return this; }, loadHeroAll : function () { var load_attrs = function ( func ) { WoDTool.loader( 'wod/spiel/hero/attributes.php?IS_POPUP=1', function ( dummy ) { WoDTool.getAttr( dummy ); func(); }); }; var load_skills = function ( func ) { WoDTool.loader( 'wod/spiel/hero/skills.php?IS_POPUP=1', function ( dummy ) { WoDTool.getSkillPages( dummy ); func(); }); }; var load_items = function ( func ) { WoDTool.loader( 'wod/spiel/hero/items.php?IS_POPUP=1&view=gear', function ( dummy ) { WoDTool.getItem( dummy ); func(); }); }; load_skills(function () { load_items(function () { load_attrs(function() { return true } ); }); }); return this; }, getAttr : function ( context ) { context = context || document; //英雄属性的表 var attrTable = false, attrs = [], skills =[]; //遍历所有标签,找出正确标签 WoDTool.walker( 'th', function ( th ) { if ( th.innerHTML == '属性' ) { attrTable = th.parentNode.parentNode; return true; } }, context ); if( !attrTable ) return false; WoDTool.walker( 'tr', function ( tr ) { if ( tr.className.indexOf( 'row' ) != -1 ) { if ( tr.childNodes[1] ) { var attr = []; if ( tr.childNodes[1].childNodes[1] ) { attr[0] = tr.childNodes[1].childNodes[1].innerHTML.txt(); } else { attr[0] = tr.childNodes[1].innerHTML.txt(); } var valueTds = tr.childNodes[3].childNodes[1].getElementsByTagName( 'td' ); attr[1] = valueTds[1].innerHTML.txt(); attrs.push( attr ); } } }, attrTable ); // 英雄 强化 / 弱化 WoDTool.walker( 'form > table:nth-of-type(2) tbody tr > td:nth-of-type(3) table.content_table td', function ( td ) { var skill = []; if ( td.childNodes[1] && td.childNodes[1].innerHTML) { skill[0] = td.childNodes[1].innerHTML.txt(); } else { skill[0] = td.innerHTML.txt(); } skill[1]='' skills.push( skill ); }, context ); WoDTool.walker( 'form > table:nth-of-type(1) tbody tr > td:nth-of-type(3) table.content_table td', function ( td ) { if ( td.innerHTML.sindexOf( ['英雄等级', '体力', '体力恢复', '法力', '法力回复', '每回合行动次数', '先攻附加值'] ) != -1 ) { var attr = []; if ( td.childNodes[1] ) { attr[0] = td.childNodes[1].innerHTML.txt(); } else { attr[0] = td.innerHTML.txt(); }; if ( attr[0].indexOf( '体力恢复' ) != -1 ) { attr[0] = '体力恢复'; attr[1] = td.innerHTML.txt().substr( td.innerHTML.txt().indexOf( '体力恢复' ) + 5 ); } else if ( attr[0].indexOf( '法力回复') != -1 ){ attr[0] = '法力回复'; attr[1] = td.innerHTML.txt().substr( td.innerHTML.txt().indexOf( '法力回复' ) + 5 ); } else { attr[1] = td.parentNode.childNodes[3].innerHTML.txt(); }; attrs.push( attr ); } }, context ); WoDTool.attrs = attrs; if ( WoDTool.skill_L ){ WoDTool.skill_L[0] = skills; } else { WoDTool.skill_L = [skills]; }; return attrs; }, getMaxRepPage : function (context) { context = context || document; WoDTool.nMaxRepPage = 1; WoDTool.walker('input', function(myinput){ var myname = myinput.getAttribute('name'); var mytest = /^SKILLPAGI_PAGE\[([0-9]+)\]$/; var mylist = mytest.exec(myname); if (mylist && mylist[1]){ var nCurrent = parseInt(mylist[1]); if (nCurrent > WoDTool.nMaxRepPage){ WoDTool.nMaxRepPage = nCurrent; }; }; }, context); return WoDTool.nMaxRepPage; }, getSkillPages : function (context) { context = context || document; if (!WoDTool.skill_L){ WoDTool.skill_L = [];}; var nMaxRepPage = WoDTool.getMaxRepPage(context); for (var i = 1; i <= WoDTool.nMaxRepPage; ++i){ var myurl = 'wod/spiel/hero/skills.php?IS_POPUP=1&SKILLPAGI_PAGE='+i; WoDTool.loader( myurl, function (dummy, t) { WoDTool.skill_L[t] = WoDTool.getSkill(dummy); }, i ); }; }, getSkill : function ( context ) { context = context || document; //英雄技能的表 var skillTable = false, skills = []; WoDTool.walker( 'th', function ( th ) { if ( th.innerHTML == '训练费' ) { skillTable = th.parentNode.parentNode; return true; } }, context); if( !skillTable ) return false; WoDTool.walker( 'a.skill_primary, a.skill_secondary, a.skill_foreign', function ( a ) { if (a.parentNode.parentNode.innerHTML.indexOf('学习') == -1) { var skill = []; skill[0] = a.innerHTML.txt(); WoDTool.walker( 'div', function ( div ) { if ( div.id.indexOf( 'skill_rang' ) != -1 ) { skill[1] = div.innerHTML.txt(); } }, a.parentNode.parentNode ); WoDTool.walker( 'span', function ( span ) { if ( span.id.indexOf( 'skill_eff_rang' ) != -1 ) { skill[1] = skill[1] + span.innerHTML.txt(); } }, a.parentNode.parentNode ); if (skill[1].indexOf( '-' ) == -1 ){ skills.push(skill); } } }, skillTable ); return skills; }, getItem : function ( context ) { context = context || document; //英雄装备的表 var itemTable = false, items = []; WoDTool.walker( 'td.texttoken',function ( td ) { if ( td.innerHTML == '头' ) { itemTable = td.parentNode.parentNode.parentNode.parentNode.parentNode; return true; } }, context ); if( !itemTable ) return false; WoDTool.walker('table tbody tr', function ( tr ) { var item =[]; var tds = mini('td',tr) // 位置 = item[0] item[0] = tds[0].innerHTML.txt(); var td = tds[1]; item[1]=[]; WoDTool.walker('select, img', function ( item_part ) { if (item_part.tagName.toLowerCase() == 'select'){ WoDTool.walker( 'option', function ( option ) { if ( option.getAttribute('selected') ) { item[1].push(['select',option.innerHTML.item_txt()]); } }, item_part ); }; if (item_part.tagName.toLowerCase() == 'img'){ // 有可裝備物品的空位 if ( ! /zustand_leer.gif$/.test(item_part.getAttribute('src'))){ item[1].push(['img',item_part.getAttribute('src')]); }; }; }, td); if (item[1].length > 0){items.push(item);}; }, itemTable ); WoDTool.items = items; return items; } }; (function () { var btn = document.createElement( 'input' ); btn.setAttribute( 'class', 'button' ); btn.setAttribute( 'type', 'button' ); btn.setAttribute( 'value', '人物卡代码' ); btn.addEventListener( "click", function () { var newdiv = document.createElement("div"); newdiv.innerHTML = "加载中"; newdiv.contentEditable = true; WoDTool.loadHeroAll().done(function () { WoDTool.skills = []; // WoDTool.skill_L[0] = 强化 / 弱化 // WoDTool.skill_L[k] = 技能第k頁 for (var i = 0; i < WoDTool.skill_L.length; ++i) { WoDTool.skills = WoDTool.skills.concat(WoDTool.skill_L[i]); } var output = "[table border=1]<br />"; var rows = Math.ceil( (WoDTool.attrs.length + WoDTool.skills.length) / 2 ); if (rows < WoDTool.attrs.length) { rows = WoDTool.attrs.length; } for (var i = 0; i < rows; ++i) { output = output + "[tr]"; if (i < WoDTool.attrs.length) { output = output + "[td][color=orange]" + WoDTool.attrs[i][0] + "[/color][/td][td]" + WoDTool.attrs[i][1] + "[/td]"; } else { var s1 = i - WoDTool.attrs.length; output = output + "[td][skill:" + WoDTool.skills[s1][0] + "][/td][td]" + WoDTool.skills[s1][1] + "[/td]"; } var s2 = i + rows - WoDTool.attrs.length; if (WoDTool.skills[s2]) { output = output + "[td][skill:" + WoDTool.skills[s2][0] + "][/td][td]" + WoDTool.skills[s2][1] + "[/td]"; } else { output = output + "[td][/td][td][/td]"; } output = output + "[/tr]<br />"; } var i = -1; while ((item = WoDTool.items[++i])) { output = output + "[tr][td][color=orange]" + item[0] + "[/color][/td][td colspan=3]"; var t = -1; while ((item_part = item[1][++t])) { if (item_part[0] == "img") { //output = output + "[img]" + item_part[1] + "[/img]"; var graft_result = pattern_graft.exec(item_part[1]); if (graft_result != null) { output = output + ":g" + graft_result[1] + ":"; } } if (item_part[0] == "select") { output = output + item_part[1][0] + "[item:" + item_part[1][1] + "]" + item_part[1][2]; } } output = output + "[/td][/tr]<br />"; } output = output + "[/table]"; newdiv.innerHTML = output; navigator.clipboard .writeText(output.replaceAll("<br />", "\n")) .then(() => { alert("人物卡已复制到剪贴板"); }) .catch((err) => { alert("不能复制人物卡到剪贴板,可能未授予剪贴板权限,请手动复制"); // This can happen if the user denies clipboard permissions: console.error("Could not copy text: ", err); }); }); this.style.display = "none"; this.parentNode.after(newdiv); }, false ); WoDTool.walker("h1", function (h1) { h1.appendChild(btn); return true; }); })();