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 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
|
||||
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.
|
||||
@ -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
|
||||
|
||||
getStockSymbols
|
||||
-------------
|
||||
---------------
|
||||
|
||||
.. js:function:: getStockSymbols()
|
||||
|
||||
@ -214,3 +214,23 @@ getStockForecast
|
||||
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
|
||||
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|" +
|
||||
"shortStock|sellShort|" +
|
||||
"placeOrder|cancelOrder|getStockVolatility|getStockForecast|" +
|
||||
"purchase4SMarketData|purchase4SMarketDataTixApi|" +
|
||||
|
||||
// Hacknet Node API
|
||||
"hacknet|numNodes|purchaseNode|getPurchaseNodeCost|getNodeStats|" +
|
||||
|
@ -714,6 +714,7 @@ function Bladeburner(params={}) {
|
||||
|
||||
//Console command history
|
||||
this.consoleHistory = [];
|
||||
this.consoleLogs = [];
|
||||
|
||||
//Initialization
|
||||
initBladeburner();
|
||||
@ -867,6 +868,12 @@ Bladeburner.prototype.process = function() {
|
||||
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)
|
||||
if (this.storedCycles >= CyclesPerSecond) {
|
||||
var seconds = Math.floor(this.storedCycles / CyclesPerSecond);
|
||||
@ -1348,7 +1355,6 @@ Bladeburner.prototype.completeAction = function() {
|
||||
Player.gainIntelligenceExp(BaseIntGain);
|
||||
Player.gainCharismaExp(charismaExpGain);
|
||||
this.changeRank(0.1 * BitNodeMultipliers.BladeburnerRank);
|
||||
console.log("DEBUG: Field Analysis effectiveness is " + (eff * this.skillMultipliers.successChanceEstimate));
|
||||
this.getCurrentCity().improvePopulationEstimateByPercentage(eff * this.skillMultipliers.successChanceEstimate);
|
||||
if (this.logging.general) {
|
||||
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);
|
||||
|
||||
this.postToConsole("Bladeburner Console BETA");
|
||||
this.postToConsole("Type 'help' to see console commands");
|
||||
for (let i = 0; i < this.consoleHistory.length; ++i) {
|
||||
this.postToConsole(this.consoleHistory[i]);
|
||||
if (this.consoleLogs.length === 0) {
|
||||
this.postToConsole("Bladeburner Console BETA");
|
||||
this.postToConsole("Type 'help' to see console commands");
|
||||
} else {
|
||||
for (let i = 0; i < this.consoleLogs.length; ++i) {
|
||||
this.postToConsole(this.consoleLogs[i], false);
|
||||
}
|
||||
}
|
||||
|
||||
DomElems.consoleInput.focus();
|
||||
}
|
||||
|
||||
@ -2738,12 +2748,22 @@ Bladeburner.prototype.updateSkillsUIElement = function(el, skill) {
|
||||
}
|
||||
|
||||
//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;}
|
||||
$("#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);
|
||||
}
|
||||
|
||||
this.updateConsoleScroll();
|
||||
}
|
||||
|
||||
@ -2759,6 +2779,8 @@ Bladeburner.prototype.clearConsole = function() {
|
||||
while (DomElems.consoleTable.childNodes.length > 1) {
|
||||
DomElems.consoleTable.removeChild(DomElems.consoleTable.firstChild);
|
||||
}
|
||||
|
||||
this.consoleLogs.length = 0;
|
||||
}
|
||||
|
||||
Bladeburner.prototype.log = function(input) {
|
||||
|
@ -505,6 +505,7 @@ let CONSTANTS = {
|
||||
v0.41.1
|
||||
* IMPORTANT - Netscript Changes:
|
||||
** 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
|
||||
|
||||
* 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)
|
||||
* 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
|
||||
* 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
|
||||
* 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 {AllServers} from "./Server";
|
||||
import {hackWorldDaemon} from "./RedPill";
|
||||
import {StockMarket,
|
||||
SymbolToStockMap} from "./StockMarket";
|
||||
import {Stock} from "./Stock";
|
||||
import {Terminal} from "./Terminal";
|
||||
import {numeralWrapper} from "./ui/numeralFormat";
|
||||
import {dialogBoxCreate} from "../utils/DialogBox";
|
||||
import {exceptionAlert} from "../utils/helpers/exceptionAlert";
|
||||
import {createElement} from "../utils/uiHelpers/createElement";
|
||||
import {removeElementById} from "../utils/uiHelpers/removeElementById";
|
||||
@ -322,6 +327,7 @@ export function createDevMenu() {
|
||||
|
||||
const bladeburnerGainRankInput = createElement("input", {
|
||||
class: "text-input",
|
||||
margin: "5px",
|
||||
placeholder: "Rank to gain (or negative to lose rank)",
|
||||
type: "number",
|
||||
});
|
||||
@ -344,6 +350,7 @@ export function createDevMenu() {
|
||||
|
||||
const gangStoredCyclesInput = createElement("input", {
|
||||
class: "text-input",
|
||||
margin: "5px",
|
||||
placeholder: "# Cycles to add",
|
||||
type: "number",
|
||||
});
|
||||
@ -372,6 +379,73 @@ export function createDevMenu() {
|
||||
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
|
||||
const devMenuContainer = createElement("div", {
|
||||
class: "generic-menupage-container",
|
||||
@ -433,6 +507,12 @@ export function createDevMenu() {
|
||||
devMenuContainer.appendChild(createElement("br"));
|
||||
devMenuContainer.appendChild(contractsHeader);
|
||||
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");
|
||||
if (entireGameContainer == null) {
|
||||
|
@ -1715,7 +1715,7 @@ function NetscriptFunctions(workerScript) {
|
||||
throw makeRuntimeRejectMsg(workerScript, "You don't have TIX API Access! Cannot use purchase4SMarketData()");
|
||||
}
|
||||
|
||||
if (Player.Player.has4SData) {
|
||||
if (Player.has4SData) {
|
||||
if (workerScript.shouldLog("purchase4SMarketData")) {
|
||||
workerScript.log("Already purchased 4S Market Data");
|
||||
}
|
||||
@ -1794,7 +1794,7 @@ function NetscriptFunctions(workerScript) {
|
||||
cost = getPurchaseServerRamCostGuard(ram);
|
||||
} catch (e) {
|
||||
workerScript.scriptRef.log("ERROR: 'getPurchasedServerCost()' " + e.message);
|
||||
return "";
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
return cost;
|
||||
|
@ -547,7 +547,7 @@ function sellShort(stock, shares, workerScript=null) {
|
||||
}
|
||||
|
||||
function processStockPrices(numCycles=1) {
|
||||
if (isNaN(StockMarket.storedCycles)) { StockMarket.storedCycles = 0; }
|
||||
if (StockMarket.storedCycles == null || isNaN(StockMarket.storedCycles)) { StockMarket.storedCycles = 0; }
|
||||
StockMarket.storedCycles += numCycles;
|
||||
|
||||
// Stock Prices updated every 6 seconds on average. But if there are stored
|
||||
@ -572,10 +572,10 @@ function processStockPrices(numCycles=1) {
|
||||
|
||||
var chc = 50;
|
||||
if (stock.b) {
|
||||
chc = (chc + stock.otlkMag)/100;
|
||||
chc = (chc + stock.otlkMag) / 100;
|
||||
if (isNaN(chc)) {chc = 0.5;}
|
||||
} else {
|
||||
chc = (chc - stock.otlkMag)/100;
|
||||
chc = (chc - stock.otlkMag) / 100;
|
||||
if (isNaN(chc)) {chc = 0.5;}
|
||||
}
|
||||
if (stock.price >= stock.cap) {
|
||||
@ -895,6 +895,7 @@ function displayStockMarketContent() {
|
||||
|
||||
//Switch to Portfolio Mode Button
|
||||
if (modeBtn) {
|
||||
stockMarketPortfolioMode = false;
|
||||
modeBtn.innerHTML = "Switch to 'Portfolio' Mode" +
|
||||
"<span class='tooltiptext'>Displays only the stocks for which you have shares or orders</span>";
|
||||
modeBtn.addEventListener("click", switchToPortfolioMode);
|
||||
|
@ -1246,6 +1246,11 @@ const Engine = {
|
||||
//Passive faction rep gain offline
|
||||
processPassiveFactionRepGain(numCyclesOffline);
|
||||
|
||||
// Stock Market offline progress
|
||||
if (Player.hasWseAccount) {
|
||||
processStockPrices(numCyclesOffline);
|
||||
}
|
||||
|
||||
//Gang progress for BitNode 2
|
||||
if (Player.bitNodeN != null && Player.bitNodeN === 2 && Player.inGang()) {
|
||||
Player.gang.process(numCyclesOffline, Player);
|
||||
|
Loading…
Reference in New Issue
Block a user