您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
在营地牌表页添加导出为桌游模拟器存档的按钮
// ==UserScript== // @name 桌游模拟器营地牌表导出工具 // @namespace http://www.iyingdi.com/ // @version 0.3 // @description 在营地牌表页添加导出为桌游模拟器存档的按钮 // @author hyper // @match https://www.iyingdi.com/** // @grant none // ==/UserScript== async function init(){ let added; window.addEventListener("popstate",() => added = undefined); while(true){ await new Promise(r => setTimeout(r, 1000)); if(added == location.href)continue; if(!location.href.match("deck(d|D)etail")){ added = undefined; continue; } const actionBox = $('.deck-detail-box .action-box, .mainDeckArea .action-box'); if(!actionBox.length)continue; createSaveBtn(actionBox); added = location.href; } } init(); async function createSaveBtn(actionBox){ if($("#tts-export").length)return null; const [name,data] = await getSave(getCards()); const href = window.URL.createObjectURL(new Blob([data]), { type: "text/plain" }); const e = $(`<div id="tts-export" class="btn-item-w"><a href="${href}" download="${name}">导出桌游模拟器存档</a></div>`); actionBox.append(e); } function getCards(){ const cards = Array.from($('.card.inline-block')).map(c => { const sideboard = c.parentElement.previousSibling.innerText.startsWith("备牌"); const image = c.dataset.image; const id = c.dataset.value; const num = parseInt(c.querySelector('.count').innerText.slice(1)) || 1; return [id, image, sideboard, num]; }); return cards; } async function getSave(cards){ const main = []; const side = []; let s = 1; await Promise.all(cards.map(async (c,i) => { let [id, image, sideboard, num] = c; const url = 'https://www.iyingdi.com/magic/card/' + id; const res = await fetch(url); const json = await res.json(); image = image || json.card.img; const stats = json.card.clazz == '生物' ? `\n${json.card.attack}/${json.card.defense}` : '\n'; const nickname = `${json.card.cname || json.card.ename} - ${json.card.mana}${stats}${json.card.mainType} ~ ${json.card.subType}`; const description = `${json.card.rule}`; for(let j = 0; j < num; j ++){ const card = makeTTSCard({name: nickname, oracle: description, face: image, id: s++}); if(sideboard)side.push(card); else main.push(card); } })); const md = makeTTSDeck(main); md.Nickname = '主牌'; const sd = makeTTSDeck(side); sd.Nickname = '备牌'; sd.Transform.posX = 3; const save = makeTTSSave(md,sd); const name = `[${$('.formatName .format, .format-name .format').text()}]${$('.formatName .name.inline-block, .format-name .name.inline-block').text()} - ${$('.basicInfo .player, .deck-info-box .player').text().slice(3)}`; //download(name + ".json", JSON.stringify(save, null, 4)); return [name + ".json", JSON.stringify(save, null, 4)]; } function download(filename, text) { var element = document.createElement('a'); element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text)); element.setAttribute('download', filename); element.style.display = 'none'; document.body.appendChild(element); element.click(); document.body.removeChild(element); } function makeTTSCard({name, oracle, face, id}){ const card = clone(TTSCard); card.Nickname = name; card.Description = oracle; card.CardID = id * 100; card.CustomDeck = {}; card.CustomDeck[id] = { FaceURL: face, BackURL: "http://ww1.sinaimg.cn/large/8239391egy1gg9acxj0ryj207d0aldj7.jpg", "NumWidth": 1, "NumHeight": 1, "BackIsHidden": true, "UniqueBack": false, "Type": 0 }; card.GUID = Math.random().toString(16).slice(-6); return card; } function makeTTSDeck(cards){ const deck = clone(TTSDeck); deck.DeckIDs = cards.map(c => c.CardID); deck.CustomDeck = cards.reduce((a,b) => clone(a, b.CustomDeck), {}); deck.ContainedObjects = cards; deck.GUID = Math.random().toString(16).slice(-6); return deck; } function makeTTSSave(...ObjectStates){ return clone(TTS, {ObjectStates}); } const TTS = { "SaveName": "", "GameMode": "", "Date": "", "Gravity": 0.5, "PlayArea": 0.5, "GameType": "", "GameComplexity": "", "Tags": [], "Table": "", "Sky": "", "Note": "", "Rules": "", "TabStates": {}, "LuaScript": "", "LuaScriptState": "", "XmlUI": "", "VersionNumber": "", } const TTSDeck = { "Name": "Deck", "Transform": { "posX": 0, "posY": 0, "posZ": 0, "rotX": 0, "rotY": 180, "rotZ": 180.0, "scaleX": 1.0, "scaleY": 1.0, "scaleZ": 1.0 }, "Nickname": "", "Description": "", "GMNotes": "", "ColorDiffuse": { "r": 0.713235259, "g": 0.713235259, "b": 0.713235259 }, "Locked": false, "Grid": true, "Snap": true, "IgnoreFoW": false, "MeasureMovement": false, "DragSelectable": true, "Autoraise": true, "Sticky": true, "Tooltip": true, "GridProjection": false, "HideWhenFaceDown": true, "Hands": false, "SidewaysCard": false, "LuaScript": "", "LuaScriptState": "", "XmlUI": "", } const TTSCard = { "Name": "Card", "Transform": { "posX": 0, "posY": 0, "posZ": 0, "rotX": 0, "rotY": 180, "rotZ": 180.0, "scaleX": 1.0, "scaleY": 1.0, "scaleZ": 1.0 }, "Nickname": "", "Description": "", "GMNotes": "", "ColorDiffuse": { "r": 0.713235259, "g": 0.713235259, "b": 0.713235259 }, "Locked": false, "Grid": true, "Snap": true, "IgnoreFoW": false, "MeasureMovement": false, "DragSelectable": true, "Autoraise": true, "Sticky": true, "Tooltip": true, "GridProjection": false, "HideWhenFaceDown": true, "Hands": true, "CardID": 0, "SidewaysCard": false, "LuaScript": "", "LuaScriptState": "", "XmlUI": "" }; function clone(...objs){ const obj = {} for(const one of objs){ for(const key in one){ obj[key] = one[key]; } } return obj; }