- // antimarty's fortune cookie script, based in part on:
- // csemaj's KoL Script
- // Copyright (c) 2007, James Cammarata
- // Based on code written by Byung Kim (Tard) http://kol.dashida.com and OneTonTomato's scripts
- // toggle preference code from lukifer's mrscript
- // http://www.noblesse-oblige.org/lukifer/scripts/
- // script update code based on DrEvi1's hatrack helper, which credits Picklish
- // fixes for lag combatting inventory screens by Firvagor
- // now using Charon's account options tab code
- // Released under the GPL license
- // http://www.gnu.org/copyleft/gpl.html
- //
- // ==UserScript==
- // @name antimarty fortune cookie script
- // @namespace antimarty
- // @include *kingdomofloathing.com/*.php*
- // @include *127.0.0.1:600*/*.php*
- // @include localhost:18481/*.php*
- // @version 0.5.7
- // @grant GM_getValue
- // @grant GM_setValue
- // @grant GM_xmlhttpRequest
- //
- // @description Kingdom of Loathing fortune cookie tracker
- // ==/UserScript==
-
- // released versions:
- // Version 0.5.7 - clan speakeasy, new topmenu frame rearrangement, gm grant stuff, move to Greasy Fork
- // Version 0.5.5 - kolhs semis; red fox; bram the stoker
- // Version 0.5.4 - new undersea SRs
- // Version 0.5.3 - new giant castle SRs, fix oxygenarian detection
- // Version 0.5.2 - updated for new level 8 and level 9 semis, and typo for friars
- // Version 0.5.1 - new hidden temple semi rare
- // Version 0.5.0 - add last location info to char pane if no popups
- // Version 0.4.9 - bug fix for deep fat friars' adventure name
- // Version 0.4.8 - bug fix for auto-attack combat macros, change version check
- // Version 0.4.7 - add disable popups option as FF4 workaround
- // Version 0.4.6 - bug fix for noncombat semis
- // Version 0.4.5 - Show initial bracket for new ascension, bug fix for puttied/faxed/arrow'd SR monsters
- // Version 0.4.4 - ascii, kge fights from fax/putty/camera/arrowing aren't semis; support new options page
- // Version 0.4.3 - add elf alley semi
- // Version 0.4.2 - add the pixel stopwatch
- // Version 0.4.1, use the turnsplayed native counter
- // Version 0.4.0, display a predicted cookie window if no cookie eaten
- // Version 0.3.9, support for billiards room semi
- // Version 0.3.8, sanity check numbers when user loads charsheet
- // Version 0.3.7, misc bug fixes
- // Version 0.3.6, fixes (courtesy Firvagor) for crimbo anti-lag changes to inventory screens; clear counter after semi-rare
- // Version 0.3.5, filter impossible cookie values; check for updates automatically
- // Version 0.3.4, support for hobopolis adventures
- // Version 0.3.3, bugfixes encore
- // Version 0.3.2, bugfixes
- // Version 0.3.1, bugfixes
- // Version 0.3.0, remember most recent semi-rare. Re-fix bugs re-introduced in 0.2.6
- // for unascended chars and compact mode, thanks to bad version control.
- // Version 0.2.6, reduced overhead, and bug fixes
- // Version 0.2.5, compact mode support and support for unascended chars
- // Version 0.2.3, improved sanity checker
- // Version 0.2.0, includes sanity checker
- // Version 0.1.1, bugfixes
- // Version 0.1.0 initial beta
-
- // Known bugs:
- // doesn't work in the kolmafia relay browser if you have this option set:
- // [] Force results to reload inline for [use] links
- // ... because the results page never reloads, so greasemonkey scripts don't run
- // may not save data correctly if Firefox doesn't exit cleanly (Greasemonkey issue)
-
- // basic logic to do this without retrieving character pane data:
- // - store an internal counter for adventures used
- // - look at the adventures remaining
- // - every time the pane is refreshed:
- // - if the remaining adventures decreases, decrease the counter by that amount
- // - if stays the same, do nothing
- // - if increases, do nothing
- // warn when hit zero
- //
- // read char sheet as a sanity check when the counter doesn't seem to be
- // decrementing normally
-
- // (temporarily?) unused, with move to Greasy Fork
- /* var currentVersion = "0.5.7";
- var scriptSite = "http://userscripts.org/scripts/show/13180"
- // this is autogenerated by userscripts.org from Userscript @ comments above, use to reduce bandwidth on version check
- var scriptURL = "http://userscripts.org/scripts/source/13180.meta.js";
- */
- ////////////////////////////////////////////////////////////////////////////////
- // 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 version number of script on the web
- function CheckScriptVersion(data)
- {
- // alert("inside version check");
- // 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 pane for the player name
- // revised version! now taken directly from kolpreviousnadventures to handle compact mode
- 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};
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // 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
- if(playerName)
- return playerName[1].toLowerCase();
- else
- return null;
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // parse the char sheet (not pane) for the total adventure count
- // taken from the csemaj cookie script
- // the "(this run)" only appears if you have ascended
- function getTurnsPlayed(data) {
- var turncount = "0";
- if(data.indexOf("Turns Played (this run)") >= 0) {
- // alert("parsing datasheet for turns for an ascended char");
- turncount = /Turns Played \(this run\)[^>]*>(<[^>]+>)*([\d,]+)/i.exec(data)[2];
- }
- else {
- // alert("parsing datasheet for turns for an UNascended char");
- turncount = /Turns Played[^>]*>(<[^>]+>)*([\d,]+)/i.exec(data)[2];
- }
- // alert("found turncount=" + turncount);
- return parseInt(turncount.replace(',',''),10);
- }
-
- 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);
- }
-
- // parse the charpane info for the password hash (use as a session ID)
- function getPwdHash(data){
- var pwdHash = /pwdhash \= \"(.*?)\"/i.exec(data)[1]; // the .*? is the non-greedy version of .*
-
- // alert("got pwdHash: " + pwdHash);
- return pwdHash;
- }
-
- // parse the charpane info for the turnsplayed counter
- // updates at the end of the adventure, not during the fight
- function getTurnsplayedVar(data){
- var turnsplayed = /turnsthisrun \= (\d+)/i.exec(data)[1];
-
- return parseInt(turnsplayed);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // parse the main page for the name of the (noncombat) adventure - assuming
- // it's the next bolded thing after "Adventure Results:"
- function getAdventureName(data) {
- var adventureName = "";
- if ( data.indexOf( "Adventure Results:" ) != -1 ) { // kol mafia can put up stuff that requires this check
- adventureName = /Results:<\/b>.*?<b>(.*?)<\/b>/i.exec(data)[1];
- }
- // the hobopolis rares are choice adventures, not normal noncombats
- else if(document.location.pathname.indexOf("choice.php") != -1) {
- // look for adventure name as something in bold on blue background
- adventureName = /bgcolor=\"blue\"><b>(.*?)<\/b>/i.exec(data)[1];
- }
-
- // check for known broken adventures
- if(adventureName == "") {
- if(data.indexOf( "There once was a bleary-eyed cyclops" ) != -1 ){
- adventureName = "The Bleary-Eyed Cyclops";
- }
- }
-
- // alert("got adventure name: " + adventureName);
- return adventureName;
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // parse the main page for the name of the adventure
- function getMonsterName(data) {
- var monsterName = /id=\"monname\"> *(.*?)<\/span>/i.exec(data);
- if(monsterName)
- monsterName = monsterName[1].toLowerCase();
- else
- return {'monsterName': "", 'fromPutty': false};
-
- // don't count monsters from putty/fax/camera/arrowing
- var fromPutty = data.indexOf("You put the copied monster on the ground") != -1 ? true : false;
- if(!fromPutty)
- fromPutty = data.indexOf("You gaze at the photocopy") != -1 ? true : false;
- if(!fromPutty)
- fromPutty = data.indexOf("You reach down to open up the camera") != -1 ? true : false;
- if(!fromPutty)
- fromPutty = data.indexOf("hear a wolf whistle from behind you") != -1 ? true : false;
- if(!fromPutty)
- fromPutty = data.indexOf("You play back the recording") != -1 ? true : false;
- if(!fromPutty)
- fromPutty = data.indexOf("%%") != -1 ? true : false; // some sort of error we see a lot with copied monsters
-
- // alert("got monster name: *" + monsterName + "*; from putty = " + fromPutty);
- return {'monsterName': monsterName, 'fromPutty': fromPutty};
- }
-
- // process a noncombat result for semi-rareness
- var semis =
- {
- noncombats: {
- "Play Misty For Me" : "the Haunted Kitchen",
- "Like the Sunglasses, But Less Comfortable" : "the Haunted Library",
- "The Pilsbury Doughjerk" : "the Haunted Pantry",
- "The Bleary-Eyed Cyclops" : "the Limerick Dungeon", // I don't see the title appear when I get this adv.
- "In the Still of the Alley" : "the Sleazy Back Alley",
- "Natural Selection" : "the Goatlet",
- "Not Quite as Cold as Ice" : "the Lair of the Ninja Snowmen",
- "Prior to Always" : "a Battlefield",
- "How Does He Smell?" : "the Batrat and Ratbat Burrow",
- "All The Rave" : "the Castle Top Floor",
- "Le Chauve-Souris du Parfum" : "Guano Junction",
- "Hands On" : "the Harem",
- "You Can Top Our Desserts, But You Can't Beat Our Meats" : "the Laboratory",
- "Rokay, Raggy!" : "the Menagerie Level 2",
- "A Menacing Phantom" : "the Misspelled Cemetery",
- "Lunchboxing" : "the Outskirts of Cobb's Knob",
- "Filth, Filth, and More Filth" : "South of the Border",
- "It's The Only Way To Be Sure" : "the Deep Fat Friars",
- "It's the Only Way to be Sure" : "Pandamonium slums",
- "Two Sizes Too Small" : "the Hidden City",
- "Some Bricks Do, In Fact, Hang in the Air" : "the Inexplicable Door",
- "Blaaargh! Blaaargh!" : "the Spooky Forest",
- "Monty of County Crisco" : "Whitey's Grove",
- "The Latest Sorcerous Developments" : "the Hippy Camp (pre-war)",
- "Sand in the Vaseline" : "the Orcish Frat House (pre-war)",
- "Yo Ho Ho and a Bottle of Whatever This Is" : "the Obligatory Pirate's Cove",
- "A Tight Squeeze" : "BurnBarrel Blvd.",
- "Cold Comfort" : "Exposure Esplanade",
- "Juicy!" : "the Heap",
- "Flowers for You" : "the Ancient Hobo Burial Ground",
- "Maybe It's a Sexy Snake!" : "the Purple Light District",
- "What a Tosser" : "Elf Alley",
- "A Shark's Chum" : "The Haunted Billiards Room",
- "The Time This Fire" : "Vanya's Castle Chapel",
- "Oh, <i>There</i> Have it Gone" : "A-Boo Peek",
- "Synecdoche, Twin Peak" : "Twin Peak",
- "It's a Gas Gas Gas" : "Oil Peak",
- "Fit and Finish" : "the Castle Basement",
- "Ahead of the Game" : "the Castle Ground Floor",
- "Razor, Scooter" : "the Dive Bar",
- "Deeps Impact" : "the Briny Deeps",
- "The Haggling" : "the Brinier Deepers",
- "Camera On, James" : "the Wreck of the Edgar Fitzsimmons",
- "Dragon the Line" : "Madness Reef",
- "A Drawer of Chests" : "the Mer-Kin Outpost",
- "Through the Locking Glass" : "the Hallowed Halls",
- "Clay Is Great, But Leather Is Bether" : "Ye Olde Medievale Villagee",
- "Where There's Smoke...": "The Copperhead Club",
- "Methinks the Protesters Doth Protest Too Little": "A Mob of Zeppelin Protesters",
- // fake ones for testing
- // "A Dash of Boulder" : "the Dungeons of Doom - Boulder",
- // "Meat Score!" : "the Treasury - Meat Score",
-
- },
- combats: { // use lowercase
- "some bad ascii art" : "the Valley Beyond The Orc Chasm",
- "a knob goblin elite guard captain" : "the Cobb's Knob Kitchens",
- "a knob goblin embezzler" : "the Treasury",
- "a c. h. u. m. chieftain" : "a Maze of Sewer Tunnels",
- "baa'baa'bu'ran" : "the Hidden Temple",
- "a 7-foot dwarf foreman" : "Itznotyerzitz Mine",
- "a moister oyster" : "An Octopus's Garden",
- "françois verte, art teacher" : "Art Class", // some encoding issue with this one
- "x-fingered shop teacher" : "Shop Class", // need to resolve the X (1-11)
- "mrs. k, the chemistry teacher" : "Chemistry class",
- "the red fox" : "The Red Zeppelin",
- "bram the stoker" : "The Haunted Boiler Room",
- "a full-length mirror" : "The Haunted Storage Room",
- // fake ones for testing
- // "a knob goblin elite guardsman" : "the Treasury",
- // "a swarm of killer bees" : "the Dungeons of Doom",
- },
- };
-
- function clearCounters(playerName) {
- GM_setValue(playerName+"_lastSemiTurn",-1);
- GM_setValue(playerName+"_lastSemiLocation","");
-
- GM_setValue(playerName+"_luckyTurn1", -1);
- GM_setValue(playerName+"_luckyTurn2", -1);
- GM_setValue(playerName+"_luckyTurn3", -1);
- }
-
- function checkForNoncombatSemi(data) {
- theAdv = getAdventureName(document.body.innerHTML);
- // alert("in checkForNoncombatSemi(), adv name = " + theAdv);
- // alert("semis.noncombats[theAdv] = " + semis.noncombats[theAdv]);
-
- if(semis.noncombats[theAdv] != undefined) {
- var playerName = GM_getValue("currentPlayer");
- var turncount = GM_getValue(playerName+"_turncount", 0);
- // var turncount = getTurnsplayedVar(top.frames[0].document);
-
- // alert("Found semirare adv \'" + theAdv + "\' in area " + semis.noncombats[theAdv] + " on tuncount " + turncount + " for player " + playerName);
- // found a semi, clear counters
- // this might backfire if using the counter as a generic countdown for other purposes, e.g. wossname tracking
- clearCounters(playerName);
-
- GM_setValue(playerName+"_lastSemiTurn",turncount+1); // the turncount var isn't updated yet
- GM_setValue(playerName+"_allowBracket",true);
- GM_setValue(playerName+"_lastSemiLocation",semis.noncombats[theAdv]);
-
- // trigger char pane refresh with the new info
- top.frames[0].location.reload();
- }
- }
-
- function checkForCombatSemi(data) {
- var monster = getMonsterName(document.body.innerHTML);
- theAdv = monster.monsterName;
-
- if(monster.fromPutty == false && semis.combats[theAdv] != undefined) {
- var playerName = GM_getValue("currentPlayer");
- var turncount = GM_getValue(playerName+"_turncount", 0);
- // var turncount = getTurnsplayedVar(top.frames[0].document);
-
- // alert("Found semi rare adv \'" + theAdv + "\' in area " + semis.combats[theAdv] + " - for player " + playerName + " on turn " + turncount );
- // found a semi, clear counters
- // this might backfire if using the counter as a generic countdown for other purposes, e.g. wossname tracking
- clearCounters(playerName);
-
- GM_setValue(playerName+"_lastSemiTurn",turncount+1); // the turncount var isn't updated yet
- GM_setValue(playerName+"_allowBracket",true);
- GM_setValue(playerName+"_lastSemiLocation",semis.combats[theAdv]);
-
- // trigger char pane refresh with the new info
- top.frames[0].location.reload();
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // callback function to process the main charsheet as a sanity check after
- // something questionable was spotted, or just on a new session
- // **** mostly deprecated ****
- function sanityCheckCharsheet(data) {
- // alert("entering sanity check");
- var playerName = getPlayerNameFromCharsheet(data);
- GM_setValue("currentPlayer", playerName);
-
- var turncount = getTurnsPlayed(data); // total turns played
-
- if(isNaN(turncount) ) {
- // alert("sanityCheckCharsheet - unable to parse either turncount (" + turncount + ") or remaining adv count (" + remainingAdventureCount + "), aborting");
- return; // hopefully will try again with more success, can't continue
- }
-
- GM_setValue(playerName+"_turncount", turncount); // I'll try to keep this up to date
-
- // if the previous turncount makes no sense, zero it. After ascending would be an example
- var lastSemiTurn = GM_getValue(playerName+"_lastSemiTurn",-1);
- if( lastSemiTurn > turncount+1) {
- GM_setValue(playerName+"_lastSemiTurn",-1);
- GM_setValue(playerName+"_lastSemiLocation","");
- }
- var prevDayCount = GM_getValue(playerName+"_dayCount",-1);
-
- var dayCount = getDaysPlayed(data);
- if(!isNaN(dayCount)) {
- if(dayCount < prevDayCount) { // must have ascended
- GM_setValue(playerName+"_lastSemiTurn",-1);
- GM_setValue(playerName+"_lastSemiLocation","");
- }
- GM_setValue(playerName+"_dayCount",dayCount);
- }
-
- // set a flag is we are oxy, since it affects the cookie spacing
- if( data.match("Oxygenarian"))
- GM_setValue(playerName+"_isOxy", true);
- else
- GM_setValue(playerName+"_isOxy", false);
-
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // watch for the lucky numbers result on the main page
- function processMain(doc) {
- var countdown1 = -1;
- var countdown2 = -1;
- var countdown3 = -1;
- var pos = -1;
-
- // alert("in processMain()");
- ///////NEW STUFF (Firvagor) - changed the if line to use the div instead of the body, since the results, and a hidden field is made inside the div so infinite looping doesn't occur//////////
- //if the hidden field is found, don't do anything
- if (doc.getElementById("cookiedone")!=null){return;}
-
- var playerName = GM_getValue( "currentPlayer");
- var divElement = doc.getElementById("effdiv");
-
- var bqElement = doc.getElementsByTagName("blockquote");
- // if(bqElement[0])
- // alert("processMain: speakeasy quote = " + bqElement[0]);
-
- if ( divElement ) {
- // alert("found divElement");
-
- doc.getElementById("effdiv").innerHTML += "<input type='hidden' id='cookiedone' name='completed' value='yes'>";
- if((pos = doc.getElementById("effdiv").innerHTML.indexOf( "Lucky numbers:" )) != -1 ) {
-
- // alert("found lucky numbers");
- // need to parse the text, format is "Lucky numbers: ###, ###, ###"
- var cookieText = doc.getElementById("effdiv").innerHTML.substring(pos, pos+30);
-
- // first one starts after the colon, next two after commas
- pos = cookieText.indexOf(":");
- cookieText = cookieText.substring(pos+1);
- countdown1 = parseInt(cookieText);
-
- pos = cookieText.indexOf(",");
- cookieText = cookieText.substring(pos+1);
- countdown2 = parseInt(cookieText);
-
- pos = cookieText.indexOf(",");
- cookieText = cookieText.substring(pos+1);
- countdown3 = parseInt(cookieText);
-
- // elegantly sort them
- {
- var temp;
- if(countdown1 > countdown2) {
- temp = countdown1; countdown1 = countdown2; countdown2 = temp;
- }
- if(countdown2 > countdown3) {
- temp = countdown2; countdown2 = countdown3; countdown3 = temp;
- }
- if(countdown1 > countdown2) {
- temp = countdown1; countdown1 = countdown2; countdown2 = temp;
- }
- }
- // alert("processMain: cookie cookieText=" + cookieText + ", lucky numbers are " + countdown1 + ", " + countdown2 + ", " + countdown3);
- }
- }
-
- // speakeasy drink; format is "burp-speak the number <b>30</b>"
- // doesn't work, is there really an effdiv for this? didn't see it in the text
- // try a blockquote instead... doesn't sound too reliable
- // else if((pos = doc.getElementById("effdiv").innerHTML.indexOf( "burp-speak the number" )) != -1 ) {
- if(bqElement[0] && (pos = bqElement[0].innerHTML.indexOf( "burp-speak the number" )) != -1 ) {
- // alert("processing speakeasy");
- bqElement[0].innerHTML += "<input type='hidden' id='cookiedone' name='completed' value='yes'>";
-
- var cookieText = bqElement[0].innerHTML.substring(pos, pos+30);
-
- // just one number, bolded
- pos = cookieText.indexOf("<b>");
- cookieText = cookieText.substring(pos+3);
- countdown1 = parseInt(cookieText);
- countdown2 = -1;
- countdown3 = -1;
- // alert("processMain: speakeasy cookieText=" + cookieText + ", lucky numbers are " + countdown1 + ", " + countdown2 + ", " + countdown3);
- }
-
- if(countdown1>=0 || countdown2>=0 || countdown3>=0) {
- // filter out nonsense values:
- // - too high ( > 200 since last semi, 120 for oxy)
- // - too low ( < 160 since last semi, or < 100 if oxy)
- // the filters only apply if you found a semi recently; otherwise the counter starts
- // after a would-be semi, or ascension, with your first adventure.php location
- // adventure, but it's too much trouble to keep track
- GM_setValue(playerName+"_allowSanityCheck", false); // lock out the other pane from panicking
- // must call processCharsheet now, to clear this
- var allowBracket = GM_getValue(playerName+"_allowBracket",false);
- GM_setValue(playerName+"_allowBracket",false); // no reason to put up reminder after this
-
- var turncount = GM_getValue(playerName+"_turncount", 0);
- var lastSemiTurn = GM_getValue(playerName+"_lastSemiTurn",-1);
- var wasOxy = GM_getValue(playerName+"_isOxy", false);
- GM_setValue(playerName+"_isOxy", false); // ate a cookie, must not be oxy
- var minCount = 160; var maxCount = 200;
- if( wasOxy ) {
- minCount = 100; maxCount = 120;
- }
- if(turncount < 70) { // newly ascended
- minCount = 70; maxCount = 80; lastSemiTurn = 0;
- }
- var turnsSinceSemi = turncount - lastSemiTurn;
-
- // alert("filtering lucky numbers for " + playerName + " based on turncount=" + turncount + ", lastSemiTurn=" + lastSemiTurn + ", wasOxy=" + wasOxy + ", turnsSinceSemi = " + turnsSinceSemi );
- // eliminate counters that are too high on an absolute basis, then try to
- // eliminate ones too high and low based on last semi
- if(countdown1 > maxCount) countdown1 = -1;
- if(countdown2 > maxCount) countdown2 = -1;
- if(countdown3 > maxCount) countdown3 = -1;
-
- if(lastSemiTurn != -1 && turnsSinceSemi <= maxCount && allowBracket) {
- if( countdown1 + turnsSinceSemi > maxCount ) countdown1 = -1;
- if( countdown2 + turnsSinceSemi > maxCount ) countdown2 = -1;
- if( countdown3 + turnsSinceSemi > maxCount ) countdown3 = -1;
- }
-
- if(lastSemiTurn != -1) {
- if( countdown1 + turnsSinceSemi < minCount ) countdown1 = -1;
- if( countdown2 + turnsSinceSemi < minCount ) countdown2 = -1;
- if( countdown3 + turnsSinceSemi < minCount ) countdown3 = -1;
- }
-
- // now to compare them vs existing numbers
- // if there is no match, stick them in as the current numbers
- // if there is a match, use that and zero the other two
- var oldLuckyTurn1 = GM_getValue(playerName+"_luckyTurn1",-1);
- var oldLuckyTurn2 = GM_getValue(playerName+"_luckyTurn2",-1);
- var oldLuckyTurn3 = GM_getValue(playerName+"_luckyTurn3",-1);
- var oldCountdown1 = oldLuckyTurn1 != -1 ? oldLuckyTurn1 - turncount : -1;
- var oldCountdown2 = oldLuckyTurn2 != -1 ? oldLuckyTurn2 - turncount : -1;
- var oldCountdown3 = oldLuckyTurn3 != -1 ? oldLuckyTurn3 - turncount : -1;
-
- var noPopups = GM_getValue("noPopups", false);
-
- // need to watch out for -1 matching -1 since we reset values above
- // check for self-match in new cookie values first
- if(countdown1 != -1 && (countdown1==countdown2 || countdown1 == countdown3)) {
- if(!noPopups) alert(countdown1 + " turns until a semi-rare!");
- countdown2 = -1;
- countdown3 = -1;
- }
- else if(countdown2 != -1 && countdown2 == countdown3) {
- if(!noPopups) alert(countdown2 + " turns until a semi-rare!");
- countdown1 = -1;
- countdown3 = -1;
- }
- else if (countdown1 != -1 && (countdown1 == oldCountdown1 || countdown1 == oldCountdown2 || countdown1 == oldCountdown3 || countdown2 == -1 && countdown3 == -1)) {
- if(!noPopups) alert(countdown1 + " turns until a semi-rare!");
- countdown2 = -1;
- countdown3 = -1;
- }
- else if (countdown2 != -1 && (countdown2 == oldCountdown1 || countdown2 == oldCountdown2 || countdown2 == oldCountdown3 || countdown1 == -1 && countdown3 == -1)) {
- if(!noPopups) alert(countdown2 + " turns until a semi-rare!");
- countdown1 = -1;
- countdown3 = -1;
- }
- else if (countdown3 != -1 && (countdown3 == oldCountdown1 || countdown3 == oldCountdown2 || countdown3 == oldCountdown3 || countdown1 == -1 && countdown2 == -1)) {
- if(!noPopups) alert(countdown3 + " turns until a semi-rare!");
- countdown1 = -1;
- countdown2 = -1;
- }
-
- GM_setValue(playerName+"_luckyTurn1",countdown1 != -1 ? countdown1 + turncount : -1);
- GM_setValue(playerName+"_luckyTurn2",countdown2 != -1 ? countdown2 + turncount : -1);
- GM_setValue(playerName+"_luckyTurn3",countdown3 != -1 ? countdown3 + turncount : -1);
-
- // load and parse the main charsheet to set the behind the scene variables that
- // convert the cookie countdown into actual adventure number for each cookie
- // GM_get(baseURL + charSheet, processCharsheet);
-
- // trigger char pane refresh with the new info
- top.frames[0].location.reload();
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- function manualCookieEntry() {
- var playerName = getPlayerNameFromCharpane().username;
- // alert("player name: " + playerName);
- GM_setValue("currentPlayer", playerName); // store for other functions that need to know who's playing
- var noPopups = GM_getValue("noPopups", false);
- if(noPopups) return; // need to figure out some way to enter values without using a popup
-
- var turncount = GM_getValue(playerName+"_turncount", -1);
- var luckyTurn1 = GM_getValue(playerName+"_luckyTurn1", -1);
- var luckyTurn2 = GM_getValue(playerName+"_luckyTurn2", -1);
- var luckyTurn3 = GM_getValue(playerName+"_luckyTurn3", -1);
-
- var oldCountdown1 = luckyTurn1 > 0 ? luckyTurn1 - turncount : -1;
- var oldCountdown2 = luckyTurn2 > 0 ? luckyTurn2 - turncount : -1;
- var oldCountdown3 = luckyTurn3 > 0 ? luckyTurn3 - turncount : -1;
-
- var countdown1 = -1;
- var countdown2 = -1;
- var countdown3 = -1;
- var displayText = "";
-
- if(oldCountdown1 > -1)
- displayText += oldCountdown1;
- if(oldCountdown2 > -1) {
- if(displayText != "") displayText += ", ";
- displayText += oldCountdown2;
- }
- if(oldCountdown3 > -1) {
- if(displayText != "") displayText += ", ";
- displayText += oldCountdown3;
- }
-
- var lastSemiTurn = GM_getValue(playerName+"_lastSemiTurn",-1);
- var lastSemiLocation = GM_getValue(playerName+"_lastSemiLocation","");
- var promptText = "";
- if(lastSemiTurn > -1 && turncount >= lastSemiTurn ) {
- promptText = "Last semirare found " + (turncount - lastSemiTurn) + " turns ago, at " + lastSemiLocation + ".\n\n";
- }
- else {
- promptText = "Last semirare unknown.\n\n"
- }
- cookieText = prompt(promptText + "Enter 1-3 new cookie vals (-1 to clear)\n", displayText);
-
- if(cookieText) { // will be null if user cancels
- countdown1 = parseInt(cookieText);
- var pos = cookieText.indexOf(",");
- if(pos > 0) {
- cookieText = cookieText.substring(pos+1);
- countdown2 = parseInt(cookieText);
- pos = cookieText.indexOf(",");
-
- if(pos > 0) {
- cookieText = cookieText.substring(pos+1);
- countdown3 = parseInt(cookieText);
- }
- }
- // alert("manual text entry, got values " + countdown1 + ", " + countdown2 + ", " + countdown3);
- GM_setValue(playerName+"_luckyTurn1",countdown1+turncount);
- GM_setValue(playerName+"_luckyTurn2",countdown2+turncount);
- GM_setValue(playerName+"_luckyTurn3",countdown3+turncount);
- GM_setValue(playerName+"_needSanityCheck", false); // just in case we were in the middle of something
- GM_setValue(playerName+"_allowBracket",false); // no reason to put up reminder after this
-
- // load and parse the main charsheet to set the behind the scene variables that
- // convert the cookie countdown into actual adventure number for each cookie
- // GM_get(baseURL + charSheet, processCharsheet);
- // trigger char pane refresh with the new info
- top.frames[0].location.reload();
-
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // this function must be called when we are in the char sidepane
- 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
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // 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;
- 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) {
- // clear the counters, no point in doing anything else
- clearCounters(playerName);
- return;
- }
-
- // check the session ID to see if we are still in the same session
- // if a new session, check if an update is available
- var pwdHash = getPwdHash(document.documentElement.innerHTML);
- var oldPwdHash = GM_getValue(playerName + "_pwdHash", 0);
- if(pwdHash != oldPwdHash) {
- // new session
- GM_setValue(playerName + "_pwdHash", pwdHash);
-
- // run sanity check on new session, make sure we haven't missed anything
- // alert("calling sanity check");
- GM_get(baseURL + charSheet, sanityCheckCharsheet);
-
- // check for a new version of script if none seen already (asynch call, will run in parallel)
- // (temporarily?) removed for use with greasy fork
- /* var webVer = GM_getValue("webVersion", "Error");
- if(webVer == "Error" || webVer <= currentVersion) {
- // alert("calling version check");
- GM_get(scriptURL, CheckScriptVersion);
- }
- */
- }
-
- // new native counter!
- var turncount = getTurnsplayedVar(document.documentElement.innerHTML);
- var oldTurncount = GM_getValue(playerName+"_turncount", 0);
- GM_setValue(playerName+"_turncount", turncount);
-
- var lastSemiTurn = GM_getValue(playerName+"_lastSemiTurn",-1);
- var lastSemiLocation = GM_getValue(playerName+"_lastSemiLocation","");
- if(lastSemiTurn > turncount + 1) { // turncount var lags behind when fighting, so can have an off-by-1 issue
- // could happen if ascended
- lastSemiTurn = -1;
- GM_setValue(playerName+"_lastSemiTurn",-1);
- GM_setValue(playerName+"_lastSemiLocation","");
- }
-
- var luckyTurn1 = GM_getValue(playerName+"_luckyTurn1", -1);
- var luckyTurn2 = GM_getValue(playerName+"_luckyTurn2", -1);
- var luckyTurn3 = GM_getValue(playerName+"_luckyTurn3", -1);
-
- // if anything hit zero, warn the user
- var noPopups = GM_getValue("noPopups", false);
- var atSemi = false;
- if( turncount == luckyTurn1 || turncount == luckyTurn2 || turncount == luckyTurn3) {
- atSemi = true;
- if(!noPopups && turncount != oldTurncount) {
- var alertText = "Fortune cookie countdown hit zero!";
- if(lastSemiTurn > -1 && turncount >= lastSemiTurn) {
- alertText += "\n\nLast semirare found " + (turncount - lastSemiTurn) + " turns ago, at " + lastSemiLocation + ".";
- }
- else {
- alertText += "\n\nLast semirare unknown.";
- }
- confirm(alertText);
- }
- }
-
- var displayText = "";
- if(luckyTurn1 >= turncount)
- displayText += luckyTurn1 - turncount;
- if(luckyTurn2 >= turncount) {
- if(displayText != "") displayText += ", ";
- displayText += luckyTurn2 - turncount;
- }
- if(luckyTurn3 >= turncount) {
- if(displayText != "") displayText += ", ";
- displayText += luckyTurn3 - turncount;
- }
- if(atSemi && noPopups)
- displayText += " (last SR: " + (lastSemiLocation == "" ? "unknown" : lastSemiLocation) + ")";
- if(atSemi && fullmode) { // shows the html literally in compact mode
- displayText = "<font color=\"red\"><b>" + displayText + "</b></font>";
- }
-
- // display turn var to figure out exactly how it works
- // displayText += " (tp=" + turnsplayedVar+")";
-
- var hideIfZeros = GM_getValue("hideIfZeros", false);
-
- if(displayText != ""
- || hideIfZeros == false ) {
- // display an FC bracket if no cookie eaten, and have found a semi recently
- var isOxy = GM_getValue(playerName+"_isOxy", false);
- var turnsSinceSemi = turncount - lastSemiTurn;
- var minCount = 160; var maxCount = 200;
- if( isOxy ) {
- minCount = 100; maxCount = 120;
- }
- if(displayText == "" && lastSemiTurn != -1 && turnsSinceSemi <= maxCount ) {
- displayText = "[" + Math.max(0, minCount - turnsSinceSemi) + "...";
- displayText += Math.max(0, maxCount - turnsSinceSemi) + "]";
- } else if (displayText == "" && turncount < 70) { // default just-ascended bracket
- displayText = "[" + Math.max(0, 70 - turncount) + "...";
- displayText += Math.max(0, 80 - turncount) + "]";
- }
-
- if(fullmode) {
- var newElement = document.createElement("FONT");
- newElement.innerHTML = "<b>"
- + "<font size=2>Cookie Count: "
- + displayText
- + "</font></b><br><br>"; ;
- newElement.setAttribute("onmouseover", 'this.style.opacity="0.5"');
- newElement.setAttribute("onmouseout", 'this.style.opacity="1"');
- newElement.setAttribute("id", 'fortuneCookieCounter');
- newElement.addEventListener("click", manualCookieEntry, true);
- newElement.align = "center";
-
- var elements = document.getElementsByTagName( "FONT" );
- for ( var i = 0; i < elements.length; ++i ){
- if ( elements[i].innerHTML.indexOf( "Last Adventure" ) != -1 ){
- // insert our before this one
- elements[i].parentNode.insertBefore(newElement,elements[i]);
- break;
- }
- }
- }
- else { // compact mode - different layout, make a table row and two data element
- var newTR = document.createElement('tr');
-
- var newElement = document.createElement("td");
- newElement.appendChild(document.createTextNode("Cookie:"));
- 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", 'fortuneCookieCounter');
- newElement.addEventListener("click", manualCookieEntry, true);
- newElement.align = "left";
- newElement.style.fontWeight = "bold";
- newElement.appendChild(document.createTextNode(displayText));
- 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;
- }
- }
- }
- }
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // set preferences
- // code stolen from mr script
- // not set on a per-player basis, would need to add code to parse account pane for char name
- function toggleHideCountdown() {
- // alert("in toggleHideCountdown()");
-
- var hideIfZeros = GM_getValue("hideIfZeros", false);
- hideIfZeros = !hideIfZeros;
-
- GM_setValue("hideIfZeros", hideIfZeros);
-
- // trigger char pane refresh with the new info
- top.frames[0].location.reload();
- var msg = document.getElementById('cookiecountertoggle');
- msg.innerHTML = (hideIfZeros ? "Hiding" : "Showing") + " Inactive Counter - Click to Change";
- }
-
- function togglePopups() {
- // alert("in toggleHideCountdown()");
-
- var noPopups = GM_getValue("noPopups", false);
- noPopups = !noPopups;
-
- GM_setValue("noPopups", noPopups);
-
- // trigger char pane refresh with the new info
- var msg = document.getElementById('cookiepopups');
- msg.innerHTML = (noPopups ? "Popups Disabled " : "Using Popups") + " (disable for FF4) - Click to Change";
- top.frames[0].location.reload();
- }
-
- // --------------------------------------------
- // ---------- account menu option -------------
- // --------------------------------------------
-
- // Charon's code
- function buildPrefs() {
- if (!document.querySelector('#privacy'))
- return;
- if (!document.querySelector('#scripts')) {
- //scripts tab is not built, do it here
- var scripts = document.querySelector('ul').appendChild(document.createElement('li'));
- scripts.id = 'scripts';
- var a = scripts.appendChild(document.createElement('a'));
- a.href = '#';
- var img = a.appendChild(document.createElement('img'));
- img.src = 'http://images.kingdomofloathing.com/itemimages/cmonkey1.gif';
- img.align = 'absmiddle';
- img.border = '0';
- img.style.paddingRight = '10px';
- a.appendChild(document.createTextNode('Scripts'));
- a.addEventListener('click', function (e) {
- //make our new tab active when clicked, clear out the #guts div and add our settings to it
- e.stopPropagation();
- document.querySelector('.active').className = '';
- document.querySelector('#scripts').className = 'active';
- document.querySelector('#guts').innerHTML = '<div class="scaffold"></div>';
- document.querySelector('#guts').appendChild(getSettings());
- }, false);
- } else {
- //script tab already exists
- document.querySelector('#scripts').firstChild.addEventListener('click', function (e) {
- //some other script is doing the activation work, just add our settings
- e.stopPropagation();
- document.querySelector('#guts').appendChild(getSettings());
- }, false);
- }
- }
-
- function getSettings() {
- //build our settings and return them for appending
- var guts = document.body.appendChild(document.createElement('div'));
- guts.id = 'cookieprefs';
- var subhead = guts.appendChild(document.createElement('div'));
- subhead.className = 'subhead';
- subhead.textContent = 'Fortune Cookie Counter';
- var section = guts.appendChild(document.createElement('div'));
- section.className = 'indent';
- //call function in main script to actually make the settings
- section.appendChild(buildSettings());
- return guts;
- }
-
- function buildSettings() {
- var prefLink = document.createElement('a');
- var hideIfZeros = GM_getValue("hideIfZeros", false);
-
- prefLink.setAttribute('href','javascript:void(0)');
- prefLink.setAttribute('id','cookiecountertoggle');
- prefLink.innerHTML = (hideIfZeros ? "Hiding" : "Showing") + " Inactive Counter - Click to Change";
- prefLink.addEventListener("click", toggleHideCountdown, true);
-
- var prefAnchor = document.createElement('a');
- prefAnchor.setAttribute('name','opt'); prefAnchor.innerHTML = " ";
- var pDiddy = document.createElement('p');
- with(pDiddy)
- { appendChild(prefAnchor);
- appendChild(prefLink);
- }
-
- prefLink = document.createElement('a');
- var noPopups = GM_getValue("noPopups", false);
-
- prefLink.setAttribute('href','javascript:void(0)');
- prefLink.setAttribute('id','cookiepopups');
- prefLink.innerHTML = (noPopups ? "Popups Disabled " : "Using Popups") + " (disable for FF4) - Click to Change";
- prefLink.addEventListener("click", togglePopups, true);
-
- prefAnchor = document.createElement('p');
- prefAnchor.setAttribute('name','opt'); prefAnchor.innerHTML = " ";
-
- with(pDiddy)
- { appendChild(prefAnchor);
- appendChild(prefLink);
- }
-
- // add a link to update, if an update is available
- // (temporarily?) removed for use with Greasy Fork
- /* var webVer = GM_getValue("webVersion");
- if (webVer != "Error" && webVer > currentVersion) { // this is actually a text string comparison, not numerical
- var newElement = document.createElement('p');
- newElement.style.fontSize = "x-small";
- newElement.appendChild(document.createTextNode("New cookie script version " + webVer + " available: "));
-
- var hrefElement = document.createElement('a');
- hrefElement.setAttribute('href', scriptSite);
- hrefElement.setAttribute('target', "_blank");
- hrefElement.appendChild(document.createTextNode("here"));
- newElement.appendChild(hrefElement);
-
- pDiddy.appendChild(newElement);
- }
- */
- return pDiddy;
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- // main prog, just call the proper routine if we are on a pane we care about
- var nodeBody = document.getElementsByTagName("body").item(0);
- var textBody = "";
- var baseURL = "";
- var charSheet = "charsheet.php";
- var playerName = GM_getValue( "currentPlayer");
-
- if (nodeBody) {
- if (nodeBody.textContent) {
- textBody = nodeBody.textContent;
- }
- else if (nodeBody.text) {
- textBody = nodeBody.text;
- }
- baseURL = nodeBody.baseURI.substring(0,nodeBody.baseURI.lastIndexOf('/')+1);
- }
-
- // do normal page processing independently of whether started sanity check
- if ( document.location.pathname.indexOf("charpane.php") != -1 ) {
- //////NEW STUFF (Firvagor) - since the charpane refreshes every time something is used, if the results section is found, run main function using manually located mainpane (can only use indexing for some reason)/////
- if (top.frames[2].document.getElementById("effdiv")!=null) // was frames[1] until aug 2014 topmenu update
- processMain(top.frames[2].document);
- updateCharacterPane();
- }
- else if ( document.location.pathname.indexOf("inventory.php") != -1
- || document.location.pathname.indexOf("clan_viplounge.php")!= -1){
- //alert("calling processMain() for " + document.location.pathname);
- //////NEW STUFF (Firvagor) - passes in current document instead of nothing, just to define the frame used/////
- GM_setValue(playerName+"_fighting",0);
- processMain(document);
- }
- else if ( document.location.pathname.indexOf("charsheet.php") != -1){
- // alert("calling sanityCheckCharsheet() for " + document.location.pathname);
- GM_setValue(playerName+"_fighting",0);
- sanityCheckCharsheet(document.body.innerHTML);
- }
- else if ( document.location.pathname.indexOf("account.php") != -1 ) {
- // alert("calling set prefs for " + document.location.pathname);
- GM_setValue(playerName+"_fighting",0);
- buildPrefs();
- // setPrefs();
- }
- else if ( document.location.pathname.indexOf("adventure.php") != -1
- || document.location.pathname.indexOf("choice.php") != -1) {
- // adventure.php should trap all "normal" noncombats
- // choice noncombats are in choice.php - now needed for hobopolis
- // for the fortune cookie combat rares, need to process fight.php
- GM_setValue(playerName+"_fighting",0);
- checkForNoncombatSemi(document.body.innerHTML);
- }
- else if ( document.location.pathname.indexOf("fight.php") != -1 ) {
- // see if we are actively fighting (no asynch calls allowed while fighting!)
- var fighting = GM_getValue(playerName+"_fighting",0)
- // alert("prefight check - page = " + document.location.pathname + ", fighting = " + fighting);
- {
- if( fighting == 0) {
- // just started a fight, see if it's a combat semi (orc chasm, kitchens, treasury)
- checkForCombatSemi(document.body.innerHTML);
- }
- // alert("incrementing fighting from " + fighting);
- fighting = fighting + 1; // also count rounds, prevents doing things twice in same fight
- // fighting, but maybe we're done, look for adventure again tag
- // I forget why we look at paragraphs here!
- // var paragraphs = document.getElementsByTagName( "p" );
- // for ( var i = 0; i < paragraphs.length; ++i ) {
- // if ( paragraphs[i].innerHTML.indexOf( "Adventure Again (" ) != -1
- // || paragraphs[i].innerHTML.indexOf("Go back to Your Inventory") != -1) {
- if ( document.body.innerHTML.indexOf( "Adventure Again (" ) != -1
- || document.body.innerHTML.indexOf("Go back to Your Inventory") != -1) {
- fighting = 0;
- // break;
- }
- // }
- }
- GM_setValue(playerName+"_fighting",fighting);
- // alert("post fight - fighting = " + fighting);
-
- }
- else {
- // alert("ignoring " + document.location.pathname);
- }
-
- // do sanity check (load charsheet asynchronously) if requested - not while fighting
- if(GM_getValue(playerName+"_needSanityCheck",false) == true
- && GM_getValue(playerName+"_allowSanityCheck",false) == true ) {
- // alert("need sanity check flag detected!");
- // no sanity check allowed if fighting
- if( GM_getValue(playerName+"_fighting",0) == 0) {
- // alert("calling sanity check");
- GM_setValue(playerName+"_needSanityCheck", false);
- // alert("calling sanity check");
- GM_get(baseURL + charSheet, sanityCheckCharsheet);
- }
- }