NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name WFTargettingScore
// @namespace sk.seko
// @description Computes targetting score for ship design.
// @include http://*.war-facts.com/ship_designs.php*
// @grant none
// @version 2.6
// ==/UserScript==
// Version 1.0 = grab params from displayed design, calculate targeting score and display it
// Version 2.0 = added support for "dynamic" display, i.e. during design creation
// Version 2.1 = fixed sliders and input fields for armor/shields
// Version 2.2 = fixed keyboard input
// Version 2.3 = fixed float vs. int speed issue, and fixed score display during ship design
// Version 2.4 = fixed formula for H5 (it has been changed, apparently!)
// Version 2.5 = fixed html/css changes in H6
// Version Screwup = Quick hack to work with new design - prosoft
// ----------------------------------------------------------------------------------------
// Note for v2.4:
// TS value calculated (and displayed) on View ship class screen is not accurate, i.e. real
// TS is probably lower. This is because formula is using 'Hull mass', not 'Total mass' and
// there is no way to find you what hull mass exactly is. This is only possible on Ship
// design screen, for wich TS displayed should be correct. Sorry for inconveniece!
// - Seko
// ----------------------------------------------------------------------------------------
function eval(s) {
if (s) {return Math.round(parseFloat(s.replace(/[,]/g,'')));}
return 0;
}
function evalNode(node) {
if (node) {return eval(node.data.split(" ")[0]);}
return 0.0;
}
// returns number formatted with commas, like 1234567 => "1,234,567"
function addCommas(nStr) {
var x = nStr.split('.');
var x1 = x[0];
var x2 = x.length > 1 ? '.' + x[1] : '';
var rgx = /(\d+)(\d{3})/;
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + ',' + '$2');
}
return x1 + x2;
}
// calculate targeting score and return it as formatted string
function calculateAndFormatTS(firepower, base_armor, base_shield, hull_mass, speed) {
// =====================================================================================
// THIS is formula for targetting score (TS); it can change in the future instances :-(
// =====================================================================================
var ts = firepower * ((base_armor + base_shield + hull_mass - speed) / 2);
//alert('fire=' + firepower + ', armor=' + base_armor + ', shield=' + base_shield + ', mass=' + hull_mass + ', speed=' + speed + ', ts=' + ts);
return addCommas(String(ts));
}
/* I don't care about incorrect targetting scores, it just makes people compare the wrong shit.
// grab params and compute targeting score for existing design
window.grabAndCalculateStatic = function() {
// GET SHIP DESIGN ATTRIBUTES
var speed = evalNode(document.evaluate("//td[(child::text() = 'Cruise Speed:')]/following-sibling::node()/child::text()",
document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue);
var fireIter = document.evaluate("//td[(child::text() = 'Full Strike:')]/following-sibling::node()/child::text()",
document, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
var fire = 0.0;
var fireVal = fireIter.iterateNext();
while (fireVal) {
if (fireVal.nodeValue && fireVal.nodeValue.replace(/\s/,'') != '') {
fire += evalNode(fireVal);
}
fireVal = fireIter.iterateNext();
}
var shield = evalNode(document.evaluate("//td[(child::text() = 'Shield:')]/following-sibling::node()/child::text()",
document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue);
var armor = evalNode(document.evaluate("//td[(child::text() = 'Armor:')]/following-sibling::node()/child::text()",
document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue);
var mass = evalNode(document.evaluate("//td[(child::text() = 'Mass:')]/following-sibling::node()/child::text()",
document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue);
// CALCULATE TARGETING SCORE
return calculateAndFormatTS(fire, armor, shield, mass, speed);
}
*/
// compute targeting score for ship being designed
window.grabAndCalculateDynamic = function() {
// GET SHIP DESIGN ATTRIBUTES
var speed = evalNode(document.evaluate("//span[@id='drivespeed']/child::text()",
document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue);
var firegun = evalNode(document.evaluate("//span[@id='vgunAstrike']/child::text()",
document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue);
var firecannon = evalNode(document.evaluate("//span[@id='vcannonAstrike']/child::text()",
document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue);
var shield = evalNode(document.evaluate("//span[@id='veffshield']/child::text()",
document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue);
var armor = evalNode(document.evaluate("//span[@id='veffarmor']/child::text()",
document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue);
var mass = eval(document.evaluate("//div[text()[contains(.,'Hull Mass')]]",
document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.innerHTML.split(" ")[2]);
// CALCULATE TARGETING SCORE
var fire = (firecannon ? firecannon : 0.0) + (firegun ? firegun : 0.0);
document.getElementById("massused").innerHTML = mass;
document.getElementById("speedused").innerHTML = speed;
document.getElementById("fireused").innerHTML = fire;
document.getElementById("armorused").innerHTML = armor;
document.getElementById("shieldused").innerHTML = shield;
return calculateAndFormatTS(fire, armor, shield, mass, speed);
}
// compute and display targeting score for ship being designed
window.processDynamic = function() {
var ts = grabAndCalculateDynamic();
document.getElementById("targetingscore").innerHTML = ts
}
function insertAfter(newNode, referenceNode) {
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}
/*
// displays targeting score as a table row
window.displayTS = function(tablerow, ts) {
var ncol1 = document.createElement('td');
ncol1.setAttribute("class","strong");
ncol1.appendChild(document.createTextNode('Targeting Score:'));
var ncol2 = document.createElement('td');
ncol2.setAttribute("colspan", "3");
var scoreElem = document.createTextNode(ts);
ncol2.appendChild(scoreElem);
var nrow = document.createElement('tr');
nrow.appendChild(ncol1);
nrow.appendChild(ncol2);
tablerow.parentNode.insertBefore(nrow, tablerow);
return scoreElem;
}
// compute and display targeting score for existing design
window.processStatic = function() {
// check if this is design is displayed
//var tablerow = document.evaluate("//center/table/tbody/tr[2]",
var check = document.evaluate("//input[@value='Delete Design']",
document, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null).iterateNext();
if (!check) {
return; // design is not displayed, just quit
}
var tablerow = document.evaluate("//center/table/tbody/tr[2]",
document, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null).iterateNext();
if (!tablerow) {
return; // something wrong, just quit
}
// calculate targeting score
var ts = grabAndCalculateStatic();
// DISPLAY TARGETING SCORE
displayTS(tablerow, 'less than ' + ts);
}
// adds 'processDynamic' callback to all elements matching elements event
window.registerDynamicElements = function(xpath, attr) {
var it = document.evaluate(xpath, document, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
if (it) {
var b = it.iterateNext();
var elems = [];
while (b) {
elems.push(b);
b = it.iterateNext();
}
for (x in elems) {
elems[x].setAttribute(attr,elems[x].getAttribute(attr) + ";setTimeout(\"processDynamic()\", 100);");
}
}
}
*/
// compute and display targeting score for existing design
window.initializeScript = function() {
var massdiv = document.createElement("div");
massdiv.className = "padding5 light tbborder";
massdiv.innerHTML = 'Mass Used: <span id="massused"></span>';
var speeddiv = document.createElement("div");
speeddiv.className = "padding5 light tbborder";
speeddiv.innerHTML = 'Speed Used: <span id="speedused"></span>';
var firediv = document.createElement("div");
firediv.className = "padding5 light tbborder";
firediv.innerHTML = 'Fire Used: <span id="fireused"></span>';
var shielddiv = document.createElement("div");
shielddiv.className = "padding5 light tbborder";
shielddiv.innerHTML = 'Shield Used: <span id="shieldused"></span>';
var armordiv = document.createElement("div");
armordiv.className = "padding5 light tbborder";
armordiv.innerHTML = 'Armor Used: <span id="armorused"></span>';
insertAfter(shielddiv, document.getElementById("targetingscore").parentNode);
insertAfter(armordiv, document.getElementById("targetingscore").parentNode);
insertAfter(firediv, document.getElementById("targetingscore").parentNode);
insertAfter(speeddiv, document.getElementById("targetingscore").parentNode);
insertAfter(massdiv, document.getElementById("targetingscore").parentNode);
}
document.onclick = function(){
if(evalNode(document.evaluate("//span[@id='drivespeed']/child::text()",
document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue) != 0) {
processDynamic();
}
}
//document.getElementById("targetingscore").insertAdjacentHTML( 'beforeBegin', '<input type="button" value="Update Score" onclick="processDynamic();">' );
if( document.location.href.indexOf('designid') == -1 ) {
initializeScript();
}
//window.addEventListener("load", initializeScript, false);