桌游模拟器营地牌表导出工具

在营地牌表页添加导出为桌游模拟器存档的按钮

目前为 2020-07-03 提交的版本。查看 最新版本

// ==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;
}

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址