* infiltration use buttons instead of a links

* minor accessibility patch

* Hospitalization will not cost more than 10% of the players money.

* Adde hospitalization netscript function

* Removed the suggestion that the combat path will lead to Daedalus, it still will. But new players should not be told that this is a viable path to completing a BitNode.

* getMemberInformation now returns everything about the member.

* New netscript function to get the players hacknet server hash capacity

* yesno dialog box will not keep older messages anymore

* v0.51.1
This commit is contained in:
hydroflame
2021-04-06 03:50:09 -04:00
committed by GitHub
parent 6f330efc44
commit db2bf79e3b
27 changed files with 215 additions and 110 deletions

10
README_contribution.md Normal file
View File

@ -0,0 +1,10 @@
Deploying a new version
-----------------------
Update the following
- `src/Constants.ts` `Version` and `LatestUpdate`
- `package.json` `version`
- `doc/source/conf.py` `version` and `release`
- `doc/source/changelog.rst`
- post to discord
- post to reddit.com/r/Bitburner

View File

@ -184,5 +184,4 @@
#infiltration-buttons .a-link-button { #infiltration-buttons .a-link-button {
display: inline; display: inline;
width: 25%;
} }

File diff suppressed because one or more lines are too long

View File

@ -1,2 +1,2 @@
!function(n){function t(t){for(var e,i,f=t[0],c=t[1],l=t[2],p=0,s=[];p<f.length;p++)i=f[p],u[i]&&s.push(u[i][0]),u[i]=0;for(e in c)Object.prototype.hasOwnProperty.call(c,e)&&(n[e]=c[e]);for(a&&a(t);s.length;)s.shift()();return r.push.apply(r,l||[]),o()}function o(){for(var n,t=0;t<r.length;t++){for(var o=r[t],e=!0,f=1;f<o.length;f++){var c=o[f];0!==u[c]&&(e=!1)}e&&(r.splice(t--,1),n=i(i.s=o[0]))}return n}var e={},u={1:0},r=[];function i(t){if(e[t])return e[t].exports;var o=e[t]={i:t,l:!1,exports:{}};return n[t].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=n,i.c=e,i.d=function(n,t,o){i.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:o})},i.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},i.t=function(n,t){if(1&t&&(n=i(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var o=Object.create(null);if(i.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var e in n)i.d(o,e,function(t){return n[t]}.bind(null,e));return o},i.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return i.d(t,"a",t),t},i.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},i.p="";var f=window.webpackJsonp=window.webpackJsonp||[],c=f.push.bind(f);f.push=t,f=f.slice();for(var l=0;l<f.length;l++)t(f[l]);var a=c;r.push([395,0]),o()}({338:function(n,t,o){},340:function(n,t,o){},342:function(n,t,o){},344:function(n,t,o){},346:function(n,t,o){},348:function(n,t,o){},350:function(n,t,o){},352:function(n,t,o){},354:function(n,t,o){},356:function(n,t,o){},358:function(n,t,o){},360:function(n,t,o){},362:function(n,t,o){},364:function(n,t,o){},366:function(n,t,o){},368:function(n,t,o){},370:function(n,t,o){},372:function(n,t,o){},374:function(n,t,o){},376:function(n,t,o){},378:function(n,t,o){},380:function(n,t,o){},382:function(n,t,o){},384:function(n,t,o){},386:function(n,t,o){},388:function(n,t,o){},390:function(n,t,o){},392:function(n,t,o){},395:function(n,t,o){"use strict";o.r(t);o(394),o(392),o(390),o(388),o(386),o(384),o(382),o(380),o(378),o(376),o(374),o(372),o(370),o(368),o(366),o(364),o(362),o(360),o(358),o(356),o(354),o(352),o(350),o(348),o(346),o(344),o(342),o(340),o(338)}}); !function(n){function t(t){for(var e,i,f=t[0],c=t[1],l=t[2],p=0,s=[];p<f.length;p++)i=f[p],u[i]&&s.push(u[i][0]),u[i]=0;for(e in c)Object.prototype.hasOwnProperty.call(c,e)&&(n[e]=c[e]);for(a&&a(t);s.length;)s.shift()();return r.push.apply(r,l||[]),o()}function o(){for(var n,t=0;t<r.length;t++){for(var o=r[t],e=!0,f=1;f<o.length;f++){var c=o[f];0!==u[c]&&(e=!1)}e&&(r.splice(t--,1),n=i(i.s=o[0]))}return n}var e={},u={1:0},r=[];function i(t){if(e[t])return e[t].exports;var o=e[t]={i:t,l:!1,exports:{}};return n[t].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=n,i.c=e,i.d=function(n,t,o){i.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:o})},i.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},i.t=function(n,t){if(1&t&&(n=i(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var o=Object.create(null);if(i.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var e in n)i.d(o,e,function(t){return n[t]}.bind(null,e));return o},i.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return i.d(t,"a",t),t},i.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},i.p="";var f=window.webpackJsonp=window.webpackJsonp||[],c=f.push.bind(f);f.push=t,f=f.slice();for(var l=0;l<f.length;l++)t(f[l]);var a=c;r.push([396,0]),o()}({339:function(n,t,o){},341:function(n,t,o){},343:function(n,t,o){},345:function(n,t,o){},347:function(n,t,o){},349:function(n,t,o){},351:function(n,t,o){},353:function(n,t,o){},355:function(n,t,o){},357:function(n,t,o){},359:function(n,t,o){},361:function(n,t,o){},363:function(n,t,o){},365:function(n,t,o){},367:function(n,t,o){},369:function(n,t,o){},371:function(n,t,o){},373:function(n,t,o){},375:function(n,t,o){},377:function(n,t,o){},379:function(n,t,o){},381:function(n,t,o){},383:function(n,t,o){},385:function(n,t,o){},387:function(n,t,o){},389:function(n,t,o){},391:function(n,t,o){},393:function(n,t,o){},396:function(n,t,o){"use strict";o.r(t);o(395),o(393),o(391),o(389),o(387),o(385),o(383),o(381),o(379),o(377),o(375),o(373),o(371),o(369),o(367),o(365),o(363),o(361),o(359),o(357),o(355),o(353),o(351),o(349),o(347),o(345),o(343),o(341),o(339)}});
//# sourceMappingURL=engineStyle.bundle.js.map //# sourceMappingURL=engineStyle.bundle.js.map

View File

@ -1374,8 +1374,7 @@ button {
margin-top: 20px; } margin-top: 20px; }
#infiltration-buttons .a-link-button { #infiltration-buttons .a-link-button {
display: inline; display: inline; }
width: 25%; }
/** /**
* Styling for the Augmentations UI. This is the page that displays all of the * Styling for the Augmentations UI. This is the page that displays all of the

26
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

View File

@ -3,6 +3,32 @@
Changelog Changelog
========= =========
v0.51.1 - 2021-04-06 Bugfixes because the author of the last patch sucks (it's hydroflame)
------------------------------------------------------------------------------------------
**Netscript**
* 'getPlayer' returns players faction and tor
* 'hospitalization' is a new singularity function.
* 'gang.getMemberInformation' now returns more information.
* 'hacknet.hashCapacity' is a new hacknet function that returns the maximum hash capacity.
**Hospitalization**
* Now only cost at most 10% of your money.
**Bugfix**
* confirmation dialog box no longer use previous text
**Accessibility**
* The game is a little easier to handle for screen readers (yes, there's an
absolute legend playing this game with a screen reader)
* Infiltration use buttons instead of a-links
* New option to disable ASCII art. This will make the metro map and world
map display as a list of buttons.
**Misc.**
* 'fl1ght.exe' will no longer suggest the combat path. Related faction
requirements unchanged.
v0.51.0 - 2021-03-31 Formulas (hydroflame) v0.51.0 - 2021-03-31 Formulas (hydroflame)
------------------------------------------ ------------------------------------------

View File

@ -66,7 +66,7 @@ documentation_title = '{0} Documentation'.format(project)
# The short X.Y version. # The short X.Y version.
version = '0.51' version = '0.51'
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = '0.51.0' release = '0.51.1'
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.

View File

@ -0,0 +1,12 @@
hashCapacity() Netscript Function
=================================
.. warning:: This page contains spoilers for the game
.. js:function:: hashCapacity()
:RAM cost: 0 GB
:returns: The players maximum hash capacity.
.. note:: This function is only applicable for Hacknet Servers (the upgraded version of
a Hacknet Node).

View File

@ -46,6 +46,7 @@ In :ref:`netscriptjs`::
upgradeCache() <hacknetnodeapi/upgradeCache> upgradeCache() <hacknetnodeapi/upgradeCache>
getCacheUpgradeCost() <hacknetnodeapi/getCacheUpgradeCost> getCacheUpgradeCost() <hacknetnodeapi/getCacheUpgradeCost>
numHashes() <hacknetnodeapi/numHashes> numHashes() <hacknetnodeapi/numHashes>
hashCapacity() <hacknetnodeapi/hashCapacity>
hashCost() <hacknetnodeapi/hashCost> hashCost() <hacknetnodeapi/hashCost>
spendHashes() <hacknetnodeapi/spendHashes> spendHashes() <hacknetnodeapi/spendHashes>
getHashUpgradeLevel() <hacknetnodeapi/getHashUpgradeLevel> getHashUpgradeLevel() <hacknetnodeapi/getHashUpgradeLevel>

View File

@ -28,6 +28,7 @@ level 3, then you will be able to access all of the Singularity Functions.
connect() <singularityfunctions/connect> connect() <singularityfunctions/connect>
manualHack() <singularityfunctions/manualHack> manualHack() <singularityfunctions/manualHack>
getPlayer() <singularityfunctions/getPlayer> getPlayer() <singularityfunctions/getPlayer>
hospitalize() <singularityfunctions/hospitalize>
isBusy() <singularityfunctions/isBusy> isBusy() <singularityfunctions/isBusy>
stopAction() <singularityfunctions/stopAction> stopAction() <singularityfunctions/stopAction>
upgradeHomeRam() <singularityfunctions/upgradeHomeRam> upgradeHomeRam() <singularityfunctions/upgradeHomeRam>

View File

@ -0,0 +1,11 @@
hospitalize() Netscript Function
===================================
.. js:function:: hospitalize()
:RAM cost: 1 GB
:returns: The cost of your visit to the hospital.
If you are not in BitNode-4, then you must have Level 1 of Source-File 4 in order to use this function.
Hospitalize yourself. Recovering all lost hp.

View File

@ -261,16 +261,16 @@
<div id="infiltration-left-panel"> <div id="infiltration-left-panel">
<p id="infiltration-level-text"> </p> <p id="infiltration-level-text"> </p>
<div id="infiltration-buttons"> <div id="infiltration-buttons">
<a class="a-link-button tooltip" id="infiltration-kill"> </a> <button class="a-link-button tooltip" id="infiltration-kill"> </button>
<a class="a-link-button tooltip" id="infiltration-knockout"> </a> <button class="a-link-button tooltip" id="infiltration-knockout"> </button>
<a class="a-link-button tooltip" id="infiltration-stealthknockout"> </a> <button class="a-link-button tooltip" id="infiltration-stealthknockout"> </button>
<a class="a-link-button tooltip" id="infiltration-assassinate"> </a> <button class="a-link-button tooltip" id="infiltration-assassinate"> </button>
<a class="a-link-button tooltip" id="infiltration-hacksecurity"> </a> <button class="a-link-button tooltip" id="infiltration-hacksecurity"> </button>
<a class="a-link-button tooltip" id="infiltration-destroysecurity"> </a> <button class="a-link-button tooltip" id="infiltration-destroysecurity"> </button>
<a class="a-link-button tooltip" id="infiltration-sneak"> </a> <button class="a-link-button tooltip" id="infiltration-sneak"> </button>
<a class="a-link-button tooltip" id="infiltration-pickdoor"> </a> <button class="a-link-button tooltip" id="infiltration-pickdoor"> </button>
<a class="a-link-button tooltip" id="infiltration-bribe"> </a> <button class="a-link-button tooltip" id="infiltration-bribe"> </button>
<a class="a-link-button tooltip" id="infiltration-escape"> </a> <button class="a-link-button tooltip" id="infiltration-escape"> </button>
</div> </div>
</div> </div>
<div id="infiltration-right-panel"> <div id="infiltration-right-panel">
@ -387,7 +387,7 @@
<!-- Game Options --> <!-- Game Options -->
<div id="game-options-container" class="popup-box-container"> <div id="game-options-container" class="popup-box-container">
<div id="game-options-content" class="game-options-box"> <div id="game-options-content" class="game-options-box">
<button id="game-options-close-button">&times;</button> <button id="game-options-close-button" aria-label="close options dialog">&times;</button>
<h1> Game Options </h1> <h1> Game Options </h1>
<br/> <br/>
<div id="game-options-left-panel"> <div id="game-options-left-panel">

View File

@ -121,5 +121,5 @@
"watch": "webpack --watch --mode production", "watch": "webpack --watch --mode production",
"watch:dev": "webpack --watch --mode development" "watch:dev": "webpack --watch --mode development"
}, },
"version": "0.50.1" "version": "0.51.1"
} }

View File

@ -8,6 +8,7 @@ import { Factions, factionExists } from "./Faction/Factions";
import { joinFaction, displayFactionContent } from "./Faction/FactionHelpers"; import { joinFaction, displayFactionContent } from "./Faction/FactionHelpers";
import { Player } from "./Player"; import { Player } from "./Player";
import { hackWorldDaemon, redPillFlag } from "./RedPill"; import { hackWorldDaemon, redPillFlag } from "./RedPill";
import { calculateHospitalizationCost } from "./Hospital/Hospital";
import { Page, routing } from "./ui/navigationTracking"; import { Page, routing } from "./ui/navigationTracking";
import { numeralWrapper } from "./ui/numeralFormat"; import { numeralWrapper } from "./ui/numeralFormat";
@ -728,9 +729,10 @@ Bladeburner.prototype.completeAction = function() {
damage = action.hpLoss * difficultyMultiplier; damage = action.hpLoss * difficultyMultiplier;
damage = Math.ceil(addOffset(damage, 10)); damage = Math.ceil(addOffset(damage, 10));
this.hpLost += damage; this.hpLost += damage;
const cost = calculateHospitalizationCost(Player, damage);
if (Player.takeDamage(damage)) { if (Player.takeDamage(damage)) {
++this.numHosp; ++this.numHosp;
this.moneyLost += (CONSTANTS.HospitalCostPerHp * Player.max_hp); this.moneyLost += cost;
} }
} }
var logLossText = ""; var logLossText = "";
@ -800,9 +802,10 @@ Bladeburner.prototype.completeAction = function() {
if (action.hpLoss) { if (action.hpLoss) {
damage = action.hpLoss * difficultyMultiplier; damage = action.hpLoss * difficultyMultiplier;
damage = Math.ceil(addOffset(damage, 10)); damage = Math.ceil(addOffset(damage, 10));
const cost = calculateHospitalizationCost(Player, damage);
if (Player.takeDamage(damage)) { if (Player.takeDamage(damage)) {
++this.numHosp; ++this.numHosp;
this.moneyLost += (CONSTANTS.HospitalCostPerHp * Player.max_hp); this.moneyLost += cost;
} }
} }
teamLossMax = Math.floor(teamCount); teamLossMax = Math.floor(teamCount);
@ -1771,7 +1774,7 @@ Bladeburner.prototype.updateOverviewContent = function() {
Stamina Penalty: {formatNumber((1-this.calculateStaminaPenalty())*100, 1)}%<br /><br /> Stamina Penalty: {formatNumber((1-this.calculateStaminaPenalty())*100, 1)}%<br /><br />
Team Size: {formatNumber(this.teamSize, 0)}<br /> Team Size: {formatNumber(this.teamSize, 0)}<br />
Team Members Lost: {formatNumber(this.teamLost, 0)}<br /><br /> Team Members Lost: {formatNumber(this.teamLost, 0)}<br /><br />
Num Times Hospitalized: this.numHosp<br /> Num Times Hospitalized: {this.numHosp}<br />
Money Lost From Hospitalizations: {Money(this.moneyLost)}<br /><br /> Money Lost From Hospitalizations: {Money(this.moneyLost)}<br /><br />
Current City: {this.city}<br /> Current City: {this.city}<br />
</>, DomElems.overviewGen1); </>, DomElems.overviewGen1);

View File

@ -6,7 +6,7 @@
import { IMap } from "./types"; import { IMap } from "./types";
export let CONSTANTS: IMap<any> = { export let CONSTANTS: IMap<any> = {
Version: "0.51.0", Version: "0.51.1",
/** Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience /** Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience
* and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then * and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then
@ -228,25 +228,30 @@ export let CONSTANTS: IMap<any> = {
LatestUpdate: LatestUpdate:
` `
v0.51.0 - 2021-03-31 Formulas (hydroflame) v0.51.1 - 2021-04-06 Bugfixes because the author of the last patch sucks (it's hydroflame)
------- -------
Formulas API
* A new API is introduced, this gives players access to various formulas used in the game.
It'll help you make more informed decisions.
Netscript Netscript
* 'getServer' is a new function meant to be used with the formulas API. * 'getPlayer' returns players faction and tor
* 'getPlayer' is a new function meant to be used with the formulas API. * 'hospitalization' is a new singularity function.
* 'getStats' and 'getCharacterInformation' are deprecated in favor of 'getPlayer' * 'gang.getMemberInformation' now returns more information.
* 'getCurrentServer' is a new function that returns the server the player is currently connected. * 'hacknet.hashCapacity' is a new hacknet function that returns the maximum hash capacity.
Display Hospitalization
* All money should now consistently be orange. * Now only cost at most 10% of your money.
* All rep should now consistently be light-yellow.
* Most numbers should display consistently now (aka all money is formatted the same).
Click to copy Bugfix
* Certain UI elements are now 'click-to-copy' * confirmation dialog box no longer use previous text
Accessibility
* The game is a little easier to handle for screen readers (yes, there's an
absolute legend playing this game with a screen reader)
* Infiltration use buttons instead of a-links
* New option to disable ASCII art. This will make the metro map and world
map display as a list of buttons.
Misc.
* 'fl1ght.exe' will no longer suggest the combat path. Related faction
requirements unchanged.
` `
} }

View File

@ -42,11 +42,9 @@ export class GeneralInfo extends React.Component {
hackers all around the world to anonymously share computing power and hackers all around the world to anonymously share computing power and
perform distributed cyberattacks without the fear of being traced. perform distributed cyberattacks without the fear of being traced.
</p> </p>
<br />
<p className={"hacknet-general-info"}> <p className={"hacknet-general-info"}>
{this.getSecondParagraph()} {this.getSecondParagraph()}
</p> </p>
<br />
<p className={"hacknet-general-info"}> <p className={"hacknet-general-info"}>
{this.getThirdParagraph()} {this.getThirdParagraph()}
</p> </p>

View File

@ -134,19 +134,22 @@ export class HacknetNode extends React.Component {
</span> </span>
</div> </div>
<div className={"row"}> <div className={"row"}>
<p>Level:</p><span className={"text upgradable-info"}>{node.level}</span> <p>Level:</p>
<span className={"text upgradable-info"}>{node.level}</span>
<button className={upgradeLevelClass} onClick={upgradeLevelOnClick}> <button className={upgradeLevelClass} onClick={upgradeLevelOnClick}>
{upgradeLevelContent} {upgradeLevelContent}
</button> </button>
</div> </div>
<div className={"row"}> <div className={"row"}>
<p>RAM:</p><span className={"text upgradable-info"}>{node.ram}GB</span> <p>RAM:</p>
<span className={"text upgradable-info"}>{node.ram}GB</span>
<button className={upgradeRamClass} onClick={upgradeRamOnClick}> <button className={upgradeRamClass} onClick={upgradeRamOnClick}>
{upgradeRamContent} {upgradeRamContent}
</button> </button>
</div> </div>
<div className={"row"}> <div className={"row"}>
<p>Cores:</p><span className={"text upgradable-info"}>{node.cores}</span> <p>Cores:</p>
<span className={"text upgradable-info"}>{node.cores}</span>
<button className={upgradeCoresClass} onClick={upgradeCoresOnClick}> <button className={upgradeCoresClass} onClick={upgradeCoresOnClick}>
{upgradeCoresContent} {upgradeCoresContent}
</button> </button>

26
src/Hospital/Hospital.ts Normal file
View File

@ -0,0 +1,26 @@
import { CONSTANTS } from "../Constants";
import { IPlayer } from "../PersonObjects/IPlayer"
export function getHospitalizationCost(p: IPlayer): number {
let money;
if (typeof p.money === 'number') {
money = p.money;
} else {
money = p.money.toNumber();
}
if (money < 0) {
return 0;
}
return Math.min(money*0.1, (p.max_hp - p.hp) * CONSTANTS.HospitalCostPerHp);
}
export function calculateHospitalizationCost(p: IPlayer, damage: number): number {
const oldhp = p.hp;
p.hp -= damage
if (p.hp < 0) p.hp = 0;
const cost = getHospitalizationCost(p);
p.hp = oldhp;
return cost;
}

View File

@ -7,6 +7,7 @@ import * as React from "react";
import { CONSTANTS } from "../../Constants"; import { CONSTANTS } from "../../Constants";
import { IPlayer } from "../../PersonObjects/IPlayer"; import { IPlayer } from "../../PersonObjects/IPlayer";
import { getHospitalizationCost } from "../../Hospital/Hospital";
import { numeralWrapper } from "../../ui/numeralFormat"; import { numeralWrapper } from "../../ui/numeralFormat";
import { AutoupdatingStdButton } from "../../ui/React/AutoupdatingStdButton"; import { AutoupdatingStdButton } from "../../ui/React/AutoupdatingStdButton";
@ -42,7 +43,7 @@ export class HospitalLocation extends React.Component<IProps, IState> {
} }
getCost(): number { getCost(): number {
return (this.props.p.max_hp - this.props.p.hp) * CONSTANTS.HospitalCostPerHp; return getHospitalizationCost(this.props.p);
} }
getHealed(e: React.MouseEvent<HTMLElement>): void { getHealed(e: React.MouseEvent<HTMLElement>): void {

View File

@ -183,6 +183,7 @@ export const RamCosts: IMap<any> = {
getStats: () => RamCostConstants.ScriptSingularityFn1RamCost / 4, getStats: () => RamCostConstants.ScriptSingularityFn1RamCost / 4,
getCharacterInformation: () => RamCostConstants.ScriptSingularityFn1RamCost / 4, getCharacterInformation: () => RamCostConstants.ScriptSingularityFn1RamCost / 4,
getPlayer: () => RamCostConstants.ScriptSingularityFn1RamCost / 4, getPlayer: () => RamCostConstants.ScriptSingularityFn1RamCost / 4,
hospitalize: () => RamCostConstants.ScriptSingularityFn1RamCost / 4,
isBusy: () => RamCostConstants.ScriptSingularityFn1RamCost / 4, isBusy: () => RamCostConstants.ScriptSingularityFn1RamCost / 4,
stopAction: () => RamCostConstants.ScriptSingularityFn1RamCost / 2, stopAction: () => RamCostConstants.ScriptSingularityFn1RamCost / 2,
upgradeHomeRam: () => RamCostConstants.ScriptSingularityFn2RamCost, upgradeHomeRam: () => RamCostConstants.ScriptSingularityFn2RamCost,

View File

@ -766,6 +766,10 @@ function NetscriptFunctions(workerScript) {
if (!hasHacknetServers()) { return 0; } if (!hasHacknetServers()) { return 0; }
return Player.hashManager.hashes; return Player.hashManager.hashes;
}, },
hashCapacity: function() {
if (!hasHacknetServers()) { return 0; }
return Player.hashManager.capacity;
},
hashCost : function(upgName) { hashCost : function(upgName) {
if (!hasHacknetServers()) { return Infinity; } if (!hasHacknetServers()) { return Infinity; }
@ -2976,6 +2980,11 @@ function NetscriptFunctions(workerScript) {
Object.assign(data.jobs, Player.jobs); Object.assign(data.jobs, Player.jobs);
return data; return data;
}, },
hospitalize: function() {
updateDynamicRam("hospitalize", getRamCost("hospitalize"));
checkSingularityAccess("hospitalize", 1);
return Player.hospitalize();
},
isBusy: function() { isBusy: function() {
updateDynamicRam("isBusy", getRamCost("isBusy")); updateDynamicRam("isBusy", getRamCost("isBusy"));
checkSingularityAccess("isBusy", 1); checkSingularityAccess("isBusy", 1);
@ -3576,27 +3585,35 @@ function NetscriptFunctions(workerScript) {
checkGangApiAccess("getMemberInformation"); checkGangApiAccess("getMemberInformation");
const member = getGangMember("getMemberInformation", name); const member = getGangMember("getMemberInformation", name);
return { return {
agility: member.agi, name: member.name,
agilityEquipMult: member.agi_mult, task: member.task,
agilityAscensionMult: member.agi_asc_mult, earnedRespect: member.earnedRespect,
augmentations: member.augmentations.slice(), hack: member.hack,
charisma: member.cha, str: member.str,
charismaEquipMult: member.cha_mult, def: member.def,
charismaAscensionMult: member.cha_asc_mult, dex: member.dex,
defense: member.def, agi: member.agi,
defenseEquipMult: member.def_mult, cha: member.cha,
defenseAscensionMult: member.def_asc_mult, hack_exp: member.hack_exp,
dexterity: member.dex, str_exp: member.str_exp,
dexterityEquipMult: member.dex_mult, def_exp: member.def_exp,
dexterityAscensionMult: member.dex_asc_mult, dex_exp: member.dex_exp,
equipment: member.upgrades.slice(), agi_exp: member.agi_exp,
hacking: member.hack, cha_exp: member.cha_exp,
hackingEquipMult: member.hack_mult, hack_mult: member.hack_mult,
hackingAscensionMult: member.hack_asc_mult, str_mult: member.str_mult,
strength: member.str, def_mult: member.def_mult,
strengthEquipMult: member.str_mult, dex_mult: member.dex_mult,
strengthAscensionMult: member.str_asc_mult, agi_mult: member.agi_mult,
task: member.task, cha_mult: member.cha_mult,
hack_asc_mult: member.hack_asc_mult,
str_asc_mult: member.str_asc_mult,
def_asc_mult: member.def_asc_mult,
dex_asc_mult: member.dex_asc_mult,
agi_asc_mult: member.agi_asc_mult,
cha_asc_mult: member.cha_asc_mult,
upgrades: member.upgrades.slice(),
augmentations: member.augmentations.slice(),
} }
}, },
canRecruitMember: function() { canRecruitMember: function() {

View File

@ -43,6 +43,7 @@ import { applyExploit } from "../../Exploits/applyExploits";
import { SourceFiles } from "../../SourceFile/SourceFiles"; import { SourceFiles } from "../../SourceFile/SourceFiles";
import { SourceFileFlags } from "../../SourceFile/SourceFileFlags"; import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
import { influenceStockThroughCompanyWork } from "../../StockMarket/PlayerInfluencing"; import { influenceStockThroughCompanyWork } from "../../StockMarket/PlayerInfluencing";
import { getHospitalizationCost } from "../../Hospital/Hospital";
import Decimal from "decimal.js"; import Decimal from "decimal.js";
@ -1588,18 +1589,19 @@ export function regenerateHp(amt) {
} }
export function hospitalize() { export function hospitalize() {
const cost = getHospitalizationCost(this);
if (Settings.SuppressHospitalizationPopup === false) { if (Settings.SuppressHospitalizationPopup === false) {
dialogBoxCreate(<> dialogBoxCreate(<>
You were in critical condition! You were taken to the hospital where You were in critical condition! You were taken to the hospital where
luckily they were able to save your life. You were charged&nbsp; luckily they were able to save your life. You were charged&nbsp;
{Money(this.max_hp * CONSTANTS.HospitalCostPerHp)} {Money(cost)}
</>); </>);
} }
const cost = this.max_hp * CONSTANTS.HospitalCostPerHp
this.loseMoney(cost); this.loseMoney(cost);
this.recordMoneySource(-1 * cost, "hospitalization"); this.recordMoneySource(-1 * cost, "hospitalization");
this.hp = this.max_hp; this.hp = this.max_hp;
return cost;
} }
/********* Company job application **********/ /********* Company job application **********/

View File

@ -2139,23 +2139,11 @@ let Terminal = {
const numAugReq = Math.round(BitNodeMultipliers.DaedalusAugsRequirement*30) const numAugReq = Math.round(BitNodeMultipliers.DaedalusAugsRequirement*30)
const fulfilled = Player.augmentations.length >= numAugReq && const fulfilled = Player.augmentations.length >= numAugReq &&
Player.money.gt(1e11) && Player.money.gt(1e11) &&
((Player.hacking_skill >= 2500)|| Player.hacking_skill >= 2500;
(Player.strength >= 1500 &&
Player.defense >= 1500 &&
Player.dexterity >= 1500 &&
Player.agility >= 1500));
if(!fulfilled) { if(!fulfilled) {
post(`Augmentations: ${Player.augmentations.length} / ${numAugReq}`); post(`Augmentations: ${Player.augmentations.length} / ${numAugReq}`);
postElement(<>Money: {Money(Player.money.toNumber())} / {Money(1e11)}</>); postElement(<>Money: {Money(Player.money.toNumber())} / {Money(1e11)}</>);
post("One path below must be fulfilled...");
post("----------HACKING PATH----------");
post(`Hacking skill: ${Player.hacking_skill} / 2500`); post(`Hacking skill: ${Player.hacking_skill} / 2500`);
post("----------COMBAT PATH----------");
post(`Strength: ${Player.strength} / 1500`);
post(`Defense: ${Player.defense} / 1500`);
post(`Dexterity: ${Player.dexterity} / 1500`);
post(`Agility: ${Player.agility} / 1500`);
return; return;
} }

View File

@ -274,16 +274,16 @@ if (htmlWebpackPlugin.options.googleAnalytics.trackingId) { %>
<div id="infiltration-left-panel"> <div id="infiltration-left-panel">
<p id="infiltration-level-text"> </p> <p id="infiltration-level-text"> </p>
<div id="infiltration-buttons"> <div id="infiltration-buttons">
<a class="a-link-button tooltip" id="infiltration-kill"> </a> <button class="a-link-button tooltip" id="infiltration-kill"> </button>
<a class="a-link-button tooltip" id="infiltration-knockout"> </a> <button class="a-link-button tooltip" id="infiltration-knockout"> </button>
<a class="a-link-button tooltip" id="infiltration-stealthknockout"> </a> <button class="a-link-button tooltip" id="infiltration-stealthknockout"> </button>
<a class="a-link-button tooltip" id="infiltration-assassinate"> </a> <button class="a-link-button tooltip" id="infiltration-assassinate"> </button>
<a class="a-link-button tooltip" id="infiltration-hacksecurity"> </a> <button class="a-link-button tooltip" id="infiltration-hacksecurity"> </button>
<a class="a-link-button tooltip" id="infiltration-destroysecurity"> </a> <button class="a-link-button tooltip" id="infiltration-destroysecurity"> </button>
<a class="a-link-button tooltip" id="infiltration-sneak"> </a> <button class="a-link-button tooltip" id="infiltration-sneak"> </button>
<a class="a-link-button tooltip" id="infiltration-pickdoor"> </a> <button class="a-link-button tooltip" id="infiltration-pickdoor"> </button>
<a class="a-link-button tooltip" id="infiltration-bribe"> </a> <button class="a-link-button tooltip" id="infiltration-bribe"> </button>
<a class="a-link-button tooltip" id="infiltration-escape"> </a> <button class="a-link-button tooltip" id="infiltration-escape"> </button>
</div> </div>
</div> </div>
<div id="infiltration-right-panel"> <div id="infiltration-right-panel">
@ -400,7 +400,7 @@ if (htmlWebpackPlugin.options.googleAnalytics.trackingId) { %>
<!-- Game Options --> <!-- Game Options -->
<div id="game-options-container" class="popup-box-container"> <div id="game-options-container" class="popup-box-container">
<div id="game-options-content" class="game-options-box"> <div id="game-options-content" class="game-options-box">
<button id="game-options-close-button">&times;</button> <button id="game-options-close-button" aria-label="close options dialog">&times;</button>
<h1> Game Options </h1> <h1> Game Options </h1>
<br /> <br />
<div id="game-options-left-panel"> <div id="game-options-left-panel">

View File

@ -40,9 +40,9 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
function Hacknet(): React.ReactElement { function Hacknet(): React.ReactElement {
// Can't import HacknetHelpers for some reason. // Can't import HacknetHelpers for some reason.
if(!(p.bitNodeN === 9 || SourceFileFlags[9] > 0)) { if(!(p.bitNodeN === 9 || SourceFileFlags[9] > 0)) {
return <><span>Hacknet Nodes owned: {p.hacknetNodes.length}</span><br /></> return <><span>{`Hacknet Nodes owned: ${p.hacknetNodes.length}</span>`}</span><br /></>
} else { } else {
return <><span>Hacknet Servers owned: {p.hacknetNodes.length} / {HacknetServerConstants.MaxServers}</span><br /></> return <><span>{`Hacknet Servers owned: ${p.hacknetNodes.length} / ${HacknetServerConstants.MaxServers}</span>`}</span><br /></>
} }
} }
@ -97,8 +97,8 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
<table> <table>
<tbody> <tbody>
{props.rows.map((r: any) => <tr key={r[0]}> {props.rows.map((r: any) => <tr key={r[0]}>
<td key='0'>{r[0]} multiplier: </td> <td key='0'>{`${r[0]} multiplier:`}</td>
<td key='1' style={{textAlign: 'right'}}>{numeralWrapper.formatPercentage(r[1])}</td> <td key='1' style={{textAlign: 'right', paddingLeft: '5px'}}>{numeralWrapper.formatPercentage(r[1])}</td>
{bn5Stat(r)} {bn5Stat(r)}
</tr>)} </tr>)}
</tbody> </tbody>
@ -234,9 +234,9 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
]} /><br /><br /> ]} /><br /><br />
<b>Misc.</b><br /><br /> <b>Misc.</b><br /><br />
<span>Servers owned: {p.purchasedServers.length} / {getPurchaseServerLimit()}</span><br /> <span>{`Servers owned: ${p.purchasedServers.length} / ${getPurchaseServerLimit()}`}</span><br />
<Hacknet /> <Hacknet />
<span>Augmentations installed: {p.augmentations.length}</span><br /><br /> <span>{`Augmentations installed: ${p.augmentations.length}`}</span><br /><br />
{StatsTable(timeRows, null)} {StatsTable(timeRows, null)}
<br /> <br />
<CurrentBitNode /> <CurrentBitNode />

View File

@ -134,7 +134,9 @@ export function yesNoTxtInpBoxGetInput(): string {
export function yesNoTxtInpBoxCreate(txt: string | JSX.Element) { export function yesNoTxtInpBoxCreate(txt: string | JSX.Element) {
yesNoBoxOpen = true; yesNoBoxOpen = true;
if (yesNoTextInputBoxTextElement) { if (yesNoTextInputBoxTextElement) {
yesNoTextInputBoxTextElement.innerHTML = '';
if(typeof txt === 'string') { if(typeof txt === 'string') {
yesNoTextInputBoxTextElement.innerHTML = txt; yesNoTextInputBoxTextElement.innerHTML = txt;
} else { } else {