您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Version 0.3.1 - grant needed GM_ permissions, improve efficiency, track some KOL changes, move to Greasy Fork
// antimarty's bird form attack counter // counts your uses of birdform attacks on your way to a glimmering roc feather in Kingdom of Loathing // // mostly based on the antimarty fortune cookie script, which was mostly stolen // script update code based on DrEvi1's hatrack helper, which credits Picklish // support for wild hare, greatest pants, and organ grinder added by knitbone // // Released under the GPL license // http://www.gnu.org/copyleft/gpl.html // // ==UserScript== // @name antimarty birdform script // @namespace antimarty // @include *kingdomofloathing.com/*.php* // @include *127.0.0.1:600*/*.php* // @include *localhost:600*/*.php* // @version 0.3.2 // @grant GM_getValue // @grant GM_setValue // @grant GM_xmlhttpRequest // // @description Version 0.3.1 - grant needed GM_ permissions, improve efficiency, track some KOL changes, move to Greasy Fork // // ==/UserScript== // released versions: // Version 0.2.7 - angry jung man, unconscious collective, gnome adventures. // Version 0.2.6 - "new" Mr store fams (with only two weeks left in Mr Store) // Version 0.2.5 - add support for stompin boots // Version 0.2.4 - new navel run percentages, typo corrections, xenomorph, new update method // Version 0.2.3 counts v-mask advs, hipster fights, greats pants runaways, organ grinder parts/pies, wild hare advs // Version 0.2.2 handles generic drops more generically, handle multiround combat macros // Version 0.2.0 counts floaty sand drops, squamous gibberer bonus adventures, game grid token drops // Version 0.1.9 counts baby sandworm drops, hobo underling summons, mayfly summons // Version 0.1.8 more robust reset on new day, , fix auto-update bug // Version 0.1.7 fix navel ring runaway counting - only free runaways count // Version 0.1.6 add navel ring, bandersnatch runaway counters // Version 0.1.5 fix for mafia "recently seen" changes // Version 0.1.3 fix for drop counts bug introduced in 0.1.2 // Version 0.1.2 bugfix for drop counts when ascending // Version 0.1.1 trivial update: update link opens in new window // Version 0.1.0 add astral badger drops; check for updates // Version 0.0.9 Count daily gong drops // Version 0.0.8 bugfix for autoattacks // Version 0.0.7 can manually clear and hide the counter // Version 0.0.6 support compact mode // version 0.0.5 another bug fix for "plural" opponents // version 0.0.4 bug fix for "plural" opponents // version 0.0.3 support for elemental attacks // Version 0.0.1 initial beta // Known bugs: /* // (temporarily?) removed for move to greasy fork var currentVersion = "0.3.1"; var scriptSite = "http://userscripts.org/scripts/show/28640" // this is a small file autogenerated by userscripts.org from Userscript @ comments above, use to reduce bandwidth on version check var scriptURL = "http://userscripts.org/scripts/source/28640.meta.js"; */ var ATTACK_NONE = -1; var ATTACK_TALON_SLASH = 0; var ATTACK_WING_BUFFET = 1; var ATTACK_STATUE_TREATMENT = 2; var ATTACK_THE_BIRD = 3; var ATTACK_ANTARCTIC_FLAP = 4; var ATTACK_RISE_FROM_ASHES = 5; var ATTACK_FEAST_ON_CARRION = 6; // can't use the symbolic names here, not set yet, I guess // text is from You -> first comma or period var attackTexts = { "You repeatedly slash your opponent with your razor-sharp talons,": 0, "You repeatedly slash your opponents with your razor-sharp talons,": 0, // multiple oppenents like dread squad "You furiously flap your wings,": 1, "You pretend that your opponent is a statue and do what comes naturally,": 2, // seems to work even for multiple opponents "You give your opponent \"the bird.": 3, "You give your opponents \"the bird.": 3, // multiple oppenents like dread squad "You flap your wings,": 4, "You fold your wings around you and burst into flames.": 5, "You start eating bits of your opponent's flesh,": 6, "You start eating bits of your opponents' flesh,": 6, }; var attackSuffixes = { 0: "_talon_slash", 1: "_wing_buffet", 2: "_statue_treatment", 3: "_the_bird", 4: "_antarctic_flap", 5: "_rise_from_ashes", 6: "_feast_on_carrion", }; // chance of a navel ring runaway after successful try x var navelPercentages = [ 100, 100, 100, 80, 80, 80, 50, 50, 50, 20, 20 ]; // turns til next pie on try x var grinderTurns = [ 5, 10, 16, 23, 31, 50, 50, 50, 50, 50, 50 ]; var stogieTurns = [ 5, 5, 11, 18, 26, 45, 45, 45, 45, 45, 45 ]; // all the random drops we count - just add a row to the "array" to add an item to count // [in-game drop text, gm_counterName, gm_seenItFlag, our label, daily max] var DROP_TEXT_IDX = 0; // deprecated var DROP_GM_VAR_IDX = 0; var DROP_GM_FLAG_IDX = 1; var DROP_LABEL_IDX = 2; var DROP_DAILY_MAX_IDX = 3; // there has to be a better way to make a 2 dimensional global array // to add a "normal" drop item - just add a line here, rest should be automatic var allDrops = { // keyed to in-game text for the drop "astral mushroom":[ "_mushroomDrops", "_hasBadger", "Astral Mushroom Drops", "5"], "llama lama gong":[ "_gongDrops", "_hasLlama", "Llama Gong Drops", "5"], "tiny bottle of absinthe":[ "_absintheDrops", "_hasPixie", "Absinthe Drops", "5"], "disintegrating sheet music":["_musicDrops", "_hasTroll", "Sheet Music Drops", "?"], "Spooky Putty monster":[ "_puttyUses", "_hasPutty", "Putty Uses", "5"], "agua de vida":[ "_aguaDrops", "_hasSandworm", "Agua De Vida Drops", "5"], "Game Grid token":[ "_GameGridDrops", "_hasRogueProgram", "Game Grid Token Drops","5"], "transporter transponder":["_transponderDrops","_hasXenomorph", "Transponder Drops", "5"], // a zillion kinds of paste, oh well "beastly paste":["_pasteDrops","_hasBoots", "Boot Stomps", "7"], "bug paste":["_pasteDrops","_hasBoots", "Boot Stomps", "7"], "chlorophyll paste":["_pasteDrops","_hasBoots", "Boot Stomps", "7"], "cosmic paste":["_pasteDrops","_hasBoots", "Boot Stomps", "7"], "Crimbo paste":["_pasteDrops","_hasBoots", "Boot Stomps", "7"], "demonic paste":["_pasteDrops","_hasBoots", "Boot Stomps", "7"], "ectoplasmic paste":["_pasteDrops","_hasBoots", "Boot Stomps", "7"], "elemental paste":["_pasteDrops","_hasBoots", "Boot Stomps", "7"], "fishy paste":["_pasteDrops","_hasBoots", "Boot Stomps", "7"], "goblin paste":["_pasteDrops","_hasBoots", "Boot Stomps", "7"], "gooey paste":["_pasteDrops","_hasBoots", "Boot Stomps", "7"], "greasy paste":["_pasteDrops","_hasBoots", "Boot Stomps", "7"], "hippy paste":["_pasteDrops","_hasBoots", "Boot Stomps", "7"], "hobo paste":["_pasteDrops","_hasBoots", "Boot Stomps", "7"], "indescribably horrible paste":["_pasteDrops","_hasBoots", "Boot Stomps", "7"], "Mer-kin paste":["_pasteDrops","_hasBoots", "Boot Stomps", "7"], "oily paste":["_pasteDrops","_hasBoots", "Boot Stomps", "7"], "orc paste":["_pasteDrops","_hasBoots", "Boot Stomps", "7"], "penguin paste":["_pasteDrops","_hasBoots", "Boot Stomps", "7"], "pirate paste":["_pasteDrops","_hasBoots", "Boot Stomps", "7"], "slimy paste":["_pasteDrops","_hasBoots", "Boot Stomps", "7"], "strange paste":["_pasteDrops","_hasBoots", "Boot Stomps", "7"], // lobster in the crown of thrones will probably break this. And faxed clod hopper definitely does. "floaty sand":["_floatySandDrops","_hasLobster", "Floaty Sand Drops", "?"], "devilish folio":["_devilishFolioDrops","_hasKloop", "Devilish Folio Drops", "5"], "groose grease":["_grooseGreaseDrops","_hasGroose", "Groose Grease Drops", "5"], // TWO zillion kinds of siphoned spirits, oh well oh well // some names are subsets of others, and confuse this - e.g. the sloe comfortable zoo (on fire) // 33":[beastly paste","_pasteDrops","_hasBoots", "Boot Stomps", "7"], "Zoodriver":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Sloe Comfortable Zoo":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Sloe Comfortable Zoo on Fire":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Grasshopper":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Locust":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Plague of Locusts":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Green Velvet":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Green Muslin":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Green Burlap":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Dark & Starry":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Black Hole":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Event Horizon":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Lollipop Drop":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Candy Alexander":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Candicaine":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Suffering Sinner":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Suppurating Sinner":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Sizzling Sinner":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Drac & Tan":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Transylvania Sling":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Shot of the Living Dead":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Firewater":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Earth and Firewater":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Earth, Wind and Firewater":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Caipiranha":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Flying Caipiranha":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Flaming Caipiranha":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Buttery Knob":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Slippery Knob":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Flaming Knob":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Humanitini":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "More Humanitini than Humanitini":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Oh, the Humanitini":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Red Dwarf":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Golden Mean":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Green Giant":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Fauna Libre":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Chakra Libre":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Aura Libre":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Mohobo":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Moonshine Mohobo":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Flaming Mohobo":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Great Old Fashioned":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Fuzzy Tentacle":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Crazymaker":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Punchplanter":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Doublepunchplanter":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Haymaker":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Cement Mixer":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Jackhammer":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Dump Truck":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Sazerorc":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Sazuruk-hai":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Flaming Sazerorc":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Herring Daiquiri":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Herring Wallbanger":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Herringtini":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Aye Aye":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Aye Aye, Captain":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Aye Aye, Tooth Tooth":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Slimosa":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Extra-slimy Slimosa":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Slimebite":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Drunken Philosopher":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Drunken Neurologist":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], "Drunken Astrophysicist":["_spiritDrops","_hasMedium", "Siphoned Spirits", "?"], // oh boy, 100 items "Rain-Doh box full of monster":[ "_Rain-DohUses", "_hasRain-Doh", "Rain-Doh Uses", "5"], "psychoanalytic jar":[ "_analyticJarDrops", "_hasJungMan", "Analytic Jar Drops", "1"], "Unconscious Collective Dream Jar":[ "_dreamJarDrops", "_hasCollective", "Dream Jar Drops", "5"], // buddy bjorn/crown of thrones will break these "grimstone mask":[ "_grimstoneMaskDrops", "_hasGrimGolem", "Grimstone Mask Drops", "1"], "grim fairy tale":[ "_grimFairyTaleDrops", "_hasGrimBrother", "Grim Fairy Tale Drops", "5"], "hot ashes":[ "_hotAshesDrops", "_hasGallopingGrill", "Hot Ashes Drops", "5"], "carrot nose":[ "_carrotNoseDrops", "_hasSnowSuit", "Carrot Nose Drops", "3"], }; // second array for pie drops. although counting functions and combat displays are the same, account page displays should not loop var pieDrops = { 0:["liver and let pie", "_PieDrops", "_hasOrganGrinder", "Pie Drops", "?"], 1:["stomach turnover", "_PieDrops", "_hasOrganGrinder", "Pie Drops", "?"], 2:["piping organ pie", "_PieDrops", "_hasOrganGrinder", "Pie Drops", "?"], 3:["dead lights pie", "_PieDrops", "_hasOrganGrinder", "Pie Drops", "?"], 4:["throbbing organ pie", "_PieDrops", "_hasOrganGrinder", "Pie Drops", "?"], 5:["igloo pie", "_PieDrops", "_hasOrganGrinder", "Pie Drops", "?"], 6:["shoo-fish pie", "_PieDrops", "_hasOrganGrinder", "Pie Drops", "?"], 7:["badass pie", "_PieDrops", "_hasOrganGrinder", "Pie Drops", "?"], }; // pie part collecting text messages - don't track type for now var pieParts = { // do they change for multiple opponents? 0:["a few choice bits to put in his grinder", "_pieParts", "_hasOrganGrinder", "Parts", "?"], 1:["smells like Betty, guv", "_pieParts", "_hasOrganGrinder", "Parts", "?"], 2:["burning his Longers and Lingers", "_pieParts", "_hasOrganGrinder", "Parts", "?"], 3:["the upper story on his Gregory", "_pieParts", "_hasOrganGrinder", "Parts", "?"], 4:["My Hampton has a funny feeling", "_pieParts", "_hasOrganGrinder", "Parts", "?"], 5:["catch his death of Boris", "_pieParts", "_hasOrganGrinder", "Parts", "?"], 6:["getting his Tony Blair wet", "_pieParts", "_hasOrganGrinder", "Parts", "?"], 7:["a bloody Pich and Toss", "_pieParts", "_hasOrganGrinder", "Parts", "?"], }; //////////////////////////////////////////////////////////////////////////////// // Based on a function taken from OneTonTomato's UpUp skill script function GM_get(target, callback) { GM_xmlhttpRequest({ method: 'GET', url: target, onload:function(details) { if( typeof callback=='function' ){ callback(details.responseText); } } }); } // Check for an updated script version function CheckScriptVersion(data) { // Preemptively set error, in case request fails... GM_setValue("webVersion", "Error") var m = data.match(/@version\s*([0-9.]+)/); if (m) { GM_setValue("webVersion", m[1]); } } //////////////////////////////////////////////////////////////////////////////// // parse the char sheet (not the sidepane) for the player name function getPlayerNameFromCharsheet(data) { // it's an href with syntax something like // showplayer.php?who=PlayerID">PlayerName</a> var playerName = /showplayer\.php\?who\=\d+\">([^<]+)<\/a/i.exec(data); // sometimes this fails, don't know why // alert("got player name from charsheet: " + playerName); if(playerName) return playerName[1].toLowerCase(); else return null; } //////////////////////////////////////////////////////////////////////////////// // get player name from the sidepane html // code taken from kolpreviousnadventures script function getPlayerNameFromCharpane() { var username = document.getElementsByTagName("b"); if (!username || username.length < 1) return false; username = username[0]; if (!username) return false; username = username.firstChild; if (!username) return false; // in full mode the link is <a><b>Name</b></a> // in compact mode it's <b><a>Name</a></b> // so have to handle this, and also can use it to tell // whether it's in compact mode or not. var fullmode = true; while (username && username.nodeType == 1) { username = username.firstChild; fullmode = false; } if (!username) return false; username = username.nodeValue; if (!username) return false; username = username.toLowerCase(); // alert("found username " + username + ", fullmode: " + fullmode); return {'username': username, 'fullmode': fullmode}; } function getDaysPlayed(data) { var dayCount = 0; if(data.indexOf("Days Played (this run)") >= 0) { // alert("parsing datasheet for days for an ascended char"); dayCount = /Days Played \(this run\)[^>]*>(<[^>]+>)*([\d,]+)/i.exec(data)[2]; } else { // alert("parsing datasheet for days for an UNascended char"); dayCount = /Days Played[^>]*>(<[^>]+>)*([\d,]+)/i.exec(data)[2]; } // alert("found dayCount=" + dayCount); return parseInt(dayCount.replace(',',''),10); } //////////////////////////////////////////////////////////////////////////////// // watch for use of a birdform attack on the fight page function checkForBirdAttack(data) { var birdAttackFound = new Array; var attackText = data.match(/You (.*?)[\.\,]/gi); // the .*? is the non-greedy version of .* if(attackText != null) { for ( var i = 0; i < attackText.length; ++i ){ if(attackTexts[attackText[i]] != undefined) { birdAttackFound.push(attackTexts[attackText[i]]); // alert("found bird attack " + birdAttackFound + " (" + attackText[i] + ")"); // break; } } } return birdAttackFound; } //////////////////////////////////////////////////////////////////////////////// // get monster name, need this to check for hipster // the from putty doesn't work, need to make it persistent after 1st fight page function getMonsterName(data) { var monsterName = /id=\"monname\">(.*?)<\/span>/i.exec(data); if( monsterName ) monsterName = monsterName[1]; else monsterName = ""; var fromPutty = data.indexOf("You put the copied monster on the ground") != -1 ? true : false; return {'monsterName': monsterName, 'fromPutty': fromPutty}; } function getRunAwayButton() { var allElements = document.getElementsByTagName("input"); var button = null; for(var i=0; i < allElements.length; i++) { if(allElements[i].value == "Run Away" ) { // if using mafia, will have some other text added, and fail (which we want) button = allElements[i]; break; } } return button; } // also counts GA pants, peppermint parasol (partially!) function checkForNavelRingRunaway(data) { // only counts as a runaway if succeeds (for purposes of success rate next time) if(data.indexOf( "you quickly float away" ) != -1 || data.indexOf( "your pants suddenly activate") != -1 || data.indexOf( "You hold up the parasol") != -1) return true; else return false; } function checkForSnatchRunaway(data) { if(data.indexOf( "the combat becomes a small dot" ) != -1 || data.indexOf( "kicks you in the butt to speed your escape") != -1) return true; else return false; } function checkForUnderlingSummon(data) { if(data.indexOf( "A hobo runs up to you" ) != -1 ) return true; else return false; } function checkForMayflySummon(data) { if(data.indexOf( "You open the little container full of mayfly bait" ) != -1 ) return true; else return false; } function checkForGibbererAdv(data) { if(data.indexOf( "you feel time slow down" ) != -1 ) return true; else return false; } function checkForGnomeAdv(data) { if(data.indexOf( "scrubs the mildew out of your grout" ) != -1 || data.indexOf( "bundles your recycling for you" ) != -1 || data.indexOf( "teaches you how to power-nap instead of sleeping all day" ) != -1 || data.indexOf( "sharpens all your pencils and lines them up in a neat row" ) != -1 || data.indexOf( "folds all your clean laundry" ) != -1 || data.indexOf( "shows you how to shave a full minute off of your teeth brushing routine" ) != -1 || data.indexOf( "organizes your sock drawer and alphabetizes your spice rack" ) != -1 || data.indexOf( "hauls all of your scrap lumber to the dump" ) != -1 || data.indexOf( "does all that tedious campsite cleaning you were going to do today" ) != -1 ) return true; else return false; } function checkForHareAdv(data) { if(data.indexOf( "Two days slow, that's what it is" ) != -1 ) return true; else return false; } function checkForVMaskAdv(data) { if(data.indexOf( "into last week. It saves you some time" ) != -1 ) return true; else return false; } // only detect the initial page, so that don't keep re-detecting it // as coded now, it's redundant to even look at the monster name, but maybe I'll fix it up later function checkForHipsterAdv(data) { var monster = getMonsterName(data); // alert("In checkForHipsterAdv, monster name is " + monster.monsterName + ", from putty: " + monster.fromPutty); if(monster.fromPutty == false) { if(monster.monsterName == "an angry bassist" && data.indexOf("a lanky dude with a knit cap") != -1 || monster.monsterName == "a blue-haired girl" && data.indexOf( "a girl with bright blue hair skates") != -1 || monster.monsterName == "an evil ex-girlfriend" && data.indexOf( "A skinny woman in an over-sized sweater") != -1 || monster.monsterName == "a peeved roommate" && data.indexOf( "an immaculately-dressed-and-coiffed guy") != -1 || monster.monsterName == "a random scenester" && data.indexOf( "A random hipster" ) != -1 ) return true; } return false; } // return list of dropped items (as the bold html elements) function getDrops( ) { // limit our checks to first table in the content div - allows us to skip extra "previously seen" repeats var allElements = document.getElementById("content_").getElementsByTagName("table")[0].getElementsByClassName("item"); var drops = []; if(allElements) { for(var i=0; i < allElements.length; i++) { drops.push(allElements[i].getElementsByTagName("b")[0]); } } return drops; } function checkForDrop( dropText ) { // limit our checks to the content div - allows us to skip extra "previously seen" repeats divElement = document.getElementById("content_"); var allElements = divElement.getElementsByTagName("table")[0].getElementsByClassName("item"); var dropElement = null; if(allElements) { for(var i=0; i < allElements.length; i++) { if(allElements[i].innerHTML.indexOf( dropText ) != -1 ) { dropElement = allElements[i].getElementsByTagName("b")[0]; break; // we're done, no matter what (? unless can get 2 of same drop, e.g. grim fairy tale from bjorn) } } } return dropElement; } function checkForPieDrop( dropText ) { // Look at all the <td> items, and return the one for the given drop text // in theory could check that it's a familiar message, there is a tag <!--familiarmessage--> var allElements = document.getElementsByTagName("td"); // mafia's "previously seen" breaks this, now need to watch for previously seen and discount it var dropElement = null; for(var i=allElements.length-1; i >= 0; i--) { // go backwards, to get lowest level one if(allElements[i].innerHTML.indexOf( dropText ) != -1 ) { dropElement = allElements[i]; break; // we're done, no matter what } } return dropElement; } // from one ton tomato's mallsearch script function getParent(el, pTagName) { if (el == null) { return null; } else if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase()) { // Gecko bug, supposed to be uppercase return el; } else { return getParent(el.parentNode, pTagName); } } function getPwdHash(data){ var pwdHash = /pwdhash \= \"(.*?)\"/i.exec(data)[1]; // alert("got pwdHash: " + pwdHash); return pwdHash; } function getPlayerLevel(data) { var playerLevel = /Level (\d+)/i.exec(data); // full mode if( !playerLevel) playerLevel = /Lvl\. (\d+)/i.exec(data); // compact mode if( playerLevel) return parseInt(playerLevel[1],10); // normal level checks fail if astral spirit if(data.indexOf("Astral Spirit") != -1) return 0; // astral spirit else return -1; // error } // check charpane data to see if wearing navel ring function checkNavelRing(data) { if(data.indexOf("Omphaloskepsis") == -1) return false; else return true; } // check charpane data to see if Ode to Booze is active function checkOde(data) { if(data.indexOf("Ode to Booze") == -1) return false; else return true; } // get familiar name (as used by the familiar gif) from charpane // get weight, also function getFamiliar(data, fullmode) { // alert("in getFamiliar, data = " + data); // <img src="http://images.kingdomofloathing.com/itemimages/bandersnatch.gif" // <img src="/images/itemimages/stompboots.gif" var type = ""; var weight = 0; var parsedData; if(fullmode == true) { parsedData = /itemimages\/([^\.]+)\.gif[^<]+<\/a>[^:]+<b>(\d+)<\/b> pound/i.exec(data); } else { parsedData = /itemimages\/([^\.]+)\.gif[^<]+<\/a><br>(\d+) lbs/i.exec(data); } // alert("parsedData = " + parsedData); if(parsedData) { type = parsedData[1]; weight = parseInt(parsedData[2]); } // alert("found familiar type = " + type + ", weight = " + weight); return { 'type' : type, 'weight': weight }; } //////////////////////////////////////////////////////////////////////////////// // init all the tracking vars when entering birdform function setBirdform(playerName) { GM_setValue(playerName+"_hasBirdform",true); GM_setValue(playerName + attackSuffixes[ATTACK_TALON_SLASH], 0); GM_setValue(playerName + attackSuffixes[ATTACK_WING_BUFFET], 0); GM_setValue(playerName + attackSuffixes[ATTACK_STATUE_TREATMENT], 0); GM_setValue(playerName + attackSuffixes[ATTACK_THE_BIRD], 0); GM_setValue(playerName + attackSuffixes[ATTACK_ANTARCTIC_FLAP], 0); GM_setValue(playerName + attackSuffixes[ATTACK_RISE_FROM_ASHES], 0); GM_setValue(playerName + attackSuffixes[ATTACK_FEAST_ON_CARRION], 0); } //////////////////////////////////////////////////////////////////////////////// // clear all the tracking vars when leaving birdform function clearBirdform(playerName) { GM_setValue(playerName+"_hasBirdform", false); GM_setValue(playerName + attackSuffixes[ATTACK_TALON_SLASH], 0); GM_setValue(playerName + attackSuffixes[ATTACK_WING_BUFFET], 0); GM_setValue(playerName + attackSuffixes[ATTACK_STATUE_TREATMENT], 0); GM_setValue(playerName + attackSuffixes[ATTACK_THE_BIRD], 0); GM_setValue(playerName + attackSuffixes[ATTACK_ANTARCTIC_FLAP], 0); GM_setValue(playerName + attackSuffixes[ATTACK_RISE_FROM_ASHES], 0); GM_setValue(playerName + attackSuffixes[ATTACK_FEAST_ON_CARRION], 0); } //////////////////////////////////////////////////////////////////////////////// // check for a birdform attack, increment proper count if see one // also check for all the various drops, and navel ring/bandersnatch runaways function processFight() { var attacksFound = checkForBirdAttack(document.body.innerHTML); var playerName = GM_getValue("currentPlayer"); var attack = attacksFound.pop(); while(attack != null) { var hasBirdform = GM_getValue(playerName+"_hasBirdform",false); // force birdform if it's not set (e.g. used the llama gong from mafia cli but playing manually) if(hasBirdform == false) { setBirdform(playerName); } // increment the proper attack count var attackCount = GM_getValue(playerName+attackSuffixes[attack],0); GM_setValue(playerName+attackSuffixes[attack],attackCount+1); attack = attacksFound.pop(); } // check for all the standard drops, and decorate them { var drops = getDrops(); var i; for(i in drops) { var dropText = drops[i].innerHTML; // alert("checking drop " + dropText + " against list"); if(allDrops[dropText] != null) { var dropCount = GM_getValue(playerName+allDrops[dropText][DROP_GM_VAR_IDX],0)+1; // alert("new drops value is " + dropCount); GM_setValue(playerName+allDrops[dropText][DROP_GM_VAR_IDX],dropCount); GM_setValue(playerName+allDrops[dropText][DROP_GM_FLAG_IDX], true); // a one time flag, never reset. Easier than checking terrarium! // kind of bogus, but the best I could come up with if(allDrops[dropText][DROP_GM_FLAG_IDX]=="_hasPutty" && GM_getValue(playerName+"_hasRain-Doh")==true) { var dropsLeft = Math.min(5, Math.max(0,6 - GM_getValue(playerName+"_Rain-DohUses",0))); allDrops[dropText][DROP_DAILY_MAX_IDX] = dropsLeft.toString(); } else if(allDrops[dropText][DROP_GM_FLAG_IDX]=="_hasRain-Doh" && GM_getValue(playerName+"_hasPutty")==true) { var dropsLeft = Math.min(5, Math.max(0,6 - GM_getValue(playerName+"_puttyUses",0))); allDrops[dropText][DROP_DAILY_MAX_IDX] = dropsLeft.toString(); } // add a bit of html to decorate the drop var newElement = document.createElement("FONT"); newElement.innerHTML = "<font size=0>" + " (" + dropCount + "/" + allDrops[dropText][DROP_DAILY_MAX_IDX] + ")" + "</font>"; drops[i].parentNode.insertBefore(newElement, drops[i].nextSibling); } } } // check for organ grinder drops, and decorate them if(GM_getValue(playerName+"_usingGrinder", false)) { var i; var gotPie = false; //pies for(i in pieDrops) { var dropElement = checkForDrop(pieDrops[i][DROP_TEXT_IDX]); if(dropElement != null) { var drops = GM_getValue(playerName+pieDrops[i][DROP_GM_VAR_IDX],0)+1; GM_setValue(playerName+pieDrops[i][DROP_GM_VAR_IDX],drops); GM_setValue(playerName+pieDrops[i][DROP_GM_FLAG_IDX], true); // a one time flag, never reset. Easier than checking terrarium! gotPie = true; // add a bit of html to decorate the drop var gturns = drops + 1 <= grinderTurns.length ? grinderTurns[drops] : grinderTurns[grinderTurns.length - 1]; var sturns = drops + 1 <= stogieTurns.length ? stogieTurns[drops] : stogieTurns[stogieTurns.length - 1]; var newElement = document.createElement("FONT"); var tempText = "<font size=0><br />" + "Pie #" + drops + ". Next pie needs " + gturns + " parts"; if(sturns != gturns) tempText += ", or " + sturns + " with stogie.</font>"; else tempText += ".</font>"; newElement.innerHTML = tempText; dropElement.parentNode.insertBefore(newElement, dropElement.nextSibling); // set pie part counter back to 0 when a pie drops GM_setValue(playerName+pieParts[i][DROP_GM_VAR_IDX],0); break; // can only get one pie per fight } } // pie parts - don't bother if grinder handed us a pie this turn if(!gotPie) { for(i in pieParts) { var dropElement = checkForPieDrop(pieParts[i][DROP_TEXT_IDX]); if(dropElement != null) { var parts = GM_getValue(playerName+pieParts[i][DROP_GM_VAR_IDX],0)+1; GM_setValue(playerName+pieParts[i][DROP_GM_VAR_IDX],parts); GM_setValue(playerName+pieParts[i][DROP_GM_FLAG_IDX], true); // a one time flag, never reset. Easier than checking terrarium! // add a bit of html to decorate the drop var pies = GM_getValue(playerName+pieDrops[i][DROP_GM_VAR_IDX],0); var gturns = pies < grinderTurns.length ? grinderTurns[pies] : grinderTurns[grinderTurns.length - 1]; var sturns = pies < stogieTurns.length ? stogieTurns[pies] : stogieTurns[stogieTurns.length - 1]; var tempText = "<font size=0>" + " (part " + parts + ", next pie at " + gturns; if(sturns != gturns) tempText += ", or " + sturns + " with stogie)</font>"; else tempText += ")</font>"; dropElement.innerHTML += tempText; break; // can only get one part per fight } } } } // we branch out into counting navel ring and bandersnatch runaways and more if(checkForNavelRingRunaway(document.body.innerHTML)) { var count = GM_getValue(playerName+"_navelRingRunaways",0); GM_setValue(playerName+"_navelRingRunaways",count+1); } // now includes stomping boots runaways if(checkForSnatchRunaway(document.body.innerHTML)) { var count = GM_getValue(playerName+"_snatchRunaways",0); GM_setValue(playerName+"_snatchRunaways",count+1); } if(checkForUnderlingSummon(document.body.innerHTML)) { var count = GM_getValue(playerName+"_underlingSummons",0); GM_setValue(playerName+"_underlingSummons",count+1); GM_setValue(playerName+"_hasFrippery", true); // one time flag } if(checkForGibbererAdv(document.body.innerHTML)) { var count = GM_getValue(playerName+"_gibbererAdv",0); GM_setValue(playerName+"_gibbererAdv",count+1); GM_setValue(playerName+"_hasGibberer", true); // one time flag // stick something on the screen to indicate how many this it? } if(checkForGnomeAdv(document.body.innerHTML)) { var count = GM_getValue(playerName+"_gnomeAdv",0); GM_setValue(playerName+"_gnomeAdv",count+1); GM_setValue(playerName+"_hasGnome", true); // one time flag // stick something on the screen to indicate how many this it? } if(checkForHareAdv(document.body.innerHTML)) { var count = GM_getValue(playerName+"_HareAdv",0); GM_setValue(playerName+"_HareAdv",count+1); GM_setValue(playerName+"_hasHare", true); // one time flag // stick something on the screen to indicate how many this it? } if(checkForVMaskAdv(document.body.innerHTML)) { var count = GM_getValue(playerName+"_VMaskAdv",0); GM_setValue(playerName+"_VMaskAdv",count+1); GM_setValue(playerName+"_hasVMask", true); // one time flag // stick something on the screen to indicate how many this it? } if(checkForHipsterAdv(document.body.innerHTML)) { var count = GM_getValue(playerName+"_hipsterAdv",0); GM_setValue(playerName+"_hipsterAdv",count+1); GM_setValue(playerName+"_hasHipster", true); // one time flag // stick something on the screen to indicate how many this it? } // update skill menu with remaining summon underilng info if(GM_getValue(playerName+"_hasFrippery", false)){ var allElements = document.getElementsByTagName("option"); for(var i=0; i < allElements.length; i++) { if(allElements[i].value == "7052" ) { var remaining = 5 - GM_getValue(playerName+"_underlingSummons",0); allElements[i].innerHTML = allElements[i].innerHTML.replace("Points)", "Points) (" + remaining + "/5 left)"); break; } } } if(checkForMayflySummon(document.body.innerHTML)) { var count = GM_getValue(playerName+"_mayflySummons",0); GM_setValue(playerName+"_mayflySummons",count+1); GM_setValue(playerName+"_hasMayflies", true); // one time flag } // update skill menu with remaining summon mayflies info if(GM_getValue(playerName+"_hasMayflies", false)){ var allElements = document.getElementsByTagName("option"); for(var i=0; i < allElements.length; i++) { if(allElements[i].value == "7024" ) { var remaining = 30 - GM_getValue(playerName+"_mayflySummons",0); allElements[i].innerHTML = allElements[i].innerHTML.replace("Points)", "Points) (" + remaining + "/30 left)"); break; } } } // add some info to the run away button // currently doesn't work for Greatest American Pants - how to tell that I'm wearing them? var runAwayButton = getRunAwayButton(); if(runAwayButton) { // alert("found run away button, decorating"); var newElement = document.createElement("FONT"); if(GM_getValue(playerName + "_haveOde", false) && GM_getValue(playerName + "_usingBandersnatch", false) || GM_getValue(playerName + "_usingBoots", false)){ var count = GM_getValue(playerName+"_snatchRunaways", 0); var max = Math.floor(GM_getValue(playerName + "_familiarWeight",0) / 5); newElement.innerHTML = "<font size=0>" + " \'snatch/boots: " + Math.max(max-count, 0) + "/" + max + " left</font>"; runAwayButton.parentNode.insertBefore(newElement, runAwayButton.nextSibling); } else if (GM_getValue(playerName + "_usingNavelRing", false)) { var count = GM_getValue(playerName+"_navelRingRunaways",0); var runPercent = count + 1 <= navelPercentages.length ? navelPercentages[count] : navelPercentages[navelPercentages.length - 1]; // alert("adding navel ring info - runaways = " + count + ", percent = " + runPercent); newElement.innerHTML = "<font size=0>" + " (\Navel: " + runPercent + "%)</font>"; runAwayButton.parentNode.insertBefore(newElement, runAwayButton.nextSibling); } } // find and label the runaway button in the combat bar, if any // this it broken - CAB is filling the action bar -after- the script runs, so all the buttons are blank when we search { var allElements = document.getElementsByTagName("img"); var button = null; for(var i=0; i < allElements.length; i++) { if(allElements[i].title == "Run Away" ) { button = allElements[i]; break; } } if(button) { var theTable = getParent(button,'table'); // first row is label, 2nd is buttons, 3rd is labels that we want to edit var rows = theTable.getElementsByTagName("tr"); var buttons = rows[1].getElementsByTagName("td"); var labels = rows[2].getElementsByTagName("td"); for(var i=0; i < buttons.length; i++) { if(buttons[i].innerHTML.indexOf("Run Away") != -1) { // edit the corresponding label if(GM_getValue(playerName + "_haveOde", false) && GM_getValue(playerName + "_usingBandersnatch", false)){ var count = GM_getValue(playerName+"_snatchRunaways", 0); var max = Math.floor(GM_getValue(playerName + "_familiarWeight",0) / 5); labels[i].innerHTML = Math.max(max-count,0) + " left"; } else if (GM_getValue(playerName + "_usingNavelRing", false)) { var count = GM_getValue(playerName+"_navelRingRunaways",0); var runPercent = count + 1 <= navelPercentages.length ? navelPercentages[count] : navelPercentages[navelPercentages.length - 1]; labels[i].innerHTML = "(" + runPercent + "%)"; } } } } } } //////////////////////////////////////////////////////////////////////////////// // watch choice.php for the arrival of bird form, // and for the the talk-to-the-llama that signals the end of birdform function processChoice() { if ( (pos = document.body.innerHTML.indexOf( "Form of...Bird!" )) != -1 ) { // we are starting a new birdform session var playerName = GM_getValue( "currentPlayer"); setBirdform(playerName); // trigger char pane refresh to make counter visible top.frames[0].location.reload(); } else if ( (pos = document.body.innerHTML.indexOf( "The llama looks deep into your eyes" )) != -1 ) { // we are done // what if we miss this for some reason - maybe the user did it in mafia or something - // we don't want birdform forever. Maybe a manual clear button? var playerName = GM_getValue( "currentPlayer"); clearBirdform(playerName); // trigger char pane refresh to make counter visible top.frames[0].location.reload(); } } function manualClearCounter() { var playerName = getPlayerNameFromCharpane().username; GM_setValue("currentPlayer", playerName); // store for other functions that need to know who's playing if( confirm("Clear and hide birdform counter?")) { clearBirdform(playerName); // trigger char pane refresh to make counter visible - will this work? top.frames[0].location.reload(); } } // clear the counters if a new day or ascension function zeroDropVars(playerName){ // all the generic ones for(var drop in allDrops) { GM_setValue(playerName+allDrops[drop][DROP_GM_VAR_IDX], 0); } // and the "special" ones that aren't in the array GM_setValue(playerName+"_underlingSummons",0); GM_setValue(playerName+"_mayflySummons",0); GM_setValue(playerName+"_navelRingRunaways",0); GM_setValue(playerName+"_snatchRunaways",0); GM_setValue(playerName+"_gibbererAdv",0); GM_setValue(playerName+"_gnomeAdv",0); GM_setValue(playerName+"_HareAdv",0); GM_setValue(playerName+"_VMaskAdv",0); GM_setValue(playerName+"_hipsterAdv",0); GM_setValue(playerName+"_PieDrops",0); GM_setValue(playerName+"_pieParts",0); } //////////////////////////////////////////////////////////////////////////////// // callback function to process the main charsheet if we find ourselves in a // new session, to see if it is a new day function processCharsheet(data) { var playerName = getPlayerNameFromCharsheet(data); GM_setValue("currentPlayer", playerName); var prevDayCount = GM_getValue(playerName+"_dayCount",-1); var dayCount = getDaysPlayed(data); // alert("got daycount: " + dayCount + " for " + playerName); if(isNaN(dayCount)) { // alert("processCharsheet - unable to parse dayCount, aborting"); return; // hopefully will try again with more success, can't continue } GM_setValue(playerName+"_dayCount", dayCount); GM_setValue(playerName + "_checkForReset", false); // says we succeeded, don't try again // if a new day, zero the current gong drop count if( dayCount != prevDayCount ) { // current dayCount is more, less (ascended) or prevDayCount was -1 are all valid zeroDropVars(playerName); } } // add a charsheet row for a given daily drop function addDropRow(lastTR, dropText, dropCount, maxDrops) { var newTR = document.createElement("tr"); var newElement = document.createElement("td"); newElement.appendChild(document.createTextNode(dropText)); newElement.align = "right"; newTR.appendChild(newElement); newElement = document.createElement("td"); newElement.align = "left"; newElement.style.fontWeight = "bold"; newElement.appendChild(document.createTextNode(dropCount + (maxDrops != "" ? "/" + maxDrops : ""))); newTR.appendChild(newElement); lastTR.parentNode.insertBefore(newTR, lastTR.nextSibling); return newTR; } function checkForHardcore(data) { if ( (pos = data.indexOf( "You are in Hardcore mode" )) != -1 ) return true; else return false; } // edit the charsheet display with the gongs-dropped-today info function processCharsheetDisplay() { // maybe we should only print these if they actually have that familiar, or // if the count is > 0 // on the other hand, this is also where we post the update-available link, so we // probably want the gong drops no matter what. // as a sanity check thing, could call processCharSheet() here // if it resets the count to zero after something has already dropped - is that better than nothing? var playerName = getPlayerNameFromCharsheet(document.body.innerHTML); GM_setValue("currentPlayer", playerName); var inHardcore = checkForHardcore(document.body.innerHTML); // stick it after the "Days Played (this run)" line (but "this run" doesn't appear for unascended chars) var allElements = document.getElementsByTagName("td"); var targetElement = null; // where to insert our info for(var i=0; i < allElements.length; i++) { if(allElements[i].innerHTML.indexOf( "Days Played" ) != -1 && allElements[i].innerHTML.indexOf( "Turns Played" ) == -1 // awkward way to ensure we don't get some parent container with the right text && allElements[i].innerHTML.indexOf( "(total)" ) == -1 ) { // ensure that it's not Days Played (total) targetElement = allElements[i]; break; } } if(targetElement != null) { // add a row for each drop we are tracking // "generic" ones first, then the special ones we track in some other way var lastTR = targetElement.parentNode; var lastDrop = ""; for(var drop in allDrops) { if(GM_getValue(playerName+allDrops[drop][DROP_GM_FLAG_IDX], false)) { // so can filter out repeats on same counter (e.g. pastes) if(lastDrop != allDrops[drop][DROP_GM_VAR_IDX]) { lastDrop = allDrops[drop][DROP_GM_VAR_IDX]; var dropCount = GM_getValue(playerName+allDrops[drop][DROP_GM_VAR_IDX],0); // kind of bogus, but the best I could come up with if(allDrops[drop][DROP_GM_FLAG_IDX]=="_hasPutty" && GM_getValue(playerName+"_hasRain-Doh")==true) { var dropsLeft = Math.min(5, 6 - GM_getValue(playerName+"_Rain-DohUses",0)); allDrops[drop][DROP_DAILY_MAX_IDX] = dropsLeft.toString(); } else if(allDrops[drop][DROP_GM_FLAG_IDX]=="_hasRain-Doh" && GM_getValue(playerName+"_hasPutty")==true) { var dropsLeft = Math.min(5, 6 - GM_getValue(playerName+"_puttyUses",0)); allDrops[drop][DROP_DAILY_MAX_IDX] = dropsLeft.toString(); } lastTR = addDropRow(lastTR, allDrops[drop][DROP_LABEL_IDX] + " Today:", dropCount, allDrops[drop][DROP_DAILY_MAX_IDX]); } } } // these aren't in the all-drops array, since they require some custom coding or another if( GM_getValue(playerName+"_hasOrganGrinder", false)) { var pies = GM_getValue(playerName+"_PieDrops",0); var parts = GM_getValue(playerName+"_pieParts",0); lastTR = addDropRow(lastTR, "Pie Drops Today:", pies + " pie" + (pies != 1 ? "s" : "") + ", " + parts + " part" + (parts != 1 ? "s" : ""), ""); } if(!inHardcore && GM_getValue(playerName+"_hasFrippery", false)) { var summonses = GM_getValue(playerName+"_underlingSummons",0); lastTR = addDropRow(lastTR, "Hobo Underling Summons Today:", summonses, 5); } if(!inHardcore && GM_getValue(playerName+"_hasMayflies", false)) { var summonses = GM_getValue(playerName+"_mayflySummons",0); lastTR = addDropRow(lastTR, "Mayfly Summons Today:", summonses, 30); } if(!inHardcore && GM_getValue(playerName+"_hasNavelRing", false)) { var navelRingRunaways = GM_getValue(playerName+"_navelRingRunaways",0); lastTR = addDropRow(lastTR, "Navel Ring/GAP Runaways Today:", navelRingRunaways, ""); } if(GM_getValue(playerName+"_hasSnatch", false)) { var snatchRunaways = GM_getValue(playerName+"_snatchRunaways",0); lastTR = addDropRow(lastTR, "Bander/Boots Runaways Today:", snatchRunaways, ""); } if(GM_getValue(playerName+"_hasGibberer", false)) { var advs = GM_getValue(playerName+"_gibbererAdv",0); lastTR = addDropRow(lastTR, "Gibberer Bonus Adventures Today:", advs, ""); } if(GM_getValue(playerName+"_hasGnome", false)) { var advs = GM_getValue(playerName+"_gnomeAdv",0); lastTR = addDropRow(lastTR, "Gnome Bonus Adventures Today:", advs, ""); } if(GM_getValue(playerName+"_hasHare", false)) { var hadvs = GM_getValue(playerName+"_HareAdv",0); lastTR = addDropRow(lastTR, "Wild Hare Bonus Adventures Today:", hadvs, ""); } if(GM_getValue(playerName+"_hasVMask", false)) { var advs = GM_getValue(playerName+"_VMaskAdv",0); lastTR = addDropRow(lastTR, "V-mask Bonus Adventures Today:", advs, ""); } if(GM_getValue(playerName+"_hasHipster", false)) { var advs = GM_getValue(playerName+"_hipsterAdv",0); lastTR = addDropRow(lastTR, "Hipster Fights Today:", advs, ""); } } // throw in something to tell user if new script version is available /* { var message; var href = null; var webVer = GM_getValue("webVersion"); if (webVer != "Error" && webVer > currentVersion) { // this is actually a text string comparison, not numerical newTR = document.createElement("tr"); newElement = document.createElement("td"); newElement.appendChild(document.createTextNode("New birdform script version " + webVer + " available:")); newElement.align = "right"; newElement.style.fontSize = "x-small"; newTR.appendChild(newElement); newElement = document.createElement("td"); newElement.align = "left"; newElement.style.fontWeight = "bold"; newElement.style.fontSize = "x-small"; var hrefElement = document.createElement("a"); hrefElement.setAttribute('href', scriptSite); hrefElement.setAttribute('target', "_blank"); hrefElement.appendChild(document.createTextNode("here")); newElement.appendChild(hrefElement); newTR.appendChild(newElement); lastTR.parentNode.insertBefore(newTR, lastTR.nextSibling); } } */ } /////////////////////////////////////////////////////////////////////////////// // update display information - this function must be called when we are in the char sidepane function updateCharacterPane() { var a = getPlayerNameFromCharpane(); var playerName = a.username; var fullmode = a.fullmode; // alert("in updateCharacterPane; player name = " + playerName); if( playerName == null ) // not sure why we sometimes see this, but doesn't seem to be at critical times return; GM_setValue("currentPlayer", playerName); // store for other functions that need to know who's playing // if astral plane, need to reset counters // getPlayerLevel() returns 0 for astral plane var playerLevel = getPlayerLevel(document.documentElement.innerHTML); if(playerLevel == 0) { // alert("detected astral plane; zeroing counters"); // clear the counters, no point in doing anything else zeroDropVars(playerName); clearBirdform(playerName); return; } // check the free runaway prereqs - actual processing is done on the fight page var usingNavelRing = checkNavelRing(document.documentElement.innerHTML); GM_setValue(playerName + "_usingNavelRing", usingNavelRing); if(usingNavelRing) GM_setValue(playerName+"_hasNavelRing", true); // a one time flag, never reset. var familiar = getFamiliar(document.documentElement.innerHTML, fullmode); var usingBandersnatch = familiar.type == "bandersnatch" ? true: false; GM_setValue(playerName + "_usingBandersnatch", usingBandersnatch); if(usingBandersnatch) GM_setValue(playerName+"_hasSnatch", true); // a one time flag, never reset. Easier than checking terrarium! var usingGrinder = familiar.type == "organgoblin" ? true: false; GM_setValue(playerName + "_usingGrinder", usingGrinder); if(usingGrinder) GM_setValue(playerName+"_hasOrganGrinder", true); // a one time flag, never reset. Easier than checking terrarium! var usingBoots = familiar.type == "stompboots" ? true: false; GM_setValue(playerName + "_usingBoots", usingBoots); if(usingBoots) GM_setValue(playerName+"_hasBoots", true); // a one time flag, never reset. Easier than checking terrarium! GM_setValue(playerName + "_familiarWeight", familiar.weight); GM_setValue(playerName + "_haveOde", checkOde(document.documentElement.innerHTML)); // alert("using navel ring: " + usingNavelRing + ", usingBandersnatch: " + usingBandersnatch + ", weight = " + weight + ", have ode: " + haveOde); // If have birdform, display the count var hasBirdform = GM_getValue(playerName+"_hasBirdform",false); // check the session ID to see if we are still in the same session // nb can't use document.body, doesn't include the initial javascript stuff var pwdHash = getPwdHash(document.documentElement.innerHTML); var oldPwdHash = GM_getValue(playerName + "_pwdHash", 0); GM_setValue(playerName + "_pwdHash", pwdHash); if(pwdHash != oldPwdHash) { // set flag to request check for new day; clear when check succeeds (sometimes takes more than 1 try) GM_setValue(playerName + "_checkForReset", true); /* // check for a new version of script if none seen already (asynch call, will run in parallel) var webVer = GM_getValue("webVersion", "Error"); if(webVer == "Error" || webVer <= currentVersion) // **BUG** fails forever if webVer gets set to a value higher than currentVersion GM_get(scriptURL, CheckScriptVersion); */ } if(GM_getValue(playerName + "_checkForReset", false) == true) { // need to check if it is a new da - asynch call, runs in parallel GM_get(baseURL + charSheet, processCharsheet); } if(hasBirdform) { // build up display text for total physical (two attacks) and elemental (one attack each) // always display physical. Others if > 0 var count = GM_getValue(playerName + attackSuffixes[ATTACK_TALON_SLASH], 0) + GM_getValue(playerName + attackSuffixes[ATTACK_WING_BUFFET], 0); var displayText = "\<font color=\"black\"\>\<b\>" + count + "\</b\>\</font\>"; count = GM_getValue(playerName + attackSuffixes[ATTACK_STATUE_TREATMENT], 0); if(count > 0) { displayText = displayText + "<font color=\"green\">+<b>" + count + "</b></font>"; } count = GM_getValue(playerName + attackSuffixes[ATTACK_THE_BIRD], 0); if(count > 0) { displayText = displayText + "<font color=\"blueviolet\">+<b>" + count + "</b></font>"; } count = GM_getValue(playerName + attackSuffixes[ATTACK_ANTARCTIC_FLAP], 0); if(count > 0) { displayText = displayText + "<font color=\"blue\">+<b>" + count + "</b></font>"; } count = GM_getValue(playerName + attackSuffixes[ATTACK_RISE_FROM_ASHES], 0); if(count > 0) { displayText = displayText + "<font color=\"red\">+<b>" + count + "</b></font>"; } count = GM_getValue(playerName + attackSuffixes[ATTACK_FEAST_ON_CARRION], 0); if(count > 0) { displayText = displayText + "<font color=\"gray\">+<b>" + count + "</b></font>"; } if(fullmode) { var newElement = document.createElement("FONT"); newElement.innerHTML = "<b>" + "<font size=2>Bird Attacks: " + displayText + "</font></b><br><br>"; ; newElement.setAttribute("onmouseover", 'this.style.opacity="0.5"'); newElement.setAttribute("onmouseout", 'this.style.opacity="1"'); newElement.setAttribute("id", 'birdAttackCounter'); newElement.addEventListener("click", manualClearCounter, true); var elements = document.getElementsByTagName( "FONT" ); for ( var i = 0; i < elements.length; ++i ){ if ( elements[i].innerHTML.indexOf( "Last Adventure" ) != -1 ){ // insert ours before this one elements[i].parentNode.insertBefore(newElement,elements[i]); break; } } } else { // compact mode - different layout, make a table row for our display var newTR = document.createElement('tr'); var newElement = document.createElement("td"); newElement.appendChild(document.createTextNode("Bird:")); newElement.align = "right"; newTR.appendChild(newElement); newElement = document.createElement("td"); newElement.setAttribute("onmouseover", 'this.style.opacity="0.5"'); newElement.setAttribute("onmouseout", 'this.style.opacity="1"'); newElement.setAttribute("id", 'birdAttackCounter'); newElement.addEventListener("click", manualClearCounter, true); var newFontElement = document.createElement("FONT"); newFontElement.innerHTML = "<b><font size=2>" + displayText + "</font></b>"; newElement.appendChild(newFontElement); newElement.align = "left"; newTR.appendChild(newElement); var elements = document.getElementsByTagName( "TR" ); var done = false; // if the last adventures script is running, insert before, else append to table for ( var i = 1; i < elements.length; ++i ){ // normally "Adv", might be "Last Adventures" if that script is running if ( elements[i].innerHTML.indexOf( "Last Adventures" ) != -1 ){ // insert ours before this one - experiment, back up one more elements[i].parentNode.insertBefore(newTR,elements[i-1]); done = true; break; } } if(!done) { // normal, no last adv script for ( var i = 0; i < elements.length; ++i ){ if ( elements[i].innerHTML.indexOf( "Adv" ) != -1 ){ // insert ours at end of the table in compact mode elements[i].parentNode.appendChild(newTR); break; } } } } } // duplicate functionality added in 0.2.3 for displaying mayfly counter on the charpane var mayflycount = GM_getValue(playerName+"_mayflySummons",0); var hasmayflies = GM_getValue(playerName+"_hasMayflies", false); if(hasmayflies && mayflycount > 0 && mayflycount < 30) { var mayflytext = "Mayfly Summons: " + mayflycount + "/30"; if(fullmode) { var newElement = document.createElement("FONT"); newElement.innerHTML = "<b><font size=2> " + mayflytext + "</font></b><br>"; ; var elements = document.getElementsByTagName( "FONT" ); for ( var i = 0; i < elements.length; ++i ){ if ( elements[i].innerHTML.indexOf( "Last Adventure" ) != -1 ){ // insert ours before this one elements[i].parentNode.insertBefore(newElement,elements[i]); break; } } } else { // compact mode - different layout, make a table row for our display var newTR = document.createElement('tr'); var newElement = document.createElement("td"); newElement.appendChild(document.createTextNode("Mayfly: ")); newElement.align = "right"; newTR.appendChild(newElement); newElement = document.createElement("td"); var newFontElement = document.createElement("FONT"); newFontElement.innerHTML = "<b><font size=2>" + mayflycount + "/30</font></b>"; newElement.appendChild(newFontElement); newElement.align = "left"; newTR.appendChild(newElement); var elements = document.getElementsByTagName( "TR" ); var done = false; // if the last adventures script is running, insert before, else append to table for ( var i = 1; i < elements.length; ++i ){ // normally "Adv", might be "Last Adventures" if that script is running if ( elements[i].innerHTML.indexOf( "Last Adventures" ) != -1 ){ // insert ours before this one - experiment, back up one more elements[i].parentNode.insertBefore(newTR,elements[i-1]); done = true; break; } } if(!done) { // normal, no last adv script for ( var i = 0; i < elements.length; ++i ){ if ( elements[i].innerHTML.indexOf( "Adv" ) != -1 ){ // insert ours at end of the table in compact mode elements[i].parentNode.appendChild(newTR); break; } } } } } } //////////////////////////////////////////////////////////////////////////////// // main prog, just call the proper routine if we are on a pane we care about var nodeBody = document.getElementsByTagName("body").item(0); var baseURL = ""; var charSheet = "charsheet.php"; if (nodeBody) { baseURL = nodeBody.baseURI.substring(0,nodeBody.baseURI.lastIndexOf('/')+1); } if(document.location.pathname.indexOf("fight.php") > 0 ) { // detect talon slashes and wingbuffets here processFight(); } else if ( document.location.pathname.indexOf("charpane.php") > 0 ) { // update display updateCharacterPane(); } else if ( document.location.pathname.indexOf("choice.php") > 0 ) { // this is where we detect that we got birdform, // and/or that we are done, and now talking to the llama processChoice(); } else if ( document.location.pathname.indexOf("charsheet.php") > 0 ) { // tell the user how many gongs have dropped today... processCharsheetDisplay(); }