mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-18 20:25:45 +01:00
Testing/bug fixes in v0.41.1. Updated Dev Menu features. Fixed 'Portfolio Mode' button on Stock market bugs
This commit is contained in:
parent
5b06a0b800
commit
e2b7418780
@ -2,7 +2,7 @@ Netscript Trade Information eXchange (TIX) API
|
|||||||
==============================================
|
==============================================
|
||||||
|
|
||||||
The Trade Information eXchange (TIX) is the communications protocol supported by the World Stock Exchange (WSE).
|
The Trade Information eXchange (TIX) is the communications protocol supported by the World Stock Exchange (WSE).
|
||||||
The WESE provides an API that allows you to automatically communicate with the
|
The WSE provides an API that allows you to automatically communicate with the
|
||||||
`Stock Market <http://bitburner.wikia.com/wiki/Stock_Market>`_. This API lets you write code using Netscript
|
`Stock Market <http://bitburner.wikia.com/wiki/Stock_Market>`_. This API lets you write code using Netscript
|
||||||
to build automated trading systems and create your own algorithmic trading strategies. Access to this
|
to build automated trading systems and create your own algorithmic trading strategies. Access to this
|
||||||
TIX API can be purchased by visiting the World Stock Exchange in-game.
|
TIX API can be purchased by visiting the World Stock Exchange in-game.
|
||||||
@ -11,7 +11,7 @@ Access to the TIX API currently costs $5 billion. After you purchase it, you wil
|
|||||||
access even after you 'reset' by installing Augmentations
|
access even after you 'reset' by installing Augmentations
|
||||||
|
|
||||||
getStockSymbols
|
getStockSymbols
|
||||||
-------------
|
---------------
|
||||||
|
|
||||||
.. js:function:: getStockSymbols()
|
.. js:function:: getStockSymbols()
|
||||||
|
|
||||||
@ -214,3 +214,23 @@ getStockForecast
|
|||||||
In other words, if this function returned 0.30 for a stock, then this means
|
In other words, if this function returned 0.30 for a stock, then this means
|
||||||
that the stock's price has a 30% chance of increasing and a 70% chance of
|
that the stock's price has a 30% chance of increasing and a 70% chance of
|
||||||
decreasing during the next tick.
|
decreasing during the next tick.
|
||||||
|
|
||||||
|
purchase4SMarketData
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
.. js:function:: purchase4SMarketData()
|
||||||
|
|
||||||
|
Purchase 4S Market Data Access.
|
||||||
|
|
||||||
|
Returns true if you successfully purchased it or if you already have access.
|
||||||
|
Returns false otherwise.
|
||||||
|
|
||||||
|
purchase4SMarketDataTixApi
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
.. js:function:: purchase4SMarketDataTixApi()
|
||||||
|
|
||||||
|
Purchase 4S Market Data TIX API Access.
|
||||||
|
|
||||||
|
Returns true if you successfully purchased it or if you already have access.
|
||||||
|
Returns false otherwise.
|
||||||
|
@ -95,6 +95,7 @@ let NetscriptFunctions =
|
|||||||
"getStockPrice|getStockPosition|getStockSymbols|buyStock|sellStock|" +
|
"getStockPrice|getStockPosition|getStockSymbols|buyStock|sellStock|" +
|
||||||
"shortStock|sellShort|" +
|
"shortStock|sellShort|" +
|
||||||
"placeOrder|cancelOrder|getStockVolatility|getStockForecast|" +
|
"placeOrder|cancelOrder|getStockVolatility|getStockForecast|" +
|
||||||
|
"purchase4SMarketData|purchase4SMarketDataTixApi|" +
|
||||||
|
|
||||||
// Hacknet Node API
|
// Hacknet Node API
|
||||||
"hacknet|numNodes|purchaseNode|getPurchaseNodeCost|getNodeStats|" +
|
"hacknet|numNodes|purchaseNode|getPurchaseNodeCost|getNodeStats|" +
|
||||||
|
@ -714,6 +714,7 @@ function Bladeburner(params={}) {
|
|||||||
|
|
||||||
//Console command history
|
//Console command history
|
||||||
this.consoleHistory = [];
|
this.consoleHistory = [];
|
||||||
|
this.consoleLogs = [];
|
||||||
|
|
||||||
//Initialization
|
//Initialization
|
||||||
initBladeburner();
|
initBladeburner();
|
||||||
@ -867,6 +868,12 @@ Bladeburner.prototype.process = function() {
|
|||||||
this.resetAction();
|
this.resetAction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the Player has no Stamina, set action to idle
|
||||||
|
if (this.stamina <= 0) {
|
||||||
|
this.log("Your Bladeburner action was cancelled because your stamina hit 0");
|
||||||
|
this.resetAction();
|
||||||
|
}
|
||||||
|
|
||||||
//A 'tick' for this mechanic is one second (= 5 game cycles)
|
//A 'tick' for this mechanic is one second (= 5 game cycles)
|
||||||
if (this.storedCycles >= CyclesPerSecond) {
|
if (this.storedCycles >= CyclesPerSecond) {
|
||||||
var seconds = Math.floor(this.storedCycles / CyclesPerSecond);
|
var seconds = Math.floor(this.storedCycles / CyclesPerSecond);
|
||||||
@ -1348,7 +1355,6 @@ Bladeburner.prototype.completeAction = function() {
|
|||||||
Player.gainIntelligenceExp(BaseIntGain);
|
Player.gainIntelligenceExp(BaseIntGain);
|
||||||
Player.gainCharismaExp(charismaExpGain);
|
Player.gainCharismaExp(charismaExpGain);
|
||||||
this.changeRank(0.1 * BitNodeMultipliers.BladeburnerRank);
|
this.changeRank(0.1 * BitNodeMultipliers.BladeburnerRank);
|
||||||
console.log("DEBUG: Field Analysis effectiveness is " + (eff * this.skillMultipliers.successChanceEstimate));
|
|
||||||
this.getCurrentCity().improvePopulationEstimateByPercentage(eff * this.skillMultipliers.successChanceEstimate);
|
this.getCurrentCity().improvePopulationEstimateByPercentage(eff * this.skillMultipliers.successChanceEstimate);
|
||||||
if (this.logging.general) {
|
if (this.logging.general) {
|
||||||
this.log("Field analysis completed. Gained 0.1 rank, " + formatNumber(hackingExpGain, 1) + " hacking exp, and " + formatNumber(charismaExpGain, 1) + " charisma exp");
|
this.log("Field analysis completed. Gained 0.1 rank, " + formatNumber(hackingExpGain, 1) + " hacking exp, and " + formatNumber(charismaExpGain, 1) + " charisma exp");
|
||||||
@ -1741,11 +1747,15 @@ Bladeburner.prototype.createContent = function() {
|
|||||||
|
|
||||||
document.getElementById("entire-game-container").appendChild(DomElems.bladeburnerDiv);
|
document.getElementById("entire-game-container").appendChild(DomElems.bladeburnerDiv);
|
||||||
|
|
||||||
|
if (this.consoleLogs.length === 0) {
|
||||||
this.postToConsole("Bladeburner Console BETA");
|
this.postToConsole("Bladeburner Console BETA");
|
||||||
this.postToConsole("Type 'help' to see console commands");
|
this.postToConsole("Type 'help' to see console commands");
|
||||||
for (let i = 0; i < this.consoleHistory.length; ++i) {
|
} else {
|
||||||
this.postToConsole(this.consoleHistory[i]);
|
for (let i = 0; i < this.consoleLogs.length; ++i) {
|
||||||
|
this.postToConsole(this.consoleLogs[i], false);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DomElems.consoleInput.focus();
|
DomElems.consoleInput.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2738,12 +2748,22 @@ Bladeburner.prototype.updateSkillsUIElement = function(el, skill) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Bladeburner Console Window
|
//Bladeburner Console Window
|
||||||
Bladeburner.prototype.postToConsole = function(input) {
|
Bladeburner.prototype.postToConsole = function(input, saveToLogs=true) {
|
||||||
|
const MaxConsoleEntries = 100;
|
||||||
|
if (saveToLogs === true) {
|
||||||
|
this.consoleLogs.push(input);
|
||||||
|
if (this.consoleLogs.length > MaxConsoleEntries) {
|
||||||
|
this.consoleLogs.shift();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (input == null || DomElems.consoleDiv == null) {return;}
|
if (input == null || DomElems.consoleDiv == null) {return;}
|
||||||
$("#bladeubrner-console-input-row").before('<tr><td class="bladeburner-console-line" style="color: var(--my-font-color); white-space:pre-wrap;">' + input + '</td></tr>');
|
$("#bladeubrner-console-input-row").before('<tr><td class="bladeburner-console-line" style="color: var(--my-font-color); white-space:pre-wrap;">' + input + '</td></tr>');
|
||||||
if (DomElems.consoleTable.childNodes.length > 200) {
|
|
||||||
|
if (DomElems.consoleTable.childNodes.length > MaxConsoleEntries) {
|
||||||
DomElems.consoleTable.removeChild(DomElems.consoleTable.firstChild);
|
DomElems.consoleTable.removeChild(DomElems.consoleTable.firstChild);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.updateConsoleScroll();
|
this.updateConsoleScroll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2759,6 +2779,8 @@ Bladeburner.prototype.clearConsole = function() {
|
|||||||
while (DomElems.consoleTable.childNodes.length > 1) {
|
while (DomElems.consoleTable.childNodes.length > 1) {
|
||||||
DomElems.consoleTable.removeChild(DomElems.consoleTable.firstChild);
|
DomElems.consoleTable.removeChild(DomElems.consoleTable.firstChild);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.consoleLogs.length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bladeburner.prototype.log = function(input) {
|
Bladeburner.prototype.log = function(input) {
|
||||||
|
@ -505,6 +505,7 @@ let CONSTANTS = {
|
|||||||
v0.41.1
|
v0.41.1
|
||||||
* IMPORTANT - Netscript Changes:
|
* IMPORTANT - Netscript Changes:
|
||||||
** purchaseTor() now returns true if you already have a TOR router (it used to return false)
|
** purchaseTor() now returns true if you already have a TOR router (it used to return false)
|
||||||
|
** getPurchasedServerCost() now returns Infinity if the specified RAM is an invalid amount or is greater than the max amount of RAM (2 ^ 20 GB)
|
||||||
** Added purchase4SMarketData() and purchase4SMarketDataTixApi() functions
|
** Added purchase4SMarketData() and purchase4SMarketDataTixApi() functions
|
||||||
|
|
||||||
* Stock Market changes:
|
* Stock Market changes:
|
||||||
@ -518,9 +519,11 @@ let CONSTANTS = {
|
|||||||
|
|
||||||
* Decreased the Hacking Level multiplier for BitNodes 6 and 7 to 0.4 (from 0.5)
|
* Decreased the Hacking Level multiplier for BitNodes 6 and 7 to 0.4 (from 0.5)
|
||||||
* Bladeburner console history is now saved and persists when switching screens or closing/reopening the game
|
* Bladeburner console history is now saved and persists when switching screens or closing/reopening the game
|
||||||
|
* In Bladeburner, if your stamina reaches 0 your current action will be cancelled
|
||||||
* b1t_flum3.exe is no longer removed from your home computer upon reset
|
* b1t_flum3.exe is no longer removed from your home computer upon reset
|
||||||
* Added main menu link for the Stock Market
|
* Added main menu link for the Stock Market (once you've purchased an account)
|
||||||
* Job main menu link only appears if you actually have a job
|
* Job main menu link only appears if you actually have a job
|
||||||
|
* Bug Fix: After installing Augs, the "Portfolio Mode" button on the Stock Market page should be properly reset
|
||||||
`
|
`
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,12 @@ import {Factions} from "./Faction";
|
|||||||
import {Player} from "./Player";
|
import {Player} from "./Player";
|
||||||
import {AllServers} from "./Server";
|
import {AllServers} from "./Server";
|
||||||
import {hackWorldDaemon} from "./RedPill";
|
import {hackWorldDaemon} from "./RedPill";
|
||||||
|
import {StockMarket,
|
||||||
|
SymbolToStockMap} from "./StockMarket";
|
||||||
|
import {Stock} from "./Stock";
|
||||||
import {Terminal} from "./Terminal";
|
import {Terminal} from "./Terminal";
|
||||||
|
import {numeralWrapper} from "./ui/numeralFormat";
|
||||||
|
import {dialogBoxCreate} from "../utils/DialogBox";
|
||||||
import {exceptionAlert} from "../utils/helpers/exceptionAlert";
|
import {exceptionAlert} from "../utils/helpers/exceptionAlert";
|
||||||
import {createElement} from "../utils/uiHelpers/createElement";
|
import {createElement} from "../utils/uiHelpers/createElement";
|
||||||
import {removeElementById} from "../utils/uiHelpers/removeElementById";
|
import {removeElementById} from "../utils/uiHelpers/removeElementById";
|
||||||
@ -322,6 +327,7 @@ export function createDevMenu() {
|
|||||||
|
|
||||||
const bladeburnerGainRankInput = createElement("input", {
|
const bladeburnerGainRankInput = createElement("input", {
|
||||||
class: "text-input",
|
class: "text-input",
|
||||||
|
margin: "5px",
|
||||||
placeholder: "Rank to gain (or negative to lose rank)",
|
placeholder: "Rank to gain (or negative to lose rank)",
|
||||||
type: "number",
|
type: "number",
|
||||||
});
|
});
|
||||||
@ -344,6 +350,7 @@ export function createDevMenu() {
|
|||||||
|
|
||||||
const gangStoredCyclesInput = createElement("input", {
|
const gangStoredCyclesInput = createElement("input", {
|
||||||
class: "text-input",
|
class: "text-input",
|
||||||
|
margin: "5px",
|
||||||
placeholder: "# Cycles to add",
|
placeholder: "# Cycles to add",
|
||||||
type: "number",
|
type: "number",
|
||||||
});
|
});
|
||||||
@ -372,6 +379,73 @@ export function createDevMenu() {
|
|||||||
innerText: "Generate Random Contract",
|
innerText: "Generate Random Contract",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Stock Market
|
||||||
|
const stockmarketHeader = createElement("h2", {innerText: "Stock Market"});
|
||||||
|
|
||||||
|
const stockInput = createElement("input", {
|
||||||
|
class: "text-input",
|
||||||
|
display: "block",
|
||||||
|
placeholder: "Stock symbol(s), or 'all'",
|
||||||
|
});
|
||||||
|
|
||||||
|
function processStocks(cb) {
|
||||||
|
const input = stockInput.value.toString().replace(/\s/g, '');
|
||||||
|
|
||||||
|
// Empty input, or "all", will process all stocks
|
||||||
|
if (input === "" || input.toLowerCase() === "all") {
|
||||||
|
for (const name in StockMarket) {
|
||||||
|
if (StockMarket.hasOwnProperty(name)) {
|
||||||
|
const stock = StockMarket[name];
|
||||||
|
if (stock instanceof Stock) {
|
||||||
|
cb(stock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const stockSymbols = input.split(",");
|
||||||
|
for (let i = 0; i < stockSymbols.length; ++i) {
|
||||||
|
const stock = SymbolToStockMap[stockSymbols];
|
||||||
|
if (stock instanceof Stock) {
|
||||||
|
cb(stock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const stockPriceChangeInput = createElement("input", {
|
||||||
|
class: "text-input",
|
||||||
|
margin: "5px",
|
||||||
|
placeholder: "Price to change stock(s) to",
|
||||||
|
type: "number",
|
||||||
|
});
|
||||||
|
|
||||||
|
const stockPriceChangeBtn = createElement("button", {
|
||||||
|
class: "std-button",
|
||||||
|
clickListener: () => {
|
||||||
|
const price = parseInt(stockPriceChangeInput.value);
|
||||||
|
if (isNaN(price)) { return; }
|
||||||
|
|
||||||
|
processStocks((stock) => {
|
||||||
|
stock.price = price;
|
||||||
|
});
|
||||||
|
dialogBoxCreate(`Stock Prices changed to ${price}`);
|
||||||
|
},
|
||||||
|
innerText: "Change Stock Price(s)",
|
||||||
|
});
|
||||||
|
|
||||||
|
const stockViewPriceCapBtn = createElement("button", {
|
||||||
|
class: "std-button",
|
||||||
|
clickListener: () => {
|
||||||
|
let text = "";
|
||||||
|
processStocks((stock) => {
|
||||||
|
text += `${stock.symbol}: ${numeralWrapper.format(stock.cap, '$0.000a')}<br>`;
|
||||||
|
});
|
||||||
|
dialogBoxCreate(text);
|
||||||
|
},
|
||||||
|
innerText: "View Stock Price Caps",
|
||||||
|
});
|
||||||
|
|
||||||
// Add everything to container, then append to main menu
|
// Add everything to container, then append to main menu
|
||||||
const devMenuContainer = createElement("div", {
|
const devMenuContainer = createElement("div", {
|
||||||
class: "generic-menupage-container",
|
class: "generic-menupage-container",
|
||||||
@ -433,6 +507,12 @@ export function createDevMenu() {
|
|||||||
devMenuContainer.appendChild(createElement("br"));
|
devMenuContainer.appendChild(createElement("br"));
|
||||||
devMenuContainer.appendChild(contractsHeader);
|
devMenuContainer.appendChild(contractsHeader);
|
||||||
devMenuContainer.appendChild(generateRandomContractBtn);
|
devMenuContainer.appendChild(generateRandomContractBtn);
|
||||||
|
devMenuContainer.appendChild(stockmarketHeader);
|
||||||
|
devMenuContainer.appendChild(stockInput);
|
||||||
|
devMenuContainer.appendChild(stockPriceChangeInput);
|
||||||
|
devMenuContainer.appendChild(stockPriceChangeBtn);
|
||||||
|
devMenuContainer.appendChild(createElement("br"));
|
||||||
|
devMenuContainer.appendChild(stockViewPriceCapBtn);
|
||||||
|
|
||||||
const entireGameContainer = document.getElementById("entire-game-container");
|
const entireGameContainer = document.getElementById("entire-game-container");
|
||||||
if (entireGameContainer == null) {
|
if (entireGameContainer == null) {
|
||||||
|
@ -1715,7 +1715,7 @@ function NetscriptFunctions(workerScript) {
|
|||||||
throw makeRuntimeRejectMsg(workerScript, "You don't have TIX API Access! Cannot use purchase4SMarketData()");
|
throw makeRuntimeRejectMsg(workerScript, "You don't have TIX API Access! Cannot use purchase4SMarketData()");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Player.Player.has4SData) {
|
if (Player.has4SData) {
|
||||||
if (workerScript.shouldLog("purchase4SMarketData")) {
|
if (workerScript.shouldLog("purchase4SMarketData")) {
|
||||||
workerScript.log("Already purchased 4S Market Data");
|
workerScript.log("Already purchased 4S Market Data");
|
||||||
}
|
}
|
||||||
@ -1794,7 +1794,7 @@ function NetscriptFunctions(workerScript) {
|
|||||||
cost = getPurchaseServerRamCostGuard(ram);
|
cost = getPurchaseServerRamCostGuard(ram);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
workerScript.scriptRef.log("ERROR: 'getPurchasedServerCost()' " + e.message);
|
workerScript.scriptRef.log("ERROR: 'getPurchasedServerCost()' " + e.message);
|
||||||
return "";
|
return Infinity;
|
||||||
}
|
}
|
||||||
|
|
||||||
return cost;
|
return cost;
|
||||||
|
@ -547,7 +547,7 @@ function sellShort(stock, shares, workerScript=null) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function processStockPrices(numCycles=1) {
|
function processStockPrices(numCycles=1) {
|
||||||
if (isNaN(StockMarket.storedCycles)) { StockMarket.storedCycles = 0; }
|
if (StockMarket.storedCycles == null || isNaN(StockMarket.storedCycles)) { StockMarket.storedCycles = 0; }
|
||||||
StockMarket.storedCycles += numCycles;
|
StockMarket.storedCycles += numCycles;
|
||||||
|
|
||||||
// Stock Prices updated every 6 seconds on average. But if there are stored
|
// Stock Prices updated every 6 seconds on average. But if there are stored
|
||||||
@ -572,10 +572,10 @@ function processStockPrices(numCycles=1) {
|
|||||||
|
|
||||||
var chc = 50;
|
var chc = 50;
|
||||||
if (stock.b) {
|
if (stock.b) {
|
||||||
chc = (chc + stock.otlkMag)/100;
|
chc = (chc + stock.otlkMag) / 100;
|
||||||
if (isNaN(chc)) {chc = 0.5;}
|
if (isNaN(chc)) {chc = 0.5;}
|
||||||
} else {
|
} else {
|
||||||
chc = (chc - stock.otlkMag)/100;
|
chc = (chc - stock.otlkMag) / 100;
|
||||||
if (isNaN(chc)) {chc = 0.5;}
|
if (isNaN(chc)) {chc = 0.5;}
|
||||||
}
|
}
|
||||||
if (stock.price >= stock.cap) {
|
if (stock.price >= stock.cap) {
|
||||||
@ -895,6 +895,7 @@ function displayStockMarketContent() {
|
|||||||
|
|
||||||
//Switch to Portfolio Mode Button
|
//Switch to Portfolio Mode Button
|
||||||
if (modeBtn) {
|
if (modeBtn) {
|
||||||
|
stockMarketPortfolioMode = false;
|
||||||
modeBtn.innerHTML = "Switch to 'Portfolio' Mode" +
|
modeBtn.innerHTML = "Switch to 'Portfolio' Mode" +
|
||||||
"<span class='tooltiptext'>Displays only the stocks for which you have shares or orders</span>";
|
"<span class='tooltiptext'>Displays only the stocks for which you have shares or orders</span>";
|
||||||
modeBtn.addEventListener("click", switchToPortfolioMode);
|
modeBtn.addEventListener("click", switchToPortfolioMode);
|
||||||
|
@ -1246,6 +1246,11 @@ const Engine = {
|
|||||||
//Passive faction rep gain offline
|
//Passive faction rep gain offline
|
||||||
processPassiveFactionRepGain(numCyclesOffline);
|
processPassiveFactionRepGain(numCyclesOffline);
|
||||||
|
|
||||||
|
// Stock Market offline progress
|
||||||
|
if (Player.hasWseAccount) {
|
||||||
|
processStockPrices(numCyclesOffline);
|
||||||
|
}
|
||||||
|
|
||||||
//Gang progress for BitNode 2
|
//Gang progress for BitNode 2
|
||||||
if (Player.bitNodeN != null && Player.bitNodeN === 2 && Player.inGang()) {
|
if (Player.bitNodeN != null && Player.bitNodeN === 2 && Player.inGang()) {
|
||||||
Player.gang.process(numCyclesOffline, Player);
|
Player.gang.process(numCyclesOffline, Player);
|
||||||
|
Loading…
Reference in New Issue
Block a user