Professional Documents
Culture Documents
User
User
var SCRIPT = {
url: 'http://userscripts.org/scripts/source/43573.user.js',
version: '0.9.9',
build: '520',
name: 'inthemafia',
appID: 'app10979261223',
ajaxPage: 'inner2',
presentationurl: 'http://userscripts.org/scripts/show/43573',
controller: '/remote/html_server.php?&xw_controller=',
action: '&xw_action=',
city: '&xw_city=',
opponent: '&opponent_id=',
user: '&user_id='
};
// Register debugOnOff with Greasemonkey
GM_registerMenuCommand( 'FB Mafia Wars Autoplayer - Turn Debug Log '+(GM_getValu
e('enableDebug') == 'checked' ? 'off' : 'on'), debugOnOff);
GM_registerMenuCommand( 'FB Mafia Wars Autoplayer - Clear Saved Values', functio
n() { clearSettings(); loadHome(); });
GM_registerMenuCommand( 'FB Mafia Wars Autoplayer - Display Stats Window', funct
ion() { toggleStats(); });
function clearSettings() {
if(typeof GM_listValues == 'function' &&
typeof GM_deleteValue == 'function') {
var values = GM_listValues();
for (var i in values) {
GM_deleteValue(values[i]);
}
} else {
alert('In order to do this you need at least GreaseMonkey version: 0.8.20090
123.1. Please upgrade and try again.');
}
}
// Handle Facebook error pages.
if (location.href.indexOf('error') != -1) {
var delay = 30;
var p = document.createElement('p');
var wait = function() {
if (!delay) return back();
p.innerHTML = 'You will automatically return to the previous page in ' +
delay-- + ' seconds.';
window.setTimeout(wait, 1000);
}
document.body.appendChild(p);
wait();
return;
}
customizeLayout();
function doAutoPlay () {
// Set the default auto-play timer function and delay.
Autoplay.fx = goHome;
Autoplay.delay = getAutoPlayDelay();
var running = (GM_getValue('isRunning', false) === true);
var propertyDamage = GM_getValue('propertyDamage', PROP_OK);
var previouslyIdle = idle;
idle = false;
// Auto-pause reset
if (GM_getValue('autoPauseActivated', false) === true &&
GM_getValue('autoPauseBefore', '') == 'checked' &&
GM_getValue('autoPauselvlExp') < lvlExp) {
GM_setValue('autoPauselvlExp', lvlExp);
GM_setValue('autoPauseActivated', false);
}
// Auto-heal
if (running &&
GM_getValue('autoHeal', '') == 'checked' &&
health < GM_getValue('healthLevel', '') &&
(health > 19 || autoStamBurnif ||
GM_getValue('hideInHospital', '') != 'checked')) {
autoHeal();
return;
}
// Collect any property income.
if (running && onPropertyNav()) {
var elt = xpathFirst('.//a[contains(., "Collect take")]', innerPageElt);
if (elt) {
// FIXME: Quick fix. Should actually use an "action" to report the
// results to the log.
Autoplay.fx = function() { clickElement(elt) };
Autoplay.start();
return;
}
}
// Auto-repair
if (running &&
GM_getValue('autoRepair', '') == 'checked' &&
propertyDamage == PROP_REPAIR) {
autoRepair();
return;
}
// Auto-protect
if (running &&
GM_getValue('autoProtect', '') == 'checked' &&
propertyDamage == PROP_PROTECT) {
autoProtect();
return;
}
// Auto-sell for business output.
if (running &&
level >= 35 &&
GM_getValue('autoSellCrates', '') == 'checked' &&
GM_getValue('sellHour', -1) != new Date().getHours()) {
autoSellCrates();
return;
}
// Auto-bank
if (running &&
city == NY &&
GM_getValue('autoBank', '') == 'checked' &&
cash[NY] > parseInt(GM_getValue('bankConfig', 100000))-1) {
if (document.body.innerHTML.indexOf('title">The Bank') != -1 ) {
bankClickDeposit();
} else {
Autoplay.fx = goBank;
Autoplay.start();
DEBUG('Entering the bank.');
}
return;
}
if (running &&
city == CUBA &&
GM_getValue('autoBankCuba', '') == 'checked' &&
cash[CUBA] > parseInt(GM_getValue('bankConfigCuba', 100000))-1) {
if (document.body.innerHTML.indexOf('title">The Bank') != -1) {
bankClickDeposit();
} else {
Autoplay.fx = goBank;
Autoplay.start();
DEBUG('Entering the bank.');
}
return;
}
// Determine whether a job and/or fight/rob could be attempted.
var autoMissionif = running && canMission();
var autoFightRobif = running && !skipFightRob && canFightRob(29);
// Auto-stat
if (running &&
stats > 0 &&
GM_getValue('autoStat', '') == 'checked' &&
(!(autoMissionif && energy >= maxEnergy)) &&
(!(autoFightRobif && stamina >= maxStamina))) {
if (autoStat()) {
return;
}
}
// Auto-pause logic
if (running && GM_getValue('autoPause', '') == 'checked' &&
((GM_getValue('autoPauseBefore', '') == 'checked' && GM_getValue('autoPaus
eExp', '') >= lvlExp - curExp && GM_getValue('autoPauseActivated', false) === fa
lse) || (GM_getValue('autoPauseAfter', '') == 'checked' && GM_getValue('autoPaus
elvlExp', '') < lvlExp))) {
if (GM_getValue('autoPauseBefore', '') == 'checked') {
addToLog('pause Icon', 'Auto-pause in effect. Experience threshold reached
.');
GM_setValue('autoPauseActivated', true);
pause();
} else {
addToLog('pause Icon', 'Auto-pause in effect. Leveled up.');
GM_setValue('autoPauselvlExp', lvlExp);
pause();
}
return;
}
// Player updates
if (running && GM_getValue('logPlayerUpdates', '') == 'checked') {
// Get the updates.
var pUpdates = xpath('.//div[@class="update_item"]', innerPageElt);
var pUpdatesLen = pUpdates.snapshotLength;
var logPlayerUpdatesCount = GM_getValue('logPlayerUpdatesCount');
if (logPlayerUpdatesCount == undefined) {
// The settings must have been cleared. Assume all updates were read.
logPlayerUpdatesCount = pUpdatesLen;
GM_setValue('logPlayerUpdatesCount', logPlayerUpdatesCount);
}
// Are there are less updates than we've already seen?
// FIXME: This could be better. Need to also detect the case where we are
// on the home page with zero updates showing and a non-zero count.
if (pUpdatesLen > 0 && logPlayerUpdatesCount > pUpdatesLen) {
// The player updates must have been cleared.
DEBUG('Player updates were unexpectedly cleared.');
logPlayerUpdatesCount = 0;
GM_setValue('logPlayerUpdatesCount', 0);
}
// Process new updates.
if (logPlayerUpdatesCount < pUpdatesLen) {
DEBUG('Parsing new player updates.');
for (var i = pUpdatesLen - logPlayerUpdatesCount - 1; i >= 0; i--) {
if (!parsePlayerUpdates(pUpdates.snapshotItem(i))) return;
GM_setValue('logPlayerUpdatesCount', ++logPlayerUpdatesCount);
}
}
// Clear the updates.
if (pUpdatesLen > GM_getValue('logPlayerUpdatesMax', 20) &&
logPlayerUpdatesCount == pUpdatesLen) {
Autoplay.fx = goDeleteNews;
Autoplay.start();
return;
}
}
// Auto-buy properties
if (running &&
GM_getValue('autoBuy', '') == 'checked' &&
(!(autoMissionif && energy >= maxEnergy)) &&
(!(autoFightRobif && stamina >= maxStamina))) {
if (propertyBuy()) return;
}
// Auto-lotto
if (running && GM_getValue('autoLottoOpt', 0)) {
lottoRet=autoLottoRun();
if (lottoRet==2) {
Autoplay.fx = goHome;
Autoplay.start();
return;
}
else if (lottoRet==1)
return;
}
// Auto-energypack
var ptsFromEnergyPack = maxEnergy * 1.25 * getEnergyGainRate();
var ptsToLevelProjStaminaUse = ptsToNextLevel - stamina*getStaminaGainRate();
var autoEnergyPackWaiting = running && energyPack &&
ptsFromEnergyPack <= ptsToLevelProjStaminaUse &&
GM_getValue('autoEnergyPack', '') == 'checked';
if (autoEnergyPackWaiting && energy <= 2) {
var link = 'http://apps.facebook.com/' + SCRIPT.name +
SCRIPT.controller + 'index' +
SCRIPT.action + 'use_and_energy_all' +
SCRIPT.city + (city + 1);
addToLog('energyPack Icon', 'This energy pack should give you approximately
' + parseInt(ptsFromEnergyPack) + ' xp of your ' + parseInt(ptsToLevelProjStamin
aUse) + ' projected remaining xp.' );
takeAction(link, 'energypack');
DEBUG('ptsToNextLevel is ' + (lvlExp - curExp));
Autoplay.start();
return;
}
// Do jobs or fight/rob. Give priority to jobs if extremely close to
// leveling, or if an energy pack is waiting, or if energy is fuller
// than stamina (in percentage terms).
if (autoMissionif &&
(ptsToNextLevel < 7 ||
autoEnergyPackWaiting ||
energy/maxEnergy >= stamina/maxStamina)) {
autoMission();
return;
}
if (autoFightRobif) {
if (autoFightRob()) return;
// Fight/rob failed. Let some other action happen before trying again.
skipFightRob = true;
}
if (autoMissionif) {
autoMission();
return;
}
// If we reach this point, the script is considered to be idle. Anything the
// script might do when there is nothing else to do should go below here.
idle = true;
// If not previously idle, check the home page.
if (running && !previouslyIdle) {
DEBUG('Now idle. Checking the home page.');
Autoplay.start();
return;
}
// Check for property damage. This way we are not adding any overhead, except
// on pages that we are not doing anything anyways. All this does is go to
// the Properties page, which causes the damage to be checked automatically.
if (running &&
((GM_getValue('autoProtect', '') == 'checked' &&
propertyDamage < PROP_PROTECT) ||
(GM_getValue('autoRepair', '') == 'checked' &&
propertyDamage < PROP_REPAIR))) {
// Make sure we're in New York.
if (city != NY) {
Autoplay.fx = goNY;
Autoplay.start();
return;
}
// Go to the property page.
if (!onPropertyNav()) {
Autoplay.fx = goPropertyNav;
Autoplay.start();
return;
}
}
// Absolutely nothing to do. If fight/rob is being skipped, turn it
// back on and go to the home page.
if (skipFightRob) {
skipFightRob = false;
Autoplay.start();
return;
}
}
// takes a string input in the form of 'MM:SS', 'HH:MM:SS', or 'MM minutes and S
S seconds' and returns the number of seconds it represents
function timeLeft(timeToConvert) {
if (!timeToConvert)
return 0;
var returnVal = 0;
var temp = new Array();
temp=timeToConvert.split(':');
if (temp.length == 2) // MM:SS
returnVal = ((parseInt(temp[0]) * 60) + parseInt(temp[1]));
else if (temp.length == 3) // HH:MM:SS
returnVal = ((parseInt(temp[0]) * 60 * 60) + (parseInt(temp[1]) * 60) + pars
eInt(temp[2]));
else if (temp.length == 1) { // 'MM minutes and SS seconds'
temp = timeToConvert.split(' and ');
for (i=0;i<temp.length;i++) {
spaceIndex = temp[i].indexOf(' ');
if (spaceIndex != -1) {
firstPart = temp[i].substring(0,spaceIndex);
secondPart = temp[i].substring(spaceIndex+1,temp[i].length);
if ((secondPart == 'minutes') || (secondPart == 'minute'))
returnVal = returnVal + (parseInt(firstPart) * 60);
else if ((secondPart == 'seconds') || (secondPart == 'second'))
returnVal = returnVal + (parseInt(firstPart));
}
}
}
return(returnVal);
}
// reads a date string from a stored GM value and converts it to seconds since 1
970
function getTime(GMvalue) {
var tempVal = GM_getValue(GMvalue, 0);
var d = Date.parse(tempVal);
return d/1000;
}
// takes a string input in the form of a countdown 'MM:SS', 'HH:MM:SS', 'MM minu
tes and SS seconds' and stores the
// time when the countdown is zero in a GM value. Also takes an input of 'now'
and stores the current time.
function setTime(GMvalue, countdownStr) {
var d = new Date();
d.setMilliseconds(0);
if (countdownStr != 'now')
d.setTime(d.getTime()+(timeLeft(countdownStr)*1000));
GM_setValue(GMvalue, d.toString());
}
// returns the number of seconds left until a date stored in a GM value
function timeLeftGM(GMvalue) {
var timeToCompare = getTime(GMvalue);
var d = new Date();
d.setMilliseconds(0);
return (timeToCompare-(d.getTime()/1000));
}
function getAutoPlayDelay() {
return Math.floor(parseFloat(GM_getValue('d1', '3')) + parseFloat((GM_getValue
('d2', '5'))-parseFloat(GM_getValue('d1', '3')))*Math.random())*1000;
}
function autoReload() {
if (GM_getValue('autoClick', '') == 'checked') {
Reload.fx = loadHome;
Reload.delay = Math.floor(parseFloat(GM_getValue('r1', '30')) +
parseFloat((GM_getValue('r2', '110')) -
parseFloat(GM_getValue('r1', '30')))*Math.random())*1000;
Reload.start();
}
}
function autoRepair() {
Autoplay.delay = getAutoPlayDelay();
// Make sure we're in New York.
if (city != NY) {
Autoplay.fx = goNY;
Autoplay.start();
return;
}
// Make sure we've got enough cash outside the bank.
var cost = GM_getValue('propertyDamageCost', 0);
if (cost > cash[city]) {
withdrawFromBank(cost - cash[city]);
return;
}
if (!useClickSimulation) {
var link = 'http://apps.facebook.com/' + SCRIPT.name +
SCRIPT.controller + 'property' +
SCRIPT.action + 'repair_all' +
SCRIPT.city + (city + 1);
takeAction(link, 'repair', { cost: cost });
Autoplay.fx = goPropertyNav;
Autoplay.start();
return;
}
// Make sure we're on the property page.
if (!onPropertyNav()) {
Autoplay.fx = goPropertyNav;
Autoplay.start();
return;
}
// Repair the property.
var elt = xpathFirst('.//a[contains(@onclick, "repair_all")]', innerPageElt);
if (!elt) {
addToLog('warning Icon', 'BUG DETECTED: Can\'t find repair link.');
return;
}
Autoplay.fx = function() {
clickAction = 'repair';
clickContext = { cost : cost };
clickElement(elt);
};
Autoplay.start();
}
function autoProtect() {
Autoplay.delay = getAutoPlayDelay();
// Make sure we're in New York.
if (city != NY) {
Autoplay.fx = goNY;
Autoplay.start();
return;
}
// Make sure we've got enough cash outside the bank.
var cost = GM_getValue('propertyDamageCost', 0);
if (cost > cash[city]) {
withdrawFromBank(cost - cash[city]);
return;
}
if (!useClickSimulation) {
var link = 'http://apps.facebook.com/' + SCRIPT.name +
SCRIPT.controller + 'property' +
SCRIPT.action + 'protect_all' +
SCRIPT.city + (city + 1);
takeAction(link, 'protect', { cost: cost });
Autoplay.fx = goPropertyNav;
Autoplay.start();
return;
}
// Make sure we're on the property page.
if (!onPropertyNav()) {
Autoplay.fx = goPropertyNav;
Autoplay.start();
return;
}
// Protect the property.
var elt = xpathFirst('.//a[contains(@onclick, "protect_all")]', innerPageElt);
if (!elt) {
addToLog('warning Icon', 'BUG DETECTED: Can\'t find protection link.');
return;
}
Autoplay.fx = function() {
clickAction = 'protect';
clickContext = { cost : cost };
clickElement(elt);
};
Autoplay.start();
}
function autoHeal() {
// NOTE: In the interest of time, delays are waived.
Autoplay.delay = 0;
// Make sure we're in the preferred city.
var healLocation = GM_getValue('healLocationCuba', '') == 'checked' ? CUBA : N
Y;
if (city != healLocation) {
Autoplay.fx = function() { goLocation(healLocation); }
Autoplay.start();
return;
}
if (!useClickSimulation) {
var link = 'http://apps.facebook.com/' + SCRIPT.name +
SCRIPT.controller + 'hospital' +
SCRIPT.action + 'heal' +
SCRIPT.city + (city + 1);
takeAction(link, 'heal');
Autoplay.fx = goHome;
Autoplay.start();
return;
}
// Use our custom instant-heal element (if present).
var healElt = document.getElementById('ap_heal');
if (!healElt) {
DEBUG('WARNING: Can\'t find instant-heal link.');
healElt = xpathFirst('//a[contains(@onclick, "action=heal")]');
if (!healElt) {
// Go to the hospital.
var hospitalElt = xpathFirst('//a[@class="heal_link"]');
if (hospitalElt) {
Autoplay.fx = function() {
clickElement(hospitalElt);
DEBUG('Clicked to go to hospital.');
};
Autoplay.start();
} else {
addToLog('warning Icon', 'WARNING: Can\'t find hospital link.');
}
return;
}
}
// Found a heal link. Click it.
Autoplay.fx = function() {
clickAction = 'heal';
clickElement(healElt);
DEBUG('Clicked to heal.');
};
Autoplay.start();
return;
}
function autoSellCrates() {
// Go to the correct city.
if (city != CUBA) {
Autoplay.fx = goCuba;
Autoplay.start();
return;
}
// Go to the businesses.
if (innerPageElt.innerHTML.indexOf('title">Businesses') == -1) {
Autoplay.fx = goBusinessesNav;
Autoplay.start();
DEBUG('Entering businesses.');
return;
}
// Sell anything we can.
elt = xpathFirst('.//a[contains(@onclick, "business=") and contains(@onclick,
"action=sell")]', innerPageElt);
if (elt) {
Autoplay.fx = function() {
clickAction = 'sell output';
clickElement(elt);
DEBUG('Clicked to sell output.');
};
Autoplay.start();
return;
}
// Nothing to sell.
GM_setValue('sellHour', new Date().getHours());
DEBUG('All business output sold. Checking again in an hour.');
Autoplay.fx = goHome;
Autoplay.start();
}
function autoStat() {
var link = 'http://apps.facebook.com/' + SCRIPT.name +
SCRIPT.controller + 'stats' +
SCRIPT.action + 'upgrade' +
SCRIPT.city + (city + 1);
if (GM_getValue('autoStatAttack', '') == 'checked') {
link += '&upgrade_key=attack';
} else if (GM_getValue('autoStatDefense', '') == 'checked') {
link += '&upgrade_key=defense';
} else if (GM_getValue('autoStatHealth', '') == 'checked') {
link += '&upgrade_key=max_health';
} else if (GM_getValue('autoStatEnergy', '') == 'checked') {
link += '&upgrade_key=max_energy';
} else if (GM_getValue('autoStatStamina', '') == 'checked') {
if (stats < 2) return false;
link += '&upgrade_key=max_stamina';
} else {
addToLog('warning Icon', 'Auto-stat cannot work because a statistic has not
been selected in the General tab of the settings menu. Turning auto-stat off.');
var elt = document.getElementById('autoStat');
if (elt) {
elt.checked = false;
}
GM_setValue('autoStat', 0);
return false;
}
DEBUG('Stats available.');
takeAction(link, 'stats');
Autoplay.start();
return true;
}
function canMission() {
if (GM_getValue('autoMission', '') != 'checked') return false;
if (energy < calcEnergyCost()) {
DEBUG('Skipping jobs: energy=' + energy + ', cost=' + calcEnergyCost());
return false;
}
if (energy < maxEnergy && GM_getValue('waitForFull', '') == 'checked') {
DEBUG('Skipping jobs: energy=' + energy + '/' + maxEnergy + ', waiting');
return false;
}
return true;
}
function autoMission() {
var jobno = missions[GM_getValue('selectMission', 1)][2];
var tabno = missions[GM_getValue('selectMission', 1)][3];
var cityno = missions[GM_getValue('selectMission', 1)][4];
// Go to the correct city.
if (city != cityno) {
Autoplay.fx = function() { goLocation(cityno); };
Autoplay.start();
return;
}
// Go to the correct job tab.
if (!onJobTab(tabno)) {
Autoplay.fx = function() { goJobTab(tabno); };
Autoplay.start();
return;
}
// Do the job.
if (useClickSimulation) {
Autoplay.fx = function() { goJob(jobno); };
Autoplay.start();
} else {
var link = 'http://apps.facebook.com/' + SCRIPT.name +
SCRIPT.controller + 'job' +
SCRIPT.action + 'dojob' +
SCRIPT.city + (city + 1) +
'&job=' + jobno +
'&tab=' + tabno;
takeAction(link, 'job');
}
}
function currentJobTab() {
var elt = xpathFirst('.//ul[contains(@id, "' + SCRIPT.appID + '_jobs_bar")]/li
[contains(@class, "tab_on")]//a', innerPageElt);
if (!elt || !elt.getAttribute('onclick').match(/tab=(\d+)/)) {
return -1;
}
return parseInt(RegExp.$1);
}
function onJobTab(tabno) {
return currentJobTab() == tabno? true : false;
}
function canFightRob(minHealth) {
if (GM_getValue('autoFight', '') != 'checked' &&
GM_getValue('autoRob', '') != 'checked') {
return false;
}
if (health < minHealth) {
DEBUG('Skipping fight/rob: health=' + health);
return false;
}
if (stamina <= staminaFloor && !autoStamBurnif) {
DEBUG('Skipping fight/rob: stamina=' + stamina +
', floor=' + staminaFloor + ', burn=false');
return false;
}
return true;
}
function autoHitman() {
// FIXME: If click navigation if off, this feature won't work and it should
// be shut off with a warning to the user.
// Go to the correct city.
var loc = GM_getValue('fightLocationCuba', '') == 'checked' ? CUBA : NY;
if (city != loc) {
Autoplay.fx = function() { goLocation(loc); };
Autoplay.delay = getAutoPlayDelay();
Autoplay.start();
return true;
}
// Make sure we're on the hitlist tab.
if (!onHitlistTab()) {
Autoplay.fx = goHitlistTab;
Autoplay.delay = getAutoPlayDelay();
Autoplay.start();
return true;
}
// Get the list of targets.
var opponents = getHitlist(innerPageElt);
if (!opponents) return false;
// Get the targets that are acceptable.
DEBUG('Applying criteria to displayed targets.');
var blacklist = getSavedList('fightListAvoid');
var blacklistCount = 0;
var settingsCount = 0;
var opponentsQualified = [];
for (var i = 0; i < opponents.length; i++) {
var opponent = opponents[i];
if (blacklist.indexOf(opponent.id) != -1) {
blacklistCount++;
continue;
}
if (!notFamily(decodeHTMLEntities(opponent.name))) {
settingsCount++;
continue;
}
opponentsQualified.push(opponent);
}
if (!opponentsQualified.length) {
// We looked over the hitlist but still found no targets.
DEBUG(settingsCount + ' of ' + opponents.length +
' failed settings, ' + blacklistCount + ' on blacklist.');
return false;
}
// Pick a target and attack immediately.
Autoplay.fx = function() {
clickAction = 'hitman';
clickContext = opponentsQualified[0];
clickElement(clickContext.attack);
DEBUG('Clicked to hit ' + clickContext.name +
' (' + clickContext.id + ').');
};
Autoplay.start();
return true;
}
function autoFightRob() {
var fight = (GM_getValue('autoFight', '') == 'checked');
if (!fight && GM_getValue('autoRob', '') != 'checked') {
addToLog('warning Icon', 'BUG DETECTED: reached autoFightRob() without fight
or rob enabled.');
return false;
}
if (autoStamBurnif) {
GM_setValue('autoStamBurn', 'Running');
} else {
GM_setValue('autoStamBurn', 'Stopped');
}
if (fight) {
var fightLocation = GM_getValue('fightLocationCuba', '') == 'checked' ? CUBA
: NY;
if (city != fightLocation) {
Autoplay.fx = function() { goLocation(fightLocation); };
Autoplay.delay = getAutoPlayDelay();
Autoplay.start();
return true;
}
} else if (city != NY) {
// Robbing is only supported in New York.
Autoplay.fx = goNY;
Autoplay.delay = getAutoPlayDelay();
Autoplay.start();
return true;
}
// Get an opponent.
var id = 0;
if (GM_getValue('fightRandom', '') == 'checked') {
id = findFightOpponent();
// If -1 was returned, we are already at the list but still found no one.
if (id == -1) {
DEBUG('No opponents even after seeing the fight list.');
return false;
}
// Return true if navigating to the list.
if (!id) return true;
} else if (GM_getValue('rFightList', '') == 'checked') {
id = parseInt(GM_getValue('fightList', ''));
if (!id) {
// The user-specified list is empty or invalid.
if (fight) {
addToLog('warning Icon', 'Auto-fight cannot work because the list of opp
onents is empty or invalid. Turning auto-fight off.');
var elt = document.getElementById('autoFight');
if (elt) {
elt.checked = false;
}
GM_setValue('autoFight', 0);
} else {
addToLog('warning Icon', 'Auto-rob cannot work because the list of oppon
ents is empty or invalid. Turning auto-rob off.');
var elt = document.getElementById('autoRob');
if (elt) {
elt.checked = false;
}
GM_setValue('autoRob', 0);
}
return false;
}
}
if (!id) return false;
var context = { id: String(id) };
if (GM_getValue('autoRob', '') == 'checked') {
// Rob the filthy animal
DEBUG('Rob the filthy animal ' + id + '.');
var link = 'http://apps.facebook.com/'+ SCRIPT.name +
SCRIPT.controller + 'racket' +
SCRIPT.action + 'attack' +
SCRIPT.city + (city + 1) +
'&tmp=' + fightTmp +
SCRIPT.opponent + id +
'&property_id=' + parseInt(GM_getValue('propertyId', ''));
takeAction(link, 'rob', context);
setFightOpponentRobbed(context.id);
} else {
// Attack!
var link = 'http://apps.facebook.com/' + SCRIPT.name +
SCRIPT.controller + 'fight' +
SCRIPT.action + 'attack' +
SCRIPT.city + (city + 1) +
'&tmp=' + fightTmp +
SCRIPT.opponent + id;
takeAction(link, 'fight', context);
}
return true;
}
function bankClickDeposit() {
var sform = xpathFirst('//input[@value=\'Deposit\' and @type=\'submit\']');
if (!sform) {
window.setTimeout(bankClickDeposit,1000);
} else {
sform.click();
bankDepositCheck();
}
}
function bankDepositCheck() {
var elt = xpathFirst('//td[@class=\'message_body\' and contains(text(),\'was d
eposited\')]');
if (elt) {
addToLog(city == CUBA? 'cashCuba Icon' : 'cash Icon', elt.innerHTML);
Autoplay.delay = getAutoPlayDelay();
Autoplay.start();
} else {
window.setTimeout(bankDepositCheck,1000);
}
}
function placeBounty () {
var depositBox = xpathFirst('//input[@name="amount"]');
depositBox.value = GM_getValue('bountyAmount',10000);
var sform = xpathFirst('//input[@type="submit"]');
sform.click();
placeBountyCheck();
}
function placeBountyCheck () {
if (xpathFirst('//td[@class=\'message_body\' and contains(text(),\'You just se
t a\')]')) {
DEBUG('Bounty set successfully.');
} else {
DEBUG('Bounty not set.');
}
}
// Returns a non-empty array of the displayed opponents, or undefined.
function getHitlist(element) {
var fight = (GM_getValue('autoFight', '') == 'checked');
var opponents = [];
// First, look for a traditional fight table (one with real links).
var rows = $x('.//table[@class="hit_list"]//tr', element);
// Get each target in the displayed list.
for (var i = 0; i < rows.length; i++) {
// Get the data cells in the row.
var rowData = rows[i].getElementsByTagName('td');
if (rowData.length < 5) continue;
// Get the target's profile and attack links.
var opponent = {
attack: xpathFirst('.//a', rowData[4]),
bounty: rowData[2].innerHTML.match(/C?\$[\d,]*\d/),
payer: xpathFirst('.//a', rowData[1]),
profile: xpathFirst('.//a', rowData[0]),
time: rowData[3].innerHTML.untag().trim()
};
if (!opponent.profile || !opponent.attack) continue;
// Get the target's name, id, and title.
opponent.name = opponent.profile.innerHTML;
if (opponent.profile.getAttribute('onclick').match(/user=(\w+)/)) {
opponent.id = RegExp.$1
}
if (opponent.profile.previousSibling) {
opponent.title = opponent.profile.previousSibling.nodeValue.match(/\w+(?:
\w+)*/);
}
opponents.push(opponent);
}
DEBUG(opponents.length + ' hitlist target(s) found.');
if (!opponents.length) return;
//for (var i = 0; i < opponents.length; i++) {
// GM_log('Saw id=' + opponents[i].id +
// ', title=' + opponents[i].title +
// ', name=' + opponents[i].name +
// ', bounty=' + opponents[i].bounty +
// ', time=' + opponents[i].time);
//}
return opponents;
}
// Returns a non-empty array of the displayed opponents, or undefined.
function getDisplayedOpponents(element) {
var fight = (GM_getValue('autoFight', '') == 'checked');
var opponents = [];
// First, look for a traditional fight table (one with real links).
var links = $x('.//table[@class=\'main_table fight_table\']//a[contains(@href,
\'opponent_id\') and not(contains(@href,\'property\'))]', element);
// Thanks Liquidor for the loop code
// Get each potential opponent in the displayed list.
for (var i = 0; i < links.length; i++) {
var row = links[i].parentNode.parentNode;
var rowData = row.getElementsByTagName('td');
// We need this for robbing to go to the previous tr that contains the
// name and level. (In the fight list it is all on one line.)
if (!fight) {
var nameAndLevel = row.previousSibling;
while ( nameAndLevel.nodeType != 1 ) {
nameAndLevel = nameAndLevel.previousSibling;
}
} else {
nameAndLevel = row;
}
var opponentMafia = rowData[1] ? parseInt(rowData[1].innerHTML) : 0;
var opponentLevel = parseInt(nameAndLevel.innerHTML.split('Level ')[1]);
var userElt = nameAndLevel.getElementsByTagName('a')[0];
var username = userElt? userElt.innerHTML : '';
if (!opponentLevel) {
addToLog('warning Icon','BUG DETECTED: Unable to read opponent level.');
addToLog('warning Icon', 'Row contents: '+ row.innerHTML);
} else if (!opponentMafia) {
addToLog('warning Icon','BUG DETECTED: Unable to read opponent mafia.');
addToLog('warning Icon', 'Row contents: '+ row.innerHTML);
} else if (!username) {
// So far, this has always indicated a bug in Mafia Wars itself.
DEBUG('Unable to read opponent name.');
DEBUG('Row contents: '+ row.innerHTML);
} else {
var linkElt = links[i];
var id = parseInt(linkElt.href.split(SCRIPT.opponent)[1]);
if (id) {
// Put the opponent's info into an object.
var opponent = {
name: username,
id: id,
mafia: opponentMafia,
level: opponentLevel,
attack: linkElt
};
opponents.push(opponent);
}
}
}
if (!opponents.length) {
// No traditional list was found. Look for a newer-style list.
//var ids = unsafeWindow['a10979261223_fight_list_ids'];
//GM_log('ids=' + ids);
// Find level elements.
var levelElts = $x('.//table[@class="main_table fight_table"]//td/span[conta
ins(@id, "' + SCRIPT.appID + '_fight_view_level_")]', element);
for (var i = 0; i < levelElts.length; i++) {
var levelElt = levelElts[i];
if (!levelElt.innerHTML.match(/evel (\d+)/)) continue;
// Found an opponent.
var opponent = {};
opponent.level = parseInt(RegExp.$1);
var row = levelElt.id.match(/\d+$/);
var rowElt = levelElt.parentNode.parentNode;
opponent.title = xpathFirst('.//*[@id="' + SCRIPT.appID + '_fight_view_tit
le_' + row + '"]', rowElt).innerHTML;
opponent.profile = xpathFirst('.//*[@id="' + SCRIPT.appID + '_fight_view_n
amelink_' + row + '"]/a', rowElt);
opponent.name = opponent.profile.firstChild.innerHTML;
opponent.mafia = parseInt(xpathFirst('.//*[@id="' + SCRIPT.appID + '_fight
_view_groupsize_' + row + '"]', rowElt).innerHTML);
opponent.attack = xpathFirst('.//*[@id="' + SCRIPT.appID + '_fight_view_ac
tion_' + row + '"]/a', rowElt);
opponents.push(opponent);
}
}
if (!opponents.length) return;
DEBUG(opponents.length + ' opponents listed.');
//for (var i = 0; i < opponents.length; i++) {
// GM_log('Saw id=' + opponents[i].id +
// ', mafia=' + opponents[i].mafia +
// ', level=' + opponents[i].level +
// ', title=' + opponents[i].title +
// ', name=' + opponents[i].name);
//}
return opponents;
}
// Searches the fight table in the given element for new
// random targets. Returns a new opponent, or undefined.
function findNewFightOpponent(element) {
// Use fight semantics?
var fight = (GM_getValue('autoFight', '') == 'checked');
// Don't bother searching if we still have plenty.
var newOpponents = getSavedList('fightListNew');
var len = newOpponents.length;
if (len >= 50) {
return newOpponents[Math.floor(Math.random() * len)];
}
// Check the fight table.
var opponents = getDisplayedOpponents(element);
if (!opponents) {
// No opponents displayed on this page.
return newOpponents[Math.floor(Math.random() * len)];
}
// Get the user's level and mafia size settings.
var opponentMafiaMax = parseInt(GM_getValue('fightmafiaSize', 501));
var opponentMafiaMin = parseInt(GM_getValue('fightmafiaMinSize', 1));
var opponentLevelMax = parseInt(GM_getValue('fightLevel', 100));
// Make any relative adjustments (if enabled).
if (GM_getValue('fightLevelRelative', false)) {
opponentLevelMax = opponentLevelMax + level;
}
if (GM_getValue('fightMafiaRelative', false)) {
opponentMafiaMax = opponentMafiaMax + mafia;
}
if (GM_getValue('fightMafiaMinRelative', false)) {
opponentMafiaMin = mafia - opponentMafiaMin;
}
if (opponentMafiaMin > 501) {
opponentMafiaMin = 501;
}
// Make a blacklist of opponents.
var avoidList = getSavedList('fightListAvoid');
DEBUG('new=' + newOpponents);
DEBUG('avoid=' + avoidList);
var blacklist = newOpponents.concat(avoidList);
if (!fight) {
var robList = getSavedList('fightListRobbed');
blacklist = blacklist.concat(robList);
DEBUG('robbed=' + robList);
} else if (GM_getValue('fightStealth', '') == 'checked' ||
newOpponents.length) {
var activeList = getSavedList('fightListActive');
var inactiveList = getSavedList('fightListInactive');
blacklist = blacklist.concat(activeList, inactiveList);
DEBUG('inactive=' + inactiveList);
DEBUG('active=' + activeList);
}
// Figure out which opponents are acceptable.
DEBUG('Applying criteria to displayed opponents.');
var settingsCount = 0;
var blacklistCount = 0;
for (var i = 0; i < opponents.length; i++) {
var opponent = opponents[i];
if (opponent.level <= opponentLevelMax &&
opponent.mafia <= opponentMafiaMax &&
opponent.mafia >= opponentMafiaMin &&
notFamily(decodeHTMLEntities(opponent.name))) {
// This opponent is acceptable. Save the ID (if new).
if (opponent.id) {
var idString = opponent.id.toString();
if (blacklist.indexOf(idString) == -1) {
newOpponents.push(idString);
DEBUG('<span style="color:#BCD2EA;">'+'Found new opponent ' + opponent
.name + ' (' + idString + ').'+ '</span>');
} else {
blacklistCount++;
}
}
} else {
settingsCount++;
}
}
if (!newOpponents.length) {
// We looked over the fight table but still have no new opponents.
DEBUG(settingsCount + ' of ' + opponents.length +
' opponents failed min/max/name checks. ' +
blacklistCount + ' were blacklisted.');
return -1;
}
if (newOpponents.length > len) {
setSavedList('fightListNew', newOpponents);
}
return newOpponents[Math.floor(Math.random() * newOpponents.length)];
}
// Finds a fight opponent.
//
// Returns an opponent if one is found. Otherwise, nothing
// is returned and the fight page will soon be loaded.
function findFightOpponent() {
// To be stealthy, we try to only attack inactive opponents.
// If we have enough acceptable opponents, attack them randomly.
// If not, try any new opponents first and move them into the
// the appropriate list: active, inactive, or avoid.
// Check for any new opponents.
var opponent = findNewFightOpponent(innerPageElt);
// For stealth mode fights, if we don't have a new opponent then
// choose one of the inactive opponents we've already fought.
if ((!opponent || opponent == -1) &&
GM_getValue('autoFight', '') == 'checked' &&
GM_getValue('fightStealth', '') == 'checked') {
var opponentList = getSavedList('fightListInactive');
var len = opponentList.length;
if (len) {
opponent = opponentList[Math.floor(Math.random() * len)];
}
}
if (!opponent) {
// Go to the fight or rob page to find opponents.
if (GM_getValue('autoRob', '') == 'checked') {
addToLog('process Icon', '<span style="color:#BCD2EA;">'+ 'No opponents. G
oing to rob list.' + '</span>');
Autoplay.fx = loadRobTab;
Autoplay.start();
} else {
addToLog('process Icon', '<span style="color:#BCD2EA;">'+ 'No opponents. G
oing to fight list.' + '</span>');
Autoplay.fx = goFightNav;
Autoplay.start();
}
return;
}
return opponent;
}
function setFightOpponentActive(opponent) {
if (!opponent) return;
// Add the opponent to the active list.
DEBUG('Marking opponent ' + opponent + ' active.');
addSavedListItem('fightListActive', opponent, 10);
// Remove the opponent from the other fight lists.
while(removeSavedListItem('fightListInactive', opponent));
while(removeSavedListItem('fightListNew', opponent));
while(removeSavedListItem('fightListAvoid', opponent));
}
function setFightOpponentInactive(opponent) {
if (!opponent) return;
// Add the opponent to the inactive list.
DEBUG('Marking opponent ' + opponent + ' inactive.');
addSavedListItem('fightListInactive', opponent, 10);
// Remove the opponent from the other fight lists.
while(removeSavedListItem('fightListActive', opponent));
while(removeSavedListItem('fightListNew', opponent));
while(removeSavedListItem('fightListAvoid', opponent));
}
function setFightOpponentRobbed(opponent) {
if (!opponent) return;
// Add the opponent to the robbed list.
DEBUG('Marking opponent ' + opponent + ' robbed.');
addSavedListItem('fightListRobbed', opponent, 10);
// Remove the opponent from the other fight lists.
while(removeSavedListItem('fightListNew', opponent));
}
function setFightOpponentAvoid(opponent) {
if (!opponent) return;
// Add the opponent to the avoid list.
DEBUG('Marking opponent ' + opponent + ' avoid.');
addSavedListItem('fightListAvoid', opponent, 50);
// Remove the opponent from all other fight lists.
while(removeSavedListItem('fightListActive', opponent));
while(removeSavedListItem('fightListInactive', opponent));
while(removeSavedListItem('fightListNew', opponent));
// Only remove the first occurence from the user-supplied list.
removeSavedListItem('fightList', opponent);
}
function toggleSettings() {
if (settingsOpen === false) {
settingsOpen = true;
if(!document.getElementById('settingsBoxBg') && !document.getElementById('se
ttingsBox')) {
//setup menu
createMenu();
} else {
showSettingsBox();
}
// Stop any running timers so the settings box won't disappear.
Autoplay.clearTimeout();
Reload.clearTimeout();
} else {
settingsOpen = false;
if(document.getElementById('settingsBoxBg') && document.getElementById('sett
ingsBox')) {
hideSettingsBox();
}
Autoplay.delay = 150;
Autoplay.start();
autoReload();
}
}
function toggleStats() {
if (settingsOpen === true) {
toggleSettings;
}
if (statsOpen === false) {
statsOpen = true;
if(!document.getElementById('statsWindowBg') && !document.getElementById('st
atsWindow')) {
//setup menu
createStatWindow();
} else {
showStatsWindow();
}
// Stop any running timers so the settings box won't disappear.
Autoplay.clearTimeout();
Reload.clearTimeout();
} else {
statsOpen = false;
if(document.getElementById('statsWindowBg') && document.getElementById('stat
sWindow')) {
hideStatsWindow();
}
Autoplay.delay = 150;
Autoplay.start();
autoReload();
}
}
function showSettingsBox() {
var settingsBgDiv = document.getElementById('settingsBoxBg');
var settingsBoxContainer = document.getElementById('GenDialogPopDialog');
settingsBgDiv.style.display = 'block';
settingsBoxContainer.style.display = 'block';
}
function showMafiaLogBox() {
if(!document.getElementById('mafiaLogBox')) {
createLogBox();
} else {
var mafiaLogBoxDiv = document.getElementById('mafiaLogBox');
mafiaLogBoxDiv.style.display = 'block';
}
if(GM_getValue('autoLog', '') != 'checked' && GM_getValue('logOpen', 'closed')
!= 'open') {
alert('Logging is not enabled, to see anything here please go into\nthe Sett
ings, the General tab, and check Enable logging.');
}
GM_setValue('logOpen', 'open');
}
function showStatsWindow() {
var statsBgDiv = document.getElementById('statsWindowBg');
var statsWindowContainer = document.getElementById('sWindowGenDialogPopDialog'
);
statsBgDiv.style.display = 'block';
statsWindowContainer.style.display = 'block';
}
function hideSettingsBox() {
if(document.getElementById('settingsBoxBg')) {
var settingsBgDiv = document.getElementById('settingsBoxBg');
var settingsBoxContainer = document.getElementById('GenDialogPopDialog');
settingsBoxContainer.style.display = 'none';
settingsBgDiv.style.display = 'none';
}
}
function hideMafiaLogBox() {
var mafiaLogBoxDiv = document.getElementById('mafiaLogBox');
mafiaLogBoxDiv.style.display = 'none';
GM_setValue('logOpen', 'closed');
}
function hideStatsWindow() {
if(document.getElementById('statsWindowBg')) {
var statsBgDiv = document.getElementById('statsWindowBg');
var statsWindowContainer = document.getElementById('sWindowGenDialogPopDialo
g');
statsBgDiv.style.display = 'none';
statsWindowContainer.style.display = 'none';
}
}
function handleVersionChange() {
addToLog('updateGood Icon', 'Now running version ' + SCRIPT.version + ' build
' + SCRIPT.build);
GM_setValue('version', SCRIPT.version);
// Check for invalid settings and upgrade them.
// In an old version, the bonus had been up to 15%.
var val = GM_getValue('selectEnergyBonus');
if (val > 11) {
GM_setValue('selectEnergyBonus', 11);
}
// In an old version, there was no cap. But it definitely must be under 100,
// and it probably wouldn't work properly with more than 75.
var val = parseInt(GM_getValue('logPlayerUpdatesMax', '100'));
if (isNaN(val) || val > 75) {
GM_setValue('logPlayerUpdatesMax', '75');
}
}
function saveDefaultSettings() {
// Assume all settings have been cleared and set defaults.
// For groups of radio buttons, one must be checked and all others cleared.
// For checkboxes, no need to default if the option should be off.
// General tab.
GM_setValue('autoClick', 'checked');
GM_setValue('r1', '30');
GM_setValue('r2', '110');
GM_setValue('autoHeal', 'checked');
GM_setValue('healthLevel', '50');
GM_setValue('healLocationNY', 'checked');
GM_setValue('healLocationCuba', 0);
GM_setValue('bankConfig', '50000');
GM_setValue('bankConfigCuba', '50000');
GM_setValue('autoPauseBefore', 'checked');
GM_setValue('autoPauseAfter', 0);
GM_setValue('autoPauseExp', '50');
GM_setValue('autoLog', 'checked');
GM_setValue('autoLogLength', '300');
GM_setValue('logPlayerUpdates', 'checked');
GM_setValue('logPlayerUpdatesMax', '25');
GM_setValue('autoStat', 0);
GM_setValue('autoStatAttack', 0);
GM_setValue('autoStatDefense', 0);
GM_setValue('autoStatHealth', 0);
GM_setValue('autoStatEnergy', 'checked');
GM_setValue('autoStatStamina', 0);
GM_setValue('d1', '3');
GM_setValue('d2', '5');
// Energy tab.
GM_setValue('estimateJobRatio', '1');
// Fight/Rob tab.
GM_setValue('fightLocationNY', 'checked');
GM_setValue('fightLocationCuba', 0);
GM_setValue('fightRandom', 'checked');
GM_setValue('rFightList', 0);
GM_setValue('fightLevel', 100);
GM_setValue('fightmafiaSize', 501);
GM_setValue('fightmafiaMinSize', 1);
GM_setValue('fightStealth', 'checked');
GM_setValue('fightAvoidBodyguards', 'checked');
GM_setValue('fightRemoveStronger', 'checked');
GM_setValue('clanMember', 'checked');
GM_setValue('clanName', defaultClans.join('\n'));
GM_setValue('selectStaminaKeep', 10);
// Property tab.
GM_setValue('buyMinAmount', '0');
// Other settings.
GM_setValue('logOpen', 'open');
addToLog('process Icon', 'Options reset to defaults.');
}
function saveSettings() {
/*
//FIXME: works once then crashes... not good
// Transfer statLog to graphBox
if (typeof(GM_getValue('statLog') != 'undefined')) {
GM_setValue('graphBox',GM_getValue('statLog'));
GM_deleteValue('statLog');
}
*/
// Validate the settings and alert the user if the settings are invalid.
var logPlayerUpdates = (document.getElementById('logPlayerUpdates').checked ==
= true);
var logPlayerUpdatesMax = parseInt(document.getElementById('logPlayerUpdatesMa
x').value);
if (logPlayerUpdates && (isNaN(logPlayerUpdatesMax) || logPlayerUpdatesMax < 0
|| logPlayerUpdatesMax > 75)) {
alert('The maximum number of player updates must be between 0 and 75.');
return;
}
var autoBankOn = (document.getElementById('autoBank').checked === true);
var autoBankCubaOn = (document.getElementById('autoBankCuba').checked === tru
e);
var bankConfig = document.getElementById('bankConfig').value;
var bankConfigCuba = document.getElementById('bankConfigCuba').value;
var bankConfigInt = parseInt(bankConfig);
var bankConfigCubaInt = parseInt(bankConfigCuba);
if (autoBankOn && (isNaN(bankConfigInt) || bankConfigInt < 1)) {
alert('Minimum auto-bank amount must be 1 or higher.');
return;
}
if (autoBankCubaOn && (isNaN(bankConfigCubaInt) || bankConfigCubaInt < 1)) {
alert('Minimum Cuba auto-bank amount must be 1 or higher.');
return;
}
var autoFightOn = (document.getElementById('autoFight').checked === true);
var autoRobOn = (document.getElementById('autoRob').checked === true);
var autoFightRandom = (document.getElementById('fightRandom').checked === true
);
var fightLevelRelative = (document.getElementById('fightLevelRelative').checke
d === true);
var fightMafiaRelative = (document.getElementById('fightMafiaRelative').checke
d === true);
var fightMafiaMinRelative = (document.getElementById('fightMafiaMinRelative').
checked === true);
var fightLevel = parseInt(document.getElementById('fightLevel').value);
var fightMafia = parseInt(document.getElementById('fightmafiaSize').value);
var fightMafiaMin = parseInt(document.getElementById('fightmafiaMinSize').valu
e);
var estimateJobRatio = parseInt(document.getElementById('estimateJobRatio').va
lue);
var autoEnergyPackOn = (document.getElementById('autoEnergyPack').checked ===
true );
if ((autoFightOn || autoRobOn) && autoFightRandom) {
// Validate the fight level settings.
if (isNaN(fightLevel)) {
alert('Please enter a maximum fight level.');
return;
} else if (fightLevelRelative && (fightLevel < 0)) {
alert('Please enter a relative fight level of zero or more.');
return;
} else if (!fightLevelRelative && (fightLevel < level)) {
alert('Please enter a fight level of ' + level +
' (your current level) or more.');
return;
}
// Validate the fight mafia size settings.
if (isNaN(fightMafia)) {
alert('Please enter a maximum mafia size for fighting.');
return;
} else if (!fightMafiaRelative && (fightMafia < 1)) {
alert('Please enter a maximum mafia size of one or more for fighting.');
return;
} else if (fightMafiaRelative && (fightMafia + mafia < 1)) {
alert('Please enter a larger relative mafia size for fighting.');
return;
}
// Validate the fight mafia minimum size settings.
if (isNaN(fightMafiaMin)) {
alert('Please enter a minimum mafia size for fighting.');
return;
} else if (!fightMafiaMinRelative && (fightMafiaMin < 1)) {
alert('Please enter a minimum mafia size of one or more for fighting.');
return;
} else if (fightMafiaMinRelative && (mafia - fightMafiaMin < 1)) {
alert('Please enter a smaller relative mafia size for fighting.');
return;
}
}
// Validate the estimated job ratio setting.
if (autoEnergyPackOn) {
if (isNaN(estimateJobRatio)) {
alert('Please enter a number between 0 and 3 for your estimated job xp to
energy ratio');
return;
}
}
// Validate the auto-stat setting.
var autoStatOn = (document.getElementById('autoStat').checked === true);
var autoStatAttackOn = (document.getElementById('autoStatAttack').checked ===
true);
var autoStatDefenseOn = (document.getElementById('autoStatDefense').checked ==
= true);
var autoStatHealthOn = (document.getElementById('autoStatHealth').checked ===
true);
var autoStatEnergyOn = (document.getElementById('autoStatEnergy').checked ===
true);
var autoStatStaminaOn = (document.getElementById('autoStatStamina').checked ==
= true);
if (autoStatOn && !autoStatAttackOn && !autoStatDefenseOn &&
!autoStatHealthOn && !autoStatEnergyOn && !autoStatStaminaOn) {
alert('Please select a statistic to use with auto-stat.');
return;
}
//
// All settings are valid. Save them.
//
if (document.getElementById('autoClick').checked === true) {
GM_setValue('autoClick', 'checked');
} else {
GM_setValue('autoClick', 0);
}
if (document.getElementById('autoLog').checked === true) {
GM_setValue('autoLog', 'checked');
} else {
GM_setValue('autoLog', 0);
}
if (logPlayerUpdates) {
GM_setValue('logPlayerUpdates', 'checked');
} else {
GM_setValue('logPlayerUpdates', 0);
}
if (document.getElementById('hideAttacks').checked === true) {
GM_setValue('hideAttacks', 'checked');
} else {
GM_setValue('hideAttacks', 0);
}
if (document.getElementById('autoHitlist').checked === true) {
GM_setValue('autoHitlist', 'checked');
} else {
GM_setValue('autoHitlist', 0);
}
function updateLogStats() {
var fightCount = document.getElementById('fightCount');
if (!fightCount) return;
fightCount.firstChild.nodeValue = makeCommaValue(GM_getValue('fightWinCountI
nt', 0) + GM_getValue('fightLossCountInt', 0));
document.getElementById('fightWinCount').firstChild.nodeValue = makeCommaValue
(GM_getValue('fightWinCountInt', 0));
var fightWinPct = (GM_getValue('fightWinCountInt', 0)/(GM_getValue('fightWinCo
untInt', 0) + GM_getValue('fightLossCountInt', 0)) * 100).toFixed(1);
document.getElementById('fightWinPct').firstChild.nodeValue = (isNaN(fightW
inPct)) ? '0.0%' : fightWinPct + '%';
document.getElementById('fightLossCount').firstChild.nodeValue = makeCommaValu
e(GM_getValue('fightLossCountInt', 0));
var fightLossPct = (GM_getValue('fightLossCountInt', 0)/(GM_getValue('fightWin
CountInt', 0) + GM_getValue('fightLossCountInt', 0)) * 100).toFixed(1)
document.getElementById('fightLossPct').firstChild.nodeValue = (isNaN(fight
LossPct)) ? '0.0%' : fightLossPct + '%';
document.getElementById('robCount').firstChild.nodeValue = makeCommaValue(GM_g
etValue('robWinCountInt', 0) + GM_getValue('robLossCountInt', 0));
document.getElementById('robWinCount').firstChild.nodeValue = makeCommaValue(G
M_getValue('robWinCountInt', 0));
var robWinPct = (GM_getValue('robWinCountInt', 0)/(GM_getValue('robWinCountInt
', 0) + GM_getValue('robLossCountInt', 0)) * 100).toFixed(1);
document.getElementById('robWinPct').firstChild.nodeValue = (isNaN(robWinPc
t)) ? '0.0%' : robWinPct + '%';
document.getElementById('robLossCount').firstChild.nodeValue = makeCommaValue(
GM_getValue('robLossCountInt', 0));
var robLossPct = (GM_getValue('robLossCountInt', 0)/(GM_getValue('robWinCountI
nt', 0) + GM_getValue('robLossCountInt', 0)) * 100).toFixed(1);
document.getElementById('robLossPct').firstChild.nodeValue = (isNaN(robLoss
Pct)) ? '0.0%' : robLossPct + '%';
document.getElementById('totalWinDollars').firstChild.nodeValue = '$' + makeCo
mmaValue(GM_getValue('totalWinDollarsInt', 0)); //Accomodates up to $999,999,99
9,999
document.getElementById('totalLossDollars').firstChild.nodeValue = '$' + makeC
ommaValue(GM_getValue('totalLossDollarsInt', 0));
document.getElementById('totalExp').firstChild.nodeValue = makeCommaValue(GM_g
etValue('totalExpInt', 0));
var rate = getStaminaGainRate();
document.getElementById('expRate').firstChild.nodeValue = rate.toFixed(2);
document.getElementById('expToNext').firstChild.nodeValue = makeCommaValue(pts
ToNextLevel);
document.getElementById('stamToNext').firstChild.nodeValue = rate? (ptsToNextL
evel / rate).toFixed(0): 'n/a';
}
function debugOnOff() {
if (GM_getValue('enableDebug') == 'checked') {
GM_setValue('enableDebug', 0);
debug = false;
addToLog('info Icon', 'Debug logging disabled.');
GM_setValue('debugSettingsDump', 'false');
GM_setValue('autoLog', GM_getValue('priorLogSetting'));
} else {
GM_setValue('enableDebug', 'checked');
debug = true;
GM_setValue('priorLogSetting', GM_getValue('autoLog'));
GM_setValue('autoLog', 'checked');
addToLog('info Icon', 'Debug logging enabled.');
if (GM_getValue('debugSettingsDump') != 'true') {
debugDumpSettings();
GM_setValue('debugSettingsDump', 'true');
}
}
location.reload();
}
function DEBUG(line, level) {
var level = (level == null) ? 0 : level;
if (debug) {
addToLog('info Icon', line);
GM_log(line, level);
}
}
function makeCommaValue(nStr) {
nStr += '';
x = nStr.split('.');
x1 = x[0];
var rgx = /(\d+)(\d{3})/;
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + ',' + '$2');
}
return x1;
}
function showIfUnchecked(setting) {
if (setting == '0') {
setting = 'un-checked';
}
return setting;
}
function showIfSelected(setting) {
if (setting == '0') {
setting = 'not selected';
} else {
setting = 'selected';
}
return setting;
}
// Save an array of strings. The strings must not contain "\n".
function setSavedList(listName, list) {
GM_setValue(listName, list.join('\n'));
}
// Get an array of strings that was saved with setSavedList().
function getSavedList(listName) {
var savedList = GM_getValue(listName, '');
return savedList? savedList.split('\n') : [];
}
// Add an item to a list saved with setSavedList().
// If the size of the list is greater than the "max"
// parameter, the first item in the list is removed.
function addSavedListItem(listName, item, max) {
var savedList = getSavedList(listName);
// Only add if it isn't already there.
if (savedList.indexOf(item) != -1) {
return;
}
savedList.push(item);
if (max > 0) {
while (max < savedList.length) {
var item = savedList.shift();
DEBUG('Removing ' + item + ' from ' + listName + '.');
}
}
setSavedList(listName, savedList);
}
// Remove an item from a list saved with setSavedList().
function removeSavedListItem(listName, item) {
var savedList = getSavedList(listName);
var idx = savedList.indexOf(item);
if (idx != -1) {
savedList.splice(idx, 1);
setSavedList(listName, savedList);
return true;
}
// No matches.
return false;
}
function CycleFightList() {
// Move the first opponent to the end of the list.
var opponents = GM_getValue('fightList', '').split('\n');
var first = opponents.shift();
if (first) {
opponents.push(first);
}
GM_setValue('fightList', opponents.join('\n'));
}
function CyclePropertyList() {
DEBUG('CyclePropertyList(): '+ GM_getValue('propertyId', ''));
if (GM_getValue('propertyId') <= 6) {
CycleRobList();
var i = 12; //back to casinos
} else {
var i = GM_getValue('propertyId') - 1;
}
GM_setValue('propertyId', i);
}
function clearLog() {
GM_setValue('itemLog', '');
//reset the log box
var logBox = document.getElementById('logBox');
logBox.innerHTML = '';
}
function clearStats() {
//reset log statistics
GM_setValue('fightWinCountInt', 0);
GM_setValue('fightLossCountInt', 0);
GM_setValue('robWinCountInt', 0);
GM_setValue('robLossCountInt', 0);
GM_setValue('totalExpInt', 0);
GM_setValue('totalWinDollarsInt', 0);
GM_setValue('totalLossDollarsInt', 0);
GM_setValue('lastHitXp', 0);
GM_setValue('totalHits', 0);
GM_setValue('totalXp', 0);
GM_setValue('currentHitXp',0);
//ATK
//New tracking stats for NY
GM_setValue('hourlyStats', '0');
GM_setValue('fightExpNY',0); //Number of exper. points earned from fig
hts in NY
GM_setValue('fightWinsNY',0); //Count of fights won in NY
GM_setValue('fightWin$NY',0); //$ won from fights in NY
GM_setValue('fightLossesNY',0); //Count of fights lost in NY
GM_setValue('fightLoss$NY',0); //$ lost from fights in NY
GM_setValue('fightLossBGCHNY',0); //Bodyguard Critical Hit loss type count
from NY fights
GM_setValue('fightLossBGCH$NY',0); //$ lost from Bodyguard Critical Hit in
NY fights
GM_setValue('fightLossCHNY', 0); //Critical Hit loss type count from NY fi
ghts
GM_setValue('fightLossCH$NY', 0); //$ lost from Critical Hit in NY fights
GM_setValue('fightLossStrongNY', 0); //Too Strong loss type count from NY figh
ts
GM_setValue('fightLossStrong$NY', 0); //$ lost from Too Strong in NY fights
//New tracking stats for Cuba
GM_setValue('fightExpCuba',0); //Number of exper. points earned from f
ights in Cuba
GM_setValue('fightWinsCuba',0); //Count of fights won in Cuba
GM_setValue('fightWin$Cuba',0); //Cuban pesos won from fights
GM_setValue('fightLossesCuba',0); //Count of fights lost in Cuba
GM_setValue('fightLoss$Cuba',0); //Cuban pesos lost from fights
GM_setValue('fightLossBGCHCuba',0); //Bodyguard Critical Hit loss type coun
t from Cuba fights
GM_setValue('fightLossBGCH$Cuba',0); //$ lost from Bodyguard Critical Hit i
n Cuba fights
GM_setValue('fightLossCHCuba', 0); //Critical Hit loss type count from Cub
a fights
GM_setValue('fightLossCH$Cuba', 0); //$ lost from Critical Hit in Cuba fig
hts
GM_setValue('fightLossStrongCuba', 0); //Too Strong loss type count from Cuba
fights
GM_setValue('fightLossStrong$Cuba', 0); //$ lost from Too Strong in Cuba fight
s
updateLogStats();
}
function clearHitlistArray () {
GM_setValue('onHitlist', 0);
}
function clearHitStats () {
GM_setValue('lastHitXp', 0);
GM_setValue('totalHits', 0);
GM_setValue('totalXp', 0);
GM_setValue('currentHitXp',0);
}
function minBankCheck() {
// Don't allow zero value in autobank setting.
var amount = parseInt(document.getElementById('bankConfig').value);
if (isNaN(amount) || amount < 1) {
alert('Minimum auto-bank amount must be 1 or higher');
document.getElementById('bankConfig').focus();
}
var amountCuba = parseInt(document.getElementById('bankConfigCuba').value);
if (isNaN(amountCuba) || amountCuba < 1) {
alert('Minimum Cuba auto-bank amount must be 1 or higher');
document.getElementById('bankConfigCuba').focus();
}
}
function takeAction(link, action, context) {
if (!link) {
addToLog('warning Icon','BUG DETECTED: No link passed to takeAction().');
return;
}
DEBUG('Action set to: ' + action);
GM_xmlhttpRequest({ method: 'GET',
url: link,
headers:{'Content-type':'application/x-www-form-urlencoded'},
onload: function(responseDetails) { handleResponse(responseDetails, action,
context); },
onerror: function(responseDetails) { addToLog('warning Icon', 'error status
'+ responseDetails.status); }
});
}
function withdrawFromBank(withdrawcash) {
if (document.body.innerHTML.indexOf('title">The Bank') != -1) {
GM_setValue('withdrawcash', withdrawcash);
bankClickWithdraw();
} else {
Autoplay.fx = goBank;
Autoplay.delay = getAutoPlayDelay();
Autoplay.start();
DEBUG('Entering the bank.');
}
}
function bankClickWithdraw() {
DEBUG('Withdrawing: '+GM_getValue('withdrawcash'));
var sform = xpathFirst('//input[@value=\'Withdraw\' and @type=\'submit\']');
if(!sform) {
DEBUG('sform null');
window.setTimeout(bankClickWithdraw,1000);
} else {
DEBUG('Setting amount to take out.');
xpathFirst('//form[@id=\''+SCRIPT.appID+'_bank_withdraw\']/table/tbody/tr/td
/input[@name=\'amount\']').value = GM_getValue('withdrawcash');
sform.click();
bankWithdrawCheck();
}
}
function bankWithdrawCheck() {
if (!xpathFirst('//td[@class=\'message_body\' and contains(text(),\'You withdr
ew\')]')) {
window.setTimeout(bankWithdrawCheck,1000);
} else {
addToLog('process Icon', '<span style="color:#885588;">Withdrew <span class=
"money">$'+makeCommaValue(GM_getValue('withdrawcash'))+'</span> from the bank.</
span>');
Autoplay.delay = getAutoPlayDelay();
Autoplay.start();
}
}
function createLogBox() {
// Define CSS styles.
makeElement('style', document.getElementsByTagName('head')[0], {'type':'text/c
ss'}).appendChild(document.createTextNode(
'#mafiaLogBox div.mouseunderline:hover{text-decoration:underline}' +
'#mafiaLogBox .logEvent{border-bottom:1px solid #333; padding:4px 0px}' +
'#mafiaLogBox .eventTime{color:#888; font-size: 11px; width:75px; float:lef
t}' +
'#mafiaLogBox .eventBody{width:315px; float:right}' +
'#mafiaLogBox .eventTime,#mafiaLogBox .eventIcon,#mafiaLogBox .eventBody{}'
+
'#mafiaLogBox .eventBody .money {color:#52E259;font-weight:bold;}' +
'#mafiaLogBox .eventBody .experience {color:#52E259;font-weight:bold;}' +
'#mafiaLogBox .eventBody .user {color:#FFD927;}' +
'#mafiaLogBox .eventBody .attacker {color:#EC2D2D;}' +
'#mafiaLogBox .eventBody .job {color:#52E259;font-weight:bold;}' +
'#mafiaLogBox .clear{clear:both}' +
'#mafiaLogBox .logEvent.Icon{background-repeat: no-repeat; background-positi
on: 75px}' +
'#mafiaLogBox .logEvent.process.Icon{background-image:url(' + stripURI(proce
ssIcon) + ')}' +
'#mafiaLogBox .logEvent.search.Icon{background-image:url(' + stripURI(search
Icon) + ')}' +
'#mafiaLogBox .logEvent.warning.Icon{background-image:url(' + stripURI(warni
ngIcon) + ')}' +
'#mafiaLogBox .logEvent.info.Icon{background-image:url(' + stripURI(infoIcon
) + ')}' +
'#mafiaLogBox .logEvent.lootbag.Icon{background-image:url(' + stripURI(lootb
agIcon) + ')}' +
'#mafiaLogBox .logEvent.found.Icon{background-image:url(' + stripURI(lootbag
Icon) + ')}' +
'#mafiaLogBox .logEvent.updateGood.Icon{background-image:url(' + stripURI(up
dateGoodIcon) + ')}' +
'#mafiaLogBox .logEvent.updateBad.Icon{background-image:url(' + stripURI(upd
ateBadIcon) + ')}' +
'#mafiaLogBox .logEvent.pause.Icon{background-image:url(' + stripURI(pauseIc
on) + ')}' +
'#mafiaLogBox .logEvent.play.Icon{background-image:url(' + stripURI(playIcon
) + ')}' +
'#mafiaLogBox .logEvent.good.Icon{background-image:url(' + stripURI(goodIcon
) + ')}' +
'#mafiaLogBox .logEvent.bad.Icon{background-image:url(' + stripURI(badIcon)
+ ')}' +
'#mafiaLogBox .logEvent.experience.Icon{background-image:url(' + stripURI(ex
perienceIcon) + ')}' +
'#mafiaLogBox .logEvent.experience.Icon{background-image:url(' + stripURI(ex
perienceIcon) + ')}' +
'#mafiaLogBox .logEvent.health.Icon{background-image:url(' + stripURI(health
Icon) + ')}' +
'#mafiaLogBox .logEvent.cash.Icon{background-image:url(' + stripURI(cashIcon
) + ')}' +
'#mafiaLogBox .logEvent.cashCuba.Icon{background-image:url(' + stripURI(cash
CubaIcon) + ')}' +
'#mafiaLogBox .logEvent.energyPack.Icon{background-image:url(' + stripURI(en
ergyPackIcon) + ')}'
));
DEBUG('Menu created.');
}
function createFightRobTab() {
var elt, title, id, label;
var eltStack = [];
var fightRobTab = makeElement('div', null, {'id':'fightRobTab', 'class':'tabco
ntent'});
//
// First column of options.
//
elt = makeElement('div', fightRobTab,
{'style':'position: relative; top: 10px; margin-right: 20px;
width: 300px; line-height:150%; float: left'});
title = 'Fight opponents automatically.';
id = 'autoFight';
var autoFightCheckbox = makeElement('input', elt, {'type':'checkbox', 'id':id,
'title':title, 'style':'vertical-align:middle', 'value':'checked'}, 'autoFight'
);
label = makeElement('label', elt, {'for':id, 'title':title});
label.appendChild(document.createTextNode('Enable auto-fight'));
autoFightCheckbox.addEventListener('click', clickFight, false);
title = 'Rob opponents automatically.';
id = 'autoRob';
var autoRobCheckbox = makeElement('input', elt, {'type':'checkbox', 'id':id, '
title':title, 'style':'vertical-align:middle', 'value':'checked'}, 'autoRob');
label = makeElement('label', elt, {'for':id, 'title':title});
label.appendChild(document.createTextNode('Enable auto-rob'));
autoRobCheckbox.addEventListener('click', clickRob, false);
// Begin fight options
eltStack.push(elt);
// Select location
elt = makeElement('div', elt, {'style':'position: static; margin-left: 21px'})
;
elt.appendChild(document.createTextNode('Fight in: '));
title = 'New York';
id = 'fightLocationNY';
label = makeElement('label', elt, {'for':id, 'title':title});
makeElement('input', label, {'type':'radio', 'name':'r5', 'id':id, 'title':tit
le, 'style':'vertical-align:top', 'value':'checked'}, 'fightLocationNY');
label.appendChild(document.createTextNode(title));
title = 'Cuba';
id = 'fightLocationCuba';
label = makeElement('label', elt, {'for':id, 'title':title});
makeElement('input', label, {'type':'radio', 'name':'r5', 'id':id, 'title':tit
le, 'style':'vertical-align:top', 'value':'checked'}, 'fightLocationCuba');
label.appendChild(document.createTextNode(title));
makeElement('br', elt);
title = 'Pick opponents from the random lists supplied by Mafia Wars.';
id = 'fightRandom';
label = makeElement('label', elt, {'for':id, 'title':title});
makeElement('input', label, {'type':'radio', 'name':'r1', 'id':id, 'title':tit
le, 'style':'vertical-align:top', 'value':'checked'}, 'fightRandom', 'checked');
label.appendChild(document.createTextNode('Fight/Rob random mafia'));
// Begin options specific to random mafia
eltStack.push(elt);
elt = makeElement('div', elt, {'style':'position: static; margin-left: 22px'})
;
title = 'Avoid opponents higher than this level.';
id = 'fightLevel';
label = makeElement('label', elt, {'for':id, 'title':title, 'style':'width: 9e
m; float: left; margin-right: 0.5em; display: block'});
label.appendChild(document.createTextNode('Maximum level:'));
makeElement('input', elt, {'type':'text', 'id':id, 'title':title, 'style':'wid
th: 30px; border: 1px solid #781351', 'value':GM_getValue('fightLevel', '100'),
'size':'1'});
title = 'Make the maximum level be relative to your own. For example, if your
level is 10, and maximum level is set to 5, opponents higher than level 15 will
be avoided.';
id = 'fightLevelRelative';
makeElement('input', elt, {'type':'checkbox', 'id':id, 'title':title, 'style':
'vertical-align: middle', 'value':'checked'}, 'fightLevelRelative');
label = makeElement('label', elt, {'for':id, 'title':title});
label.appendChild(document.createTextNode('Relative'));
makeElement('br', elt);
id = 'fightmafiaSize';
title = 'Avoid opponents with mafia sizes larger than this.',
label = makeElement('label', elt, {'for':id, 'title':title, 'style':'width: 9e
m; float: left; margin-right: 0.5em; display: block'});
label.appendChild(document.createTextNode('Maximum mafia:'));
makeElement('input', elt, {'type':'text', 'id':id, 'title':title, 'style':'wid
th: 30px; border: 1px solid #781351', 'value':GM_getValue('fightmafiaSize', '501
'), 'size':'1'});
title = 'Make the maximum mafia size be relative to your own. For example, if
you have 300 mafia members, and maximum mafia is set to 50, opponents with more
than 350 mafia members will be avoided.';
id = 'fightMafiaRelative';
makeElement('input', elt, {'type':'checkbox', 'id':id, 'title':title, 'style':
'vertical-align: middle', 'value':'checked'}, 'fightMafiaRelative');
label = makeElement('label', elt, {'for':id, 'title':title});
label.appendChild(document.createTextNode('Relative'));
makeElement('br', elt);
id = 'fightmafiaMinSize';
title = 'Avoid opponents with mafia sizes smaller than this.',
label = makeElement('label', elt, {'for':id, 'title':title, 'style':'width: 9e
m; float: left; margin-right: 0.5em; display: block'});
label.appendChild(document.createTextNode('Minimum mafia:'));
makeElement('input', elt, {'type':'text', 'id':id, 'title':title, 'style':'wid
th: 30px; border: 1px solid #781351', 'value':GM_getValue('fightmafiaMinSize', '
1'), 'size':'1'});
title = 'Make the minimum mafia size be relative to your own. For example, if
you have 300 mafia members, and minimum mafia is set to 50, opponents with less
than 250 mafia members will be avoided.';
id = 'fightMafiaMinRelative';
makeElement('input', elt, {'type':'checkbox', 'id':id, 'title':title, 'style':
'vertical-align: middle', 'value':'checked'}, 'fightMafiaMinRelative');
label = makeElement('label', elt, {'for':id, 'title':title});
label.appendChild(document.createTextNode('Relative'));
makeElement('br', elt);
title = 'Prefer opponents who won\'t be notified of your attacks.';
id = 'fightStealth';
makeElement('input', elt, {'type':'checkbox', 'id':id, 'title':title, 'style':
'vertical-align:middle', 'value':'checked'}, 'fightStealth', 'checked');
label = makeElement('label', elt, {'for':id, 'title':title});
label.appendChild(document.createTextNode('Use fight stealth'));
makeElement('br', elt);
title = 'Avoid opponents known to be Top Mafia bodyguards. This may ' +
'decrease the frequency of losses due to critical hits.';
id = 'fightAvoidBodyguards';
makeElement('input', elt, {'type':'checkbox', 'id':id, 'title':title, 'style':
'vertical-align:middle', 'value':'checked'}, 'fightAvoidBodyguards', 'checked');
label = makeElement('label', elt, {'for':id, 'title':title});
label.appendChild(document.createTextNode('Avoid Top Mafia bodyguards'));
// Finish options specific to random mafia
elt = eltStack.pop();
title = 'Use a custom list of opponents. Enter each opponent\'s ID' +
' (not their name) on a separate line.';
id = 'rFightList';
label = makeElement('label', elt, {'for':id, 'title':title});
makeElement('input', label, {'type':'radio', 'name':'r1', 'id':id, 'title':tit
le, 'style':'vertical-align:top', 'value':'checked'}, 'rFightList');
label.appendChild(document.createTextNode('Fight/Rob list'));
// Begin options specific to opponent list
eltStack.push(elt);
elt = makeElement('div', elt, {'style':'position: static; margin-left: 22px'})
;
makeElement('textarea', elt, {'style':'position: static; width: 180px; height:
105px;', 'id':'fightList', 'title':'Enter each opponent\'s ID (not their name)
on a separate line.'}).appendChild(document.createTextNode(GM_getValue('fightLis
t', '')));
makeElement('br', elt);
title = 'Remove stronger opponents from the list automatically.';
id = 'fightRemoveStronger';
makeElement('input', elt, {'type':'checkbox', 'id':id, 'title':title, 'style':
'vertical-align:middle', 'value':'checked'}, 'fightRemoveStronger', 'checked');
label = makeElement('label', elt, {'for':id, 'title':title});
label.appendChild(document.createTextNode('Remove stronger opponents'));
// Finish options specific to opponent list
elt = eltStack.pop();
// End of radio buttons
makeElement('br', elt);
elt = eltStack.pop();
//Stamina preservation options
title = 'Suspend automatic play below this level of stamina.';
id = 'selectStaminaKeep';
label = makeElement('label', elt, {'for':id, 'title':title, 'style':'width: 17
em; float: left; margin-left: 6px; margin-right: 0.5em; display: block'});
label.appendChild(document.createTextNode('% Stamina to keep on hand (±1)'));
var selectStaminaKeep = makeElement('select', elt, {'id':id, 'title':title});
for (i=100;i>-1;i=i-10) {
var choice = document.createElement('option');
choice.value = i;
choice.appendChild(document.createTextNode(i));
selectStaminaKeep.appendChild(choice);
}
if (GM_getValue('selectStaminaKeep', 'NotSet') == 'NotSet' || GM_getValue('sel
ectStaminaKeep', 0) > selectStaminaKeep.length - 1) {
GM_setValue('selectStaminaKeep', selectStaminaKeep.length - 1);
}
selectStaminaKeep.selectedIndex = GM_getValue('selectStaminaKeep', 0);
makeElement('br', elt);
title = 'Ignore minimum stamina settings if a level up is within reach.';
id = 'allowStaminaToLevelUp';
makeElement('input', elt, {'type':'checkbox', 'id':id, 'title':title, 'style':
'vertical-align: middle', 'value':'checked'}, 'allowStaminaToLevelUp');
label = makeElement('label', elt, {'for':id, 'title':title});
label.appendChild(document.createTextNode('Use all stamina to level up'));
//
// Second column of options.
//
elt = makeElement('div', fightRobTab, {'style':'position: relative; float: lef
t; top: 159px;'});
// Clan names.
title = 'Avoid random opponents whose names contain specific patterns.';
id = 'clanMember';
makeElement('input', elt, {'type':'checkbox', 'id':id, 'title':title, 'style':
'vertical-align:middle', 'value':'checked'}, 'clanMember', 0);
label = makeElement('label', elt, {'for':id, 'title':title});
label.appendChild(document.createTextNode('Avoid mafia families '));
makeElement('img', label, {'src':stripURI(mafiaHatIcon)});
makeElement('br', elt);
eltStack.push(elt);
elt = makeElement('div', elt, {'style':'position: static; margin-left: 22px'})
;
makeElement('textarea', elt, {'style':'position: static; width: 180px; height:
105px;', 'id':'clanName', 'title':'Enter each pattern (such as a clan name) on
a separate line.'}).appendChild(document.createTextNode(GM_getValue('clanName',
defaultClans.join('\n'))));;
makeElement('br', elt);
elt = eltStack.pop();
return fightRobTab;
}
function createHitlistTab() {
var elt, title, id, label;
var eltStack = [];
var hitlistTab = makeElement('div', null, {'id':'hitlistTab', 'class':'tabcont
ent'});
//
// First column of options.
//
elt = makeElement('div', hitlistTab,
{'style':'top: 25px; text-decoration: line-through;'});
title = 'Keep Players on Hitlist.';
id = 'autoHitlist';
var autoHitlistCheckbox = makeElement('input', elt, {'type':'checkbox', 'id':i
d, 'title':title, 'style':'vertical-align:middle', 'value':'checked'}, 'autoHitl
ist');
label = makeElement('label', elt, {'for':id, 'title':title});
label.appendChild(document.createTextNode('Enable auto-hitlist '));
elt = makeElement('div', elt, {'style':'position: static; margin-left: 13px'})
;
title = 'Use a custom list of opponents. Enter each opponent\'s ID' +
' (not their name) on a separate line.';
id = 'toHitlist';
makeElement('textarea', elt, {'style':'position: static; width: 180px; height:
105px;', 'id':id, 'title':title}).appendChild(document.createTextNode(GM_getVal
ue(id, '')));
elt = makeElement('div', hitlistTab,
{'style':'top: 175px;'});
title = 'Only Show Summary of Attacks.';
id = 'hideAttacks';
var hideAttacksCheckbox = makeElement('input', elt, {'type':'checkbox', 'id':i
d, 'title':title, 'value':'checked'}, 'hideAttacks');
label = makeElement('label', elt, {'for':id, 'title':title});
label.appendChild(document.createTextNode('Summarize Attacks From Player Updat
es '));
//second column of Hitlist Tab
elt = makeElement('div', hitlistTab, {'style':'top: 25px; right: 10px; text-de
coration: line-through;'});
title = 'This will be the bounty amount for all auto-hitlists.';
id = 'bountyAmount';
label = makeElement('label', elt, {'for':id, 'title':title});
label.appendChild(document.createTextNode('Bounty Amount: '));
var bountyAmountCheckbox = makeElement('input', elt, {'type':'text', 'style':'
width: 80px;', 'title':title, 'value':GM_getValue(id, '10000'), 'id':id, 'size':
'1'});
makeElement('br', elt);
elt = makeElement('div', elt, {'style':'position: static; margin-right: 10px'}
);
title = 'Players currently on hitlist';
id = 'onHitlist';
makeElement('textarea', elt, {'style':'position: static; width: 180px; height:
105px;', 'id':id, 'title':title}).appendChild(document.createTextNode(GM_getVal
ue(id, '')));
title = 'Press this button to clear all the names and return them to the auto-
hitlist array.';
id = 'clrHitlistArray';
var clearHitlistButton = makeElement('span', elt, {'class':'sexy_button', 'tit
le':title});
makeElement('button', clearHitlistButton).appendChild(document.createTextNode(
'Clear Players'));
clearHitlistButton.addEventListener('click', clearHitlistArray, false);
return hitlistTab;
}
function makeElement(type, appendto, attributes, checked, chkdefault) {
var element = document.createElement(type);
if (attributes != null) {
for (var i in attributes) {
element.setAttribute(i, attributes[i]);
}
}
if (checked != null) {
if (GM_getValue(checked, chkdefault) == 'checked') {
element.setAttribute('checked', 'checked');
}
}
if (appendto) {
appendto.appendChild(element);
}
return element;
}
function stripURI(img) {
img = img.split('"')[1];
return img.replace('" />', '');
}
function createStatWindow() {
if(settingsOpen === true) {
toggleSettings()
};
makeElement('style', document.getElementsByTagName('head')[0], {'type':'text/c
ss'}).appendChild(document.createTextNode(
'#statsWindow #sWindowTabNav div{border-right:1px solid #000;float:left;padd
ing:0 7px;position:static;text-align:center}' +
'#statsWindow #sWindowTabNav div.selected{background-image:url(' + stripURI(
tabSelectedImage) + ')}' +
'#statsWindow #sWindowTabNav div a{color:#fff;font-weight:700}' +
'#statsWindow .sexy_button{position:absolute;background-image:url(' + stripU
RI(redBgImage) + ');border:1px solid #FFD927;color:#FFD927;cursor:pointer;displa
y:block;float:left;font-size:14px;font-weight:700;padding:5px;text-decoration:no
ne;width:auto}' +
'#statsWindow .sexy_button button{background:transparent;border:medium none
#FFF;color:#FFD927;cursor:pointer;font-size:14px;font-weight:700;margin:0}' +
'#statsWindow .sexy_button button:hover{color:#BCD2EA;font-weight:700;text-d
ecoration:none}' +
'#statsWindow .tabcontent{display:none;height:475px;top:110px;width:600px}'
+
'#statsWindow div,#statsWindow select,#statsWindow textarea{position:absolut
e}' +
'#statsWindow label {font-weight: normal; color: #BCD2EA}'
));
// trying to make stats window appear like popup in MW
// This will fade the background when the settings box is up, just like facebo
ok popups
makeElement('div', document.body, {'style':'height: 100%; position: fixed; dis
play:block; left:0; top:0; width:100%; z-index:100;', 'class':'dark_dialog_overl
ay', 'id':'statsWindowBg'});
// This creates the settings box just like a facebook popup
var sWindowGenDialogPopDialog = makeElement('div', document.body, {'class':'ge
neric_dialog pop_dialog', 'id':'sWindowGenDialogPopDialog'});
var sWindowGenDialogPopup = makeElement('div', sWindowGenDialogPopDialog, {'
class':'generic_dialog_popup', 'style':'top: 40px;'});
var sWindowPopDialogTable = makeElement('table', sWindowGenDialogPopup, {'
class':'pop_dialog_table', 'id':'sWindowpop_dialog_table', 'style':'width: 620px
;'});
var sWindowTableTR = makeElement('tr', sWindowPopDialogTable);
makeElement('td', sWindowTableTR, {'class':'pop_topleft'});
makeElement('td', sWindowTableTR, {'class':'pop_border pop_top'});
makeElement('td', sWindowTableTR, {'class':'pop_topright'});
var sWindowTableTR2 = makeElement('tr', sWindowPopDialogTable);
makeElement('td', sWindowTableTR2, {'class':'pop_border pop_side'});
var sWindowTDPopContent = makeElement('td', sWindowTableTR2, {'class':
'pop_content', 'id':'sWindowTDPop_content'});
// This creates the settings container
var statsWindow = makeElement('div', sWindowTDPopContent, {'style':'
position: relative; width: 600px; height: 580px; font-size: 14px; color: #BCD2EA
; background: black no-repeat scroll 0 110px', 'id':'statsWindow'});
makeElement('td', sWindowTableTR2, {'class':'pop_border pop_side'});
var sWindowTableTR3 = makeElement('tr', sWindowPopDialogTable, {'id':'SW
indowTablePop_tr3'});
makeElement('td', sWindowTableTR3, {'class':'pop_bottomleft'});
makeElement('td', sWindowTableTR3, {'class':'pop_border pop_bottom'});
makeElement('td', sWindowTableTR3, {'class':'pop_bottomright'});
//End settings box
var statsWindowTopBG = makeElement('div', statsWindow, {'style':'background: b
lack;; position: static; height: 80px;'});
var statsWindowTitle = makeElement('div', statsWindowTopBG, {'style':'font-s
ize: 18px; font-weight: bold;'});
statsWindowTitle.appendChild(document.createTextNode('Facebook Mafia Wars
Autoplayer'));
makeElement('br', statsWindowTitle);
statsWindowTitle.appendChild(document.createTextNode('Player Stats '));
makeElement('br', statsWindowTitle);
makeElement('img', statsWindowTopBG, {'src':stripURI(mwLogoSmall), 'style':'
position: absolute; top: 0px; right: 25px;'});
makeElement('img', statsWindowTopBG, {'src':stripURI(closeButtonIcon), 'styl
e':'position: absolute; top: 0px; right: 0px; cursor: pointer;'}).addEventListen
er('click', toggleStats, false);