This modifies the combat calculator to take into account.
- Attacker’s ETA
- Defender’s industry, manufacturing, and new ships created
Basically given a time until combat (ETA) it will add new ships created by the defender during that time:
The problem with this before was no access to the decimal number of partially constructed ships on a star. Now, it appears that information is exposed.
Let me know what you think!
Bookmarklet (remove leading ‘+’):
+javascript:(function(){var e=NeptunesPride.universe,t=NeptunesPride.npui;t.CombatCalc=function(){var r=10,a=0,c=1,o=1,d=0,n=0,s=NeptunesPride.gameConfig.productionTicks;e.selectedSpaceObject&&(r=e.selectedSpaceObject.st,"star"===e.selectedSpaceObject.kind&&(r=e.selectedSpaceObject.totalDefenses,a=e.selectedSpaceObject.c,d=e.selectedSpaceObject.i),e.selectedSpaceObject.player&&(c=e.selectedSpaceObject.player.tech.weapons.value,o=e.selectedSpaceObject.player.tech.manufacturing.value));var i=t.Screen("combat_calculator"),u=Crux.Widget("rel").roost(i),x=0,p=30,l=20,g=10,T=3,_=.5,f=1.5,C=3;Crux.Text("defender_weapon_tech","pad12 col_accent").grid(x,C,p,T).roost(i),i.defenderWeaponsUI=Crux.TextInput(!0,!0).setText(c).grid(l,C,g,T).roost(i),C+=T,Crux.Text("defender_ships","pad12 col_accent").grid(x,C,p,T).roost(i),i.defenderShipsUI=Crux.TextInput(!0,!0).setText(r).grid(l,C,g,T).roost(i),C+=T,Crux.Text("","pad12 col_accent").grid(x,C,p,T).rawHTML("Defender Industry").roost(i),i.defenderIndustryUI=Crux.TextInput(!0,!0).setText(d).grid(l,C,g,T).roost(i),C+=T,Crux.Text("","pad12 col_accent").grid(x,C,p,T).rawHTML("Defender Manufacturing").roost(i),i.defenderManufacturingUI=Crux.TextInput(!0,!0).setText(o).grid(l,C,g,T).roost(i),C+=T,Crux.Text("defender_ships_bonus","pad12 col_accent").grid(x,C,p,T).roost(i),Crux.Text("","pad4 col_base rad4 txt_center").grid(l,C,g,T).inset(8).rawHTML("+1 Weapons").roost(i),C+=T,Crux.Widget("col_black").grid(x,C,p,_).roost(i),C+=f,Crux.Text("attacker_weapon_tech","pad12 col_accent").grid(x,C,p,T).roost(i),i.attackerWeaponsUI=Crux.TextInput(!0,!0).setText(c).grid(l,C,g,T).roost(i),C+=T,Crux.Text("attacker_ships","pad12 col_accent").grid(x,C,p,T).roost(i),i.attackerShipsUI=Crux.TextInput(!0,!0).setText(r).grid(l,C,g,T).roost(i),C+=T,Crux.Text("eta","pad12 col_accent").grid(x,C,p,T).roost(i),i.attackerEtaUI=Crux.TextInput(!0,!0).setText(n).grid(l,C,g,T).roost(i),C+=T,Crux.Widget("col_black").grid(x,C,p,_).roost(i),C+=f,Crux.Button("fight","pre_calculate_combat").grid(l,C,g,T).roost(i),C+=T+1,i.result=Crux.Text("","pad12 col_accent txt_center").grid(x,C,p,T).rawHTML("").roost(i);var I=T+1;C+=I;var b=I*Crux.gridSize,S=p*Crux.gridSize,h=C*Crux.gridSize,k=48;return i.size(S,h-b),u.size(S,h-k),i.onPreCalcCombat=function(){var e=i.defenderShipsUI.getText(),t=1+i.defenderWeaponsUI.getText(),r=i.defenderIndustryUI.getText(),c=i.defenderManufacturingUI.getText(),o=i.attackerEtaUI.getText();o>0&&--o;var d=r*(c+5)/s,n=d*o;e=Math.floor(e+a+n);var u=i.attackerWeaponsUI.getText(),x=i.attackerShipsUI.getText();if(i.defenderShipsUI.setText(e),i.attackerEtaUI.setText(0),0===e||0===x)return void i.result.update("combat_calc_no_combat");for(var p="";!p;){if(x-=t,0>=x){p="combat_calc_win_defend";break}if(e-=u,0>=e){p="combat_calc_win_attack";break}}var l={};l.as=x,l.ds=e,i.result.updateFormat(p,l),i.h<h&&i.size(i.w,h)},i.on("pre_calculate_combat",i.onPreCalcCombat),i},NeptunesPride.np.trigger("map_refresh")})();
See the top of this post for information on how to create the bookmarklet.
Un-minified code:
// MIT License
//
// Copyright (c) 2016 Jay Kyburz, Dakota Hawkins
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
(function () {
var universe = NeptunesPride.universe;
var npui = NeptunesPride.npui;
npui.CombatCalc = function () {
var defenderShips = 10;
var defenderPartialShips = 0;
var defenderWeapons = 1;
var defenderManufacturing = 1;
var defenderIndustry = 0;
var attackerEta = 0;
var productionTicks = NeptunesPride.gameConfig.productionTicks;
if (universe.selectedSpaceObject) {
defenderShips = universe.selectedSpaceObject.st;
if (universe.selectedSpaceObject.kind === "star") {
defenderShips = universe.selectedSpaceObject.totalDefenses;
defenderPartialShips = universe.selectedSpaceObject.c;
defenderIndustry = universe.selectedSpaceObject.i;
}
if (universe.selectedSpaceObject.player) {
defenderWeapons = universe.selectedSpaceObject.player.tech.weapons.value;
defenderManufacturing = universe.selectedSpaceObject.player.tech.manufacturing.value;
}
}
var combatCalcWindow = npui.Screen("combat_calculator");
var relativeUIContainer = Crux.Widget("rel").roost(combatCalcWindow);
var col1_x = 0;
var col1_width = 30;
var col2_x = 20;
var col2_width = 10;
var row_height = 3;
var pad_height = .5;
var post_pad_y_offset = 1.5;
var totalUIHeight = 3;
Crux.Text("defender_weapon_tech", "pad12 col_accent").grid(col1_x, totalUIHeight, col1_width, row_height).roost(combatCalcWindow);
combatCalcWindow.defenderWeaponsUI = Crux.TextInput(true, true).setText(defenderWeapons).grid(col2_x, totalUIHeight, col2_width, row_height).roost(combatCalcWindow);
totalUIHeight += row_height;
Crux.Text("defender_ships", "pad12 col_accent").grid(col1_x, totalUIHeight, col1_width, row_height).roost(combatCalcWindow);
combatCalcWindow.defenderShipsUI = Crux.TextInput(true, true).setText(defenderShips).grid(col2_x, totalUIHeight, col2_width, row_height).roost(combatCalcWindow);
totalUIHeight += row_height;
Crux.Text("", "pad12 col_accent").grid(col1_x, totalUIHeight, col1_width, row_height).rawHTML("Defender Industry").roost(combatCalcWindow);
combatCalcWindow.defenderIndustryUI = Crux.TextInput(true, true).setText(defenderIndustry).grid(col2_x, totalUIHeight, col2_width, row_height).roost(combatCalcWindow);
totalUIHeight += row_height;
Crux.Text("", "pad12 col_accent").grid(col1_x, totalUIHeight, col1_width, row_height).rawHTML("Defender Manufacturing").roost(combatCalcWindow);
combatCalcWindow.defenderManufacturingUI = Crux.TextInput(true, true).setText(defenderManufacturing).grid(col2_x, totalUIHeight, col2_width, row_height).roost(combatCalcWindow);
totalUIHeight += row_height;
Crux.Text("defender_ships_bonus", "pad12 col_accent").grid(col1_x, totalUIHeight, col1_width, row_height).roost(combatCalcWindow);
Crux.Text("", "pad4 col_base rad4 txt_center").grid(col2_x, totalUIHeight, col2_width, row_height).inset(8).rawHTML("+1 Weapons").roost(combatCalcWindow);
totalUIHeight += row_height;
Crux.Widget("col_black").grid(col1_x, totalUIHeight, col1_width, pad_height).roost(combatCalcWindow);
totalUIHeight += post_pad_y_offset;
Crux.Text("attacker_weapon_tech", "pad12 col_accent").grid(col1_x, totalUIHeight, col1_width, row_height).roost(combatCalcWindow);
combatCalcWindow.attackerWeaponsUI = Crux.TextInput(true, true).setText(defenderWeapons).grid(col2_x, totalUIHeight, col2_width, row_height).roost(combatCalcWindow);
totalUIHeight += row_height;
Crux.Text("attacker_ships", "pad12 col_accent").grid(col1_x, totalUIHeight, col1_width, row_height).roost(combatCalcWindow);
combatCalcWindow.attackerShipsUI = Crux.TextInput(true, true).setText(defenderShips).grid(col2_x, totalUIHeight, col2_width, row_height).roost(combatCalcWindow);
totalUIHeight += row_height;
Crux.Text("eta", "pad12 col_accent").grid(col1_x, totalUIHeight, col1_width, row_height).roost(combatCalcWindow);
combatCalcWindow.attackerEtaUI = Crux.TextInput(true, true).setText(attackerEta).grid(col2_x, totalUIHeight, col2_width, row_height).roost(combatCalcWindow);
totalUIHeight += row_height;
Crux.Widget("col_black").grid(col1_x, totalUIHeight, col1_width, pad_height).roost(combatCalcWindow);
totalUIHeight += post_pad_y_offset;
Crux.Button("fight", "pre_calculate_combat").grid(col2_x, totalUIHeight, col2_width, row_height).roost(combatCalcWindow);
totalUIHeight += row_height + 1;
combatCalcWindow.result = Crux.Text("", "pad12 col_accent txt_center").grid(col1_x, totalUIHeight, col1_width, row_height).rawHTML("").roost(combatCalcWindow);
var resultsUIHeight = row_height + 1;
totalUIHeight += resultsUIHeight;
var resultsUIPixelHeight = resultsUIHeight * Crux.gridSize;
var totalUIPixelWidth = col1_width * Crux.gridSize;
var totalUIPixelHeight = totalUIHeight * Crux.gridSize;
var windowTitleHeight = 48;
combatCalcWindow.size(totalUIPixelWidth, totalUIPixelHeight - resultsUIPixelHeight);
relativeUIContainer.size(totalUIPixelWidth, totalUIPixelHeight - windowTitleHeight);
combatCalcWindow.onPreCalcCombat = function () {
var updatedDefenderShips = combatCalcWindow.defenderShipsUI.getText();
var updatedDefenderWeapons = 1 + combatCalcWindow.defenderWeaponsUI.getText();
var updatedDefenderIndustry = combatCalcWindow.defenderIndustryUI.getText();
var updatedDefenderManufacturing = combatCalcWindow.defenderManufacturingUI.getText();
var updatedAttackerETA = combatCalcWindow.attackerEtaUI.getText();
if (updatedAttackerETA > 0) {
// Industry builds ships after combat, so subtract 1 from the attacker's ETA.
--updatedAttackerETA;
}
var defenderShipsPerTick = (updatedDefenderIndustry * (updatedDefenderManufacturing + 5)) / productionTicks;
var defenderNewShips = defenderShipsPerTick * updatedAttackerETA;
updatedDefenderShips = Math.floor(
updatedDefenderShips +
defenderPartialShips +
defenderNewShips
);
if (false) {
console.log("updatedAttackerETA: " + updatedAttackerETA);
console.log("defenderShipsPerTick: " + defenderShipsPerTick);
console.log("defenderPartialShips: " + defenderPartialShips);
console.log("defenderNewShips: " + defenderNewShips);
console.log("updatedDefenderShips: " + updatedDefenderShips);
}
var updatedAttackerWeapons = combatCalcWindow.attackerWeaponsUI.getText();
var updatedAttackerShips = combatCalcWindow.attackerShipsUI.getText();
combatCalcWindow.defenderShipsUI.setText(updatedDefenderShips);
combatCalcWindow.attackerEtaUI.setText(0);
if (updatedDefenderShips === 0 || updatedAttackerShips === 0) {
combatCalcWindow.result.update("combat_calc_no_combat");
return;
}
var winner = "";
while (!winner) {
updatedAttackerShips -= updatedDefenderWeapons;
if (updatedAttackerShips <= 0) {
winner = "combat_calc_win_defend";
break;
}
updatedDefenderShips -= updatedAttackerWeapons;
if (updatedDefenderShips <= 0) {
winner = "combat_calc_win_attack";
break;
}
}
var td = {};
td.as = updatedAttackerShips;
td.ds = updatedDefenderShips;
combatCalcWindow.result.updateFormat(winner, td);
// Show the results
if (combatCalcWindow.h < totalUIPixelHeight) {
combatCalcWindow.size(combatCalcWindow.w, totalUIPixelHeight);
}
};
combatCalcWindow.on("pre_calculate_combat", combatCalcWindow.onPreCalcCombat);
return combatCalcWindow;
};
NeptunesPride.np.trigger("map_refresh");
})();