BvS Quickfield

GPS for fields

// ==UserScript==
// @name           BvS Quickfield
// @namespace      http://userscripts.org/users/dtkarlsson
// @description    GPS for fields
// @include        http*://*animecubed.com/billy/bvs/villagefields*
// @include        http*://*animecubedgaming.com/billy/bvs/villagefields*
// @licence        MIT; http://www.opensource.org/licenses/mit-license.php
// @copyright      2009, Daniel Karlsson
// @version        1.0.4
// @history        1.0.4 New domain - animecubedgaming.com - Channel28
// @history        1.0.3 Now https compatible (Updated by Channel28)
// @history        1.0.2 Fixed various issues (Updated by Sena)
// @history        1.0.1 Added grant permissions (Updated by Channel28)
// @history        1.0.0 Changed to a more console-y design
// @history        1.0.0 Simplified field reordering
// @history        1.0.0 Script now calculates field difficulty range
// @history        1.0.0 Minor tweaks here and there
// @history        0.3.0 Added key reordering by drag and drop
// @history        0.2.0 Change from GM_set/getValue to DOM Storage API
// @history        0.2.0 Redesigned the UI
// @grant          GM_log
// @grant          GM_addStyle
// ==/UserScript==
 
/*
        DOM Storage wrapper class
        Constructor:
                var store = new DOMStorage({"session"|"local"}, [<namespace>]);
        Set item:
                store.setItem(<key>, <value>);
        Get item:
                store.getItem(<key>[, <default value>]);
        Remove item:
                store.removeItem(<key>);
        Get all keys in namespace as array:
                var array = store.keys();
*/
function DOMStorage(type, namespace)
{
        var my = this;
       
        if (typeof(type) != "string")
                type = "session";
        switch (type) {
                case "local": my.storage = localStorage; break;
                case "session": my.storage = sessionStorage; break;
                default: my.storage = sessionStorage;
        }
       
        if (!namespace || typeof(namespace) != "string")
                namespace = "Greasemonkey";
 
        my.ns = namespace + ".";
        my.setItem = function(key, val) {
                try {
                        my.storage.setItem(encodeURIComponent(my.ns + key), val);
                }
                catch (e) {
                        GM_log(e);
                }
        },
        my.getItem = function(key, def) {
                try {
                        var val = my.storage.getItem(encodeURIComponent(my.ns + key));
                        if (val)
                                return val;
                        else
                                return def;
                }
                catch (e) {
                        return def;
                }
        }
        my.removeItem = function(key) {
                try {
                        // Kludge, avoid Firefox crash
                        my.storage.setItem(encodeURIComponent(my.ns + key), null);
                }
                catch (e) {
                        GM_log(e);
                }
        }
        my.keys = function() {
                // Return array of all keys in this namespace
                var arr = [];
                var i = 0;
                do {
                        try {
                                if (i>my.storage.length) {
                                        throw 'error';
                                }
                                var key = decodeURIComponent(my.storage.key(i));
                                if (key.indexOf(my.ns) == 0)
                                        arr.push(key.slice(my.ns.length));
                        }
                        catch (e) {
                                break;
                        }
                        i++;
                } while (true);
                return arr;
        }
}
var DS = new DOMStorage("local", "BvSQuickfield");
 
const KEYDIFF = {
        simple: 0, training: 0, aquafield: 0,
        dimlylit: 5, crumbling: 5, dealersroom: 5,
        blaring: 10, hairy: 10, parkinglot: 10,
        pulsating: 15, worst: 15, core: 15,
        hidden: 20, forbidden: 20, holyground: 20,
        darkside: 20,
        raging: 25, passionate: 25, melody: 25,
        cursed: 40, filthy: 40, noodleshop: 40,
        chosen: 60, hopeless: 60, nothingness: 60,
        brilliant: 65, delicious: 65, dancefloor: 65,
        beautiful: 70, passedover: 70, touchstone: 70,
        corrupted: 80, despaired: 80, paradise: 80,
        sickened: 100, imprisoned: 100, fallenangel: 100,
        merciless: 130, grieving: 130, furnace: 130
};
 
function Field()
{
        var my = this;
 
        my.keys = [];
        my.notes = "";
       
        my.unpack = function(str) {
                if (!str || typeof(str) != "string")
                        return false;
                // Restore from string "<key>|<key>|<key>|<notes>"
                var match = str.match(/(.*)\|(.*)\|(.*)\|(.*)/);
                if (match) {
                        var field = new Field();
                        my.keys = [];
                        my.keys[0] = match[1];
                        my.keys[1] = match[2];
                        my.keys[2] = match[3];
                        my.notes = match[4];
                        return true;
                }
                return false;
        }
        my.pack = function() {
                // Return string "<key>|<key>|<key>|<notes>"
                return my.keys.join("|") + "|" + my.notes;
        }
        my.difficulty = function() {
                return KEYDIFF[keyStyle(my.keys[0])] + KEYDIFF[keyStyle(my.keys[1])] +
                        KEYDIFF[keyStyle(my.keys[2])];
        }
}
 
function FieldList()
{
        var my = this;
       
        my.fields = [];
        my.load = function(store) {
                my.fields = [];
                var keys = store.keys();
                for (var i in keys) {
                        if (/field(\d+)/.test(keys[i])) {
                                var index = parseInt(RegExp.lastParen);
                                var field = new Field();
                                if (field.unpack(store.getItem(keys[i])))
                                        my.fields[index] = field;
                                else
                                        store.removeItem(keys[i]);
                        } else
                                store.removeItem(keys[i]);
                }
        }
        my.save = function(store) {
                var keys = store.keys();
                for (var i in keys)
                        store.removeItem(keys[i]);
                var i = 0;
                for (var j in my.fields) {
                        store.setItem("field" + i, my.fields[j].pack());
                        i++;
                }
        }
}
var FIELDLIST = new FieldList();
FIELDLIST.load(DS);
 
// Event handlers
 
// Update Add button and difficulty hint
function updateDifficulty()
{
        var f = new Field();
        f.keys = getField();
 
        var dnode = document.evaluate("//form/table/tbody/tr/td[@colspan='2'][contains(text(), 'Stamina')]", document, null,
                XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
        if (dnode) {
                var d = f.difficulty();
                var sta = dnode.textContent.replace(/Stamina.*/, "Stamina");
                dnode.textContent = sta + ", Difficulty: " + d + " - " + (d + 5) + ")";
        }
 
        var button = document.getElementById("addfield");
        if (button)
                button.textContent = "Add " + f.keys.join(" - ");
}
 
function buttonClick(event)
{
        var id = event.target.getAttribute("id");
        if (/remove(\d+)/.test(id)) {
                var index = parseInt(RegExp.lastParen);
                removeField(index);
        } else if (/setfield(\d+)/.test(id)) {
                var index = parseInt(RegExp.lastParen);
                setField(FIELDLIST.fields[index].keys);
                updateDifficulty();
        } else if (/addfield/.test(id)) {
                addField();
        }
}
 
var dragging = null;
var hover = null;
var prevHover = null;
function mousedownEvent(event)
{
        // Find td with class = "key"
        var cl = event.target.getAttribute("class");
        if (!/key/.test(cl))
                return;
 
        // Get parent tr
        dragging = event.target.parentNode;
        event.preventDefault();
        window.addEventListener('mouseup', mouseupEvent, true);
        window.addEventListener('mousemove', moveEvent, true);
}
 
function moveEvent(event)
{
        if (!dragging)
                return;
        event.preventDefault();
        var cl = event.target.getAttribute("class");
        if (!/key/.test(cl)) {
                window.removeEventListener('mouseup', mouseupEvent, true);
                window.removeEventListener('mousemove', moveEvent, true);
                dragging = null;
                hover = null;
                prevHover = null;
        }
        hover = event.target.parentNode;
 
        var r1 = parseInt(dragging.id.replace(/row/, ""));
        var r2 = parseInt(hover.id.replace(/row/, ""));
        if (r1 != r2) {
                var f = FIELDLIST.fields[r1];
                FIELDLIST.fields[r1] = FIELDLIST.fields[r2];
                FIELDLIST.fields[r2] = f;
                FIELDLIST.save(DS);
                updateTable();
                dragging = hover;
        }
}
 
function mouseupEvent(event)
{
        if (!dragging)
                return;
        window.removeEventListener('mouseup', mouseupEvent, true);
        window.removeEventListener('mousemove', moveEvent, true);
 
        dragging = null;
        hover = null;
        prevHover = null;
}
 
// UI
 
// Return currently selected item from dropdown
function getSelectedItem(xpath)
{
        var dropdown = document.evaluate(xpath, document, null,
                XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
        return dropdown.options[dropdown.selectedIndex].text;
}
 
// Current field keys
function getField()
{
        var keys = [];
        keys[0] = getSelectedItem("//select[@name='key_1']");
        keys[1] = getSelectedItem("//select[@name='key_2']");
        keys[2] = getSelectedItem("//select[@name='key_3']");
        return keys;
}
 
// Set field keys
function setField(keys)
{
        for (var i = 0; i < 3; i++) {
                var dropdown = document.evaluate("//select[@name='key_" + (i + 1) + "']", document,
                        null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
                for (var j in dropdown.options)
                        if (dropdown.options[j].text == keys[i]) {
                                dropdown.selectedIndex = j
                                break;
                        }
        }
        uselessCrap(keys, "cd ");
}
 
// Add a field to DB
function addField(keys)
{
        if (!keys)
                keys = getField();
 
        var notes = prompt("Notes for " + keys.join(" - "), "-");
        if (notes) {
                var field = new Field();
                field.keys = keys;
                field.notes = notes;
                FIELDLIST.fields.push(field);
                FIELDLIST.save(DS);
                updateTable();
                uselessCrap(keys, "mkdir -p ");
        }
}
 
// Change field notes
function changeNotes(index)
{
        var notes = prompt("Notes for " + FIELDLIST.fields[index].keys.join(" - "),
                FIELDLIST.fields[index].notes);
        if (notes) {
                FIELDLIST.fields[index].notes = notes;
                FIELDLIST.save(DS);
                updateTable();
        }
}
 
// Remove a field from DB
function removeField(index)
{
        if (FIELDLIST.fields[index] && confirm("Remove field " + FIELDLIST.fields[index].keys.join(" - ") + "?")) {
                var keys = FIELDLIST.fields[index].keys;
                FIELDLIST.fields.splice(index, 1);
                FIELDLIST.save(DS);
                updateTable();
                uselessCrap(keys, "rm -rf ");
        }
}
 
// Create the UI table
function createTable()
{
        var addtable = document.getElementById("quickfield");
        if (!addtable) {
                addtable = document.createElement("table");
                addtable.setAttribute("id", "quickfield");
                addtable.innerHTML = '<caption><span id="cli">//Quickfield</span>' +
                        '<span class="blink">_</span></caption>' +
                        '<col width="auto"/><col/><col/><col/>' +
                        '<col/><col width="auto"/><thead><tr><td/><td>Key 1</td><td>Key 2</td>' +
                        '<td>Key 3</td><td>Notes</td><td/></tr></thead><tfoot><tr><td colspan="6">' +
                        '<div id="addfield">Add Field</div></td></tr></tfoot><tbody/>';
        }
 
        var form = document.evaluate("//form[@name='field']", document, null,
                XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
        form.parentNode.appendChild(addtable);
       
        document.getElementById("addfield").addEventListener('click', buttonClick, false);
 
        updateTable();
}
 
// Helper: create TD with class=cls and style=sty
function tableData(html, cls, sty)
{
        var td = document.createElement("td");
        td.innerHTML = html;
        if (cls)
                td.setAttribute("class", cls);
        if (sty)
                td.setAttribute("style", sty);
        return td;
}
 
// Helper: remove non-alpha characters and convert to lower case
function keyStyle(key)
{
        if (key) {
                return key.replace(/\W/g, "").toLowerCase();
        }
        return "";
}
 
// Create a div with class="button" and attach eventlistener
function createButton(text, id, onclick)
{
        var div = document.createElement("div");
        div.appendChild(document.createTextNode(text));
        div.setAttribute("class", "button");
        div.setAttribute("id", id);
        div.addEventListener('click', onclick, false);
        return div;
}
 
// Create a field row
function tableRow(n, key1, key2, key3, notes)
{
        n = parseInt(n);
        var tr = document.createElement("tr");
        tr.setAttribute("id", "row" + n);
       
        var td = document.createElement("td");
        var b = createButton("X", "remove" + n, buttonClick);
        b.setAttribute("title", "Remove Field");
        td.appendChild(b);
        tr.appendChild(td);
        tr.appendChild(tableData(key1, "key " + keyStyle(key1)));
        tr.appendChild(tableData(key2, "key " + keyStyle(key2)));
        tr.appendChild(tableData(key3, "key " + keyStyle(key3)));
 
        td = document.createElement("td");
        td.setAttribute("class", "notes");
        td.appendChild(document.createTextNode(notes));
        td.addEventListener('mousedown', function(event) {changeNotes(n);}, false);
        tr.appendChild(td);
       
        td = document.createElement("td");
        b = createButton("Set", "setfield" + n, buttonClick);
        b.setAttribute("title", "Set Field");
        td.appendChild(b);
        tr.appendChild(td);
 
        return tr;
}
 
// Updates UI table, creates and removes rows if needed
function updateTable()
{
        var tbody = document.getElementById("quickfield").getElementsByTagName("tbody")[0];
        tbody.innerHTML = "";
       
        var i;
        for (i in FIELDLIST.fields) {
                var tr = document.getElementById("row" + i);
                if (tr) {
                        // Row exists, update content
                        var tds = tr.getElementsByTagName("td");
                        for (var k = 0; k < 3; k++) {
                                tds[k + 1].textContent = FIELDLIST.fields[i].keys[k];
                                tds[k + 1].setAttribute("class",  "key " + keyStyle(FIELDLIST.fields[i].keys[k]));
                        }
                        tds[4].textContent = FIELDLIST.fields[i].notes;
                        tds[4].setAttribute("title", "Difficulty: " + FIELDLIST.fields[i].difficulty() + " - " +
                                (FIELDLIST.fields[i] + 5));
                } else {
                        // Create new row
                        tr = tableRow(i, FIELDLIST.fields[i].keys[0], FIELDLIST.fields[i].keys[1],
                                FIELDLIST.fields[i].keys[2], FIELDLIST.fields[i].notes);
                        tr.getElementsByTagName("td")[4].setAttribute("title",
                                "Difficulty: " + FIELDLIST.fields[i].difficulty() + " - " +
                                (FIELDLIST.fields[i].difficulty() + 5));
                        tbody.appendChild(tr);
                }
        }
        // Remove remaining rows
        do {
                var tr = document.getElementById("row" + (++i));
                if (tr)
                        tr.parentNode.removeChild(tr);
        } while (tr);
}
 
var tehStuff = {};
function uselessCrap(keys, pre)
{
        if (tehStuff.timer)
                clearTimeout(tehStuff.timer);
        tehStuff.i = 0;
        tehStuff.str = pre;
        if (keys) {
                tehStuff.str += keys.join("/").replace(/\s/g, "_").toLowerCase().replace(/[^a-z_\/]/g, "");
        }
        tehStuff.el = document.getElementById("cli");
        tehStuff.timer = setTimeout(moarCrap, 50);
}
function moarCrap()
{
        if (tehStuff.i > tehStuff.str.length) {
                tehStuff.timer = null;
        } else {
                tehStuff.el.textContent = "# " + tehStuff.str.substr(0, tehStuff.i++);
                tehStuff.timer = setTimeout(moarCrap, 50);
        }
}
 
GM_addStyle("table#quickfield {width: 100%; background-color: black; color: rgb(33%, 100%, 0%); border-collapse: collapse; font-size: 12px;}");
GM_addStyle("#quickfield thead {font-weight: bold;}");
GM_addStyle("#quickfield caption {background-color: black; font-size: 18px; font-weight: bold; margin-top: 6px;}");
GM_addStyle("#quickfield td {border: 1px solid black; text-align: center;}");
GM_addStyle("#quickfield input {width: auto;}");
GM_addStyle("#quickfield td.key {font-variant: small-caps; cursor: move;}");
GM_addStyle("#quickfield td.notes {color: rgb(100%, 66%, 0%); cursor: pointer;}");
GM_addStyle("#addfield {border: 1px solid rgb(25%, 75%, 0%); background-color: black; color: rgb(25%, 75%, 0%); cursor: pointer;}");
GM_addStyle("#addfield:hover {border: 1px solid rgb(33%, 100%, 0%); background-color: rgb(16%, 50%, 0%); color: rgb(33%, 100%, 0%);}");
GM_addStyle("div.button {border: 1px solid rgb(25%, 75%, 0%); background-color: black; color: rgb(25%, 75%, 0%); cursor: pointer;}");
GM_addStyle("div.button:hover {border: 1px solid rgb(33%, 100%, 0%); background-color: rgb(16%, 50%, 0%); color: rgb(33%, 100%, 0%);}");
GM_addStyle("span.blink {text-decoration: blink;}"); // YA RLY
 
// tier 1 key style
GM_addStyle(".simple {color: #FFFFFF; background-color: #006600;}");
GM_addStyle(".training {color: #FFFFFF; background-color: #006666;}");
GM_addStyle(".aquafield {color: #FFFFFF; background-color: #006600;}");
 
// tier 2 key style
GM_addStyle(".dimlylit {color: #FFFFFF; background-color: #006666;}");
GM_addStyle(".crumbling {color: #FFFFFF; background-color: #006600;}");
GM_addStyle(".dealersroom {color: #FFFFFF; background-color: #006666;}");
 
// tier 3 key style
GM_addStyle(".blaring {color: #FFFFFF; background-color: #660000;}");
GM_addStyle(".hairy {color: #FFFFFF; background-color: #660000;}");
GM_addStyle(".parkinglot {color: #FFFFFF; background-color: #660000;}");
 
// tier 4 key style
GM_addStyle(".pulsating {color: #FFFFFF; background-color: #666600;}");
GM_addStyle(".worst {color: #FFFFFF; background-color: #663300;}");
GM_addStyle(".core {color: #FFFFFF; background-color: #666666;}");
 
// tier 5 key style
GM_addStyle(".hidden {color: #000000; background-color: #CCCC00;}");
GM_addStyle(".forbidden {color: #000000; background-color: #CCCC00;}");
GM_addStyle(".holyground {color: #000000; background-color: #CCCC00;}");
 
// tier 6 key style
GM_addStyle(".raging {color: #000000; background-color: #CC0000;}");
GM_addStyle(".passionate {color: #000000; background-color: #CC0000;}");
GM_addStyle(".melody {color: #000000; background-color: #CC0000;}");
 
// tier 7 key style
GM_addStyle(".cursed {color: #FFFFFF; background-color: #006666;}");
GM_addStyle(".filthy {color: #FFFFFF; background-color: #006666;}");
GM_addStyle(".noodleshop {color: #FFFFFF; background-color: #006666;}");
 
// tier 8 key style
GM_addStyle(".chosen {color: #FFFFFF; background-color: #000000;}");
GM_addStyle(".hopeless {color: #FFFFFF; background-color: #000000;}");
GM_addStyle(".nothingness {color: #FFFFFF; background-color: #000000;}");
 
// tier 9 key style
GM_addStyle(".brilliant {color: #FFFFCC; background-color: #666600;}");
GM_addStyle(".delicious {color: #FFFFCC; background-color: #666600;}");
GM_addStyle(".dancefloor {color: #FFFFCC; background-color: #666600;}");
 
// tier 10 key style
GM_addStyle(".beautiful {color: #FFCCCC; background-color: #660000;}");
GM_addStyle(".passedover {color: #FFCCCC; background-color: #660000;}");
GM_addStyle(".touchstone {color: #FFCCCC; background-color: #660000;}");
 
// tier 11 key style
GM_addStyle(".corrupted {color: #660000; background-color: #FF5555;}");
GM_addStyle(".despaired {color: #660000; background-color: #FF5555;}");
GM_addStyle(".paradise {color: #660000; background-color: #FF5555;}");
 
// tier 12 key style
GM_addStyle(".sickened {color: #222222; background-color: #DDDDDD;}");
GM_addStyle(".imprisoned {color: #222222; background-color: #DDDDDD;}");
GM_addStyle(".fallenangel {color: #222222; background-color: #DDDDDD;}");
 
createTable();
document.getElementById("quickfield").addEventListener('mousedown', mousedownEvent, true);
for (var i = 1; i < 4; i++) {
        var input = document.evaluate("//select[@name='key_" + i + "']", document, null,
                XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
        if (input)
                input.addEventListener('change', updateDifficulty, false);
}
updateDifficulty();

QingJ © 2025

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