?

Log in

No account? Create an account

Murkon's Refuge on steroids

« previous entry | next entry »
Jun. 24th, 2014 | 10:25 pm

I've continued playing Murkon's Refuge for a while again, and the Greasemonkey script I'd started quickly grew into something much larger, with several useful bits of functionality. Since I've lost much interest in the game again in the last few days (this always happens), I'd like to go ahead and share the current revision of the Greasemonkey script.

// ==UserScript==
// @name        Murkon's Refuge on Steroids
// @namespace   None
// @include     http://rinkworks.com/vault/games/refuge/refuge.cgi
// @include     http://*.rinkworks.com/vault/games/refuge/refuge.cgi
// @version     6
// @grant       none
// ==/UserScript==

// ### USER CONFIGURATION SECTION ###

var autodropEnabled = true;
var autodropCutOff = 100000; // suggested: 100000 for XP farming, 20000 for gold farming

var neverDrop = new Object();
neverDrop["Amulet Half"]          = true;
neverDrop["Bronze Key"]           = true;
neverDrop["Death's Key"]          = true;
neverDrop["Gatekeeper's Key"]     = true;
neverDrop["Gold Key"]             = true;
neverDrop["Pass Gem"]             = true;
neverDrop["Proper Authorization"] = true;
neverDrop["Silver Key"]           = true;
neverDrop["Stone of Passage"]     = true;

var autotradeEnabled = true;
var autotradeCutOff = 100000; // suggested: same as autodropCutoff

var neverTrade = new Object();
neverTrade["Death's Key"] = true;

var neverSell = new Object();
neverSell["Amulet Half"]          = true;
neverSell["Bronze Key"]           = true;
// suggested: keep Death's Key sellable, as it's useful for gold and XP farming.
neverSell["Gatekeeper's Key"]     = true;
neverSell["Gold Key"]             = true;
neverSell["Pass Gem"]             = true;
neverSell["Proper Authorization"] = true;
neverSell["Silver Key"]           = true;
neverSell["Stone of Passage"]     = true;

// #####################################################
// ### NO NEED TO CONFIGURE ANYTHING BELOW THIS LINE ###
// #####################################################

// ### VARIABLES ###

// item prices are for the town of Teralt
var itemPrices = new Object();
itemPrices["Amulet Half"]             = 5;
itemPrices["Anointed Crossbow"]       = 82500;
itemPrices["Anointed Dagger"]         = 487;
itemPrices["Anti-Cold Leather"]       = 42750;
itemPrices["Anti-Heat Leather"]       = 43875;
itemPrices["Anti-Heat Leather +1"]    = 63750;
itemPrices["Anti-Cold Shield"]        = 17062;
itemPrices["Anti-Heat Shield"]        = 17062;
itemPrices["Assassin's Boots"]        = 525000;
itemPrices["Assassin's Robe"]         = 354375;
itemPrices["Blade of Power"]          = 750000;
itemPrices["Blanket of Silence"]      = 1875;
itemPrices["Boots of Agility"]        = 13312;
itemPrices["Boots of Agility +1"]     = 31687;
itemPrices["Boots of Agility +2"]     = 60000;
itemPrices["Boots of Healing"]        = 225000;
itemPrices["Boots of Maneuvering"]    = 330000;
itemPrices["Boots of Speed +1"]       = 48937;
itemPrices["Boots of Speed"]          = 26250;
itemPrices["Boots of Speed +1"]       = 48937;
itemPrices["Bow and Arrows"]          = 1425;
itemPrices["Breast Plate"]            = 675;
itemPrices["Breast Plate +1"]         = 1687;
itemPrices["Breast Plate +2"]         = 5625;
itemPrices["Bright Stone"]            = 375;
itemPrices["Bronze Gauntlets"]        = 4125;
itemPrices["Bronze Gauntlets +1"]     = 9000;
itemPrices["Bronze Gauntlets +2"]     = 33562;
itemPrices["Bronze Helmet"]           = 2137;
itemPrices["Bronze Helmet +1"]        = 5625;
itemPrices["Bronze Helmet +2"]        = 13875;
itemPrices["Bronze Key"]              = 5;
itemPrices["Buckler"]                 = 75;
itemPrices["Buckler +1"]              = 2250;
itemPrices["Buckler +2"]              = 7500;
itemPrices["Cap of I.Q."]             = 11250;
itemPrices["Cap of I.Q. +1"]          = 26250;
itemPrices["Cap of I.Q. +2"]          = 41250;
itemPrices["Cap of Vision"]           = 19875;
itemPrices["Cap of Wisdom"]           = 11625;
itemPrices["Cap of Wisdom +1"]        = 26625;
itemPrices["Cap of Wisdom +2"]        = 41625;
itemPrices["Chain Mail"]              = 412;
itemPrices["Chain Mail +1"]           = 1312;
itemPrices["Chain Mail +2"]           = 4875;
itemPrices["Cloak of Healing"]        = 166875;
itemPrices["Cloth Hood"]              = 225;
itemPrices["Cloth Slippers"]          = 1312;
itemPrices["Cloth Slippers +1"]       = 2812;
itemPrices["Combat Gloves"]           = 363750;
itemPrices["Cooler Shield"]           = 58125;
itemPrices["Copper Gauntlets"]        = 975;
itemPrices["Copper Gauntlets +1"]     = 7125;
itemPrices["Copper Gauntlets +2"]     = 16500;
itemPrices["Copper Helmet"]           = 337;
itemPrices["Copper Helmet +1"]        = 3000;
itemPrices["Copper Helmet +2"]        = 7687;
itemPrices["Crossbow"]                = 28500;
itemPrices["Dagger"]                  = 15;
itemPrices["Dagger +1"]               = 262;
itemPrices["Dagger +2"]               = 900;
itemPrices["Darts"]                   = 525;
itemPrices["Death's Key"]             = 187500;
itemPrices["Deflector Shield"]        = 26250;
itemPrices["Displacer Hide"]          = 6562;
itemPrices["Dome Stone"]              = 1500;
itemPrices["Dreamer's Stone"]         = 2437;
itemPrices["Druid's Garb"]            = 600000;
itemPrices["Druid's Hood"]            = 412500;
itemPrices["Empty Stone"]             = 0; // no, really.
itemPrices["Evolving Figurine"]       = 11625;
itemPrices["Fire Arc Stone"]          = 1305;
itemPrices["Fire Bolt Scroll"]        = 75;
itemPrices["Fire Lance Scroll"]       = 322;
itemPrices["Fire Stream Stone"]       = 2250;
itemPrices["Fire Wand"]               = 73125;
itemPrices["Flail"]                   = 87;
itemPrices["Flail +1"]                = 1425;
itemPrices["Flail +2"]                = 7312;
itemPrices["Flamberge"]               = 5587;
itemPrices["Full-Leg Boots"]          = 6000;
itemPrices["Gatekeeper's Key"]        = 5;
itemPrices["Gloves of Dexterity"]     = 15000;
itemPrices["Gloves of Dexterity +1"]  = 33937;
itemPrices["Gloves of Dexterity +2"]  = 62812;
itemPrices["Gloves of Speed"]         = 22500;
itemPrices["Gloves of Speed +1"]      = 56625;
itemPrices["Gloves of Speed +2"]      = 97500;
itemPrices["Gloves of Strength"]      = 15000;
itemPrices["Gloves of Strength +1"]   = 33937;
itemPrices["Gloves of Strength +2"]   = 62812;
itemPrices["Gold Key"]                = 5;
itemPrices["Health Amulet"]           = 86250;
itemPrices["Heater Shield"]           = 58125;
itemPrices["Heavy Boots"]             = 132;
itemPrices["Heavy Cloak"]             = 42;
itemPrices["Heavy Healing Potion"]    = 4725;
itemPrices["Helmet of Healing"]       = 67500;
itemPrices["Homing Stone"]            = 3750;
itemPrices["Hovering Shield"]         = 9375;
itemPrices["Ice Arc Stone"]           = 1305;
itemPrices["Ice Bolt Scroll"]         = 75;
itemPrices["Ice Lance Scroll"]        = 322;
itemPrices["Ice Stream Stone"]        = 2250;
itemPrices["Information Highway"]     = 675;
itemPrices["Iron Armor"]              = 3750;
itemPrices["Iron Boots"]              = 3750;
itemPrices["Iron Gauntlets"]          = 4500;
itemPrices["Iron Gauntlets +1"]       = 8437;
itemPrices["Iron Helmet"]             = 2437;
itemPrices["Iron Shield"]             = 4312;
itemPrices["Iron Shield +1"]          = 20062;
itemPrices["Knight's Crest"]          = 225000;
itemPrices["Knight's Suit"]           = 450000;
itemPrices["Large Shield"]            = 357;
itemPrices["Large Shield +1"]         = 1875;
itemPrices["Leather Armor"]           = 150;
itemPrices["Leather Armor +1"]        = 1125;
itemPrices["Leather Armor +2"]        = 3937;
itemPrices["Leather Boots"]           = 150;
itemPrices["Leather Boots +1"]        = 1687;
itemPrices["Leather Boots +2"]        = 4912;
itemPrices["Leather Boots +3"]        = 9562;
itemPrices["Leather Cap"]             = 60;
itemPrices["Leather Cap +1"]          = 1050;
itemPrices["Leather Cap +2"]          = 7312;
itemPrices["Leather Cap +3"]          = 29625;
itemPrices["Leather Gloves"]          = 187;
itemPrices["Leather Gloves +1"]       = 2437;
itemPrices["Leather Gloves +2"]       = 6562;
itemPrices["Light Armor"]             = 17625;
itemPrices["Light Healing Potion"]    = 95;
itemPrices["Light Sword"]             = 71812;
itemPrices["Location Scroll"]         = 72;
itemPrices["Long Sword"]              = 207;
itemPrices["Long Sword +1"]           = 1837;
itemPrices["Long Sword +2"]           = 12375;
itemPrices["Long Sword +3"]           = 22125;
itemPrices["Magic Cloth Gloves"]      = 275625;
itemPrices["Mail Boots"]              = 1387;
itemPrices["Mail Boots +1"]           = 2382;
itemPrices["Mail Boots +2"]           = 5362;
itemPrices["Mail Boots +3"]           = 13500;
itemPrices["Mail Boots +4"]           = 33750;
itemPrices["Mail Gauntlets"]          = 450;
itemPrices["Mail Gauntlets +1"]       = 5437;
itemPrices["Mail Gauntlets +2"]       = 10500;
itemPrices["Moderate Healing Potion"] = 252;
itemPrices["Orientation Scroll"]      = 65;
itemPrices["Pass Gem"]                = 5;
itemPrices["Plate Armor"]             = 937;
itemPrices["Plate Armor +1"]          = 2437;
itemPrices["Plate Armor +2"]          = 6750;
itemPrices["Plate Armor +3"]          = 19875;
itemPrices["Poison Arc Stone"]        = 5625;
itemPrices["Poison Darts"]            = 7500;
itemPrices["Poison Stream Stone"]     = 2362;
itemPrices["Poison Wand"]             = 75000;
itemPrices["Proper Authorization"]    = 5;
itemPrices["Quivering Wand"]          = 5400;
itemPrices["Reclaiming Amulet"]       = 1462;
itemPrices["Restoration Amulet"]      = 12750;
itemPrices["Robes"]                   = 15;
itemPrices["Robes +1"]                = 750;
itemPrices["Robes +2"]                = 4500;
itemPrices["Rod of Catastrophe"]      = 168750;
itemPrices["Rogue's Cowl"]            = 300000;
itemPrices["Salve of Emanation"]      = 60000;
itemPrices["Samurai Sword"]           = 107062;
itemPrices["Scroll of Calamity"]      = 33975;
itemPrices["Scroll of Great Pain"]    = 712;
itemPrices["Scroll of Hovering"]      = 200;
itemPrices["Scroll of Light"]         = 35;
itemPrices["Scroll of Mass Pain"]     = 2625;
itemPrices["Scroll of Pain"]          = 90;
itemPrices["Scroll of Pounding"]      = 52500;
itemPrices["Scroll of Protection"]    = 282;
itemPrices["Scroll of Shielding"]     = 525;
itemPrices["Shield +1"]               = 2100;
itemPrices["Shield +2"]               = 4500;
itemPrices["Shield +3"]               = 19875;
itemPrices["Shield +4"]               = 48750;
itemPrices["Shield of Healing"]       = 56250;
itemPrices["Short Sword"]             = 112;
itemPrices["Short Sword +1"]          = 1500;
itemPrices["Short Sword +2"]          = 7500;
itemPrices["Short Sword +3"]          = 18750;
itemPrices["Silver Key"]              = 5;
itemPrices["Small Shield"]            = 207;
itemPrices["Small Shield +1"]         = 1687;
itemPrices["Small Shield +2"]         = 4312;
itemPrices["Snow Wand"]               = 73125;
itemPrices["Sorcerer's Gloves"]       = 405000;
itemPrices["Sorcerer's Hood"]         = 318750;
itemPrices["Staff"]                   = 27;
itemPrices["Staff +1"]                = 1125;
itemPrices["Staff +2"]                = 6187;
itemPrices["Staff of Healing"]        = 79687;
itemPrices["Stealth Blade"]           = 70500;
itemPrices["Stick"]                   = 7;
itemPrices["Stone of Passage"]        = 5;
itemPrices["Stun Wand"]               = 20250;
itemPrices["Teleport Stone"]          = 3750;
itemPrices["Thief Sneakers"]          = 457500;
itemPrices["Wizard's Buckler"]        = 225000;
itemPrices["Wizard's Cap"]            = 318750;

// XP values are per group member, assuming a group of six.
// FIXME: many monsters are missing, particularly lower level ones.
var monsterXP = new Object;
monsterXP["Assassin"]           = 196;
monsterXP["Balrog"]             = 2155;
monsterXP["Banshee"]            = 299;
monsterXP["Basilisk"]           = 563;
monsterXP["Behemoth"]           = 1034;
monsterXP["Black Belt"]         = 363;
monsterXP["Black Wight"]        = 317;
monsterXP["Chimaera"]           = 198;
monsterXP["Cyclops"]            = 136;
monsterXP["Death Wight"]        = 1032;
monsterXP["Displacer"]          = 591;
monsterXP["Dracolich"]          = 2593;
monsterXP["Evil Eyestalk"]      = 222;
monsterXP["Fire Dragon"]        = 1912;
monsterXP["Fire Drake"]         = 598;
monsterXP["Fire Giant"]         = 1234;
monsterXP["Fire Wraith"]        = 516;
monsterXP["Forest Wight"]       = 161;
monsterXP["Frost Wraith"]       = 454;
monsterXP["Gelatinous Cube"]    = 634;
monsterXP["Giant Cougar"]       = 140;
monsterXP["Goblin"]             = 149;
monsterXP["Golem"]              = 173;
monsterXP["Gorgon"]             = 305;
monsterXP["Grim Reaper"]        = 121288; // miniboss
monsterXP["Gryphon"]            = 142;
monsterXP["High Druid"]         = 705;
monsterXP["Hippogriff"]         = 227;
monsterXP["Hobgoblin"]          = 287;
monsterXP["Hydra"]              = 454;
monsterXP["Ice Dragon"]         = 1405;
monsterXP["Jackal"]             = 139;
monsterXP["Kraken"]             = 324;
monsterXP["Lake Sprite"]        = 146;
monsterXP["Leviathan"]          = 35121; // miniboss
monsterXP["Lich"]               = 1652;
monsterXP["Manticore"]          = 196;
monsterXP["Mist Wraith"]        = 258;
monsterXP["Night Lord"]         = 475;
monsterXP["Ninja"]              = 411;
monsterXP["Owlbear"]            = 271;
monsterXP["Phoenix"]            = 147;
monsterXP["Poltergeist"]        = 1047;
monsterXP["Professional Thief"] = 283;
monsterXP["Rock Dragon"]        = 2422
monsterXP["Royal Escort"]       = 882;
monsterXP["Sap Hound"]          = 240;
monsterXP["Satyr"]              = 155;
monsterXP["Shadow Wight"]       = 451;
monsterXP["Skeletal Lord"]      = 1627;
monsterXP["Smoke Dragon"]       = 1993;
monsterXP["Smoke Giant"]        = 1343;
monsterXP["Snow Giant"]         = 2276;
monsterXP["Specter"]            = 427;
monsterXP["Steam Dragon"]       = 600;
monsterXP["Titan"]              = 382;
monsterXP["Valkyrie"]           = 284;
monsterXP["Valkyrie Empress"]   = 1530;
monsterXP["Vampire"]            = 372;
monsterXP["Vampire Bat"]        = 174;
monsterXP["Vampire Guardian"]   = 607;
monsterXP["Vampire Lord"]       = 1155;
monsterXP["Water Drake"]        = 214;
monsterXP["Water Sprite"]       = 399;
monsterXP["Wispball"]           = 480;
monsterXP["Wood Sprite"]        = 174;
monsterXP["Wyvern"]             = 405;
monsterXP["Zombie"]             = 170;

// These only need to be filled in if the singular can't be guessed, e.g.
// singular["Mice"] = "Mouse";
var singular = new Object;
singular["Cyclopes"]             = "Cyclops";
singular["Dracoliches"]          = "Dracolich";
singular["Liches"]               = "Lich";
singular["Men In Armor"]         = "Man In Armor";
singular["Men in Black"]         = "Man in Black"; // yes, the capitalization is inconsistent
singular["Professional Thieves"] = "Professional Thief";
singular["Valkyrie Empresses"]   = "Valkyrie Empress";
singular["Winged Women"]         = "Winged Woman";

// ### HELPER FUNCTIONS ###

// Page names include:
// "${NAME}'s Known Spells"
// "Buying Items"
// "Change Character Name"
// "Change Class"
// "Character Roster"
// "Create a Character"
// "Delete a Character"
// "Drop Items"
// "Edit Attributes for ${NAME}"
// "Error"
// "Equip ${NAME}"
// "Equipment Shop - ${TOWN}"
// "Equipment Lists"
// "Examine Inventory"
// "Inn - ${TOWN}"
// "Item Lists"
// "Reorder the Roster"
// "Rest at the Inn"
// "Selling Items"
// "Town - ${TOWN}"
// "Trade Items"
// "View ${NAME}"
function getPageName() {
    
    var h2s = document.getElementsByTagName("h2");
    if(h2s.length == 1)
        return h2s[0].textContent;
    
    // undefined is returned by default
}

function isErrorPage() {
    
    return(getPageName() == "Error");
    
}

// Return the singular form of a monster name (from a group of monsters).
function singularMonster(numberOfMonsters, nameOfMonster) {
    
    if(numberOfMonsters == 1)
        return nameOfMonster;

    if(singular[nameOfMonster])
        return singular[nameOfMonster];

    // unknown, so we'll make an educated guess
    // console.log("singularMonster(): guessing singular of " + nameOfMonster);

    if(nameOfMonster.endsWith("s"))
        return nameOfMonster.substr(0, nameOfMonster.length - 1);

    // nothing at all?
    return nameOfMonster;

}

// Return monsters encountered in a fight. Returns an array of arrays, one for each group, containing (in order)
// the number of monsters in that group, and the name of the monster (singular form).
function getMonsters() {
    
    var monsters = [];
    var elems = document.getElementsByTagName("td");

    for(var i = 0; i < elems.length; i++) {
        
        var currElem = elems[i];
        if(currElem.getAttribute("valign") == "top")
            if(currElem.textContent.match(/^\d+\.$/)) {
                
                var numMonsters = currElem.nextSibling.childNodes[0].textContent;
                var monsterType = singularMonster(numMonsters, currElem.nextSibling.childNodes[2].textContent);

                // characters don't recognize these monsters yet
                if(monsterType == "?")
                    monsterType = "?" + singularMonster(numMonsters, currElem.nextSibling.childNodes[3].textContent) + "?";
                
                monsters.push(
                    [
                        numMonsters,
                        monsterType
                    ]
                );
                
            }
    }
    
    return monsters;
}

// Return the number of monster groups in a fight.
function getNumberOfMonsterGroups() {
    
    return getMonsters().length;
    
}

// ### MAJOR FUNCTIONALITY ###

// annotateItems: add item prices (for Teralt) to items.
// if autodrop is enabled, automatically select items of inferior value for dropping.
// if autotrade is enabled, automatically select valuable items for trading.
function annotateItems() {

    var elems = document.getElementsByTagName("td");
    for(var i = 0; i < elems.length; i++) {
        
        var item = elems[i].textContent;
        var price = itemPrices[item];
        
        // need to use elem[i] here (liveview update), as well as innerHTML (avoid removing font tags)
        if(price > 0) {
            elems[i].innerHTML += " (" + price + ")";

            // FIXME: this shouldn't be in here; but it is because it's convenient, as price and item are already defined here.
            if(autodropEnabled && (getPageName() == "Drop Items") && (price < autodropCutOff) && !neverDrop[item])
                elems[i].nextSibling.nextSibling.firstChild.setAttribute("checked", "checked");

            // FIXME: as above
            if(autotradeEnabled && (getPageName() == "Trade Items") && (price > autotradeCutOff) && !neverTrade[item])
                elems[i].nextSibling.nextSibling.firstChild.setAttribute("checked", "checked");
                    
        }
    }
}

// selectTradingPartner: automatically select the first party member with free slots for trading
function selectTradingPartner() {

    // not really necessary, but speeds things up
    if(getPageName() != "Trade Items")
        return;
    
    var elems = document.getElementsByTagName("td");
    for(var i = 0; i < elems.length; i++) {
        
        if((elems[i].getAttribute("bgcolor") == "#ccccff") && (elems[i].textContent.match(/free inventory slots/))) {

            var tradingPartner = "";

            // going through these backwards makes it easier to find the *first* eligible trading partner.
            var lines = elems[i].innerHTML.split(/<br>/);
            for(var j = lines.length - 1; j >= 0; j--) {

                // if a match is found, matches[0] contains the entire matching substring,
                // matches[1] contains the (\w+) match, and matches[2] contains the (no|\d+) match.
                var matches = lines[j].match(/^(\w+) has (no|\d+) free inventory slot/);
                if(matches)
                    if(matches[2] != "no")
                        tradingPartner = matches[1];
                   
            }
            
            if(tradingPartner == "")
                return;
            
            // found a suitable trading partner, now select them.
            var elems2 = document.getElementsByTagName("option");
            for(var j = 0; j < elems2.length; j++)
                if(elems2[j].textContent == tradingPartner)
                    elems2[j].setAttribute("selected", "selected");
                else
                    elems2[j].removeAttribute("selected");
                
        }
        
    }
}

// saneCombatDefaults: set sane default values for combat
function saneCombatDefaults() {
    
    var monGroups = getNumberOfMonsterGroups();
    var elems = document.getElementsByTagName("select");

    for(var i = 0; i < elems.length; i++) {
        
        var currElem = elems[i];        
        for (var j = 0; j < currElem.childElementCount; j++) {
            
            var currChild = currElem.children[j];

            // make sure that the tanks are all fighting different monster groups.
            // FIXME: intelligent targetting, e.g. Snow Giants and other monsters that might survive a triple QUAKE.
            if(currChild.textContent.startsWith("Group "))
                if(i == j)
                    currChild.setAttribute("selected", "selected");
                else
                    currChild.removeAttribute("selected");

            // if there's more than three monster groups, get the spellcasters involved.
            // note that QUAKE is already the default combat spell.
            if(monGroups > 3)
                if(currChild.textContent == "Parry")
                    currChild.removeAttribute("selected");
                else if(currChild.textContent == "Spell")
                    currChild.setAttribute("selected", "selected");

        }
    }
}

// calculateXP: calculate XP to be received after combat
function calculateXP() {
    var monsters             = getMonsters();
    var missingMonsters      = "";
    var unrecognizedMonsters = "";
    
    // this avoids spurious messages outside of fights.
    if(monsters.length == 0)
        return;
    
    var totalXP = monsters.reduce(
        function(XP, currentMonsterGroup) {

             if(currentMonsterGroup[1].startsWith("?"))
                 unrecognizedMonsters += currentMonsterGroup[1].substr(1, currentMonsterGroup[1].length - 2) + ", ";
             else if(!monsterXP[currentMonsterGroup[1]])
                 missingMonsters += currentMonsterGroup[1] + ", ";
             else
                 return XP + currentMonsterGroup[0] * monsterXP[currentMonsterGroup[1]];
            
        },
    0);

    var XPnode = document.createElement("p");
    XPnode.setAttribute("style", "font-size: smaller");
    
    if(missingMonsters != "")
        XPnode.textContent = "Monsters missing from script: " + missingMonsters.substr(0, missingMonsters.length - 2);
    else if(unrecognizedMonsters != "")
        XPnode.textContent = "Cannot calculate XP payout due to unrecognized monsters: " + unrecognizedMonsters.substr(0, unrecognizedMonsters.length - 2);
    else
        XPnode.textContent = "Expected XP payout per character for current opponents: " + totalXP;
    
    var elems = document.getElementsByTagName("td");
    for(var i = 0; i < elems.length; i++)
        if(elems[i].getAttribute("bgcolor") == "#eeeeff")
            elems[i].appendChild(XPnode);

    
}

// dontSellKeys: disable sell buttons for important items
function dontSellKeys() {

    if(getPageName() != "Selling Items")
        return;
    
    var elems = document.getElementsByTagName("td");
    for(var i = 0; i < elems.length; i++)
        if(neverSell[elems[i].textContent])
            elems[i].nextSibling.nextSibling.nextSibling.nextSibling.firstChild.children[5].setAttribute("disabled", "disabled");
        
}

// autoFocus: automatically put the focus on the right button.
function autoFocus() {
    
    var elems = document.getElementsByTagName("input");
    
    for(var i = 0; i < elems.length; i++) {
        
       var inputElement = elems[i];
       var inputValue = inputElement.getAttribute("value");
        
       if((inputValue == " Next ") 
          || (inputValue == " OK ") 
          || (inputValue == " Done ") 
          || (inputValue == " Disarm ") 
          || (inputValue == " Dive ") 
          || (inputValue == " Cast ") 
          || (inputValue == " Rest Again ") 
          || (inputValue == " Back " )
          || (inputValue == " Cast " )
          || (inputValue == " Plummet ")
          || (inputValue == " Use Roster Order ")
          || (inputValue == " Go Up ")
          || (inputValue == " Go Down ")
         )
          inputElement.focus();

    }
}

// ### MAIN ###

dontSellKeys(); // this should come before annotateItems.
selectTradingPartner();
saneCombatDefaults();
calculateXP();
annotateItems();
autoFocus();

It's neither perfect nor done, as evidenced by the FIXMEs strewn about the code, but it works, and it's making my adventuring life that much easier. I don't think anybody else is playing Murkon's Refuge, so this is probably a pointless post, but I'd like to preserve this for posterity anyway, just because.

Link | Leave a comment | Share

Comments {0}