evofr+
By Toukan31
—
Last update Jul 26, 2006
—
Installed
182 times.
Add Syntax Highlighting (this will take a few seconds, probably freezing your browser while it works)
// ==UserScript==
// @name evofr+
// @version 2.4.0
// @namespace http://wildservices.net/userscripts
// @description Enchances evo game :-)
// @include http://ev5.neondragon.net/*
// @include http://evo-dev.neondragon.net/*
// @author ~ravenlord~ (r4v3n10rd@gmail.com) - original 1.0x source
// @author HETMAN (kanarinios@gmail.com) - upgrades
// @author mindfox & Fire - upgrades
// @author MadFrog (mbfrog@gmail.com)
// @author Roland
// @author WhyteWolf (whytewolf1@gmail.com)
// @author Gavry
// @author Ressol
// @author Toukan
// ==/UserScript==
/*
* evofr+
* 2006/07/28 Updated for french interface by Toukan
*
* $Id: evoplus.user.js,v 1.19 2006/07/24 09:51:22 pinky Exp $
*
* $Log: evoplus.user.js,v $
* Revision 1.20 2006/07/24 09:51:22 pinky
* Make it work with the new layout
* Scan Amp:Land ratio on scans page
* Max land possible to allocate on resources page
* Highlighting added to new alliances system
* Highlighting on rankings
* Notepad feature (c/o Gavry)
*
* Revision 1.19 2006/07/01 20:55:50 madfrog
* Added a quick "add to buddies" link to the alliance members pages
*
* Revision 1.18 2006/06/29 18:26:41 madfrog
* Updated dEvo stats
* The allocated % on the Sector Scan was not taking the food into account
* Optimized parsing on the Sector Scan
*
* Revision 1.17 2006/06/22 23:57:46 madfrog
* Saving the Efficient Breeding Center coefficient as float was breaking GM
* Removed an unused configuration item (for the scan page)
*
* Revision 1.16 2006/06/22 23:14:53 madfrog
* Implemented changes from Ressol:
* Sector Scan: Max/min attacker score in scan result.
* Sector Scan: Allocated land ratio and estimated land defense.
* Sector Scan: Number formatting / fields colorful.
* Creature Scan: Estimated creatures launch cost.
* Battle Report: Add land loss ratio in defense side.
* Alliances Page: Add average member score
*
* Revision 1.15 2006/06/22 19:59:32 madfrog
* Enabled the use of plugin scripts
* Efficient Breeding Center setting is now saved in a GM_Variable (useful?)
* Fixed a typo (Archological path)
* Moved all utility functions at the bottom
*
* Revision 1.14 2006/06/21 22:39:17 madfrog
* Fixed a problem with Efficient Breeding Center on the create page
*
* Revision 1.13 2006/03/17 17:12:38 madfrog
* Fixed a problem with the land ratio calculator that caused an infinite loop
*
* Revision 1.12 2006/03/09 22:00:36 madfrog
* removed a [NOD] tag from the script name :P
*
* Revision 1.11 2006/03/09 11:47:02 madfrog
* added automatic handling ot the evo-dev.neondragon.net URL
* forgot to credit Hemna for the evo-dev critter stats
*
* Revision 1.10 2006/03/09 01:55:06 madfrog
* added support for evo-dev (5 mns ticks and creature stats - thanks to [BT]Hemna)
* added support for the Efficient Breeding center on on the create page
* fixed problems on the news page (NaNs on the BRs. /0 is innocent ;))
* added average land per alliance member on the alliance ranking page (Gavry)
*
* Revision 1.9 2006/02/19 17:13:30 madfrog
* Corrected a bug in the cost evaluation of losses (it broke with defenses like forts)
* Removed a couple of NaNs caused by a div by zero (pun intended)
*
* Revision 1.8 2006/02/17 18:56:39 madfrog
* Simplified land ratio on the resources page
* Disabled land grab stats if defending
* Added cost evaluation of losses on battle reports
* Version bump
*
* Revision 1.7 2006/02/09 18:35:52 madfrog
* Adapted to the new user interface
*
* Revision 1.6 2006/02/02 13:19:33 whytewolf
* minor cost fix for OP and MP costs
* also spelling correction
*
* Revision 1.5 2006/02/01 19:56:01 madfrog
*
* Implemented Maximum possible boosts (for scans, affected by previous change) separated from the players's boosts (for create and fleets).
* Hooked the boost configuration to a menu command.
* A bit of code cleanup in the land ratio display.
* Better tooltip information in the scans att2/def2 evaluations.
*
* Revision 1.4 2006/01/31 22:56:12 whytewolf
*
* typo correction and version bump
* and version change to include magor.minor.bug
*
* Revision 1.3 2006/01/31 22:42:36 whytewolf
*
* added land ratio function
* and MaxBoost Configureation
*
* Revision 1.2 2006/01/30 16:19:18 madfrog
* Added land grab stats on the news page (from Roland's)
*
* Revision 1.1 2006/01/30 13:21:09 madfrog
* First 2.0 version. Almost complete rewrite of the 1.x series with some addtional features.
*
*/
// ***************************************************************************
// ** Global Variables
// ***************************************************************************
const scriptversion = '2.4.0';
const scriptversionID = 'evofr+ ' + scriptversion;
const scriptTag = 'Armageddon';
GM_log(scriptversionID + " start");
// xscript data sharing
unsafeWindow.evo_plus = new Array();
// page handlers
var pageHandlers = new Array();
var units = new Object(); // units :P
var contents = null; // pointer to the 'content' node in the page
// boosts
const UT_NONE = 0;
const UT_NATURAL = 1;
const UT_ENG = 2;
// max possible boosts
var maxBoosts = new Array();
maxBoosts[UT_NONE] = 0;
maxBoosts[UT_NATURAL] = 0.3946625; //max boost for natural
maxBoosts[UT_ENG] = 0.33126875; //max boost for eng
unsafeWindow.evo_plus['maxBoosts'] = maxBoosts;
// user current boosts
var boosts = new Array();
boosts[UT_NONE] = 0;
boosts[UT_NATURAL] = Number(GM_getValue('boostNat', maxBoosts[UT_NATURAL]));
boosts[UT_ENG] = Number(GM_getValue('boostEng', maxBoosts[UT_ENG]));
unsafeWindow.evo_plus['boosts'] = boosts;
var pMetal = 0, pMineral = 0, pFood = 0; //player's resources
var pRank = null, pScore = null; // player's ranking and score
var eeb = Number(GM_getValue('eeb', 1)); // efficient breeding center ratio
var dEvo = /^http:\/\/evo-dev\./.test(document.location.href);
//
// ***************************************************************************
// ** Page handlers
// ***************************************************************************
//
// Add stuff to the scans and create pages
regPageHandler(/^\/create/i, function () { evoCreate(1); evoCreate(2); evoCreate(3); });
regPageHandler(/^\/scans/i, function () { evoCreate(1); });
// handle each creation table
function evoCreate(tableID) {
//
// event handlers
//
// refreshes the max numbers when click on "max" or form field change
function evoUpdateAvailableUnits(table) {
var tmpMetal = pMetal;
var tmpMineral = pMineral;
var rows = table.rows;
var row, unit, unitsToOrder, maxUnitsAvailable, span;
// keep data between the two passes
var createDataArray = new Array();
function createData(unit, unitsToOrder, isTooMuch) {
this.unit = unit;
this.unitsToOrder = unitsToOrder;
this.isTooMuch = isTooMuch;
}
// first pass
// - gather all necessary data for second pass
// - adjust metal/mineral amount
for(var i = 2; i < (rows.length - 1); i++) {
row = rows[i];
unit = row.cells[1].getElementsByTagName('SPAN')[0].textContent.toLowerCase();
unit = units[unit];
unitsToOrder = Number(row.cells[3].getElementsByTagName('INPUT')[0].value);
if( isNaN(unitsToOrder) ) unitsToOrder = 0;
createDataArray[i] = new createData(unit, unitsToOrder, unitsToOrder > unit.getMaxUnits(tmpMetal, tmpMineral));
if(! createDataArray[i].isTooMuch ) {
tmpMetal = Math.max(tmpMetal - unitsToOrder * unit.getMetal(), 0);
tmpMineral = Math.max(tmpMineral - unitsToOrder * unit.getMineral(), 0);
}
}
// second pass
// - ui logic
for(var i = 2; i < (rows.length - 1); i++) {
row = rows[i];
maxUnitsAvailable = createDataArray[i].unit.getMaxUnits(tmpMetal, tmpMineral);
span = row.cells[3].getElementsByTagName('SPAN')[0];
// have to replace the data of the child text node
// span.textContent = html would recreate the child text node and cancel the onclick event
span.firstChild.data = 'max: ' + String(createDataArray[i].isTooMuch ? maxUnitsAvailable : (maxUnitsAvailable + createDataArray[i].unitsToOrder));
span.style.color = createDataArray[i].isTooMuch ? 'red' : '#CCCCCC';
}
}
var onBlur = function() { evoUpdateAvailableUnits(table); };
var onClick = function(e) {
if( e.target.tagName.toLowerCase() == 'input' ) return;
this.getElementsByTagName('input')[0].value = /max: (\d+)/m.exec(this.textContent)[1];
evoUpdateAvailableUnits(table);
};
//
// Helper functions
//
function addHeader(cellIndex, label) {
var cell = table.rows[0].insertCell(cellIndex);
cell.innerHTML = label;
cell.align = "center"; cell.vAlign = "bottom"; cell.width = "60px";
cell = table.rows[1].insertCell(cellIndex); cell.className = "alt1";
}
function addStat(row, cellIndex, base, square, value, boost) {
var cell = row.insertCell(cellIndex);
cell.className = row.cells[1].className; cell.align = "center";
cell.innerHTML = '<span title="Unboosted: ' + base + '">' + (base*boost).toFixed(1)
+ '</span><br /><span class="t_enormous" title="Unboosted: ' + square + '">' + (square*boost*boost).toFixed(0)
+ '</span><br /><span title="Unboosted: ' + evoNumber2String(value) + '">' + evoNumber2String((value*boost*boost).toFixed(0)) + '</span>';
}
//
// main
//
var unit, cell, unitCost, row;
var table = null;
var isScanPage = document.location.pathname == '/scans';
var xPathTerm = ".//div[@class='"+(dEvo?"separator title":"separator title")+"'";
if( isScanPage)
xPathTerm = xPathTerm+ "][3]/following-sibling::table[1]";
else
xPathTerm = xPathTerm + "]["+tableID+"]/following-sibling::table[1]";
table = document.evaluate(xPathTerm, contents, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
if(table == null) return;
var showstats = !isScanPage && (tableID == 1 || tableID == 2);
// Efficient breeding center?
if( showstats && tableID == 1 ) {
var monkey = document.evaluate(".//tbody/tr/td[2][./a/span[@class='b' and text()='Monkey']]/text()",
table, null, XPathResult.STRING_TYPE, null).stringValue;
if( monkey ) {
var match = /(\d+) metal, (\d+) mineral each\./.exec(monkey);
if( match ) {
eeb = parseInt(match[1]) / units['monkey'].metal;
GM_setValue('eeb', String(eeb));
}
}
}
// add creatures/items stats
if( showstats ) {
// column headers
addHeader(4, 'Attaque/<br /><strong>Attaque<sup>2</sup></strong>/<br /><span title="Att2 pour 100,000 ressources (m\u00e9tal + min\u00e9ral)">pour 100K</span>');
addHeader(5, 'Defence/<br /><strong>Defence<sup>2</sup></strong>/<br /><span title="Def2 pour 100,000 ressources (m\u00e9tal + min\u00e9ral)">pour 100K</span>');
addHeader(6, 'Total/<br /><strong>Total<sup>2</sup></strong>/<br /><span title="Att2+Def2 pour 100,000 ressources (m\u00e9tal + min\u00e9ral)">pour 100K</span>');
}
// display stats for each item
for( var i = 2; i < (table.rows.length - 1); i++ ) {
row = table.rows[i];
if( showstats ) {
unit = (row.cells[1].getElementsByTagName('SPAN'))[0].textContent.toLowerCase();
unit = units[unit];
unitCost = unit.getMetal() + unit.getMineral();
var att2 = unit.getAttackScore(1);
var def2 = unit.getDefenseScore(1);
var average = att2 + def2;
var boost = 1 + unit.getBoost();
addStat(row, 4, unit.attack, att2, Math.round(att2*100000/unitCost), boost);
addStat(row, 5, unit.defense, def2, Math.round(def2*100000/unitCost), boost);
addStat(row, 6, (unit.defense + unit.attack), average, Math.round(average*100000/unitCost), boost);
}
// new UI
cell = document.createElement('SPAN');
cell.style.display = "block";
row.cells[3].style.cursor = "pointer";
cell.textContent = ' '; // forces the creation of a text node
row.cells[3].appendChild(cell);
// update hook
row.cells[3].getElementsByTagName('INPUT')[0].addEventListener('blur', onBlur, false);
// order max amount hook
row.cells[3].addEventListener('click', onClick, false);
}
// hook up a confirmation dialog on the form
var youSure = function(e)
{
if(! confirm('Etes-vous sur de vouloir produire ces \u00e9l\u00e9ments/cr\u00e9atures?'))
e.preventDefault();
}
var daForm = table.getElementsByTagName('FORM')[0];
daForm.addEventListener('Submit', youSure, false);
evoUpdateAvailableUnits(table);
}
//
// changes to the overview page
//
regPageHandler(/^\/(overview)?$/i, evoOverview);
function evoOverview() {
var tick = dEvo ? 5 : 60;
var i, ticks, total;
var node, match;
var now = new Date(document.lastModified);
var searchKey = dEvo ? "separator title":"separator title";
now.setUTCMinutes(now.getUTCMinutes() - now.getUTCMinutes() % tick);
// let's try to grab the player's coords
node = document.evaluate(".//span[preceding-sibling::span[@class='t_medium b' and text()='Statut du continent']]",
contents, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
if( node != null && (match = node.innerHTML.match(/(\d*?),(\d*?),(\d*?):\w/)) ) {
GM_setValue(dEvo?'devoCoords':'evoCoords', match[0]);
unsafeWindow.evo_plus.coords = match[0];
} else
GM_log("Impossible de trouver vos coordonn\u00e9es :(", 1);
// look for the fleets status table and show the ETA
node = document.evaluate('.//div[@class="'+searchKey+'" and contains(., "Statut des flottes")]/following-sibling::div[1]/table', contents, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
if( node ) {
node.rows[0].cells[3].textContent = 'Ticks';
node.rows[0].insertCell(4);
node.rows[0].cells[4].textContent = 'ETA';
// let's parse the ETAs...
for(i = 1; i < node.rows.length; i++) {
if( node.rows[i].cells.length == 4 ) {
node.rows[i].insertCell(4);
if(! isNaN(ticks = parseInt(node.rows[i].cells[3].textContent)) ) {
var eta = new Date(now.valueOf() + (ticks * tick * 60000));
node.rows[i].cells[4].textContent = evoFromatNumberZ(eta.getUTCHours(),2) + ":" + evoFromatNumberZ(eta.getUTCMinutes(),2) + " GMT";
}
}
}
}
// Same for the R&D
var nodes = document.evaluate(".//div[@class='alt2 t_little' and preceding-sibling::div[@class='"+searchKey+"' and starts-with(.,'D\u00e9veloppement')]]",
contents, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
if( !dEvo ) {
for( i = 0; node = nodes.snapshotItem(i); i++ ) {
node.innerHTML = node.innerHTML.replace(/(\d+)% \((\d+)\/(\d+)\) termin.\./,
function(str, p1, p2, p3, offset, s) {
var minutes = (Number(p3) - Number(p2)) * tick;
var eta = new Date(now.valueOf() + (minutes * 60000));
return p1 + '% (' + p2 + '/' + p3 + ') termin\u00e9 - ETA: ' + evoFromatNumberZ(eta.getUTCHours(),2) + ":" + evoFromatNumberZ(eta.getUTCMinutes(),2) + " GMT" + (minutes > 1440 ? ' (+' + Math.floor(minutes/1440) + ' day' + ( minutes >= 2880 ? 's' : '' ) + ')' : '');
});
}
}
var nodes = document.evaluate(".//div[@class='alt2 t_little' and preceding-sibling::div[@class='"+searchKey+"' and starts-with(.,'Currently')]]",
contents, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
if( !dEvo ) {
for( i = 0; node = nodes.snapshotItem(i); i++ ) {
node.innerHTML = node.innerHTML.replace(/(\d+)% \((\d+)\/(\d+)\) termin.\./,
function(str, p1, p2, p3, offset, s) {
var minutes = (Number(p3) - Number(p2)) * tick;
var eta = new Date(now.valueOf() + (minutes * 60000));
return p1 + '% (' + p2 + '/' + p3 + ') termin\u00e9 - ETA: ' + evoFromatNumberZ(eta.getUTCHours(),2) + ":" + evoFromatNumberZ(eta.getUTCMinutes(),2) + " GMT" + (minutes > 1440 ? ' (+' + Math.floor(minutes/1440) + ' day' + ( minutes >= 2880 ? 's' : '' ) + ')' : '');
});
}
}
// same for the creatures and stuff
if( !dEvo)
nodes = document.evaluate(".//div[@class='separator title']/following-sibling::div[@class='alt2 t_little']/table/tbody/tr[count(td)=3]",
contents, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
else
nodes = document.evaluate(".//div[@class='separator title']/following-sibling::div[@class='alt2 t_little']/table/tbody/tr[count(td)=3]",
contents, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
for( i = 0; node = nodes.snapshotItem(i); i++ ) {
// add a column
node.insertCell(3);
if( match = /\d+% termin.s, il reste (\d+) ticks/.exec(node.cells[2].textContent) ) {
var eta = new Date(now.valueOf() + (Number(match[1]) * tick * 60000));
node.cells[3].textContent = evoFromatNumberZ(eta.getUTCHours(),2) + ":" + evoFromatNumberZ(eta.getUTCMinutes(),2) + " GMT";
}
}
// add a link to the continent/planet
nodes = document.evaluate(".//td[child::span[@class='t_medium b']]", contents, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
for( i= 0; node = nodes.snapshotItem(i); i++ )
node.innerHTML = node.innerHTML.replace(/<span class="t_little".*\((\d+,\d+,\d+)(:\w)?\)<\/span>/i, '<a href="/$1" style="text-decoration:none">$&</a>');
// attackers - defenders
if( node = document.evaluate(".//div[@class='alt2 t_little']/center/span[@class='t_little']", contents, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue ) {
attackers = new Array();
defenders = new Array();
var j, first = 24, last = 0;
nodes = node.getElementsByTagName('font');
for(i=0; i < 24; i++) attackers[i] = defenders[i] = 0;
for(i = 0; i < nodes.length; i++ ) {
if( match = /Incoming (\d+) creatures .* they will be here to (ATTACK|DEFEND) in (\d+) tick/.exec(nodes[i].innerHTML) ) {
var num = parseInt(match[3]);
if( match[2] == 'ATTACK' ) {
for(j = num; j < num + 3; j++) attackers[j] += parseInt(match[1]);
} else {
for(j = num; j < num + 6; j++) defenders[j] += parseInt(match[1]);
}
if( j > last ) last = j;
if( num < first ) first = num;
} else if( match = /(\d+) creatures (DEFENDING|ATTACKING) .* - (\d+) tick/.exec(nodes[i].innerHTML) ) {
var num = match[3];
if( match[2] == 'ATTACKING' ) {
for(j = 0; j < num; j++) attackers[j] += parseInt(match[1]);
} else {
for(j = 0; j < num; j++) defenders[j] += parseInt(match[1]);
}
if( num > last ) last = num;
first = 0;
}
}
var table = document.createElement('table');
table.className = 't_little';
table.cellSpacing = 1;
var rowT = table.insertRow(table.rows.length);
var rowA = table.insertRow(table.rows.length);
var rowD = table.insertRow(table.rows.length);
var cell;
rowT.innerHTML = "<td class=\"row1 b\">Tick</td>";
rowA.innerHTML = "<td class=\"row1 b\">Attackers</td>";
rowD.innerHTML = "<td class=\"row1 b\">Defenders</td>";
for( i = first; i < last; i++ ) {
(cell = rowT.insertCell(rowT.cells.length)).textContent = i; cell.style.textAlign = "center"; cell.style.padding = "0 2px 0 2px";
(cell = rowA.insertCell(rowA.cells.length)).textContent = attackers[i]; cell.style.textAlign = "center"; cell.style.padding = "0 2px 0 2px";
(cell = rowD.insertCell(rowD.cells.length)).textContent = defenders[i]; cell.style.textAlign = "center"; cell.style.padding = "0 2px 0 2px";
}
node.parentNode.insertBefore(table, node.nextSibling);
}
//
// Unallocated land percentage
//
var landtable = document.evaluate(".//table[@class='t_little' and parent::div[@class='alt2' and preceding-sibling::div[@class='separator title' and child::span[text()='Terrain']]]]", contents, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
var alloc = evoString2Number(landtable.rows[1].cells[1].textContent)+evoString2Number(landtable.rows[2].cells[0].textContent)+evoString2Number(landtable.rows[2].cells[1].textContent);
var total = alloc+ evoString2Number(landtable.rows[1].cells[0].textContent)
var per = Math.round(alloc/total*10000);
per = (10000 - per)/100; // We just worked out the percentage allocated, so let's take it away from 100. This avoids a /0
var elm = document.createElement('DIV');
elm.className = 'separator title';
elm.innerHTML = 'Vous avez actuellement '+per+'% de Terrain Inutilis\u00e9s';
landtable.parentNode.appendChild(elm);
}
//
// restores the land cost display on the resources page
//
regPageHandler(/^\/resources\/overview/i, evoResources);
function evoResources() {
var resourcetable = document.evaluate(".//table[@class='t_little' and preceding-sibling::div[@class='separator title'and child::span[text()='Land']]]", contents, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
evoLandRatio();
// Max land that can be allocated
// get current amount of allocated
// Layout check
if( resourcetable.rows[0].cells[0].innerHTML == 'Unused Land' ) var z = 1; else var z = 0;
var land = evoString2Number(resourcetable.rows[1+z].cells[1].textContent) + evoString2Number(resourcetable.rows[2+z].cells[1].textContent) + evoString2Number(resourcetable.rows[3+z].cells[1].textContent);
var totcost = 0;
var nbr =0; var qrty=0;
while (totcost < pMetal){
qrty++;
totcost += ( ( ( land -1 ) * 150) + 1000 + (qrty * 150) );
if(totcost < pMetal) { nbr++; }
}
// We need to have unallocated land
if (z == 1){
unallocland = resourcetable.rows[0].cells[1].textContent;
if (unallocland < nbr){ nbr = unallocland; }
}else{
nbr = 0;
}
// Add the text
var newRow = resourcetable.insertRow(resourcetable.rows.length);
newCell = newRow.insertCell(0);
newCell.colSpan = '5';
newCell.className = 'alt1 b';
newCell.textContent = (nbr == 0) ? 'Il n\'y a aucun terrain \u00e0 allouer' :'Vous pouvez allouer un maximum de '+nbr+' terrain(s)';
newCell.style.textAlign ='center';
if( resourcetable ) {
// do we have the graphic?
if( resourcetable.rows[0].cells[0].innerHTML == 'Unused Land' ) return;
// onclick function....
showAllocCost = function(e) {
var parent = this.parentNode;
this.style.cursor = 'auto';
this.style.textDecoration = "none";
if( parent.nextSibling != null ) return;
parent = parent.parentNode;
var elm = document.createElement('IMG');
elm.src = 'http://ev5.neondragon.net/graphs.land/'+land+'?width=799';
parent.appendChild(elm);
elm = document.createElement('BR');
parent.appendChild(elm);
elm = document.createElement('SPAN');
elm.className = 't_little';
elm.innerHTML = 'Les valeurs en <SPAN class="red">Rouge</SPAN> sont les couts en m\u00e9tal pour allouer le nombre de terrains definit sur l\'axe des x.';
parent.appendChild(elm);
};
var elm = document.createElement('DIV');
var span = document.createElement('SPAN');
elm.className = "title";
span.innerHTML = 'Couts d\'allocation des Terrains inutilis\u00e9s';
span.style.textDecoration = "underline";
span.style.cursor = "pointer";
span.addEventListener('click',showAllocCost, false);
elm.appendChild(span);
resourcetable.parentNode.appendChild(elm);
}
function evoLandRatio() {
var fields = resourcetable.rows.length;
var food = Number(evoString2Number(resourcetable.rows[fields - 1].cells[1].textContent));
var mineral = Number(evoString2Number(resourcetable.rows[fields - 2].cells[1].textContent));
var metal = Number(evoString2Number(resourcetable.rows[fields - 3].cells[1].textContent));
if( isNaN(food) || isNaN(mineral) || isNaN(metal) ) return;
var gcd = gcf(gcf(metal,mineral),food);
metal = metal / gcd;
mineral = mineral / gcd;
food = food / gcd;
var row = resourcetable.insertRow(fields);
row.className = 'row2';
node = row.insertCell(0);
node.innerHTML = 'Ratio';
node.className = 'alt1 b';
node.style.textAlign = 'right';
node = row.insertCell(1);
node.innerHTML = metal + ':' + mineral + ':' + food;
node.style.textAlign = 'center';
// give approx. ratio with: 1 <= food <= 2
if( food > 2 && food < metal && food < mineral ) {
gcd = Math.pow(2, Math.floor(Math.log(food) / Math.log(2))) // divider
gcd = food / (food = Math.round(food / gcd)); // refine the divider
metal = Math.round(metal / gcd);
mineral = Math.round(mineral / gcd);
gcd = gcf(gcf(metal,mineral),food);
food /= gcd;
mineral /= gcd;
metal /= gcd;
node = row.insertCell(2);
node.innerHTML = '(~' + metal + ':' + mineral + ':' + food + ')';
node.style.textAlign = 'center';
node = row.insertCell(3);
node.colSpan = 2;
} else {
node = row.insertCell(2);
node.colSpan = 3;
}
}
}
//
// Alliances page
//
regPageHandler(/^\/alliances$/i, evoAlliances);
function evoAlliances() {
var row;
var rows = document.evaluate(".//table/tbody[tr/td[text()='Alliance Name']]/tr[count(td)=5]",
contents, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
for(var i = 1; row = rows.snapshotItem(i); i++) {
row.cells[3].innerHTML = evoNumber2String(row.cells[3].textContent) + "<br><font color='#AAAAFF'>"+ evoNumber2String(Math.ceil(evoString2Number(row.cells[3].textContent)/evoString2Number(row.cells[2].textContent)))+"</font>";
row.cells[3].style.textAlign = "right";
row.cells[3].style.padding = "0 2px 0 2px";
}
}
//
// Alliance members
//
regPageHandler(/^\/alliances\/(.*)\/members/i, evoAllianceMembers);
function evoAllianceMembers() {
var smin = Math.ceil(pScore * 0.35);
var tmax = Math.floor(pScore / 0.35);
var memberTables = document.evaluate(".//div[@id='alliancememberlist']/table", contents, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
// if we have rank edit powers.. we need another snapshot
if (memberTables.snapshotItem(0) == null){
var memberTables = document.evaluate(".//div[@id='alliancememberlist']/form/table", contents, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
}
var nbr = 0; var snbr = 0;
var totscore = 0; var stotscore = 0;
// get the alliance's tag
var thisTag = unescape(window.location.href.match(/\/alliances\/(.*)\/members$/)[1]);
for (var i = 0; memberTable = memberTables.snapshotItem(i); i++) {
// Add some formatting
memberTable.style.width = '100%';
memberTable.rows[0].cells[0].style.width = '500px';
memberTable.rows[0].cells[3].style.textAlign = 'right';
memberTable.rows[0].style.fontWeight = 'right';
memberTable.rows[0].style.fontWeight = 'bold';
for (var j = 1; j < memberTable.rows.length; j++){
var perTag = (memberTable.rows[j].cells[0].textContent.match(/\[(.*)\]/) != null) ? memberTable.rows[j].cells[0].textContent.match(/\[(.*)\]/)[1]: '';
var isPrimary = (perTag == thisTag ) ? true : false;
score = memberTable.rows[j].cells[2];
target = evoString2Number(score.textContent);
if (isPrimary == true){ totscore = totscore + target; }else{ stotscore = stotscore + target;}
if( target < smin ){score.style.color = '#CC4411';}
else if( target > tmax ){score.style.color ='#0000FF'; if (isPrimary == true){ nbr++; }else{ snbr++;} }
else{score.style.color = '#00FF00'; if (isPrimary == true){ nbr++; }else{ snbr++;} }
memberTable.rows[j].cells[2].textContent = evoNumber2String(memberTable.rows[j].cells[2].textContent);
memberTable.rows[j].cells[3].style.textAlign = 'right';
}
}
// Show the info at the top
var div = document.evaluate(".//div[@id='alliancememberlist']", contents, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
div.innerHTML = '<div class="separator title">Il y a <span style="color:#00ff00;">'+nbr+'</span> Membres Primaire dans cette alliance ('+evoNumber2String(totscore)+')</div><div class="separator title">Il y a <span style="color:#00aaff;">'+snbr+'</span> Membres Secondaires dans cette alliance ('+evoNumber2String(stotscore)+')</div><div class="separator title">Un Total de '+evoNumber2String(nbr+snbr)+' Membres ('+evoNumber2String(totscore+stotscore)+')</div>' + div.innerHTML;
// quick buddy
// This feature makes a direct request to the server which is deemed illegal
// neon has however kindly accepted to allow it only for this particular feature
// since it puts less strain on the server than doing it the regular way
// AGAIN, THIS IS AN EXCEPTION. DON't USE XmlHttpRequest!!! IT IS ILLEGAL!
function onBuddy(e) {
var postData;
e.preventDefault();
try {
postData = e.target.href.match(/\/buddies\/add\?(.*)$/)[1];
} catch ( e ) {
return;
}
if( count++ ) {
alert("Wow... tranquille! Un seul ami \u00e0 la fois, svp?");
--count;
return;
}
e.target.textContent = "Patientez...";
e.target.href = '#';
GM_xmlhttpRequest({
method: 'POST',
url: 'http://'+document.location.hostname+'/buddies/add',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
data: postData,
onreadystatechange: function(responseDetails) {
if( responseDetails.readyState == 4 && responseDetails.status == 200 ) {
e.target.parentNode.removeChild(e.target);
--count;
}
},
onerror: function(responseDetails) {
e.target.href = "/buddies/add?" + postData;
e.target.textContent = ' Add to buddies';
--count;
}
});
}
var i, match;
var re = /javascript:return continentBox\(\d+,(\d+),(\d+),(\d+),(\d+),'(\w)','([^']+)','([^']+)','([^']+)','([^']+)','([^']*)',\s*'([^']*)'/;
var users = document.evaluate(".//a[@class='cleanlink continfo']", contents, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for(i = 0; node = users.snapshotItem(i); i++) {
if( match = re.exec(node.getAttribute('onclick')) ) {
if( match[11] == '' ) {
var br, td = node.parentNode.parentNode;
var a = document.createElement('a');
a.href = '/buddies/add?x=' + match[2] + '&y=' + match[3] + '&z=' + match[4] + '&c=' + match[5] + '&nickname=' + encodeURIComponent(match[6]) + '&label=' + encodeURIComponent(node.textContent.match(/\[([^\]]+)\]/)[1]);
a.appendChild(document.createTextNode(' Add to buddies'));
a.addEventListener('click', onBuddy, false);
if(! (br = node.parentNode.nextSibling) )
td.appendChild(document.createElement('br'));
else
br.nextSibling.textContent += ' ';
td.appendChild(a);
}
}
}
}
//
// Add some color to the scores on the universe pages
//
regPageHandler(/^\/(universe\/(home|search)|(\d+(,\d+)*))$/i, evoUniverse);
function evoUniverse() {
var smin = Math.ceil(pScore * 0.35);
var tmax = Math.floor(pScore / 0.35);
var table = document.getElementById('cont_list');
if( table != null ) {
// let's add some color and look for potential targets ;)
for(var i=2; i < table.rows.length; i++) {
if( table.rows[i].cells.length < 4 )
continue;
var cell1 = table.rows[i].cells[1];
var cell3 = table.rows[i].cells[3];
var target = evoString2Number(cell3.innerHTML);
if( target < smin )
cell3.style.color = '#CC4411';
else if( target > tmax )
cell3.style.color ='#0000FF';
else
cell3.style.color = '#00FF00';
}
var git = document.evaluate(".//table[tbody/tr[1]/td[1][text() = 'Clef']]", contents, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
if( git != null ) {
var d = git.insertRow(4);
d.className = "lightblue_bg_row2";
d.innerHTML = '<td>Couleurs des Textes:</td><td colspan="3" align="center"><font color="#FFFFFF">Les noms en Blanc</font> indique que la personne est actuellement conn\u00e9ct\u00e9<BR><font color="#C4C4C4">Les noms en Gris</font> indique que la personne est d\u00e9conn\u00e9ct\u00e9<BR><font color="#646464">Les noms en Gris Fonc\u00e9</font> indique que la personne ne s\'est pas conn\u00e9ct\u00e9 depuis au moins une semaine</td>';
var c = git.insertRow(5);
c.className = "lightblue_bg_row1";
c.innerHTML = '<td>Couleurs des Score:</td><td colspan="3" align="center">Les joueurs avec ce <font color="#CC4411">score</font> peuvent vous attaquer, mais vous ne pouvez pas<BR>Les joueurs avec ce <font color="#00FF00">score</font> peuvent vous attaquer, et vous le pouvez aussi<BR>Les joueurs avec ce <font color="#0000FF">score</font> ne peuvent pas vous attaquer, mais vous pouvez :D</td>';
}
}
}
//
// Evaluation of att/def on scans
//
regPageHandler(/^\/scans/i, evoScans );
regPageHandler(/^\/scans/i, evoAmpRatio );
function evoAmpRatio(){
var scantable = document.evaluate(".//table[@class='t_little' and preceding-sibling::div[@class='separator title'and child::span[text()='Order Scans']]]", contents, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
var land = document.getElementById('panelinfo').textContent.match(/Terrain:\s(\d+)/);
var curAmps = evoString2Number(scantable.rows[3].cells[2].textContent);
var curLand = evoString2Number(land[1]);
var ratio = Math.round((curAmps / curLand)*1000)/1000;
scantable.rows[3].cells[2].innerHTML = scantable.rows[3].cells[2].innerHTML + '<br /><span style="text-size:0.8em;color:#00ff00">'+ratio+'</span>';
//bastard
}
function evoScans(){
var scan = document.evaluate(".//div[@class='helpmessage']/strong", contents, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
if (!scan) return;
var table = document.evaluate("./following-sibling::table", scan, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
scan = scan.textContent;
if (scan.indexOf("Sector Scan") != -1) {
var defenceData = new Array(
new Array(7, 'fort'),
new Array(8, 'satellite mark 2'),
new Array(9, 'nanowire wall')
);
var attack, defence, overallAttack = 0, overallDefence = 0;
var row, cells, nDef, unit, newCell;
var landAmt = 0, nLands = 0, unused = 0;
var rows = table.rows;
for (var i = 0; i < defenceData.length; i++){
cells = rows[defenceData[i][0]].cells;
if( cells.length == 4) {
// land defence
nLands = parseInt(cells[1].innerHTML);
if (!isNaN(nLands)) landAmt += nLands;
// static defences
nDef = parseInt(cells[3].innerHTML);
if (isNaN(nDef)) continue;
unit = units[defenceData[i][1]];
attack = unit.getAttackScore(nDef);
defence = unit.getDefenseScore(nDef);
overallAttack += attack;
overallDefence += defence;
cells[3].title = 'Estimated boosted att2/def2: ' + evoNumber2String(attack.toFixed(0)) + ' / ' + evoNumber2String(defence.toFixed(0));
}
}
// formatting score number / add attacker's score range
var resPics = new Array ('metal.png','mineral.png','food.png');
for (var i = 2; i < 5; i++) {
rows[i].cells[2].innerHTML = "<img style=\"vertical-align: top\" src='http://images.neondragon.net/ev5/resources/"+resPics[i-2]+"' border='0'> "+rows[i].cells[2].innerHTML;
rows[i].cells[3].innerHTML = "<font color=#ADD8E6>"+evoNumber2String(parseInt(rows[i].cells[3].innerHTML))+"<font>";
}
resPics = null;
var score = parseInt(rows[2].cells[1].innerHTML);
rows[2].cells[1].innerHTML = "<font color#FF850B>"+evoNumber2String(score)+"<font>";
rows[3].cells[0].innerHTML = "Max. Attacker Score";
rows[3].cells[0].className = "alt1 b";
rows[3].cells[1].innerHTML = "<font color=#FF850B>"+evoNumber2String(Math.ceil(score/.35))+"<font>";
rows[4].cells[0].innerHTML = "Min. Attacker Score";
rows[4].cells[0].className = "alt1 b";
rows[4].cells[1].innerHTML = "<font color=#FF850B>"+evoNumber2String(Math.ceil(score/2.5))+"<font>";
unused = parseInt(rows[6].cells[1].innerHTML);
row = table.insertRow(10);
row.title = "This DOES NOT include the creature stats";
newCell = row.insertCell(0);
newCell.className = "alt1 b";
newCell.innerHTML = "Land ratio/def2<sup>*</sup>";
newCell = row.insertCell(1);
newCell.innerHTML = "<font color=yellow>"+evoNumber2String((landAmt/(landAmt+unused)*100).toFixed(2))+"%</font> / <font color=#8FED9B>"+ evoNumber2String(((landAmt+unused)*(105*105)*1.4).toFixed(0))+"</font>";
newCell = row.insertCell(2);
newCell.className = "alt1 b";
newCell.innerHTML = "Overall att2/def2<sup>*</sup>";
newCell = row.insertCell(3);
newCell.innerHTML = "<font color=#F25763>"+evoNumber2String(overallAttack.toFixed(0)) + "</font> / <font color=#8FED9B>" + evoNumber2String(overallDefence.toFixed(0))+"</font>";
for( var i=6; i<=9; i++) {
if( rows[i].cells[1].innerHTML.length > 0)
rows[i].cells[1].innerHTML = evoNumber2String(parseInt(rows[i].cells[1].innerHTML));
if( rows[i].cells[3].innerHTML.length>0)
rows[i].cells[3].innerHTML = evoNumber2String(parseInt(rows[i].cells[3].innerHTML));
}
} else if (scan.indexOf("Creature Scan") != -1) {
var rows = table.rows;
var row, cells, cell, unit, quantity, boost;
var attack, defence, overallAttack = 0, overallDefence = 0;
var foodCost = 0;
for (var i = 2; i < rows.length; i++){
row = rows[i];
cells = row.cells;
for (var j = 0; j < cells.length; j += 2) {
unit = units[cells[j].textContent.toLowerCase()];
cell = cells[j + 1];
quantity = parseInt(cell.innerHTML);
boost = 1 + unit.getMaxBoost();
attack = unit.getAttackScore(quantity) * boost * boost;
defence = unit.getDefenseScore(quantity) * boost * boost;
foodCost += unit.getFoodCost(quantity);
overallAttack += attack;
overallDefence += defence;
cell.title = 'Estimated boosted att2/def2: ' + evoNumber2String(attack.toFixed(0)) + ' / ' + evoNumber2String(defence.toFixed(0));
}
}
var newRow = table.insertRow(rows.length);
newRow.title = 'Estimation of att2/def2 with max possible boosts';
var newCell = newRow.insertCell(0);
newCell.className = "alt1 b";
newCell.innerHTML = "Overall att2/def2<sup>*</sup>";
newCell = newRow.insertCell(1);
newCell.innerHTML = "<font color=#F25763>"+evoNumber2String(overallAttack.toFixed(0)) + "</font> / <font color=#8FED9B>" + evoNumber2String(overallDefence.toFixed(0))+"</font>"; // modify by ressol
newCell.colSpan = 5;
newRow = table.insertRow(rows.length);
newCell = newRow.insertCell(0);
newCell.className = "alt1 b";
newCell.innerHTML = "Launch cost";
newCell = newRow.insertCell(1);
newCell.innerHTML = "<font color=#FF850B>"+evoNumber2String(foodCost.toFixed(0)) + "</font>"; // modify by ressol
newCell.colSpan = 5;
}
}
//
// Fleets page
//
regPageHandler(/^\/fleets/i, evoFleets );
function evoFleets(){
function updateFleetsAddCell(row, cellIndex, className, scores){
var cell = row.insertCell(cellIndex);
cell.className = className;
cell.style.textAlign = 'center';
cell.colSpan = 2;
if (cellIndex > 0) {
cell.style.fontSize = "12px";
cell.innerHTML = evoNumber2String(scores[1]);
cell.title = 'Unboosted: ' + evoNumber2String(scores[0]);
} else {
cell.innerHTML = scores; // cell title actually
}
}
function updateFleetsAddRow(fleetsTable, isAttack){
var row = fleetsTable.insertRow(fleetsTable.rows.length - 2);
updateFleetsAddCell(row, 0, "alt1 b", (isAttack ? "Attaque" : "Defense") + '<br /><span style="font-size:smaller; font-weight: normal">(estimation avec max boost)</span>');
updateFleetsAddCell(row, 1, "red_bg", getFleetScore(1, fleetsTable, isAttack));
updateFleetsAddCell(row, 2, "yellow_bg", getFleetScore(2, fleetsTable, isAttack));
updateFleetsAddCell(row, 3, "green_bg", getFleetScore(3, fleetsTable, isAttack));
}
function getFleetScore(fleetNo, table, isAttack){
var rows, row;
var unit, quantity, total = 0;
var i, j, baseScore, boost, noBoostScore = 0, maxBoostScore = 0;
rows = document.evaluate(".//tr[td[1]/a]", table, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
for( i = 0; row = rows.snapshotItem(i); i++ ) {
if( row.cells[0].rowSpan > 1 ) break;
unit = units[row.cells[0].textContent.toLowerCase()];
quantity = Number(row.cells[fleetNo * 2 + 1].textContent);
total += quantity;
baseScore = isAttack ? unit.getAttackScore(quantity) : unit.getDefenseScore(quantity);
noBoostScore += baseScore;
boost = unit.getBoost() + 1;
maxBoostScore += baseScore * boost * boost;
}
// row.cells[0].rowSpan = 12;
var cell = sumRow.cells[1 + fleetNo];
cell.textContent = total;
cell.style.textAlign = 'center';
cell.style.fontSize = '12px';
return new Array(Math.round(noBoostScore), Math.round(maxBoostScore))
}
var fleetsTable = null;
if( dEvo )
fleetsTable = document.evaluate(".//table[preceding-sibling::h2[@class='forum' and text()='Organisation de la flotte']][1]",contents, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
else
fleetsTable = document.evaluate(".//table[preceding-sibling::h2[@class='title' and text()='Organisation de la flotte']][1]",
contents, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
// add row for fleet counts
var sumRow = document.evaluate(".//tr[td[position()=1 and text()='D\u00e9placer vers']]", fleetsTable, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
sumRow = fleetsTable.insertRow(sumRow.rowIndex);
sumRow.innerHTML = '<td class="alt1 b">Total</td><td class="alt2" colspan="2"></td><td class="red_bg" colspan="2"></td><td class="yellow_bg" colspan="2"></td><td class="green_bg" colspan="2"></td>';
updateFleetsAddRow(fleetsTable, true);
updateFleetsAddRow(fleetsTable, false);
}
//
// News page
//
regPageHandler(/^\/news/i, evoNews );
function evoNews() {
function addCell(row, cellIndex, attributes, html) {
var cell = row.insertCell(cellIndex);
if (attributes)
for (var i = 0; i < attributes.length; i++)
cell.setAttribute(attributes[i][0], attributes[i][1]);
if (html) cell.innerHTML = html;
return cell;
}
var dEvoExpTerm = ".//h3[@class='cnewstitle' and child::span[starts-with(.,'Battle Report')]]/following-sibling::table";
var RegExpTerm = (dEvo?dEvoExpTerm:".//h3[@class='cnewstitle' and child::span[starts-with(.,'Battle Report')]]/following-sibling::table");
var battleReports = document.evaluate(RegExpTerm, contents, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
var battleReport;
var rows, html, attDefRow, isAttacker, att, myAtt, def, myDef,
idx, idx2, unit, quantity, boost, landType, land, myLand, summaryRow, cell, j;
var ruler = document.evaluate("//p[@id='openpanel']/strong[1]/text()", document, null, XPathResult.STRING_TYPE, null).stringValue;
var attPrefixRegex = /.*att<sup>2<\/sup>:\s*/;
var attSuffixRegex = /<br.*/;
var defPrefixRegex = /.*def<sup>2<\/sup>:\s*/;
for (var i = 0; battleReport = battleReports.snapshotItem(i); i++) {
rows = battleReport.rows;
attDefRow = rows[0];
isAttacker = attDefRow.cells[1].textContent.toLowerCase().indexOf(ruler.toLowerCase()) != -1;
idx = isAttacker ? 1 : 2;
att = attDefRow.cells[idx].innerHTML.replace(attPrefixRegex, "").replace(attSuffixRegex, "");
att = parseInt(att ? att : 0);
def = attDefRow.cells[idx].innerHTML.replace(defPrefixRegex, "");
def = parseInt(def ? def : 0);
myAtt = 0;
myDef = 0;
idx2 = isAttacker ? 1 : 6;
for (j = 3; j < rows.length; j++) {
unit = units[rows[j].cells[0].innerHTML.toLowerCase()];
if (!unit) break;
idx = rows[j].cells[idx2].innerHTML.indexOf("<br>");
quantity = parseInt(rows[j].cells[idx2].innerHTML.substring(idx + 4));
boost = 1+unit.getBoost();
myAtt += unit.getAttackScore(quantity) * boost * boost;
myDef += unit.getDefenseScore(quantity) * boost * boost;
}
summaryRow = battleReport.insertRow(rows.length);
cell = addCell(summaryRow, 0, new Array(new Array("colSpan", "11"), new Array("height", "3")));
summaryRow = battleReport.insertRow(rows.length);
cell = addCell(summaryRow, 0, new Array(new Array("class", "alt1 b")), "Summary");
html = "Att: " + evoNumber2String(myAtt.toFixed(0)) + " / <b>" + evoNumber2String(att) + "</b> (" + (att != 0 ? parseInt(100 * myAtt / att) : 0) + "%)<br/>" +
"Def: " + evoNumber2String(myDef.toFixed(0)) + " / <b>" + evoNumber2String(def) + "</b> (" + (def != 0 ? parseInt(100 * myDef / def) : 0) + "%)";
if (isAttacker) {
cell = addCell(summaryRow, 1, new Array(new Array("class", "red_bg_row2"), new Array("colSpan", "2")), html);
html = "";
for (; j < rows.length - 2; j++) {
if (rows[j].cells[0].innerHTML.indexOf("Land Capture") != -1) {
j++;
break;
}
}
for (; j < rows.length - 2; j++) {
landType = rows[j].cells[0].innerHTML;
land = rows[j].cells[2].firstChild.innerHTML;
myLand = rows[j].cells[2].innerHTML.replace(/.*<br>/, "");
idx = landType.length + (11 - landType.length) * 6;
landType = (landType + " ").substring(0, idx);
html += landType + ": " + myLand + " / <b>" + land + "</b> (" + parseInt(100 * myLand / land) + "%)<br/>";
}
cell = addCell(summaryRow, 2, new Array(new Array("class", "red_bg_row2"), new Array("colSpan", "3")), html);
cell = addCell(summaryRow, 3, new Array(new Array("class", "green_bg_row2"), new Array("colSpan", "5")));
} else {
cell = addCell(summaryRow, 1, new Array(new Array("class", "red_bg_row2"), new Array("colSpan", "5")));
cell = addCell(summaryRow, 2, new Array(new Array("class", "green_bg_row2"), new Array("colSpan", "5")), html);
}
// calcul land loss ratio
for( j=rows.length-3;j>rows.length-8; j--) {
if (rows[j].cells[0].innerHTML.indexOf("Land Capture") != -1) {
j++;
for(; j < rows.length -2; j++) {
landBefo = parseInt(rows[j].cells[4].innerHTML);
landLoss = parseInt(rows[j].cells[6].innerHTML);
rows[j].cells[6].className=rows[j].cells[6].className.substring(0,13)+" red";
rows[j].cells[6].innerHTML = "<B>"+rows[j].cells[6].innerHTML+"</B>"+(isAttacker?"<BR>":" ")+"("+(100*landLoss/landBefo).toFixed(2)+"%)";
}
break;
}
}
// losses evaluation
//
var total = new Array(), losses = new Array();
total[0] = total[1] = losses[0] = losses[1] = 0;
function updateLosses(unit, cells, idx, isAtt) {
var a = cells[idx].firstChild;
if(! a ) return; // no figures in the BR for defenses on the attacker's side
a = Number(a.textContent);
var l = Number(cells[idx+1].firstChild.textContent);
if( a == 0 ) return;
cells[idx+1].title = Math.round(100*l/a) + '% (' + evoNumber2String(Math.abs(l) * (unit.metal + unit.mineral)) + ')';
// take captures into account for the global stats
total[isAtt] += (a + Number(cells[idx+3].firstChild.textContent)) * (unit.metal + unit.mineral);
losses[isAtt] += (l + Number(cells[idx+2].firstChild.textContent)) * (unit.metal + unit.mineral);
}
for (j = 3; j < rows.length; j++) {
unit = rows[j].cells[0].innerHTML.toLowerCase();
if (unit == '') break;
unit = units[unit];
if (!unit) continue; // unknown unit?
updateLosses(unit, rows[j].cells, 1, 0);
updateLosses(unit, rows[j].cells, 6, 1);
}
battleReport.insertRow(j+2).innerHTML = '<TD class="row1 b"></TD><TD class="red_bg_row1 b">' + evoNumber2String(total[0]) + '</TD><TD class="red_bg_row1 b red" colspan="4">' + evoNumber2String(losses[0]) + ' (' + (losses[0]==0?0:Math.round(100*losses[0]/total[0])) + '%)</TD>'
+ '<TD class="green_bg_row1 b">' + evoNumber2String(total[1]) + '</TD><TD class="green_bg_row1 b red" colspan="4">' + evoNumber2String(losses[1]) + ' (' + (losses[1]==0?0:Math.round(100*losses[1]/total[1])) + '%)</TD>';
}
}
//
// Rankings page
//
regPageHandler(/^\/rankings\/alliance$/i, evoRankings);
regPageHandler(/^\/rankings\/continent$/i, evoContRankings);
function evoRankings() {
var row;
var score;
var land;
var members;
var rows = document.evaluate(".//table/tbody[tr/td[text()='Alliance Name']]/tr[count(td)=5]", contents, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i = 2; row = rows.snapshotItem(i); i++ ) {
members = row.cells[2].textContent;
score = evoString2Number(row.cells[4].textContent);
land = evoString2Number(row.cells[3].textContent);
row.cells[0].style.textAlign = "center";
row.cells[1].style.padding = "0 2px 0 2px";
row.cells[2].style.textAlign = "center";
row.cells[3].innerHTML = row.cells[3].textContent + "<br><font color='#AAAAFF'>" + evoNumber2String(Math.ceil(land / members)) + "</font>";
row.cells[3].style.textAlign = "right";
row.cells[3].style.padding = "0 2px 0 2px";
row.cells[4].innerHTML = row.cells[4].textContent + "<br><font color='#AAAAFF'>" + evoNumber2String(Math.ceil(score / members)) + "</font>";
row.cells[4].style.textAlign = "right";
row.cells[4].style.padding = "0 2px 0 2px";
}
}
function evoContRankings(){
var smin = Math.ceil(pScore * 0.35);
var tmax = Math.floor(pScore / 0.35);
var rankTable = document.evaluate(".//table[@class='t_little grey_bg']", contents, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
for (var j = 1; j < rankTable.rows.length; j++){
score = rankTable.rows[j].cells[3];
target = evoString2Number(score.textContent);
if( target < smin ){score.style.color = '#CC4411';}
else if( target > tmax ){score.style.color ='#0000FF';}
else{score.style.color = '#00FF00';}
}
}
//
// Notepad, for evo!
//
regPageHandler(null, evoNotepad);
function evoNotepad() {
function toggleNotepad() {
var np = document.getElementById("hide_notepad");
if (np.style.visibility == 'hidden') {
np.style.visibility = 'visible';
} else {
np.style.visibility = 'hidden';
}
}
function saveNotepad() {
GM_setValue('notepad', this.value);
}
function clearNotepad() {
var np = this.nextSibling;
if (confirm('Vider le Pense-b\u00eate?')) {
np.value = '';
GM_setValue('notepad', '');
}
}
var helpMenu = document.evaluate(".//a[@id='openhelppanel']", document, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
var nImg = document.createElement('IMG');
nImg.src = "http://img91.imageshack.us/img91/3329/notepadpi6.png"
nImg.style.marginLeft = '10px';
nImg.style.cursor = 'pointer';
nImg.addEventListener('click', toggleNotepad, false);
helpMenu.parentNode.insertBefore(nImg, helpMenu.nextSibling);
var nDiv = document.createElement('DIV');
nDiv.id = 'hide_notepad';
nDiv.style.width = '177px';
nDiv.style.height = '580px';
nDiv.style.position = 'absolute';
nDiv.style.visibility = 'hidden';
nDiv.style.top = '30px';
nDiv.style.left = '820px';
var hDiv = document.createElement('DIV');
hDiv.style.textAlign = 'left';
hDiv.style.fontSize = '12px';
hDiv.style.fontFamily = 'Verdana';
hDiv.style.fontWeight = 'bold';
hDiv.style.padding = '2px 0px 2px 10px';
hDiv.style.backgroundColor = '#112288';
hDiv.style.color = '#FFFFFF';
hDiv.style.cursor = 'pointer';
hDiv.innerHTML = 'Note rapide';
hDiv.addEventListener('click', clearNotepad, false);
nDiv.appendChild(hDiv);
var ele = document.createElement('TEXTAREA');
ele.style.backgroundColor = '#DDEEFF';
ele.style.fontSize = '10px';
ele.style.fontFamily = 'Verdana';
ele.style.color = '#000000';
ele.cols = 29;
ele.rows = 10;
ele.id = 'notepad';
ele.wrap = 'virtual';
ele.value = GM_getValue('notepad', '');
ele.addEventListener('blur', saveNotepad, false);
nDiv.appendChild(ele);
var tb = document.getElementById("userinfocontents");
tb.appendChild(nDiv);
}
//
// ***************************************************************************
// ** CONFIG
// ***************************************************************************
//
GM_registerMenuCommand( "Configurer les Boosts...", evoConfigBoosts, null, null, 'b' );
function evoConfigBoosts() {
var n;
if( (n = prompt("Boost pour les Cr\u00e9atures Naturelles ? (e.g. 39.46625)", boosts[UT_NATURAL]*100)) != null && !isNaN(n = Number(n)) )
GM_setValue('boostNat', String(n/100));
if( (n = prompt("Boost pour les Cr\u00e9atures Arch\u00e9ologiques ? (e.g. 33.126875)", boosts[UT_ENG]*100)) != null && !isNaN(n = Number(n)) )
GM_setValue('boostEng', String(n/100));
alert("Recharger la page pour que les changements s'effectuent.");
}
//
// ***************************************************************************
// ** MAIN
// ***************************************************************************
//
(function () {
var totalPlayers = null;
var match;
var node;
var panel;
var menuCC;
var s;
var profiler = Date.now();
// Initialization
menuCC = document.getElementById("commandHeader");
if( menuCC != null ) {
s = menuCC.textContent;
s = s.replace("Centre de commande"," Actions");
menuCC.textContent = s;
};
menuCC = document.getElementById("expansionHeader");
if( menuCC != null ) {
s = menuCC.textContent;
s = s.replace("Extension"," Croissance");
menuCC.textContent = s;
};
// -----------------------------------------------------------------------
// contents node
contents = document.getElementById("content");
// get out of the bloody forums message editor
if( contents == null ) return;
// initialize the units table
evoUnitsInitialize();
// grab player's available resources
panel = document.getElementById("openpanel");
if( panel != null ) {
match = panel.textContent.match(/M.tal:\s+([\d,]+)\s+Min.ral:\s+([\d,]+)\s+Nourriture:\s+([\d,]+)\s+Or:\s+([\d,]+)\s+Score:\s+([\d,]+)/);
unsafeWindow.evo_plus['pMetal'] = pMetal = evoString2Number(match[1]);
unsafeWindow.evo_plus['pMineral'] = pMineral = evoString2Number(match[2]);
unsafeWindow.evo_plus['pFood'] = pFood = evoString2Number(match[3]);
unsafeWindow.evo_plus['pScore'] = pScore = evoString2Number(match[5]);
}
// ranking
panel = document.evaluate("//div[@id='panelinfo']/table/tbody/tr/td[2]/p", document, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null).singleNodeValue;
if( panel != null ) {
if( match = /Classement\s+actuel\s:\s+([,0-9]+)\s+sur\s+([,0-9]+)/.exec(panel.textContent) ) {
pRank = match[1];
totalPlayers = match[2];
}
}
// coords
unsafeWindow.evo_plus.coords = GM_getValue(dEvo?'devoCoords':'evoCoords');
// Dispatch
// -----------------------------------------------------------------------
for(var i = 0; i < pageHandlers.length; i++ ) {
if( pageHandlers[i].urlRegEx == null || pageHandlers[i].urlRegEx.test(document.location.pathname) )
pageHandlers[i].handler();
}
// THE evo+ bar
// -----------------------------------------------------------------------
node = document.createElement('DIV');
node.style.textAlign="right";
node.style.marginRight="5px";
node.style.marginTop="3px";
node.style.marginBottom="3px";
function addItemToContent(c, text, className, html, isLastItem) {
c.appendChild(document.createTextNode(text));
var span = document.createElement('SPAN');
span.className = className;
if (isLastItem)
html += " | ";
span.innerHTML = html;
c.appendChild(span);
}
addItemToContent(node, 'Classement: ', 't_normal b', pRank + "/" + totalPlayers, true);
addItemToContent(node, 'Score Min. Cible: ', 't_normal b', evoNumber2String(Math.ceil(pScore * 0.35)), true);
addItemToContent(node, 'Score Max. Attaquant: ', 't_normal b', evoNumber2String(Math.floor(pScore / 0.35)), false);
contents.parentNode.insertBefore(node, contents);
node = document.createElement('DIV');
node.style.color = "#6A9C01";
node.style.fontSize = "8pt"; node.style.fontWeight = "bold";
node.style.paddingLeft = "3px"; node.style.paddingTop = "3px";
node.style.position = "absolute";
node.innerHTML = scriptversionID;
node.title = scriptTag;
node.id = "evomagik";
panel = document.getElementById('userinfo');
panel.parentNode.insertBefore(node, panel);
profiler = Date.now() - profiler;
// GM_log('evo+ exec time: ' + profiler + ' ms');
}) ();
//
// ***************************************************************************
// ** Helper functions
// ***************************************************************************
function gcf(a,b){while(b!=0){t=a%b;a=b;b=t}return a;}
function evoLayoutChanged() {
alert('Oops.. La structure de page est inconnue, Neon a peut \u00eatre chang\u00e9 la page :(');
}
function evoNumber2String(num) {
var re = /(\d+)(\d{3})/g;
num = String(num);
var decimalIdx = num.indexOf('.');
var part1 = '1', part2="";
if( decimalIdx != -1 ) {
part1 = num.substring(0, decimalIdx);
part2 = num.substring(decimalIdx + 1, num.length);
}
else
part1 = num;
while( re.test(part1) )
part1 = part1.replace(re, '$1,$2');
return part2 == "" ? part1 : part1 + "." + part2;
}
function evoString2Number(num) {
return Number(num.replace(/,/g,''));
}
function evoFromatNumberZ(num, zeros) {
var str = "0000" + Math.floor(Math.abs(num));
return str.substr(-zeros);
}
//
// ***************************************************************************
// ** Objects
// ***************************************************************************
// evoUnit
function evoUnit(unitName, unitType, ticks, metal, mineral, attack, defense, intel, weight, defenseBoost, eats) {
this.unitName = unitName;
this.unitType = unitType;
this.defense = defense;
this.attack = attack;
this.metal = metal;
this.ticks = ticks;
this.intel = intel;
this.weight = weight;
this.mineral = mineral;
this.eats = eats;
this.defenseBoost = defenseBoost/100 + 1;
return this;
}
//
// Page Handler hooks
function pageHandler(urlRegEx, handler) {
this.urlRegEx = urlRegEx;
this.handler = handler;
}
function regPageHandler(urlRegEx, handler) {
pageHandlers.push(new pageHandler(urlRegEx, handler));
}
//
// ***************************************************************************
// ** MISC
// ***************************************************************************
// GM implementation of cookies :)
function evoSetCookie(name, value, hours) {
GM_setValue('cv_' + name, value);
var expire = new Date();
expire.setUTCHours(expire.getUTCHours() + hours);
GM_setValue('cx_' + name, expire.toGMTString());
}
function evoGetCookie(name) {
var value = GM_getValue('cv_' + name);
var expire = GM_getValue('cx_' + name);
if( value != null && expire != null ) {
expire = new Date(expire);
if( expire.valueOf() >= Date.now() ) return value;
}
return null;
}
//
// ***************************************************************************
// ** Evo units stats
// ***************************************************************************
function evoUnitsInitialize() {
evoUnit.prototype.getFoodCost = function(count) {
return this.eats?count * (this.mineral+this.metal)/100:0;
}
evoUnit.prototype.getAttackScore = function(count) {
return count * this.attack * this.attack;
}
evoUnit.prototype.getDefenseScore = function(count) {
//Changed to reflect correct formula, Thanks to Mefisto of Alexandria
return count * this.defense * this.defense * this.defenseBoost;
}
evoUnit.prototype.getMaxUnits = function (metal, mineral) {
if( this.unitType == UT_NATURAL )
return Math.min(Math.floor(metal / (this.metal * eeb)), Math.floor(mineral / (this.mineral * eeb)));
else
return Math.min(Math.floor(metal / this.metal), Math.floor(mineral / this.mineral));
}
evoUnit.prototype.getMetal = function() {
return this.unitType == UT_NATURAL ? (this.metal * eeb) : this.metal;
}
evoUnit.prototype.getMineral = function() {
return this.unitType == UT_NATURAL ? (this.mineral * eeb) : this.mineral;
}
evoUnit.prototype.getMaxBoost = function() {
return maxBoosts[this.unitType];
}
evoUnit.prototype.getBoost = function() {
return boosts[this.unitType];
}
if(! dEvo ) {
units['monkey'] = new evoUnit('Monkey' ,UT_NATURAL ,4 ,500 ,250 ,4 ,4 ,4 ,0 ,40 ,true);
units['sheep'] = new evoUnit('Sheep' ,UT_NATURAL ,5 ,3000 ,1500 ,13 ,9 ,7 ,0 ,40 ,true);
units['horse'] = new evoUnit('Horse' ,UT_NATURAL ,6 ,4000 ,2000 ,15 ,10 ,8 ,1 ,40 ,true);
units['cow'] = new evoUnit('Cow' ,UT_NATURAL ,6 ,4500 ,2500 ,16 ,8 ,7 ,1 ,40 ,true);
units['fox'] = new evoUnit('Fox' ,UT_NATURAL ,10 ,10000 ,4000 ,25 ,23 ,18 ,0 ,40 ,true);
units['hyena'] = new evoUnit('Hyena' ,UT_NATURAL ,11 ,11000 ,4500 ,28 ,26 ,12 ,0 ,40 ,true);
units['wolf'] = new evoUnit('Wolf' ,UT_NATURAL ,12 ,12000 ,5000 ,30 ,25 ,18 ,0 ,40 ,true);
units['python'] = new evoUnit('Python' ,UT_NATURAL ,12 ,18000 ,7500 ,45 ,35 ,10 ,1 ,40 ,true);
units['ostrich'] = new evoUnit('Ostrich' ,UT_NATURAL ,13 ,19000 ,8000 ,48 ,37 ,11 ,2 ,40 ,true);
units['kangaroo'] = new evoUnit('Kangaroo' ,UT_NATURAL ,14 ,28000 ,14000 ,55 ,55 ,7 ,1 ,40 ,true);
units['lynx'] = new evoUnit('Lynx' ,UT_NATURAL ,15 ,20000 ,9000 ,50 ,38 ,12 ,1 ,40 ,true);
units['puma'] = new evoUnit('Puma' ,UT_NATURAL ,15 ,20000 ,8000 ,45 ,40 ,12 ,1 ,40 ,true);
units['lion'] = new evoUnit('Lion' ,UT_NATURAL ,15 ,20000 ,9000 ,42 ,45 ,12 ,1 ,40 ,true);
units['panther'] = new evoUnit('Panther' ,UT_NATURAL ,16 ,25000 ,12500 ,30 ,60 ,12 ,1 ,40 ,true);
units['bear'] = new evoUnit('Bear' ,UT_NATURAL ,16 ,30000 ,15000 ,60 ,50 ,17 ,2 ,40 ,true);
units['cheetah'] = new evoUnit('Cheetah' ,UT_NATURAL ,18 ,25000 ,12500 ,60 ,25 ,12 ,1 ,40 ,true);
units['walrus'] = new evoUnit('Walrus' ,UT_NATURAL ,19 ,44000 ,22000 ,70 ,50 ,7 ,2 ,40 ,true);
units['tiger'] = new evoUnit('Tiger' ,UT_NATURAL ,20 ,30000 ,15000 ,55 ,55 ,14 ,1 ,40 ,true);
units['rhino'] = new evoUnit('Rhino' ,UT_NATURAL ,24 ,60000 ,36000 ,80 ,40 ,2 ,3 ,40 ,true);
units['elephant'] = new evoUnit('Elephant' ,UT_NATURAL ,24 ,52000 ,26000 ,75 ,55 ,7 ,4 ,40 ,true);
units['centaur'] = new evoUnit('Centaur' ,UT_ENG ,6 ,5000 ,2500 ,25 ,20 ,19 ,1 ,40 ,true);
units['unicorn'] = new evoUnit('Unicorn' ,UT_ENG ,8 ,12000 ,6000 ,40 ,30 ,20 ,1 ,40 ,true);
units['minotaur'] = new evoUnit('Minotaur' ,UT_ENG ,18 ,50000 ,25000 ,65 ,50 ,13 ,2 ,40 ,true);
units['gryphon'] = new evoUnit('Gryphon' ,UT_ENG ,14 ,28000 ,14000 ,55 ,40 ,18 ,2 ,40 ,true);
units['dragon'] = new evoUnit('Dragon' ,UT_ENG ,24 ,100000 ,50000 ,85 ,65 ,10 ,3 ,40 ,true);
units['fire sprite'] = new evoUnit('Fire Sprite' ,UT_ENG ,5 ,6000 ,3000 ,35 ,17 ,14 ,0 ,40 ,true);
units['salamander'] = new evoUnit('Salamander' ,UT_ENG ,7 ,15000 ,7500 ,56 ,26 ,15 ,1 ,40 ,true);
units['phoenix'] = new evoUnit('Phoenix' ,UT_ENG ,12 ,36000 ,18000 ,77 ,35 ,14 ,1 ,40 ,true);
units['wyvern'] = new evoUnit('Wyvern' ,UT_ENG ,14 ,64000 ,32000 ,91 ,45 ,10 ,2 ,40 ,true);
units['demon'] = new evoUnit('Demon' ,UT_ENG ,21 ,140000 ,70000 ,119 ,59 ,7 ,3 ,40 ,true);
units['dyrad'] = new evoUnit('Dyrad' ,UT_ENG ,6 ,4000 ,3750 ,28 ,22 ,21 ,1 ,40 ,true);
units['baskilisk'] = new evoUnit('Baskilisk' ,UT_ENG ,9 ,12000 ,9000 ,44 ,33 ,22 ,1 ,40 ,true);
units['medusa'] = new evoUnit('Medusa' ,UT_ENG ,15 ,30000 ,22500 ,61 ,44 ,20 ,1 ,40 ,true);
units['cockatrice'] = new evoUnit('Cockatrice' ,UT_ENG ,20 ,50000 ,37500 ,71 ,55 ,14 ,2 ,40 ,true);
units['werewolf'] = new evoUnit('Werewolf' ,UT_ENG ,26 ,100000 ,75000 ,85 ,65 ,12 ,2 ,40 ,true);
units['avimimus'] = new evoUnit('Avimimus' ,UT_ENG ,5 ,4000 ,2000 ,23 ,18 ,12 ,1 ,40 ,true);
units['therizinsaurus'] = new evoUnit('Therizinsaurus' ,UT_ENG ,7 ,9600 ,4800 ,36 ,28 ,13 ,1 ,40 ,true);
units['styracosaurus'] = new evoUnit('Styracosaurus' ,UT_ENG ,13 ,22400 ,11200 ,50 ,35 ,10 ,2 ,40 ,true);
units['carnotaurus'] = new evoUnit('Carnotaurus' ,UT_ENG ,15 ,40000 ,20000 ,58 ,45 ,6 ,3 ,40 ,true);
units['giganotosaurus'] = new evoUnit('Giganotosaurus' ,UT_ENG ,20 ,80000 ,40000 ,77 ,58 ,2 ,4 ,40 ,true);
units['scarab beetle'] = new evoUnit('Scarab Beetle' ,UT_ENG ,8 ,6500 ,3250 ,30 ,26 ,19 ,0 ,40 ,true);
units['mummy'] = new evoUnit('Mummy' ,UT_ENG ,12 ,16000 ,8000 ,52 ,39 ,13 ,1 ,40 ,true);
units['sta'] = new evoUnit('Sta' ,UT_ENG ,18 ,38000 ,19000 ,72 ,52 ,12 ,1 ,40 ,true);
units['sphinx'] = new evoUnit('Sphinx' ,UT_ENG ,22 ,70000 ,35000 ,83 ,65 ,18 ,3 ,40 ,true);
units['anubis incarnate'] = new evoUnit('Anubis Incarnate' ,UT_ENG ,32 ,180000 ,90000 ,110 ,83 ,8 ,3 ,40 ,true);
units['fort'] = new evoUnit('Fort' ,UT_NONE ,4 ,2000 ,1000 ,25 ,40 ,0 ,0 ,40 ,false);
units['satellite'] = new evoUnit('Satellite' ,UT_NONE ,6 ,8000 ,4000 ,30 ,35 ,0 ,0 ,40 ,false);
units['nanowire wall'] = new evoUnit('Nanowire wall' ,UT_NONE ,10 ,12000 ,4500 ,65 ,65 ,0 ,0 ,40 ,false);
units['satellite mark 2'] = new evoUnit('Satellite Mark 2' ,UT_NONE ,6 ,8000 ,4000 ,35 ,45 ,0 ,0 ,40 ,false);
units['wave reflector'] = new evoUnit('Wave Reflector' ,UT_NONE ,4 ,2000 ,2000 ,0 ,0 ,0 ,0 ,0 ,false);
units['biochemical missile']=new evoUnit('Biochemical Missile',UT_NONE ,12 ,10000 ,20000 ,0 ,0 ,0 ,0 ,0 ,false);
units['nanovirus missile']= new evoUnit('Nanovirus Missile',UT_NONE ,12 ,30000 ,15000 ,0 ,0 ,0 ,0 ,0 ,false);
units['bombs'] = new evoUnit('Bombs' ,UT_NONE ,12 ,11000 ,7000 ,0 ,0 ,0 ,0 ,0 ,false);
units['neural reorganiser bomb']=new evoUnit('Neural Reorganiser Bomb',UT_NONE,24,50000,32000,0 ,0 ,0 ,0 ,0 ,false);
units['poison bombs'] = new evoUnit('Poison Bombs' ,UT_NONE ,16 ,16000 ,12000 ,0 ,0 ,0 ,0 ,0 ,false);
units['land scan'] = new evoUnit('Land Scan' ,UT_NONE ,4 ,1000 ,2000 ,0 ,0 ,0 ,0 ,0 ,false);
units['scan amplifier'] = new evoUnit('Scan Amplifier' ,UT_NONE ,4 ,1000 ,1000 ,0 ,0 ,0 ,0 ,0 ,false);
units['sector scan'] = new evoUnit('Sector Scan' ,UT_NONE ,8 ,2000 ,4000 ,0 ,0 ,0 ,0 ,0 ,false);
units['creature scan'] = new evoUnit('Creature Scan' ,UT_NONE ,8 ,3000 ,6000 ,0 ,0 ,0 ,0 ,0 ,false);
units['r&d scan'] = new evoUnit('R&D Scan' ,UT_NONE ,6 ,2000 ,3000 ,0 ,0 ,0 ,0 ,0 ,false);
units['news scan'] = new evoUnit('News Scan' ,UT_NONE ,18 ,10000 ,20000 ,0 ,0 ,0 ,0 ,0 ,false);
units['military scan'] = new evoUnit('Military Scan' ,UT_NONE ,12 ,6000 ,12000 ,0 ,0 ,0 ,0 ,0 ,false);
units['microwave pulse'] = new evoUnit('Microwave Pulse' ,UT_NONE ,20 ,520000 ,1040000 ,0 ,0 ,0 ,0 ,0 ,false);
units['overload pulse'] = new evoUnit('Overload Pulse' ,UT_NONE ,24 ,1600000 ,3200000 ,0 ,0 ,0 ,0 ,0 ,false);
} else {
// DEVO Stats
units['monkey'] = new evoUnit('Monkey' ,UT_NATURAL ,4 ,500 ,250 ,5 ,5 ,4 ,0 ,40 ,true);
units['sheep'] = new evoUnit('Sheep' ,UT_NATURAL ,4 ,1500 ,750 ,11 ,11 ,5 ,0 ,40 ,true);
units['horse'] = new evoUnit('Horse' ,UT_NATURAL ,5 ,2000 ,1000 ,13 ,13 ,6 ,1 ,40 ,true);
units['cow'] = new evoUnit('Cow' ,UT_NATURAL ,6 ,4500 ,2500 ,16 ,8 ,7 ,1 ,40 ,true);
units['fox'] = new evoUnit('Fox' ,UT_NATURAL ,9 ,7200 ,3200 ,24 ,25 ,8 ,0 ,40 ,true);
units['hyena'] = new evoUnit('Hyena' ,UT_NATURAL ,10 ,8800 ,3600 ,28 ,27 ,8 ,1 ,40 ,true);
units['wolf'] = new evoUnit('Wolf' ,UT_NATURAL ,10 ,8000 ,3500 ,27 ,25 ,14 ,0 ,40 ,true);
units['python'] = new evoUnit('Python' ,UT_NATURAL ,12 ,12500 ,5000 ,36 ,31 ,7 ,1 ,40 ,true);
units['ostrich'] = new evoUnit('Ostrich' ,UT_NATURAL ,13 ,18000 ,8000 ,43 ,41 ,6 ,2 ,40 ,true);
units['kangaroo'] = new evoUnit('Kangaroo' ,UT_NATURAL ,15 ,17000 ,8000 ,37 ,42 ,5 ,1 ,40 ,true);
units['lynx'] = new evoUnit('Lynx' ,UT_NATURAL ,15 ,12000 ,5500 ,35 ,31 ,10 ,1 ,40 ,true);
units['puma'] = new evoUnit('Puma' ,UT_NATURAL ,13 ,11000 ,5000 ,32 ,32 ,6 ,1 ,40 ,true);
units['lion'] = new evoUnit('Lion' ,UT_NATURAL ,15 ,12000 ,5000 ,31 ,35 ,10 ,1 ,40 ,true);
units['panther'] = new evoUnit('Panther' ,UT_NATURAL ,16 ,14000 ,7000 ,30 ,40 ,6 ,1 ,40 ,true);
units['bear'] = new evoUnit('Bear' ,UT_NATURAL ,16 ,26000 ,13000 ,57 ,50 ,12 ,3 ,40 ,true);
units['cheetah'] = new evoUnit('Cheetah' ,UT_NATURAL ,16 ,14000 ,7000 ,41 ,29 ,5 ,1 ,40 ,true);
units['walrus'] = new evoUnit('Walrus' ,UT_NATURAL ,18 ,28000 ,14000 ,53 ,54 ,4 ,2 ,40 ,true);
units['tiger'] = new evoUnit('Tiger' ,UT_NATURAL ,20 ,18000 ,9000 ,43 ,43 ,11 ,2 ,40 ,true);
units['rhino'] = new evoUnit('Rhino' ,UT_NATURAL ,24 ,28000 ,17000 ,66 ,53 ,3 ,3 ,40 ,true);
units['elephant'] = new evoUnit('Elephant' ,UT_NATURAL ,22 ,40000 ,20000 ,65 ,69 ,21 ,4 ,40 ,true);
units['centaur'] = new evoUnit('Centaur' ,UT_ENG ,5 ,4000 ,2400 ,22 ,23 ,10 ,1 ,40 ,true);
units['unicorn'] = new evoUnit('Unicorn' ,UT_ENG ,8 ,7200 ,3600 ,30 ,25 ,6 ,1 ,40 ,true);
units['minotaur'] = new evoUnit('Minotaur' ,UT_ENG ,12 ,10800 ,5400 ,36 ,35 ,8 ,2 ,40 ,true);
units['gryphon'] = new evoUnit('Gryphon' ,UT_ENG ,18 ,19000 ,9500 ,54 ,43 ,14 ,2 ,40 ,true);
units['dragon'] = new evoUnit('Dragon' ,UT_ENG ,24 ,30000 ,10500 ,76 ,67 ,8 ,3 ,40 ,true);
units['fire sprite'] = new evoUnit('Fire Sprite' ,UT_ENG ,5 ,5000 ,2500 ,25 ,18 ,4 ,0 ,40 ,true);
units['salamander'] = new evoUnit('Salamander' ,UT_ENG ,7 ,9000 ,4500 ,36 ,26 ,10 ,1 ,40 ,true);
units['phoenix'] = new evoUnit('Phoenix' ,UT_ENG ,12 ,14600 ,7300 ,44 ,35 ,6 ,1 ,40 ,true);
units['wyvern'] = new evoUnit('Wyvern' ,UT_ENG ,14 ,25000 ,17500 ,69 ,45 ,7 ,2 ,40 ,true);
units['demon'] = new evoUnit('Demon' ,UT_ENG ,21 ,36000 ,18000 ,96 ,60 ,5 ,3 ,40 ,true);
units['dryad'] = new evoUnit('Dryad' ,UT_ENG ,6 ,3600 ,2700 ,21 ,21 ,13 ,1 ,40 ,true);
units['basilisk'] = new evoUnit('Basilisk' ,UT_ENG ,9 ,6000 ,4500 ,29 ,24 ,21 ,1 ,40 ,true);
units['medusa'] = new evoUnit('Medusa' ,UT_ENG ,15 ,10000 ,7500 ,37 ,34 ,15 ,1 ,40 ,true);
units['cockatrice'] = new evoUnit('Cockatrice' ,UT_ENG ,20 ,18000 ,13500 ,54 ,45 ,23 ,2 ,40 ,true);
units['werewolf'] = new evoUnit('Werewolf' ,UT_ENG ,26 ,28000 ,18500 ,71 ,65 ,30 ,2 ,40 ,true);
units['avimimus'] = new evoUnit('Avimimus' ,UT_ENG ,5 ,3700 ,1850 ,22 ,17 ,2 ,1 ,40 ,true);
units['therizinsaurus'] = new evoUnit('Therizinsaurus' ,UT_ENG ,7 ,5000 ,2500 ,23 ,22 ,3 ,1 ,40 ,true);
units['styracosaurus'] = new evoUnit('Styracosaurus' ,UT_ENG ,13 ,9000 ,4500 ,32 ,41 ,8 ,2 ,40 ,true);
units['carnotaurus'] = new evoUnit('Carnotaurus' ,UT_ENG ,15 ,15000 ,7500 ,48 ,55 ,5 ,3 ,40 ,true);
units['giganotosaurus'] = new evoUnit('Giganotosaurus' ,UT_ENG ,20 ,24000 ,12000 ,74 ,58 ,4 ,4 ,40 ,true);
units['scarab beetle'] = new evoUnit('Scarab Beetle' ,UT_ENG ,8 ,6000 ,3000 ,26 ,23 ,7 ,0 ,40 ,true);
units['mummy'] = new evoUnit('Mummy' ,UT_ENG ,12 ,11000 ,5500 ,36 ,34 ,1 ,0 ,40 ,true);
units['sta'] = new evoUnit('Sta' ,UT_ENG ,18 ,18000 ,9000 ,45 ,42 ,12 ,1 ,40 ,true);
units['sphinx'] = new evoUnit('Sphinx' ,UT_ENG ,22 ,28000 ,14000 ,67 ,56 ,4 ,3 ,40 ,true);
units['anubis incarnate'] = new evoUnit('Anubis Incarnate' ,UT_ENG ,32 ,42000 ,21000 ,93 ,78 ,8 ,3 ,40 ,true);
units['fort'] = new evoUnit('Fort' ,UT_NONE ,4 ,2000 ,1000 ,25 ,40 ,0 ,0 ,215 ,false);
units['satellite'] = new evoUnit('Satellite' ,UT_NONE ,6 ,8000 ,4000 ,30 ,35 ,0 ,0 ,215 ,false);
units['nanowire wall'] = new evoUnit('Nanowire wall' ,UT_NONE ,10 ,12000 ,4500 ,65 ,65 ,0 ,0 ,215 ,false);
units['satellite mark 2'] = new evoUnit('Satellite Mark 2' ,UT_NONE ,6 ,8000 ,4000 ,35 ,45 ,0 ,0 ,215 ,false);
units['wave reflector'] = new evoUnit('Wave Reflector' ,UT_NONE ,4 ,2000 ,2000 ,0 ,0 ,0 ,0 ,0 ,false);
units['biochemical missile']=new evoUnit('Biochemical Missile',UT_NONE ,12 ,10000 ,20000 ,0 ,0 ,0 ,0 ,0 ,false);
units['nanovirus missile']= new evoUnit('Nanovirus Missile',UT_NONE ,12 ,30000 ,15000 ,0 ,0 ,0 ,0 ,0 ,false);
units['bombs'] = new evoUnit('Bombs' ,UT_NONE ,12 ,11000 ,7000 ,0 ,0 ,0 ,0 ,0 ,false);
units['neural reorganiser bomb']=new evoUnit('Neural Reorganiser Bomb',UT_NONE,24,50000,32000,0 ,0 ,0 ,0 ,0 ,false);
units['poison bombs'] = new evoUnit('Poison Bombs' ,UT_NONE ,16 ,16000 ,12000 ,0 ,0 ,0 ,0 ,0 ,false);
units['land scan'] = new evoUnit('Land Scan' ,UT_NONE ,4 ,1000 ,2000 ,0 ,0 ,0 ,0 ,0 ,false);
units['scan amplifier'] = new evoUnit('Scan Amplifier' ,UT_NONE ,4 ,1000 ,1000 ,0 ,0 ,0 ,0 ,0 ,false);
units['sector scan'] = new evoUnit('Sector Scan' ,UT_NONE ,8 ,2000 ,4000 ,0 ,0 ,0 ,0 ,0 ,false);
units['creature scan'] = new evoUnit('Creature Scan' ,UT_NONE ,8 ,3000 ,6000 ,0 ,0 ,0 ,0 ,0 ,false);
units['r&d scan'] = new evoUnit('R&D Scan' ,UT_NONE ,6 ,2000 ,3000 ,0 ,0 ,0 ,0 ,0 ,false);
units['news scan'] = new evoUnit('News Scan' ,UT_NONE ,18 ,10000 ,20000 ,0 ,0 ,0 ,0 ,0 ,false);
units['military scan'] = new evoUnit('Military Scan' ,UT_NONE ,12 ,6000 ,12000 ,0 ,0 ,0 ,0 ,0 ,false);
units['microwave pulse'] = new evoUnit('Microwave Pulse' ,UT_NONE ,20 ,520000 ,1040000 ,0 ,0 ,0 ,0 ,0 ,false);
units['overload pulse'] = new evoUnit('Overload Pulse' ,UT_NONE ,24 ,1600000 ,3200000 ,0 ,0 ,0 ,0 ,0 ,false);
}
unsafeWindow.evo_plus['units'] = units;
}
GM_log("evofr+ Finished");