// 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();
}