By ViXaY Xavier
Has no other scripts.
// ==UserScript==
// @name Facebook Slayers/Werewolves/Vampires/Zombies Enhancer
// @namespace http://userscripts.org/users/42874
// @description Creates a menu to use those applications in facebook and has auto-feed function
// @include http://apps.facebook.com/slayers/*
// @include http://apps.facebook.com/werewolves/*
// @include http://apps.facebook.com/vampires/*
// @include http://apps.facebook.com/zombies/*
// @author ViXaY XaVieR
// ==/UserScript==
/*
The followings notes are in WIKIPAD style for easier export to userscripts meta data page
+++ PURPOSE
* auto feed characters - to gain money & attacks
* auto lazy fight people (for lazy people, NOT optimized attacks)
* use up all monsters attacks daily to get stronger
* do this all easily and conveniently, without manual effort (i.e. a bot)
+++ FEATURES:
* Creates a Menu on the right hand side listing all usual functions. _Benefit:_ Saves you valuable time in going about your daily tasks, especially across the different monster types.
* Creates a statistics pane on bottom left containing stats for all your monster types! convenient one glance stats!
* Auto-Feed friends for all your monsters to get money automatically.
* Currently 8 feeds allowed/day * 30 bucks/feed = *240/day/monster* * 4 monster types = *960* bucks/day total!!,
* this too in time (5 secs + 3 guesstimated secs reload time) * 3 clicks per feed * 8 feeds/day * 4 monsters = 768 secs = *12.8* mins!
* Thus gives you increased # of attacks each day! Each feed increases your number of attacks by 1 for a total of 8 bonus attacks!
* You can leave the page open in a tab all the time and it will auotmatically do it everyday without your intervention!
* Auto-Fight monsters less than 50% stronger than you.
++++ HOW AUTO-FEED WORKS:
1. There is a checkbox called autofeed in the menu that this script adds. It is disabled by default and will only activate on the correct pages.
2. On feeding pages: specifically, feed-home.php, feeding-main.php, feeding-result.php, Check that box, it will trigger a routine and start a countdown of 5 seconds ( you should see a timer value next to the checkbox. If you don't then there was some error and the routine did not fire.)
3. Once the timer reaches zero it will take the appropriate action depending on the page you are on. (see code comments for the details on that).
4. It will keep doing this until you can't feed anymore people for that particular monster.
5. Then it will try to switch your monster to the next monster type and try feeding again, until all your monsters have used up their feed quota. (you can disable this by commenting out all SwitchMonster() commands in code, I should probably use some prompting to set initial variables).
6. This helps you gain money quickly, and makes your monster stronger before fights.
7. After feeding all monsters it will wait for the time to expire before it does it's magic again!
- When encountering empty feed lists (i.e. # of friends in list < allowed feeds), it will switch_monster and mark it as Full
when all monsters are full, and you encounter an empty list, it will wait for 12 hours, before clearing all flags and checking again.
- To manually select which users to autofeed:
1) Enable the checkboxes by clicking on th menu item "togglecheckboxes"
2) Then reload the feed page, and checkboxes should now appear after each name
3) check the users that you want to autofeed and reload the page
4) now enable autofeed! Thats it!
If you have selected <8 friends, it will continue to feed on users that have not been checked as well
++++ HOW AUTO-FIGHT WORKS:
1. There is a checkbox called autofight in the menu that this script adds. It is disabled by default and will only activate on the correct pages.
2. On fighting pages: specifically, fighting-main.php, fighting-confirm.php, fighting-result.php, Check that box, it will trigger a routine and start a countdown of 5 seconds ( you should see a timer value next to the checkbox. If you don't then there was some error and the routine did not fire.)
3. Once the timer reaches zero it will take the appropriate action depending on the page you are on. (see code comments for the details on that).
4. It will keep doing this until you can't fight anymore people for that particular monster.
5. Then it will try to switch your monster to the next monster type and try fighting again, until all your monsters have used up their fight quota. (you can disable this by commenting out all SwitchMonster() commands in code, I should probably use some prompting to set initial variables).
6. This helps you gain money quickly, and points quickly.
7. After fighting all monsters it will wait for the time to expire before it does it's magic again!
Current Logic for attacking:
Go from top to bottom, choose an opponent who is less than 50% stronger than you.
Use all 3 attacks per round, and attack that one person repeatedly until all attacks are done.
Once done switch to another monster type.
++++ STATISTICS PANE
* Gets updated as you move around the different pages
* Is not guaranteed to give 100% reliable information
* Is there just for quick reference
* Feeds are not given but have to be guessed and hence are always guesses! (not 100% accurate)
* You have to visit the store or your main profile page to get the total amount of money you have in your account
* Gather Data link does all this for you, but is time consuming so use it only when starting out in the beginning
++ TIPS
- AutoFeed first before attacking (you get more attacks that way!) OR
- Have AutoFeed running in one tab, and AutoFight in another
- Select a timer of about 5-10 seconds so that you can choose items during combat if you wish to, or change to another monster type
++++ SETTINGS
* There are some additional commands available via the userscript menu.
* Right click the greasemonkey icon, and go to "User Script Commands" and you can see them there.
* Manual Update Check
- This checks the website userscripts.org to check to see if the script has been updated, and alerts you accordingly
* Reset Monster Full Flags
- this is only necessary if you see that the monsters don't switch automatically
* Change Timer
- Disable Autofight/autofeed before using this.
- Be VERY CAREFUL with this! Setting it too low might cause you to be unable to turn off autofeed/fight!
- use it to change the countdown timer before an action is executed.
* Toggle checkboxes (feed/fight)
- This is to enable manually selecting candidates that you want to autofeed each day. Please see the AutoFeed section for more information.
* Toggle Full Auto
- This is to enable autofeed followed by autofight and then waiting on autofeed page again.
- You can see if this is enabled by seeing the bottom of the menu on the right, it'll show "[FULL AUTO]" when enabled
+++ NOTES:
Tested with Firefox 2.0.0.11+ & Greasemonkey 0.7.20070607.0+
http://userscripts.org/scripts/show/20462
To help debug problems please check the Tools->Error Console and post messages from the error & messages tabs to the comments section.
http://userscripts.org/scripts/show/20462
this is the magic boon i bestow upon you to grow powerful quicker than your peers. After many years of meditation was i able to craft such a delicate spell to aid you in battle, use it wisely!
+++ CREDITS
Facebook DotA Enhancer by Vaughan Chandler (http://userscripts.org/people/14536) (for initial help & inspiration)
Script Update Checker by Jarett (http://userscripts.org/users/38602) (for script updates)
+++ CHANGELOG
* v0.00 - 15/01/2008 12:57
- started work
* v1.00 - 17/01/2008 14:00
- Auto-Feed is now working
* v1.10 - 13/02/2008 18:44:18
- Fixed errors in variable names - Damn javascript! that's what you get with no enforced delclarations!
- Changed CSS for Menu
- added another section to the menu for easier identification
- Added detection of Empty List in feeding & switching monsters
* v1.20 - 9:23 PM 2/15/2008
- significantly changed the auto-feed code
- changed the location of the auto buttons (now integrated into the menu)
- changed the location of the countdown timer (in the main heading (above subheading))
- added basic auto-fight code for testing purposes (NOT USABLE YET)
- added some more error handling
* v1.30 - 12:32 PM 2/20/2008
- Added auto-update for this script to get latest version (once per day)
- Added function to reset FULL flags for each monster each day (once per day)
- Added extraction of attacker data from page. works fine now, for fighting-main.php
* v1.40 - 5:42 PM Saturday, March 08, 2008
- Moved the timer countdown to the menu (to avoid dealing with the hassle of finding the right place to display the timer)
- Added User Script Command to Clear the flags such that when all monster flags are set you can forcefully reset them.
- Empty friend list works. Currently it switches between available monsters, and if all are full, it waits for 12 hours before trying again.
* v1.50 - 11:54 AM 3/10/2008
- Pages have changed again, so changed some code to fix it for auto-feed.
- Added a setting for the timer so that the user can change it according to their needs. Use the userscript menu
* v1.60 - 4:34 PM 3/10/2008
- Added basic fighting capability
- disabled checkboxes by default and enabled them only on the correct pages
* v1.70 - Tuesday, March 11, 2008 12:04:24
- Modified the menu code generation to use arrays instead of '+' for increased performance
- Made AutoListenClick Generic (i.e. handle both cases)
- using auto_mode everywhere now to detect which code/variables to executed
- *bugfix* in delay timer caculation, it was adding it as strings rather than integers
- Fight link in menu now by default takes you to a different monster type (rather than the same type)
- created function findsubmitbutton to remove redundant code
- *bugfix* fixed the infinite switchmonster bug, it was happening because i didn't clear the interval before trying to switch!
- *bugfix* SWITCH_MONSTER now works even if all monsters are full from yesterday (according to the flags).
now SWITCH_MONSTER clears flags once a day if all monsters are found to be full, it then calls itself
to switch to another monster
if it has already cleared flags today, then it doesnt switch if it encounters full flags.
- solved a url switching problem in a moment of epiphany! it feels great when you have those.
thats the only reason i do this i guess :). The problem was that i was trying to encode the Logic
in the actionTimer routine when i should encode the logic in the page specific area and setup the global
variable to point to the correct place!
- *bugfix* switches to fightin-main.php with another monster type
- merged checkErrorFeeding & Fighing into one CheckError!
* v1.80 - Tuesday, March 11, 2008 15:19:33
- Done Optimizing code! Lots of redundancy between the two auto modes removed, created generic functions able to handle both situations.
- Fixed a bug in switchMonster not switching to correct fight type monster.
- changed clearing flags to every half day (12 hours) rather than full day
* v2.00 - Tuesday, March 11, 2008 16:01:53
- New Version complete, removed dead code ...etc.
- both features working well
- you have to use the RESET flags sometimes to clear out old data. but it works :)
* v2.01 - Tuesday, March 11, 2008 16:32:59
- fixed parsing of Attacker points
* v2.10 - Tuesday, March 11, 2008 19:31:12
- added statistics pane with rudimentary support for values, they are not guaranteed to be accurate, but close enough.
* v2.20 - Wednesday, March 12, 2008 16:40:53
- tighter integration with the statistics pane
- added RefreshData routine that visits a bunch of pages in sequence to get data
- *bugfix* fixed bug in autofeed that was accidently introduced in the last version
- change location of ClearFlags routine so that it runs before any checking (so statistics pane can be more accurate).
* v2.31 - Thursday, March 13, 2008 14:42:46
- added checkboxes on the feeding page as the people that we have to feed first then get available candidates. Looks ugly for now, but can't insert it in prettier way
- added a user menu item to toggle the above checkboxes feature on/off (default is off)
* v2.40 - Friday, March 14, 2008 18:16:50
- added some tooltips to statistics pane to show when feed/fight was last cleared (hover over the heading)
- added flags in table to let me know when the full flag is set '(F)'
- added parsing for points on side-nav page and only when we are visiting our page!
- added info on when you can next fight and all. according to the blog... feeds are on a 22 hour cycle!
- replaced togglecheckboxes with togglevar a more generic functions
- started work on basic full-auto mode
* v2.50 - Monday, March 17, 2008 14:41:02
- added bucks integration on feed-results page
- some more work on full-auto being done
- cleaned some code
- add checkboxes to fight pages? But how to deal with the different monster types?
- used JSLint and cleaned up some more code
* v2.60 - Wednesday, March 26, 2008 10:25:49
- Fixed auto-feed after some changes by Facebook people. Sigh... are they doing it on purpose to annoy me? seems like it. Why don't they talk to me directly about it?
- Changed auto-fight to fight monsters 100% stronger or less
- full auto works for now ONLY if feed is done before fighting...
+++ KNOWN BUGS
+++ ROADMAP
- one click auto-feed & auto-fight
- auto choose strongest monster among available ones
- switch between different monsters while autofighting
-
+++ TO DO
Attacking:
Attack 1 monster type or many? start on which type? next in sequence (seems reasonable)?
Or change attack based on victory/losses and points? is there a peak ratio somehwere?
ratio to maximize is Points gained/attack, need data to determine what is optimal.
what about arsenal items? how to deal with that?
- Find Strongest opponent (within 50%) across all monster types (to get maximum points for attacking)
OPTIMIZATION
- Better code for choosing the correct branch based on the page we are on. use SELECT? SWICTH? CASE? Something like that
- auto_mode = FULL (fully automatic)
- involves feeding all monsters first
- When full switch to fighting
- then fighting with all monsters
- need find strongest opponent routine
- when all are done switch to feed of first monster in bunch (for timer)
- wait for timer to expire and repeat!
*/
/*jsl:option explicit*/
// Auto Update Script
var version_scriptNum = 20462; // Change this to the number given to the script by userscripts.org (check the address bar)
// Last Updated: Wednesday, March 26, 2008 10:26:58
//Use the " new Date().getTime() " function to get a value for this.
var version_timestamp = 1206502031970; // Used to differentiate one version of the script from an older one.
function updateCheck(forced) {if((forced)||(parseInt(GM_getValue("lastUpdate", "0"),10) + 86400000 <= (new Date().getTime()))) {try {GM_xmlhttpRequest({method: "GET",url: "http://userscripts.org/scripts/review/" + version_scriptNum + "?" + new Date().getTime(),headers: {'Cache-Control': 'no-cache'},onload: function(xhrResponse) {GM_setValue("lastUpdate", new Date().getTime() + ""); var rt = xhrResponse.responseText.replace(/ ?/gm, " ").replace(/<li>/gm, "\n").replace(/<[^>]*>/gm, ""); var scriptName = (/@name\s*(.*?)\s*$/m.exec(rt))[1]; GM_setValue("targetScriptName", scriptName); if (parseInt(/version_timestamp\s*=\s*([0-9]+)/.exec(rt)[1],10) > version_timestamp) {if (confirm("There is an update available for the Greasemonkey script \"" + scriptName + ".\"\nWould you like to go to the install page now?")) {GM_openInTab("http://userscripts.org/scripts/show/" + version_scriptNum);}} else if (forced) {alert("No update is available for \"" + scriptName + ".\"");}}});} catch (err) {if (forced) {alert("An error occurred while checking for updates:\n" + err);}}}}
// UserScript Menu Commands
GM_registerMenuCommand(GM_getValue("targetScriptName", "???") + " - Manual Update Check", function() {updateCheck(true);});
GM_registerMenuCommand(GM_getValue("targetScriptName", "???") + " - Reset Monster Full Flags", function() {ClearFlags(auto_mode);});
GM_registerMenuCommand(GM_getValue("targetScriptName", "???") + " - Change Timer", function() {ChangeTimer();});
GM_registerMenuCommand(GM_getValue("targetScriptName", "???") + " - Toggle Feed Checkboxes", function() {toggleVar('toggleCheck');});
GM_registerMenuCommand(GM_getValue("targetScriptName", "???") + " - Toggle Fight Checkboxes", function() {toggleVar('toggleFight');});
GM_registerMenuCommand(GM_getValue("targetScriptName", "???") + " - Toggle Full Auto", function() {toggleVar('fullauto');});
// check once initially when script is loaded
updateCheck(false);
// ================ Initialize Variables==================
// if loc = http://apps.facebook.com/werewolves/side-nav.php?ref=top_nav
var loc = location.href;
// then base_url = http://apps.facebook.com/werewolves/
var base_url = loc.substr(0,loc.indexOf('/',25)+1); //Get url on which we will add our parameters
// then apps_url = http://apps.facebook.com/
var apps_url = base_url.substr(0,base_url.indexOf('/',8)+1); //Get app url
// then extra_url = side-nav.php?ref=top_nav
var extra_url = loc.substr(base_url.length);
// then page = 0 (no page)
var page = loc.indexOf('page=')!=-1 ? loc.match(/page=(\d)/)[1]-0 : 0;
var browser_title = '';
var my_monsters = ["slayers", "werewolves", "vampires", "zombies"]; // monster path in url
var monster_type = ["slayer", "werewolf", "vampire", "zombie"]; // monster type name
var current_type = loc.split('/')[3]; //Fetch which applications/monster we are in
var type_ind = my_monsters.indexOf(current_type); //Get the array index value for it
var auto_timer = GM_getValue("Timer",5); // default countdown value for timer
var gotourl;
var divs;
// we can actually do with only one of this variable!
var ginterval; // to store the periodic timer function
var gcountdown; // how long that function waits
var gbuttonsubmit; // button to click on specific pages
// create and initialize hash functions to make it easy to access variables & functions using auto_mode
// call the correct function using auto_mode
//var checkfn = new Array();
//checkfn['feed'] = checkFeeding;
//checkfn['fight'] = checkFighting;
var activePages = new Array(); // 0 = main page, 1 = confirm page, 2 = results page, 3 = over quota page
activePages['feed'] = ['feed-home.php','feed-main.php','feed-result.php', 'feed-home.php'];
activePages['fight'] = ['fighting-main.php','fighting-confirm.php','fighting-result.php', 'bite.php?max_attacks=1'];
// code to use for common pages
//if (loc.indexOf(activePages[auto_mode][0]) != -1) {
var MONTH_NAMES=new Array('January','February','March','April','May','June','July','August','September','October','November','December','Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
var DAY_NAMES=new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sun','Mon','Tue','Wed','Thu','Fri','Sat');
function LZ(x) {return(x<0||x>9?"":"0")+x;}
var auto_mode; // stores what suffix to use when saving GM persistent variables
// setup suffix variable for all GM persistent variable parameters.
if (loc.indexOf('feed') != -1) {
//auto_mode = '';
auto_mode = 'feed';
} else if (loc.indexOf('fight') != -1 || loc.indexOf('bite.php?max_attacks=1') != -1) {
auto_mode = 'fight';
} else {
auto_mode = '';
}
GM_log("mode: " + auto_mode); //DEBUG //put in menu?
// Generate variable references based on auto_mode
var cCheckBoxID = 'auto' + auto_mode;
var cTimer = auto_mode + 'timer';
// should we go fullauto?
var fullauto = GM_getValue('fullauto',false);
// store default values to reset to. global to declare it only once
var sReset = new Array();
sReset['fight'] = '?';
sReset['feed'] = 8;
// used to save & populate statistics table
var statVars = ['points', 'bucks', 'fight', 'feed'];
// ================ Setup browser_title ==================
//function insertMenu() {
if (browser_title != '') {
document.title = browser_title + current_type + " enhanced by VX";
}
else {
document.title = document.title + " enhanced by VX";
}
// ================ Setup Menu ==================
{
var menuCode = []; // temporary array to store strings for concatenation
//type_ind <= 0 ? 3 : type_ind - 1; //code to auto select a monster type
// create the code for the menu
menuCode.push('<div class="monsterHeading">-' + current_type.toUpperCase() + '-</div>');
menuCode.push('<div class="monsterSection">-Battles-</div>');
menuCode.push(CreateLink("fighting-main","monster_type=" + monster_type[type_ind <= 0 ? 3 : type_ind - 1],"Fight/Auto-Fight!")+ '<br />' );
menuCode.push('<input type="checkbox" id="autofight" DISABLED/>Auto-fight' + '<span id="fighttimer"></span><br />');
menuCode.push(CreateLink("fighting-main","monster_type=" + monster_type[0],"Fight " + my_monsters[0])+ '<br />');
menuCode.push(CreateLink("fighting-main","monster_type=" + monster_type[1],"Fight " + my_monsters[1])+ '<br />');
menuCode.push(CreateLink("fighting-main","monster_type=" + monster_type[2],"Fight " + my_monsters[2])+ '<br />');
menuCode.push(CreateLink("fighting-main","monster_type=" + monster_type[3],"Fight " + my_monsters[3])+ '<br />');
menuCode.push('<div class="monsterSection">-Get Money-</div>');
menuCode.push(CreateLink("feed-home","","Feed/Auto-Feed!")+ '<br />');
menuCode.push('<input type="checkbox" id="autofeed" DISABLED/>Auto-feed' + '<span id="feedtimer"></span><br />');
menuCode.push(CreateLink("Bite")+ '<br />');
menuCode.push('<div class="monsterSection">-Stats-</div>');
menuCode.push(CreateLink("side-nav","ref=top_menu","My " + monster_type[type_ind])+ '<br />');
menuCode.push(CreateLink("fighting-history","","My Fight History") + '<br />');
menuCode.push(CreateLink("event-history","","My Feed History") + '<br />');
menuCode.push(CreateLink("friend-rank","ref=top_menu","My Friend Rank")+ '<br />');
menuCode.push(CreateLink("global-rank","ref=top_menu","My Global Rank")+ '<br />');
menuCode.push('<div class="monsterSection">-My Monsters-</div>');
menuCode.push(CreateLink("side-nav","ref=top_nav","My " + monster_type[0], apps_url + my_monsters[0] + '/')+ '<br />');
menuCode.push(CreateLink("side-nav","ref=top_nav","My " + monster_type[1], apps_url + my_monsters[1] + '/')+ '<br />');
menuCode.push(CreateLink("side-nav","ref=top_nav","My " + monster_type[2], apps_url + my_monsters[2] + '/')+ '<br />');
menuCode.push(CreateLink("side-nav","ref=top_nav","My " + monster_type[3], apps_url + my_monsters[3] + '/')+ '<br />');
menuCode.push('<div class="monsterSection">-Items-</div>');
menuCode.push(CreateLink("store-main","ref=top_menu","Store")+ '<br />');
menuCode.push('<div class="monsterSection">-Social-</div>');
menuCode.push(CreateLink("Blog")+ '<br />');
menuCode.push(CreateLink("Forum")+ '<br />');
menuCode.push('<div class="monsterSection">-Misc-</div>');
menuCode.push(CreateLink("refresh-profile","","Refresh Profile")+ '<br />');
menuCode.push(CreateLink("Help")+ '<br />');
menuCode.push('Same Page in: <br />');
menuCode.push(CreateLink("",""," " + monster_type[0], apps_url + my_monsters[0] + '/' + extra_url)+ '<br />');
menuCode.push(CreateLink("",""," " + monster_type[1], apps_url + my_monsters[1] + '/' + extra_url)+ '<br />');
menuCode.push(CreateLink("",""," " + monster_type[2], apps_url + my_monsters[2] + '/' + extra_url)+ '<br />');
menuCode.push(CreateLink("",""," " + monster_type[3], apps_url + my_monsters[3] + '/' + extra_url)+ '<br />');
menuCode.push((fullauto?' - [FULL AUTO] - ':''));
var menu = document.createElement('div');
menu.id = 'FBMonstersMenu';
menu.innerHTML = menuCode.join(''); // concatenate the string efficiently (faster than +)
// see http://aymanh.com/9-javascript-tips-you-may-not-know for more information
menuCode.length = 0; //Reset/Empty the array
menuCode.push("#FBMonstersMenu { position:fixed; top:2px; right:2px; border:2px solid #6D84B4; background:#EEEEEE; color:#3B5998; padding:2px; font-weight:bold; }");
menuCode.push("#FBMonstersMenu div.monsterSection { text-align:center; padding-top:2px; }");
menuCode.push("#FBMonstersMenu div.monsterHeading { text-align:center; background: #6D84B4; color: #FFFFFF; }");
menuCode.push("#FBMonstersMenu a { color: #BB0011; text-decoration:none; }");
menuCode.push("#FBMonstersMenu a:hover { color:#B22222; text-decoration:underline; }");
var style = document.createElement('style');
style.type = "text/css";
style.innerHTML = menuCode.join('');
menuCode.length = 0; //Reset/Empty the array
// Insert the menu code and style into the document
try {
document.getElementsByTagName('head')[0].appendChild(style);
} catch(e) {}
document.body.insertBefore(menu, document.body.lastChild);
}
// STATISTICS DISPLAY
{ //Begin scope for easier folding of code
menuCode.push('<div class="monsterHeading">-STATISTICS-</div>');
menuCode.push('<table>');
//insert the last time we cleared the flags as tooltips for the headers
var lastfight = parseInt(GM_getValue("LastClearedfight", "0"),10);
var lastfeed = parseInt(GM_getValue("LastClearedfeed", "0"),10);
var Dateformat = "MMM d, y HH:mm";
menuCode.push('<tr><th><b>M</b></th><th><b>Points</b></th><th><b>Bucks</b></th><th><b title="'+
formatDate(lastfight,Dateformat) +
'">Fights</b></th><th><b title="'+
formatDate(lastfeed,Dateformat) +
'">Feeds</b></th></tr>');
for (var i = 0; i < monster_type.length; i++) {
//menuCode.push(monster_type[i] + '(' + monster_type[i].charAt(0).toUpperCase() +')<br />');
menuCode.push('<tr><td>');
//1st cell - monster_type
menuCode.push(monster_type[i].charAt(0).toUpperCase() +'</td>');
for (var j = 0; j < statVars.length; j++) {
// variable cells with appropriate ids to fetch them easily
menuCode.push('<td id='+monster_type[i]+ statVars[j] +'> </td>');
}
// //2nd cell - Points
// menuCode.push('<td id='+monster_type[i]+'points> </td>');
// //3rd cell - $$
// menuCode.push('<td id='+monster_type[i]+'bucks> </td>');
// //4th cell - Fights
// menuCode.push('<td id='+monster_type[i]+'fight> </td>');
// //5th cell - Feeds
// menuCode.push('<td id='+monster_type[i]+'feed> </td>');
menuCode.push('</td></tr>');
}
//menuCode.push('<tr><td>');
// menuCode.push('</td></tr>');
// Add the next time we can feed - 22 hours since last cleared
var nextfight = lastfight + 79200000;
// Add the next time we can fight - 22 hours since last cleared
var nextfeed = lastfeed + 79200000;
menuCode.push('<tr> <td colspan=0 title="'+formatDate(nextfight,Dateformat) +'">Next fight in ' + ((nextfight - new Date().getTime())/(1000*3600)).toFixed(2) + ' hours. </td></tr>');
menuCode.push('<tr> <td colspan=0 title="'+formatDate(nextfeed,Dateformat) +'">Next feed in ' + ((nextfeed - new Date().getTime())/(1000*3600)).toFixed(2) + ' hours. </td></tr>');
menuCode.push('</table>');
menuCode.push('<a id="refreshStats" href="#">Gather Data</a>');
menu = document.createElement('div');
menu.id = 'FBStats';
menu.innerHTML = menuCode.join(''); // concatenate the string efficiently (faster than +)
// see http://aymanh.com/9-javascript-tips-you-may-not-know for more information
menuCode.length = 0; //Reset/Empty the array
menuCode.push("#FBStats { position:fixed; bottom:2px; left:2px; border:2px solid #6D84B4; background:#EEEEEE; color:#3B5998; padding:2px; font-weight:bold; }");
menuCode.push("#FBStats div.monsterSection { text-align:center; padding-top:2px; }");
menuCode.push("#FBStats div.monsterHeading { text-align:center; background: #6D84B4; color: #FFFFFF; }");
menuCode.push("#FBStats a { color: #BB0011; text-decoration:none; }");
menuCode.push("#FBStats a:hover { color:#B22222; text-decoration:underline; }");
menuCode.push("#FBStats table { border-spacing: 0px; }");
menuCode.push("#FBStats table th { border-width: 1px 1px 1px 1px; padding: 2px 2px 2px 2px; border-style: solid solid solid solid; }");
menuCode.push("#FBStats table td { border-width: 1px 1px 1px 1px; padding: 2px 2px 2px 2px; border-style: solid solid solid solid; }");
style = document.createElement('style');
style.type = "text/css";
style.innerHTML = menuCode.join('');
menuCode.length = 0; //Reset/Empty the array
// Insert the menu code and style into the document
try {
document.getElementsByTagName('head')[0].appendChild(style);
} catch(e) {}
document.body.insertBefore(menu, document.body.lastChild);
// add an even listener to execute the correct function for refreshing the statistics
var t_elm = document.getElementById('refreshStats');
t_elm.addEventListener("click",refreshStats,true);
//populateStats();
//*/
//recheck the checkboxes from persistent variables
if (GM_getValue('autofight', false)) document.getElementById('autofight').checked='checked';
if (GM_getValue('autofeed', false)) document.getElementById('autofeed').checked='checked';
}
//}
// ================ Utility functions ==================
function CreateLink(sPage, sParams, sTitle, sURL) {
sTitle = sTitle || sPage; // default title = Page name unless it's provided
sURL = sURL || base_url; // default to current app url
var sExt = '.php';
if (sPage == undefined || sPage == "") sExt = '';
if (sParams == undefined || sParams == "") {
return '<a href="' + sURL + sPage.toLowerCase() + sExt + '">' + sTitle + '</a>';
} else {
sParams = '?' + sParams;
return '<a href="' + sURL + sPage.toLowerCase() + sExt + sParams + '">' + sTitle + '</a>';
}
}
// Returns null if expr didn't match anything
function getFirstXPathResult(expr, node)
{
if (!node) node = document;
var res = document.evaluate(expr, node, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
return res.singleNodeValue;
}
//http://www.robertnyman.com/2005/11/07/the-ultimate-getelementsbyclassname/
function getElementsByClassName(className, tag, elm){
var testClass = new RegExp("(^|\\\\s)" + className + "(\\\\s|$)");
tag = tag || "*";
elm = elm || document;
var elements = (tag == "*" && elm.all)? elm.all : elm.getElementsByTagName(tag);
var returnElements = [];
var current;
var length = elements.length;
for(var i=0; i<length; i++){
current = elements[i];
if(testClass.test(current.className)){
returnElements.push(current);
}
}
return returnElements;
}
//http://www.webmasterworld.com/javascript/3214735.htm
// use for the new scheme they have in facebook divs naming
function getelementsbyIDPattern(inPattern,inRoot){
var elem_array = new Array;
if(typeof inRoot.firstChild!= 'undefined'){
var elem = inRoot.firstChild;
while (elem!= null){
if(typeof elem.firstChild!= 'undefined'){
elem_array = elem_array.concat(getelementsbyIDPattern(inPattern,elem));
}
if(typeof elem.id!= 'undefined'){
var reg = new RegExp('^'+inPattern+'$');
if(elem.id.match(reg)){
elem_array.push(elem);
}
}
elem = elem.nextSibling;
}
}
return elem_array;
}
//ASSERTION FUNCTIONS
//http://aymanh.com/9-javascript-tips-you-may-not-know
function AssertException(message) { this.message = message; }
AssertException.prototype.toString = function () {
return 'AssertException: ' + this.message;
};
function assert(exp, message) {
if (!exp) {
throw new AssertException(message);
}
}
//http://www.mattkruse.com/javascript/date/source.html
// ------------------------------------------------------------------
// formatDate (date_object, format)
// Returns a date in the output format specified.
// The format string uses the same abbreviations as in getDateFromFormat()
// ------------------------------------------------------------------
function formatDate(date,format) {
format=format+"";
date = new Date(date);
var result="";
var i_format=0;
var c="";
var token="";
var y=date.getYear()+"";
var M=date.getMonth()+1;
var d=date.getDate();
var E=date.getDay();
var H=date.getHours();
var m=date.getMinutes();
var s=date.getSeconds();
var yyyy,yy,MMM,MM,dd,hh,h,mm,ss,ampm,HH,KK,K,kk,k;
// Convert real date parts into formatted versions
var value=new Object();
if (y.length < 4) {y=""+(y-0+1900);}
value["y"]=""+y;
value["yyyy"]=y;
value["yy"]=y.substring(2,4);
value["M"]=M;
value["MM"]=LZ(M);
value["MMM"]=MONTH_NAMES[M-1];
value["NNN"]=MONTH_NAMES[M+11];
value["d"]=d;
value["dd"]=LZ(d);
value["E"]=DAY_NAMES[E+7];
value["EE"]=DAY_NAMES[E];
value["H"]=H;
value["HH"]=LZ(H);
if (H==0){value["h"]=12;}
else if (H>12){value["h"]=H-12;}
else {value["h"]=H;}
value["hh"]=LZ(value["h"]);
if (H>11){value["K"]=H-12;} else {value["K"]=H;}
value["k"]=H+1;
value["KK"]=LZ(value["K"]);
value["kk"]=LZ(value["k"]);
if (H > 11) { value["a"]="PM"; }
else { value["a"]="AM"; }
value["m"]=m;
value["mm"]=LZ(m);
value["s"]=s;
value["ss"]=LZ(s);
while (i_format < format.length) {
c=format.charAt(i_format);
token="";
while ((format.charAt(i_format)==c) && (i_format < format.length)) {
token += format.charAt(i_format++);
}
if (value[token] != null) { result=result + value[token]; }
else { result=result + token; }
}
return result;
}
// Takes a Time in string (3 horus 23 minutes..etc) and converts it to seconds
function GetSecondsFromString(sMsg) {
var re = /\s(\d+)\shour.*\s(\d+)\sminute.*/;
var m_result = re.exec(sMsg); //Execute regex on input string
if (m_result == undefined) return 0;
if (m_result.length <= 1) return 0;
var hours = m_result[1];
var minutes = m_result[2];
var seconds = /\s(\d+)\ssecond.*/;
seconds = seconds.exec(sMsg);//Execute regex on input string
if (seconds == undefined || seconds.length<2) {
seconds = 0;
} else {
seconds = seconds[1];
}
return (parseInt(hours,10)*3600 + parseInt(minutes,10)*60 + parseInt(seconds,10));
}
//test cases for function GetSecondsFromString()
//GetSecondsFromString("You can't feed any more Slayers for another 21 hours and 14 minutes! autofeed has been delayed.");
//GetSecondsFromString("You can't feed any more Slayers for another 21 hours and 14 minutes and 3 seconds! autofeed has been delayed.");
// returns first submit button found on page
function findSubmitButton() {
// find the right button - for interval to auto click
var elms = document.getElementsByTagName('input');
for (i=0; i<elms.length; i++) {
if (elms[i].type == 'submit') {
return elms[i];
break;
}
}
return;
}
// returns a comma seperated number without commas
function getNumber(sText,suffixPattern) {
var matchResults;
suffixPattern = suffixPattern || "\\s.*\\spoints.*";
var tmpRegex = new RegExp("(\\d+(,|\\d)*)" + suffixPattern,"i");
try {
matchResults = sText.match(tmpRegex);
//GM_log("getNumber results:" + matchResults);
matchResults[1] = matchResults[1].replace(/,/g,""); // clean up commas to get correct conversion to integer
return parseInt(matchResults[1],10);
} catch(x) {
return;
}
}
// ================= Utility functions specifically for this script ===============
function scrollpages() {
var statPages = new Array();
statPages = ['fighting-main.php','side-nav.php'];
var i = GM_getValue('i',0);
var j = GM_getValue('j',0);
var nextPage = GM_getValue('nextPage','none');
//if (GM_getValue('nextPage','none') != "none") scrollpages(); //go through the predetermined sequence
GM_log('scrollpages:'+i+j);//DEBUG
if (nextPage == "start") { //0: start sequence/setup sequence
//disable the autofeed and autofight modes
GM_setValue('autofeedDISABLED',GM_getValue('autofeed',false));
GM_setValue('autofightDISABLED',GM_getValue('autofight',false));
GM_setValue('autofeed',false);
GM_setValue('autofight',false);
i = 0;
j = 0;
GM_log('start');//DEBUG
GM_setValue('nextPage', base_url.replace(my_monsters[type_ind], my_monsters[i]) + statPages[j++]);
// save the iterators so we can continue to the next in sequence
GM_setValue('i',i);
GM_setValue('j',j);
scrollpages();//call ourself to continue
return;
} else if (nextPage == "end") { //2: end sequence/disable sequence
// reset nextPage so that we can resume normal operations
GM_setValue('nextPage','none');
//reenable the autofeed & autofight modes
GM_setValue('autofeed',GM_getValue('autofeedDISABLED',false));
GM_setValue('autofight',GM_getValue('autofightDISABLED',false));
GM_setValue('autofeedDISABLED','');
GM_setValue('autofightDISABLED','');
//disable iterators
GM_setValue('i',0);
GM_setValue('j',0);
GM_log('end');//DEBUG
alert("Done collecting fresh statistics, you can now resume your activities.");
return;
} else if (nextPage.indexOf("http") != -1) { //1: go through sequence
var urlNext;
//else if (i < my_monsters.length) {GM_setValue('i',++i);}
if (j >= statPages.length) {GM_setValue('i',++i); j=0;}
// if we have processed all monsters end the scrollpages
if (i >= my_monsters.length) {GM_setValue('nextPage',"end");}
else { GM_setValue('nextPage', base_url.replace(my_monsters[type_ind], my_monsters[i]) + statPages[j++]); }//save the next page we want to visit
// save the iterators so we can continue to the next in sequence
GM_setValue('i',i);
GM_setValue('j',j);
// switch to the page designated in the sequence
GM_log("visiting next page in sequence:" + nextPage);//DEBUG
location.href = nextPage;
return;
}
}
function refreshStats() {
var entry = '';
entry += "WARNING: the script will now visit 8 pages in order to collect up-to-date statistics, please do not interrupt this process.\n";
entry += "If you are sure please enter \"OK\" in the box below.\n";
entry += "Or else click cancel\n";
entry = prompt(entry,'');
if (entry != null) {
//statements to execute with the value
if (entry == "OK") {
GM_setValue('nextPage','start'); //start the whole sequence
scrollpages();
/*/test scrollpages function by the following routine and commenting out the above line
var k = 0;
while (GM_getValue('nextPage','') != "none") { //DEBUG
scrollpages();
//GM_log('k:'+k);
k++;
if (k>20) break; //if in a runaway loop exit!
}//*/
}
}
}
function populateStats() {
var i=0;
var j=0;
// clearflags clears feed & fight count values as well!
for (i = 0; i < monster_type.length; i++) {
for (j = 0; j < statVars.length; j++) {
document.getElementById(monster_type[i]+ statVars[j]).innerHTML = GM_getValue(monster_type[i]+ statVars[j],"?");
// j == 2,3 means in fight & feed, add the state of monster, is it full?
if (j >= 2) {
document.getElementById(monster_type[i]+ statVars[j]).innerHTML += (GM_getValue(my_monsters[i] + statVars[j],'')?' (F)':'') ;
}
}
}
}
// Change the default auto-timer value used for countdowns
function ChangeTimer() {
var entry = prompt('Enter a delay in seconds between 1 and 30:',auto_timer);
if (entry != null) {
//statements to execute with the value
if ((entry >= 1) && (entry <= 30)) {
GM_setValue("Timer",entry);
auto_timer = entry;
}
}
}
// given a full url and leads to fighting-main.php it will return fighting-main with
// an appropriate monster type chosen
function switchFightType(sPage,notIndex) {
var i;
notIndex = notIndex || type_ind;
if (sPage.indexOf(activePages['fight'][0]) != -1) {
// alternatively, return previous monster type
return sPage + "?monster_type=" + monster_type[notIndex <= 0 ? 3 : notIndex - 1]
// can also return next monster type
//i need a way to go through all monster types specifically
//need a way to save & restore the preferred monster page...
for(i = 0; i < monster_type.length; i++) {
if (i != notIndex) {
return sPage + '?monster_type=' + monster_type[i]; //switch location now
}
}
//i = 0; // if i is static type, then i can continue without resetting i until i get here
// but i don't know if static i will be persistent through different pages. i don't think so.
}
else {
return sPage;
}
}
//checkError must be called before SwitchMonster
// as checkError will have to set & clear each monsters Full flag
function SwitchMonster(sPage) {
//check flag for all full
//check current monster to see if it's quota is reached
//check next monster until
// 1 is found that is not full
// or all are full
// if all are full set flag to quit switching
// if 1 is found then switch page and load either feed-home.php or fighting-main.php
GM_log("SwitchMonster");
for(var i = 0; i < my_monsters.length; i++) {
if (GM_getValue(my_monsters[i] + auto_mode,false)) { // if quota reached do nothing, increment counter
/*jsl:pass*/
} else if (i != type_ind) { //quota not reached switch here
//switch to new monster
//base_url.replace(my_monsters[type_ind], my_monsters[i]); // replace base_path with new
// now two options switch to current url OR a specific url
// if sPage is provided switch to specific page else switch to current url
sPage = sPage || extra_url;
var newurl = base_url.replace(my_monsters[type_ind], my_monsters[i]) + sPage;
// change to a different monster type rather than the defaul same one when switching to the main fighting page
if (newurl.indexOf(activePages['fight'][0]) != -1) newurl = switchFightType(newurl,i);
location.href = newurl;
return true;
}
}
// if we reach till hear that means all monsters are full and we haven't switched page
// it's ok, i guess we can leave it at this and do nothing if that's the case or return something
GM_log("All monsters full");
// actually clear the intervals if all monsters are full? or increase the timer? What to do in the empty list case? there is no timer! hmm! in empty list
// case i just change the timer value to be 24 hour? that way it's identical to the full message!
// we will reach here only after all monsters are declared to be full.
// at this point we want to check if this script has been running for a while
return false;
}
// resets FULL flag for all monsters
function ClearFlags(vSuffix) {
for(var i = 0; i < my_monsters.length; i++) {
GM_setValue(my_monsters[i] + vSuffix,false); // reset full flag
GM_setValue(monster_type[i]+ vSuffix,sReset[vSuffix]); //statVars[3] - Statitics gathering - reset fight/feed vars
GM_setValue("LastCleared" + vSuffix, new Date().getTime() + "");
}
}
// Event handler for auto-feed/fight checkbox
function AutoListenClick(e){
//GM_log("AutoListenClick()" + auto_mode); //DEBUG
GM_setValue(cCheckBoxID, document.getElementById('auto'+ auto_mode).checked);
gcountdown = auto_timer; //reset the countdown
startActionTimer(); // call the referenced function
}
// to take action if auto is enabled and start the timer interval
function startActionTimer() {
// if auto switch is on
//GM_log("startActionTimer()"); //DEBUG
if (document.getElementById('auto'+ auto_mode).checked) {
document.getElementById(cTimer).innerHTML = '[' + gcountdown + ']';
// create annonymous function to call every second to decrement counter
// and click when counter = 0
GM_log("Setting interval in startActionTimer"); //DEBUG
// Interval function that runs every second and checks the countdown timers
// and takes appropriate action depending on which page we are on
ginterval = setInterval(function (){
//GM_log("intervalCheck()"); //DEBUG
gcountdown--;
if (gcountdown<=0) {
document.getElementById(cTimer).innerHTML = '[now]';
// we can do things slightly differently if it is in Fight Mode
// like use the attack again link instead of visiting the main page
try { // to stop the infinite recursion with switchmonster, i have to disable the interval first
clearInterval(ginterval); // disable timer function
} catch(x){}
// Take appropriate action depending on the page we are on
if (loc.indexOf(activePages[auto_mode][0])!=-1) { //main page
if (gotourl == "" || gotourl == undefined) {
//list must be empty!
// toggle flag for empty and then switch
GM_setValue(my_monsters[type_ind] + auto_mode,true); // set full flag
GM_log("Callling SwitchMonster from ActionTimer");//DEBUG
if(!SwitchMonster(activePages[auto_mode][0])) {
// lists are empty and all monsters are either full or have empty lists;
// delay by 12 hours * 3600 seconds/hour
gcountdown =12*3600; //reset the countdown - 43200 seconds
startActionTimer(); //call ourselves again since we just reset the timer
}
return;
} else {
location.href = gotourl;
}
}
else if (loc.indexOf(activePages[auto_mode][1])!=-1) {gbuttonsubmit.click();} // confirm page - click on button
else if (loc.indexOf(activePages[auto_mode][2])!=-1) {location.href = gotourl;}//result page - goto main feeding page // ||
else if (loc.indexOf(activePages[auto_mode][3])!=-1) {location.href = switchFightType(base_url + activePages[auto_mode][0]);}//result page - goto main feeding page
} else {
document.getElementById(cTimer).innerHTML = '[' + gcountdown + ']';
}
}, 1000);
} else { // else auto switch must be off
try {
clearInterval(ginterval); // disable timer function
} catch(x){}
document.getElementById(cTimer).innerHTML = '';
}
}
function checkError() {
//Error Checking for:
// - A TIMEOUT Error (NOT WORKING YET)
// - CANNOT FEED MORE ERROR (WORKS)
// - NO FRIENDS TO FEED (TO DO)
// Clear old flags if necessary
// Check if a day has passed since we last cleared flags. If yes, then clear them again.
// clear twice a day? 43200000 or full day 86400000
// feeds are on a 22 hour cycle = 22 hours * 3,600,000 milliseconds/hour = 79,200,000
// fights are on a 15 15.5 or 16 hour cycle =
// i should also clear the flags in case that the current page is ok and we haven't cleared in the last few mins?
if ((parseInt(GM_getValue("LastCleared" + auto_mode, "0"),10) + 79200000 <= (new Date().getTime()))) // Checks once a day (24 h * 60 m * 60 s * 1000 ms)
{
GM_log("Clearing full monster flags");
ClearFlags(auto_mode);
auto_timer = GM_getValue("Timer",5);
//return SwitchMonster(sPage); // call ourself again since we just cleared the flags
}
// check if achieved quota already
var errorHeader;
var errorPage = getElementsByClassName("no_icon","h2");//document.getElementById('error_message');
// based on mode, get the appropriate value into errorHeader, might be easier to understand in if statement form
try {
if (auto_mode == "feed") {
errorHeader = document.getElementById('error');
} else if (auto_mode == "fight") {
errorHeader = getElementsByClassName("status", "h1")[0];
} //else {}
} catch(x){}
// check for div id=error_message
// hit try again if error_message page.
if (errorPage != undefined && errorPage.length >= 1) {
if (errorPage[0].innerHTML.toLowerCase().indexOf('error while loading page from') != -1)
{
GM_log("error page encountered");
GM_log("Setting reload in 3 seconds");
//getElementById("try_again_button").click();
//window.location.reload();
try {
setTimeout(function() {document.getElementById("try_again_button").click();},6000);
} catch (x) {
}
return;
}
//TODO FIX HERE
//setTimeout("window.location.reload()",3000);
/*var buttons = errorPage.getElementsByTagName('input');
var buttontoclick;
for (i=0; i<buttons.length; i++) {
if (buttons[i].type == 'button' && buttons[i].value == 'Try Again') {
buttontoclick = buttons[i];
setTimeout(function() {buttontoclick.click();},5000);
break;
}
}*/
}
if (errorHeader == undefined) { //if no error
//GM_setValue(my_monsters[type_ind] + auto_mode,false); // reset full flag if no error encountered // clear flags only in clearflags now
// what about when they are full? need to add some checking here as well TO DO
auto_timer = GM_getValue("Timer",5); //reset the timer value
return;
}
// if we reach here that means that the error header message exists!
if (errorHeader.innerHTML.toLowerCase().indexOf('hours')!=-1) {
GM_log("limit reached page encountered"); //DEBUG
errorHeader.innerHTML = errorHeader.innerHTML + ' auto'+ auto_mode +' has been delayed.';
errorHeader = errorHeader.innerHTML.toLowerCase(); // to make string matching easier
auto_timer = parseInt(GetSecondsFromString(errorHeader),10) + parseInt(GM_getValue("Timer",5),10); //wait alotted time
GM_log("delayed"+ auto_mode +"by: " + auto_timer);//DEBUG
GM_setValue(my_monsters[type_ind] + auto_mode,true); // set full flag
//since we are full now set feed/fight to 0
setPersistentVar(auto_mode, 0); //statVars[2 or 3] - Statitics gathering
// if auto is enabled
if (GM_getValue(cCheckBoxID, false)) {
GM_log("Callling SwitchMonster from check" + auto_mode);//DEBUG
// Goto next monster function
if (!SwitchMonster(activePages[auto_mode][0])) {
// do something else, all monsters are full!
GM_log("cound not switch monster in checkerror! delay: " + auto_timer); //DEBUG
// switch to fight pages if we are in full auto mode and we have exhausted all our feeds
// but we have to ensure first that the fight pages haven't been touched yet!
GM_log("fullauto:" + fullauto +' ' + auto_mode +' ' + nextfight +' ' + nextfeed +' fight<feed?' + (nextfight <= nextfeed));
// using the timing of nextfight & nextfeed isn't enough! Will have to maintain state seperately somewhere
if (fullauto && auto_mode == 'feed' && nextfight <= nextfeed ) location.href = switchFightType(apps_url + my_monsters[0] + '/' + activePages['fight'][0],0); //TEST
// switch to feed page to wait out the timer once we have exhausted our fights
if (fullauto && auto_mode == 'fight' && nextfight >= nextfeed ) location.href = apps_url + my_monsters[0] + '/' + activePages['feed'][0]; //TEST
}
}
} else { // this case shouldn't occur, will occur on feed pages
//GM_setValue(my_monsters[type_ind] + auto_mode,false); // reset full flag if no error encountered // clear flags only in clearflags now
GM_log("this case shouldn't occur");
auto_timer = GM_getValue("Timer",5);
}
}
// Can put additional logic here later.
function attackUser(attackerP, defenderP) {
var diff = defenderP - attackerP;
var percent = diff/attackerP*100;
//GM_log(diff); //DEBUG
//GM_log(percent); //DEBUG
// less than double of our power? then attack!
if (percent <= 100) {
// but remember this user and don't attack again...
return true;
}
else {
return false;
}
}
// to save variable values using GM_setValue
function setPersistentVar (varName, varValue, addMode, mons_ind) {
mons_ind = mons_ind || type_ind;
if (addMode) { // get existing value and add/subtract to it, send negative values to subtract
varValue = parseInt(GM_getValue(monster_type[mons_ind]+ varName,sReset[varName]),10) + parseInt(varValue,10);
}
GM_setValue(monster_type[mons_ind]+ varName, varValue); //Statitics gathering
return varValue;
}
// get variables using GM_getValue
function getPersistentVar (varName, varValue, mons_ind) {
mons_ind = mons_ind || type_ind;
return GM_getValue(monster_type[mons_ind]+ varName,varValue);
}
// Saves the name of the user that we want to feed
function selectListen(e) {
var thetarget = e.target;
//var feednum = getPersistentVar('feednum',0);
//feednum++; //increase the number of people that we are manually feeding
//GM_log('In listen event: ' + this.checked + this.name);
if (thetarget.checked) {
//setPersistentVar('feedurl' + feednum, thetarget.name);
setPersistentVar(thetarget.name,true);
gotourl = thetarget.title; //enable the next url to feed
} else {
//feednum--;
//setPersistentVar('feedurl' + feednum, ''); // this will remove the most recent saved url! not the one relating to the checkbox
//feednum--;
setPersistentVar(thetarget.name,false);
//gotourl = '';//reset the gotourl
}
//GM_log('In listen event: ' + thetarget.checked + thetarget.name); //+ 'num' + feednum);
//setPersistentVar('feednum',feednum); // save number of feeds that are manually selected
}
// toggling of persistent variables in Greasemonkey
function toggleVar(varName) {
var toggle = GM_getValue(varName,false);
GM_setValue(varName,!toggle);
}
//code to add checkboxes to select users to feed
function addCheckBoxes(xpathExpr, checkClass) {
/*psuedocode
add checkboxes to document
add listeners for checkboxes
in listeners save url/name? to persistent vars, or delete it depening on checked state
when proceeding to feed, before getting the first default url
check if there are saved urls that we have to feed,
and check if they are available in the current document
if yes, change gotourl to that
we should reach here only after we've gone through the entire list, now that is done,
select first guy if feeds are still available
*/
// ****add checkboxes to the document
var thisDiv;
var retValue = '';
var xResults;
if (xpathExpr == undefined || checkClass == undefined) return;
// using the xPath method (which is supposed to giver results faster!)
xResults = document.evaluate(xpathExpr, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i = 0; i < xResults.snapshotLength; i++) {
thisDiv = xResults.snapshotItem(i);
// old school DOM method
// xResults = getElementsByClassName("small_avatar_user_name","div");
// for (var i = 0; i < xResults.length; i++) {
// thisDiv = xResults[i];
// do something with thisDiv
//GM_log('each div' + thisDiv.innerHTML);//DEBUG
// add information specific to this div to the cbox so we can reference is correctly, like name?
//newcbox.innerHTML = ;///>'; //add an id field?
var newcbox = document.createElement('div');
newcbox.innerHTML ='<input type="checkbox" class="'+checkClass+'" name="' + thisDiv.getElementsByTagName("a")[0].innerHTML + '" title="'+ thisDiv.getElementsByTagName("a")[0].href +'" />';
//newcbox.innerHTML ='<input type="checkbox" class="SelectFeed" />';
//GM_log(thisDiv.getElementsByTagName("a")[0].text);
//GM_log(newcbox.innerHTML);//DEBUG
thisDiv.appendChild(newcbox); // only appendChild seems to work, insertBefore doesn't! it looks ugly now, need a way to make it appear in a better way
}
//thisDiv.insertBefore(newcbox,thisDiv.getElementsByTagName("a")); //insert the checkbox
//document.insertBefore(newcbox,thisDiv.getElementsByTagName("a")[0]); //insert the checkbox
//newcbox.addEventListener('click',selectListen,true); // add listener for all the checkboxes
// ****add listeners for the checkboxes
xResults = document.evaluate("//input[@class='"+checkClass+"']", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i = 0; i < xResults.snapshotLength; i++) {
newcbox = xResults.snapshotItem(i);
//recheck the box if it was checked before
newcbox.checked = getPersistentVar(newcbox.name,false);
newcbox.addEventListener('click',selectListen,true); // add listener for all the checkboxes
//GM_log('adding event listener');//DEBUG
if (newcbox.checked) retValue = newcbox.title; //save the next url we'll visit (the last checked box)
}
return retValue;
}
/*/ ================ autofeed ==================
// 1:feed-home.php
// 2:feed-main.php
// 3:feed-result.php
// after clicking on 2)feed-main page will reload and goto different page! 3)feed-result.php
// i'll have to check if GM value 'autofeed' is true
// if yes i'll have to navigate back to main 1)feeding page
// choose another candidate & another victim and feed
// until i've run out of all feeding options
// then disable autofeed
//*/
//*** 1:feed page // where you choose the monster to feed //before actual feeding ********************
// auto: select first candidate to feed and goto his page
if (loc.indexOf('feed-home.php')!=-1) {
//GM_log("Processing feed-home.php"); //DEBUG INFO
// this works now
//divs = getFirstXPathResult("//div[@class='small_avatar_user_name']");
//GM_log('first divs' + divs.innerHTML);//DEBUG
var toggleCheck = GM_getValue('toggleCheck',false);
gotourl = ''; //reset the gotourl
if (toggleCheck) {
gotourl = addCheckBoxes("//div[@class='small_avatar_user_name']", "SelectFeed"); //returns 1st checkbox
}
//find first available candidate (if there are no saved candidates left)
if (gotourl == "" || gotourl == undefined) {
try {
gotourl = getElementsByClassName("small_avatar_user_name","div")[0].getElementsByTagName("a")[0].href;
} catch(e){
gotourl = ''; //friends list is empty or some other error has occured
}
}
}
//*** 2:feed-main page // actual page where you feed your selected monster with a victim ********************
else if (loc.indexOf('feed-main.php')!=-1) {
//GM_log("Processing feed-main.php"); //DEBUG INFO
// check the first friend in list
divs = getFirstXPathResult("//div[@class='list_item']//input");
if (divs != undefined && divs != "") {
divs.checked = true;
}
// find the right button
gbuttonsubmit = findSubmitButton();
}
//*** 3:feed-result page // this is after feeeding ********************
else if (loc.indexOf('feed-result.php')!=-1) {
//GM_log("Processing feed-result.php"); //DEBUG INFO
gotourl = base_url + activePages[auto_mode][0]; // set the url we want to go to now! the main page for feed mode
// do nothing here, just countdown and switch to -main page to choose another candidate
// decrement and save the feed count
setPersistentVar(auto_mode,"-1",true);
// increment the bucks value by 30
setPersistentVar('bucks',30,true);
//GM_setValue(monster_type[type_ind]+ auto_mode,--GM_getValue(monster_type[type_ind]+ auto_mode,sReset[auto_mode])); //statVars[3] - Statitics gathering
}
/*/ ================ autoattacks ==================
// method will be essentially the same as autofeed
// an interval function which will trigger the appropriate actions
// a check function to check global variable settings and initiate the intervals...etc.
// get current level points
// get current attacks remaining
// find attack button on fighting_confirm page
// find attack # combo box
// autofill & autoclick
// get current attacks remaining
// look if enemy is using items
// fight if not items, seek confirmation otherwise
// have it rotate between monster types?
// after using up all attacks go to history page?
// and add timer for 24 hours? or does it give exact time?
// 1:fighting-main.php (and type of monster) //shows attacks available
// 2:fighting-confirm.php //shows attacks available
// 3:fighting-result.php //shows points awarded
// 4:bite.php?max_attacks=1 //when all attacks are done
//*/
// Global variables
//var divattacker;
//var divdefender;
var fightsRemaining; // shows current users attacks remaining
var attackerPoints; // shows current users points Rating
//var defenderPoints; // shows enemy's point rating and link?
var attackPattern = new RegExp("\\[.*\\s(\\d+)\\s+attacks\\sleft\\stoday.*\\]","i"); // detect number of attacks
//var pointsPattern = new RegExp("(\\d+(,|\\d)*)\\s" + monster_type[type_ind] + "\\spoints.*","i"); // detect numbers with commas
//var bucksPattern = new RegExp("(\\d+(,|\\d)*)\\s" + monster_type[type_ind] + "\\sbucks.*","i"); // detect numbers with commas
//var earnedPattern = new RegExp("you\\searned\\s(\\d+)\\s.+point.","i");
//*** 1:fighting-main.php (and type of monster) //shows attacks available
if (loc.indexOf('fighting-main.php')!=-1) {
// attacks remaining
// when 0 attacks goes to bite.php and \\so checkerror on bite.php and fight-main.php
//shortcut to get fightsRemaining
try {
fightsRemaining = parseInt(getelementsbyIDPattern(".*main_sub_title",document.body)[0].innerHTML.match(attackPattern)[1],10);
GM_log("shortcut fightsRemaining: " + fightsRemaining);//DEBUG
setPersistentVar( auto_mode,fightsRemaining); //statVars[2] - Statitics gathering
} catch(x) {
GM_log("error in fightsRemaining: " + fightsRemaining);//DEBUG
}
// if no fights left, switch to the page that shows time remaining until attacks are available
// it will switch monster there automatically if possible
if (fightsRemaining <= 0) {
gotourl=base_url + activePages[auto_mode][3];
}
else { // otherwise find someone to attack.
gotourl='find';
}
// attacker points
// First table and first TD
// div class='small_avatar_experience'
var divattacker = document.getElementsByTagName("td");
try {
attackerPoints = getNumber(getElementsByClassName("small_avatar_experience", "div", divattacker[0])[0].innerHTML);
setPersistentVar( 'points',attackerPoints); //statVars[0] - Statitics gathering
GM_log("My Points: " + attackerPoints);//DEBUG
} catch (x) {
GM_log("error in attackerPoints: " + attackerPoints);//DEBUG
}
// add checkboxes here?
var toggleFight = GM_getValue('toggleFight',false);
if (toggleFight) {
var newgotourl = addCheckBoxes("//div[@class='small_avatar_attack_link']","selectFight");
//GM_log('new:' + newgotourl);//DEBUG
if (gotourl == "find" && newgotourl != "") gotourl = newgotourl;
}
// defender points & links list //Get once per session of current_monster
// we can skip this page later and just use the table generated to choose victims.
// fight only 1 person? or multiple people? Currently let's just choose one for convenience
// div class='rightcol' . table . each TR
// first TD class = defender_radio . A.href = link to go to
// last TD class = zombie_friend_stats. last bold tag = points (strip commas and text)
var divdefender = document.getElementsByTagName("td");
if (divdefender != undefined && divdefender.length >= 3 && (gotourl == "find" || gotourl == "")) {
divs = getElementsByClassName("small_avatar_experience", "div", divdefender[2]);
var divsurl = getElementsByClassName("small_avatar_attack_link", "div", divdefender[2]);
if (divs != undefined && divs.length >= 1) {
//defenderPoints = new Array(divs.length);
for (var i = 0; i < divs.length; i++)
{
var temparray = new Array(2);
// save points
temparray[0] = getNumber(divs[i].innerHTML);
// save url
temparray[1] = divsurl[i].getElementsByTagName("a")[0].href;
//defenderPoints[i] = temparray;
//GM_log("Enemy Points: " + defenderPoints[i]); //DEBUG
// check if we should attack this user?
if (attackUser(attackerPoints,temparray[0])) {
// save the url for the IntervalFunction to activate
gotourl = temparray[1];
GM_log("Attack this user! " + temparray[0] + ',' + gotourl); //DEBUG
break; //stop processing further entries once an attacker is found.
//save this url for all future fights on this page? OR refight user from the fighting results page?!?! TODO
}
}
// if we haven't found somebody to attack at all what to do? TODO
//if (gotourl == 'find') {
//alert("Couldn't find anyone weak enough to attack!");
//}
}
}
}
//*** 2:fighting-confirm.php //shows attacks available
else if (loc.indexOf('fighting-confirm.php')!=-1) {
// find the right button - for interval to auto click
gbuttonsubmit = findSubmitButton();
// find the # of attacks box.
// only if autofight is enabled
if (GM_getValue(cCheckBoxID, false)) {
var num_attacks = document.getElementsByName("num_attacks");
if (num_attacks != undefined && num_attacks.length >=1) {
// Add extra option EXPERIMENTAL FEATURE - Doesn't work, there is server side checking.
//num_attacks[0].options[num_attacks[0].options.length] = new Option("Max!", fightsRemaining);
if (num_attacks[0].options.length > 1) {
// change the number of attacks to the last available option
num_attacks[0].selectedIndex = num_attacks[0].options.length - 1;
}
}
}
//shortcut to get fightsRemaining
try {
fightsRemaining = parseInt(getelementsbyIDPattern(".*main_sub_title",document.body)[0].innerHTML.match(attackPattern)[1],10);
GM_log("shortcut fightsRemaining: " + fightsRemaining);//DEBUG
setPersistentVar( auto_mode,fightsRemaining); //statVars[2] - Statitics gathering
} catch(x){
GM_log("error in fightsRemaining: " + fightsRemaining);//DEBUG
}
/*// the ITEMS box - found, but it's not wise to use items automatically. Best to save them for manual combats
var item_used = document.getElementsByName("item_used");
if (item_used != undefined && item_used.length >=1) {
if (item_used[0].options.length > 1) {
// select the last item as the item to use
item_used[0].selectedIndex = item_used[0].options.length - 1;
}
}*/
}
//*** 3:fighting-result.php //shows points awarded
else if (loc.indexOf('fighting-result.php')!=-1) {
// points awarded
//get fight statistics - result_rewards or fight_story
try {
divs = getElementsByClassName("result_rewards", "div")[0].getElementsByTagName("tr");
} catch(x){}
if (divs != undefined && divs.length >= 3) {
// 0 = heading row, 1 = points row, 2 = bucks row
// td 0 = Me , td 1 = Enemy
//GM_log("column details: " + divs[1].innerHTML); //DEBUG
// change firstChild to lastChild for enemy results.
try {
var ptsEarned = parseInt(divs[1].firstChild.innerHTML.match(/(\d+(,|\d)*)/i)[1],10);
var bksEarned = parseInt(divs[2].firstChild.innerHTML.match(/(\d+(,|\d)*)/i)[1],10);
//ptsEarned = getNumber(divs[1].firstChild.innerHTML);
//bksEarned = getNumber(divs[2].firstChild.innerHTML,".*\\sbucks.*"); //may not work coz of \\s matching in digits
} catch(x) {
ptsEarned = 0;
bksEarned = 0;
}
GM_log("Pts: " + ptsEarned + " $: " + bksEarned);//DEBUG
ptsEarned = setPersistentVar('points',ptsEarned,true);
bksEarned = setPersistentVar('bucks',bksEarned,true);
//ptsEarned = GM_getValue(monster_type[type_ind]+ 'points',0) + ptsEarned;
//bksEarned = GM_getValue(monster_type[type_ind]+ 'bucks',0) + bksEarned;
GM_log("Total: Pts: " + ptsEarned + " $: " + bksEarned);//DEBUG
}
// get attack again link
try {
gotourl = getElementsByClassName("fight_story", "div")[0].getElementsByTagName("li")[0].getElementsByTagName("a")[0].href;
GM_log("Attack again: " + gotourl);//DEBUG
} catch(x) {
gotourl = '';
}
}
//******========= other pages
// SAVE BUCKS FOR STATISTICS PANE
if (loc.indexOf("side-nav.php") != -1 || loc.indexOf("store-main.php") != -1) {
var iBucks;
//avoid updating stats when visiting pages not ours
if (extra_url.indexOf("?ref=top_nav") != -1 || extra_url.length <= 25) {
try {
iBucks = getNumber(document.getElementsByTagName("sup")[0].parentNode.innerHTML,"\\s.*\\sbucks.*");
//GM_log("bucks:"+iBucks);//DEBUG
setPersistentVar('bucks',iBucks);//statVars[1] - Statitics gathering
} catch(x){
iBucks = '';
}
// try getting the points
try {
iBucks = getNumber(getElementsByClassName("centered_text emphasis", "td")[0].innerHTML,".*");
//GM_log('points'+iBucks);//DEBUG
setPersistentVar('points',iBucks);//statVars[1] - Statitics gathering
}catch(x){
iBucks = '';
}
// start full auto mode from side-nav.php
if (fullauto && nextfight > nextfeed) location.href = apps_url + my_monsters[0] + '/' + activePages['feed'][0]; //TEST
}
}
// COMMON PAGE ROUTINES
//*** 0:fightingXXXX.php //Common actions across all fighting pages here! //if (loc.indexOf('fighting')!=-1 || loc.indexOf('bite.php?max_attacks=1') != -1) {
//*** 0:feedXXXX.php //Common actions across all feed pages here! //if (loc.indexOf('feed')!=-1) {
//function common_routines() {
if (auto_mode != undefined && auto_mode != "") {
// check if finished quota or error page(timeout) has been encountered
// and update the auto_timer value accordingly
checkError();
// if auto mode is enabled reset countdown
if (GM_getValue(cCheckBoxID, false)) gcountdown = auto_timer; //reset the countdown
// enable the checkbox
document.getElementById(cCheckBoxID).disabled = false;
// add listener for checkbox
document.getElementById(cCheckBoxID).addEventListener('click', AutoListenClick, true);
// initiate & set interval timer if enabled
startActionTimer();
}
// ALL PAGE ROUTINES
populateStats(); // referesh any stats that we have
if (GM_getValue('nextPage','none') != "none") scrollpages(); //go through the predetermined sequence
//}
/*
// MAIN routine - if i every wish to change the whole code to be in functions only
// declare global vars here
// Control program flow
function main() {
// INITIALIZE VARIABLES
initVars();
// PRE GLOBAL ACTIONS (insert menu, check the boxes ...etc , associate intervals, timers, events ...etc)
insertMenu();
// PAGE SPECIFIC ACTIONS (mainly data gathering)
//run page specific functions (use select case ...etc.) use function referencing through variables ...etc
if (loc.indexOf(activePages[auto_mode][0]) != -1) { // main page
} else if (loc.indexOf(activePages[auto_mode][1]) != -1) { // confirmation page
} else if (loc.indexOf(activePages[auto_mode][2]) != -1) { // results page
} else if (loc.indexOf(activePages[auto_mode][3]) != -1) { // over the quota page
}
// PAGE OVERRIDES
// any specific page overrides, put it below
if (loc.indexOf(activePages['fight'][0]) != -1) { // main page
}
if (loc.indexOf(activePages['feed'][1]) != -1) { // confirmation page
}
// COMMON ROUTINES
if (auto_mode != undefined && auto_mode != "") { // common page routines for each mode
common_routines();
}
// GLOBAL ROUTINES
if (GM_getValue('nextPage','none') != "none") scrollpages(); //go through the predetermined sequence
//done
}
main(); // start the whole program
*/