Compare commits

...

8 Commits

Author SHA1 Message Date
Olivier Gagnon
a564957092 v0.52.7 2021-08-21 14:00:28 -04:00
Olivier Gagnon
4b8e63f342 Fix a few other bugs 2021-08-21 11:30:31 -04:00
Olivier Gagnon
4de20f8cce Made logbox drag a little smoother. 2021-08-21 02:31:37 -04:00
Olivier Gagnon
4b38d296a8 Fix corp industry wrong initial value. 2021-08-21 02:10:58 -04:00
Olivier Gagnon
6561413137 Fix Corp research popup box appearing behind one another. 2021-08-21 02:06:48 -04:00
Olivier Gagnon
b67c03ff8a hotfix broken editor shortcuts 2021-08-21 01:54:39 -04:00
Olivier Gagnon
ee5a70901b hotfix logbox width 2021-08-21 00:58:24 -04:00
Olivier Gagnon
63b2c77907 hotfix the tutorial 2021-08-21 00:51:07 -04:00
27 changed files with 215 additions and 128 deletions

View File

@@ -99,7 +99,6 @@
}
.log-box-log-container {
max-width: 400px;
overflow-y: auto;
}

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([862,0]),o()}({799:function(n,t,o){},801:function(n,t,o){},803:function(n,t,o){},805:function(n,t,o){},807:function(n,t,o){},809:function(n,t,o){},811:function(n,t,o){},813:function(n,t,o){},815:function(n,t,o){},817:function(n,t,o){},819:function(n,t,o){},821:function(n,t,o){},823:function(n,t,o){},825:function(n,t,o){},827:function(n,t,o){},829:function(n,t,o){},831:function(n,t,o){},833:function(n,t,o){},835:function(n,t,o){},837:function(n,t,o){},839:function(n,t,o){},841:function(n,t,o){},843:function(n,t,o){},845:function(n,t,o){},847:function(n,t,o){},849:function(n,t,o){},851:function(n,t,o){},853:function(n,t,o){},855:function(n,t,o){},857:function(n,t,o){},859:function(n,t,o){},862:function(n,t,o){"use strict";o.r(t);o(861),o(859),o(857),o(855),o(853),o(851),o(849),o(847),o(845),o(843),o(841),o(839),o(837),o(835),o(833),o(831),o(829),o(827),o(825),o(823),o(821),o(819),o(817),o(815),o(813),o(811),o(809),o(807),o(805),o(803),o(801),o(799)}});
!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([863,0]),o()}({800:function(n,t,o){},802:function(n,t,o){},804:function(n,t,o){},806:function(n,t,o){},808:function(n,t,o){},810:function(n,t,o){},812:function(n,t,o){},814:function(n,t,o){},816:function(n,t,o){},818:function(n,t,o){},820:function(n,t,o){},822:function(n,t,o){},824:function(n,t,o){},826:function(n,t,o){},828:function(n,t,o){},830:function(n,t,o){},832:function(n,t,o){},834:function(n,t,o){},836:function(n,t,o){},838:function(n,t,o){},840:function(n,t,o){},842:function(n,t,o){},844:function(n,t,o){},846:function(n,t,o){},848:function(n,t,o){},850:function(n,t,o){},852:function(n,t,o){},854:function(n,t,o){},856:function(n,t,o){},858:function(n,t,o){},860:function(n,t,o){},863:function(n,t,o){"use strict";o.r(t);o(862),o(860),o(858),o(856),o(854),o(852),o(850),o(848),o(846),o(844),o(842),o(840),o(838),o(836),o(834),o(832),o(830),o(828),o(826),o(824),o(822),o(820),o(818),o(816),o(814),o(812),o(810),o(808),o(806),o(804),o(802),o(800)}});
//# sourceMappingURL=engineStyle.bundle.js.map

View File

@@ -2433,7 +2433,6 @@ input[type="checkbox"] {
justify-content: space-between; }
.log-box-log-container {
max-width: 400px;
overflow-y: auto; }
.log-box-button {

30
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -3,6 +3,34 @@
Changelog
=========
v0.52.7 - 2021-07-21 Fixing the previous patch tbh (hydroflame)
-------------------------------------------
** Netscript **
* API BREAKING CHANGE: getActionEstimatedSuccessChance now returns a pair of
value to reflect the UI changes. I'm very sorry.
** Bladeburner **
* General actions now display time required.
* Recruitment now displays success chance.
* All other success chance now display a range instead of a single value
The real value is guaranteed to be within that range.
** Misc. **
* Fix tutorial not working after Monaco upate
* Fix logbox logs not taking up the whole logbox
* Fix script editor shortcut (ctrl+b)
* Fix Corporation popup appearing in the wrong order, hiding one of them
* Fix error when loading Corp
* Fix logbox dragging (smoother now)
* Fix logbox name collision
* Fix logbox allowing to open the same box multiple times
* Fix netscript write.
* nerf noodle bar
v0.52.6 - 2021-07-21 Logboxes and VS-code (hydroflame)
-------------------------------------------

View File

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

View File

@@ -6,10 +6,10 @@ getActionEstimatedSuccessChance() Netscript Function
:RAM cost: 4 GB
:param string type: Type of action. See :ref:`bladeburner_action_types`
:param string name: Name of action. Must be an exact match
:returns: Estimated success chance in decimal
:returns: Array of 2 number, lower and upper bound of the action chance.
Example:
.. code-block:: javascript
bladeburner.getActionEstimatedSuccessChance("Contracts", "Tracking"); // returns: .3
bladeburner.getActionEstimatedSuccessChance("Contracts", "Tracking"); // returns: [.3, .6]

View File

@@ -129,5 +129,5 @@
"watch": "webpack --watch --mode production",
"watch:dev": "webpack --watch --mode development"
},
"version": "0.52.6"
"version": "0.52.7"
}

View File

@@ -194,6 +194,23 @@ export class Action implements IAction {
return 1;
}
getEstSuccessChance(inst: IBladeburner): number[] {
function clamp(x: number): number {
return Math.max(0, Math.min(x, 1));
}
const est = this.getSuccessChance(inst, {est: true});
const real = this.getSuccessChance(inst);
const diff = Math.abs(real-est);
let low = real-diff;
let high = real+diff;
const city = inst.getCurrentCity();
const r = city.pop / city.popEst;
if(r < 1) low *= r;
else high *= r;
return [clamp(low), clamp(high)];
}
/**
* @inst - Bladeburner Object
* @params - options:

View File

@@ -1788,18 +1788,18 @@ export class Bladeburner implements IBladeburner {
}
}
getActionEstimatedSuccessChanceNetscriptFn(player: IPlayer, type: string, name: string, workerScript: WorkerScript): number {
getActionEstimatedSuccessChanceNetscriptFn(player: IPlayer, type: string, name: string, workerScript: WorkerScript): number[] {
const errorLogText = `Invalid action: type='${type}' name='${name}'`
const actionId = this.getActionIdFromTypeAndName(type, name);
if (actionId == null) {
workerScript.log("bladeburner.getActionEstimatedSuccessChance", errorLogText);
return -1;
return [-1, -1];
}
const actionObj = this.getActionObject(actionId);
if (actionObj == null) {
workerScript.log("bladeburner.getActionEstimatedSuccessChance", errorLogText);
return -1;
return [-1, -1];
}
switch (actionId.type) {
@@ -1807,16 +1807,17 @@ export class Bladeburner implements IBladeburner {
case ActionTypes["Operation"]:
case ActionTypes["BlackOp"]:
case ActionTypes["BlackOperation"]:
return actionObj.getSuccessChance(this, {est:true});
return actionObj.getEstSuccessChance(this);
case ActionTypes["Training"]:
case ActionTypes["Field Analysis"]:
case ActionTypes["FieldAnalysis"]:
return 1;
return [1, 1];
case ActionTypes["Recruitment"]:
return this.getRecruitmentSuccessChance(player);
const recChance = this.getRecruitmentSuccessChance(player);
return [recChance, recChance];
default:
workerScript.log("bladeburner.getActionEstimatedSuccessChance", errorLogText);
return -1;
return [-1, -1];
}
}

View File

@@ -64,6 +64,7 @@ export interface IAction {
getActionTypeSkillSuccessBonus(inst: IBladeburner): number;
getChaosCompetencePenalty(inst: IBladeburner, params: ISuccessChanceParams): number;
getChaosDifficultyBonus(inst: IBladeburner): number;
getEstSuccessChance(inst: IBladeburner): number[];
getSuccessChance(inst: IBladeburner, params: ISuccessChanceParams): number;
getSuccessesNeededForNextLevel(baseSuccessesPerLevel: number): number;
setMaxLevel(baseSuccessesPerLevel: number): void;

View File

@@ -67,7 +67,7 @@ export interface IBladeburner {
getSkillNamesNetscriptFn(): string[];
startActionNetscriptFn(player: IPlayer, type: string, name: string, workerScript: WorkerScript): boolean;
getActionTimeNetscriptFn(player: IPlayer, type: string, name: string, workerScript: WorkerScript): number;
getActionEstimatedSuccessChanceNetscriptFn(player: IPlayer, type: string, name: string, workerScript: WorkerScript): number;
getActionEstimatedSuccessChanceNetscriptFn(player: IPlayer, type: string, name: string, workerScript: WorkerScript): number[];
getActionCountRemainingNetscriptFn(type: string, name: string, workerScript: WorkerScript): number;
getSkillLevelNetscriptFn(skillName: string, workerScript: WorkerScript): number;
getSkillUpgradeCostNetscriptFn(skillName: string, workerScript: WorkerScript): number;

View File

@@ -44,6 +44,6 @@ export function AllPages(props: IProps): React.ReactElement {
{page === 'BlackOps' && <BlackOpPage bladeburner={props.bladeburner} player={props.player} />}
{page === 'Skills' && <SkillPage bladeburner={props.bladeburner} />}
</div>
<span className="text">{stealthIcon}= This action requires stealth, {killIcon} = This action involves retirement</span>
<span className="text">{stealthIcon} = This action requires stealth, {killIcon} = This action involves retirement</span>
</>);
}

View File

@@ -10,6 +10,7 @@ import { createPopup } from "../../ui/React/createPopup";
import { TeamSizePopup } from "./TeamSizePopup";
import { IBladeburner } from "../IBladeburner";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { SuccessChance } from "./SuccessChance";
interface IProps {
bladeburner: IBladeburner;
@@ -26,7 +27,7 @@ export function BlackOpElem(props: IProps): React.ReactElement {
}
const isActive = props.bladeburner.action.type === ActionTypes["BlackOperation"] && props.action.name === props.bladeburner.action.name;
const estimatedSuccessChance = props.action.getSuccessChance(props.bladeburner, {est:true});
const estimatedSuccessChance = props.action.getEstSuccessChance(props.bladeburner);
const actionTime = props.action.getActionTime(props.bladeburner);
const hasReqdRank = props.bladeburner.rank >= props.action.reqdRank;
const computedActionTimeCurrent = Math.min(props.bladeburner.actionTimeCurrent+props.bladeburner.actionTimeOverflow, props.bladeburner.actionTimeToComplete);
@@ -78,10 +79,10 @@ export function BlackOpElem(props: IProps): React.ReactElement {
Required Rank: {formatNumber(props.action.reqdRank, 0)}
</p>
<br />
<p style={{display:"inline-block"}}>
Estimated Success Chance: {formatNumber(estimatedSuccessChance*100, 1)}% {props.action.isStealth?stealthIcon:<></>}{props.action.isKill?killIcon:<></>}
<pre style={{display:"inline-block"}}>
Estimated Success Chance: <SuccessChance chance={estimatedSuccessChance} /> {props.action.isStealth?stealthIcon:<></>}{props.action.isKill?killIcon:<></>}
<br />
Time Required: {convertTimeMsToTimeElapsedString(actionTime*1000)}
</p>
</pre>
</>);
}

View File

@@ -9,6 +9,7 @@ import { stealthIcon, killIcon } from "../data/Icons";
import { BladeburnerConstants } from "../data/Constants";
import { IBladeburner } from "../IBladeburner";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { SuccessChance } from "./SuccessChance";
interface IProps {
bladeburner: IBladeburner;
@@ -19,7 +20,8 @@ interface IProps {
export function ContractElem(props: IProps): React.ReactElement {
const setRerender = useState(false)[1];
const isActive = props.bladeburner.action.type === ActionTypes["Contract"] && props.action.name === props.bladeburner.action.name;
const estimatedSuccessChance = props.action.getSuccessChance(props.bladeburner, {est:true});
const estimatedSuccessChance = props.action.getEstSuccessChance(props.bladeburner);
const successChance = props.action.getSuccessChance(props.bladeburner);
const computedActionTimeCurrent = Math.min(props.bladeburner.actionTimeCurrent+props.bladeburner.actionTimeOverflow, props.bladeburner.actionTimeToComplete);
const maxLevel = (props.action.level >= props.action.maxLevel);
const actionTime = props.action.getActionTime(props.bladeburner);
@@ -93,7 +95,7 @@ export function ContractElem(props: IProps): React.ReactElement {
<pre style={{display: 'inline-block'}}>
<span dangerouslySetInnerHTML={{__html: props.action.desc}} />
<br /><br />
Estimated success chance: {formatNumber(estimatedSuccessChance*100, 1)}% {props.action.isStealth?stealthIcon:<></>}{props.action.isKill?killIcon:<></>}<br />
Estimated success chance: <SuccessChance chance={estimatedSuccessChance} /> {props.action.isStealth?stealthIcon:<></>}{props.action.isKill?killIcon:<></>}<br />
Time Required: {convertTimeMsToTimeElapsedString(actionTime*1000)}<br />
Contracts remaining: {Math.floor(props.action.count)}<br />
Successes: {props.action.successes}<br />
@@ -114,26 +116,3 @@ Failures: {props.action.failures}
onChange={onAutolevel}/>
</>);
}
/*
// Autolevel Checkbox
el.appendChild(createElement("br"));
var autolevelCheckboxId = "bladeburner-" + action.name + "-autolevel-checkbox";
el.appendChild(createElement("label", {
for:autolevelCheckboxId, innerText:"Autolevel: ",color:"white",
tooltip:"Automatically increase contract level when possible",
}));
const checkboxInput = createElement("input", {
type:"checkbox",
id: autolevelCheckboxId,
checked: action.autoLevel,
changeListener: () => {
action.autoLevel = checkboxInput.checked;
},
});
el.appendChild(checkboxInput);
*/

View File

@@ -1,7 +1,10 @@
import React, { useState } from "react";
import { ActionTypes } from "../data/ActionTypes";
import { createProgressBarText } from "../../../utils/helpers/createProgressBarText";
import { formatNumber } from "../../../utils/StringHelperFunctions";
import {
formatNumber,
convertTimeMsToTimeElapsedString,
} from "../../../utils/StringHelperFunctions";
import { IBladeburner } from "../IBladeburner";
import { IPlayer } from "../../PersonObjects/IPlayer";
@@ -15,6 +18,20 @@ export function GeneralActionElem(props: IProps): React.ReactElement {
const setRerender = useState(false)[1];
const isActive = props.action.name === props.bladeburner.action.name;
const computedActionTimeCurrent = Math.min(props.bladeburner.actionTimeCurrent+props.bladeburner.actionTimeOverflow, props.bladeburner.actionTimeToComplete);
const actionTime = (function(): number{
switch(props.action.name) {
case "Training":
case "Field Analysis":
return 30;
case "Diplomacy":
case "Hyperbolic Regeneration Chamber":
return 60;
case "Recruitment":
return props.bladeburner.getRecruitmentTime(props.player);
}
return -1; // dead code
})();
const successChance = props.action.name === "Recruitment" ? Math.max(0, Math.min(props.bladeburner.getRecruitmentSuccessChance(props.player), 1)) : -1;
function onStart(): void {
props.bladeburner.action.type = ActionTypes[(props.action.name as string)];
@@ -42,6 +59,10 @@ export function GeneralActionElem(props: IProps): React.ReactElement {
</>}
<br />
<br />
<pre style={{display: 'inline-block'}} dangerouslySetInnerHTML={{__html: props.action.desc}}></pre>
<pre style={{display: 'inline-block'}} dangerouslySetInnerHTML={{__html: props.action.desc}}></pre><br /><br />
<pre style={{display: 'inline-block'}}>
Time Required: {convertTimeMsToTimeElapsedString(actionTime*1000)}
{successChance !== -1 && <><br />Estimated success chance: {formatNumber(successChance*100, 1)}%</>}
</pre>
</>);
}

View File

@@ -11,6 +11,7 @@ import { createPopup } from "../../ui/React/createPopup";
import { TeamSizePopup } from "./TeamSizePopup";
import { IBladeburner } from "../IBladeburner";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { SuccessChance } from "./SuccessChance";
interface IProps {
bladeburner: IBladeburner;
@@ -21,7 +22,7 @@ interface IProps {
export function OperationElem(props: IProps): React.ReactElement {
const setRerender = useState(false)[1];
const isActive = props.bladeburner.action.type === ActionTypes["Operation"] && props.action.name === props.bladeburner.action.name;
const estimatedSuccessChance = props.action.getSuccessChance(props.bladeburner, {est:true});
const estimatedSuccessChance = props.action.getEstSuccessChance(props.bladeburner);
const computedActionTimeCurrent = Math.min(props.bladeburner.actionTimeCurrent+props.bladeburner.actionTimeOverflow,props.bladeburner.actionTimeToComplete);
const maxLevel = (props.action.level >= props.action.maxLevel);
const actionTime = props.action.getActionTime(props.bladeburner);
@@ -110,7 +111,7 @@ export function OperationElem(props: IProps): React.ReactElement {
<pre style={{display:"inline-block"}}>
<span dangerouslySetInnerHTML={{__html: props.action.desc}} />
<br /><br />
Estimated success chance: {formatNumber(estimatedSuccessChance*100, 1)}% {props.action.isStealth?stealthIcon:<></>}{props.action.isKill?killIcon:<></>}<br />
Estimated success chance: <SuccessChance chance={estimatedSuccessChance} /> {props.action.isStealth?stealthIcon:<></>}{props.action.isKill?killIcon:<></>}<br />
Time Required: {convertTimeMsToTimeElapsedString(actionTime*1000)}<br />
Operations remaining: {Math.floor(props.action.count)}<br />
Successes: {props.action.successes}<br />

View File

@@ -0,0 +1,14 @@
import React from "react";
import { formatNumber } from "../../../utils/StringHelperFunctions";
interface IProps {
chance: number[];
}
export function SuccessChance(props: IProps): React.ReactElement {
if(props.chance[0] === props.chance[1]) {
return (<>{formatNumber(props.chance[0]*100, 1)}%</>);
}
return (<>{formatNumber(props.chance[0]*100, 1)}% ~ {formatNumber(props.chance[1]*100, 1)}%</>);
}

View File

@@ -6,7 +6,7 @@
import { IMap } from "./types";
export const CONSTANTS: IMap<any> = {
Version: "0.52.6",
Version: "0.52.7",
// Speed (in ms) at which the main loop is updated
_idleSpeed: 200,
@@ -228,26 +228,37 @@ export const CONSTANTS: IMap<any> = {
TotalNumBitNodes: 24,
LatestUpdate: `
v0.52.6 - 2021-07-21 Logboxes and VS-code (hydroflame)
v0.52.7 - 2021-07-21 Fixing the previous patch tbh (hydroflame)
-------------------------------------------
** Text Editor **
** Netscript **
* Ace and Codemirror have been removed in favor of monaco (web version of
vs-code). The options are a bit lackluster but more will be added as
feedback comes.
* API BREAKING CHANGE: getActionEstimatedSuccessChance now returns a pair of
value to reflect the UI changes. I'm very sorry.
** Log boxes **
** Bladeburner **
* Multiple log boxes can be opened at once. They can be moved around the
screen. (but the movement behavior is a bit weird.)
* General actions now display time required.
* Recruitment now displays success chance.
* All other success chance now display a range instead of a single value
The real value is guaranteed to be within that range.
** Misc. **
* Job promotion now correctly updates the UI.
* Milestones now call the faction CyberSec instead of CSEC
* Can no longer create file that break the filesystem.
* Remove dollar sign in blade contract UI element
* Fix tutorial not working after Monaco upate
* Fix logbox logs not taking up the whole logbox
* Fix script editor shortcut (ctrl+b)
* Fix Corporation popup appearing in the wrong order, hiding one of them
* Fix error when loading Corp
* Fix logbox dragging (smoother now)
* Fix logbox name collision
* Fix logbox allowing to open the same box multiple times
* Fix netscript write.
* nerf noodle bar
`,
/*
*/
}

View File

@@ -119,7 +119,7 @@ function Industry(params={}) {
};
this.name = params.name ? params.name : 0;
this.type = params.type ? params.type : 0;
this.type = params.type ? params.type : Industries.Agriculture;
this.sciResearch = new Material({name: "Scientific Research"});
this.researched = {}; // Object of acquired Research. Keys = research name
@@ -1397,11 +1397,12 @@ Industry.prototype.createResearchBox = function() {
researchTree.research(allResearch[i]);
this.researched[allResearch[i]] = true;
const researchBox = this.createResearchBox();
dialogBoxCreate(`Researched ${allResearch[i]}. It may take a market cycle ` +
`(~${SecsPerMarketCycle} seconds) before the effects of ` +
`the Research apply.`);
return this.createResearchBox();
return researchBox;
} else {
dialogBoxCreate(`You do not have enough Scientific Research for ${research.name}`);
}

3
src/InteractiveTutorial.d.ts vendored Normal file
View File

@@ -0,0 +1,3 @@
export declare function iTutorialNextStep(): void;
export declare const ITutorial: {isRunning: boolean, currStep: number};
export declare const iTutorialSteps: {[key: string]: number};

View File

@@ -2149,11 +2149,15 @@ function NetscriptFunctions(workerScript) {
}
return port.write(data);
} else if (isString(port)) { // Write to script or text file
const fn = removeLeadingSlash(port);
let fn = port;
if (!isValidFilePath(fn)) {
throw makeRuntimeErrorMsg("write", `Invalid filepath: ${fn}`);
}
if(fn.lastIndexOf("/") === 0) {
fn = removeLeadingSlash(fn);
}
// Coerce 'data' to be a string
try {
data = String(data);

View File

@@ -28,19 +28,6 @@ import { dialogBoxCreate } from "../../utils/DialogBox";
import { compareArrays } from "../../utils/helpers/compareArrays";
import { createElement } from "../../utils/uiHelpers/createElement";
// TODO(hydroflame): move to Monaco mount/unmount
//Define key commands in script editor (ctrl o to save + close, etc.)
$(document).keydown(function(e) {
if (Settings.DisableHotkeys === true) {return;}
if (routing.isOn(Page.ScriptEditor)) {
//Ctrl + b
if (e.keyCode == 66 && (e.ctrlKey || e.metaKey)) {
e.preventDefault();
saveAndCloseScriptEditor(); // deleted function
}
}
});
export function scriptCalculateOfflineProduction(runningScriptObj) {
//The Player object stores the last update time from when we were online
const thisUpdate = new Date().getTime();

View File

@@ -23,6 +23,11 @@ import { libSource } from "../NetscriptDefinitions";
import { NetscriptFunctions } from "../../NetscriptFunctions";
import { WorkerScript } from "../../Netscript/WorkerScript";
import { Settings } from "../../Settings/Settings";
import {
iTutorialNextStep,
ITutorial,
iTutorialSteps,
} from "../../InteractiveTutorial";
let symbols: string[] = [];
(function() {
@@ -52,6 +57,11 @@ interface IProps {
engine: IEngine;
};
/*
*/
// How to load function definition in monaco
// https://github.com/Microsoft/monaco-editor/issues/1415
// https://microsoft.github.io/monaco-editor/api/modules/monaco.languages.html
@@ -81,35 +91,34 @@ export function Root(props: IProps): React.ReactElement {
}
// TODO(hydroflame): re-enable the tutorial.
// if (ITutorial.isRunning && ITutorial.currStep === iTutorialSteps.TerminalTypeScript) {
// //Make sure filename + code properly follow tutorial
// if (filename !== "n00dles.script") {
// dialogBoxCreate("Leave the script name as 'n00dles'!");
// return;
// }
// code = code.replace(/\s/g, "");
// if (code.indexOf("while(true){hack('n00dles');}") == -1) {
// dialogBoxCreate("Please copy and paste the code from the tutorial!");
// return;
// }
if (ITutorial.isRunning && ITutorial.currStep === iTutorialSteps.TerminalTypeScript) {
//Make sure filename + code properly follow tutorial
if (filename !== "n00dles.script") {
dialogBoxCreate("Leave the script name as 'n00dles'!");
return;
}
if (code.replace(/\s/g, "").indexOf("while(true){hack('n00dles');}") == -1) {
dialogBoxCreate("Please copy and paste the code from the tutorial!");
return;
}
// //Save the script
// let s = Player.getCurrentServer();
// for (var i = 0; i < s.scripts.length; i++) {
// if (filename == s.scripts[i].filename) {
// s.scripts[i].saveScript(getCurrentEditor().getCode(), Player.currentServer, Player.getCurrentServer().scripts);
// Engine.loadTerminalContent();
// return iTutorialNextStep();
// }
// }
//Save the script
const s = props.player.getCurrentServer();
for (let i = 0; i < s.scripts.length; i++) {
if (filename == s.scripts[i].filename) {
s.scripts[i].saveScript(code, props.player.currentServer, props.player.getCurrentServer().scripts);
props.engine.loadTerminalContent();
return iTutorialNextStep();
}
}
// // If the current script does NOT exist, create a new one
// let script = new Script();
// script.saveScript(getCurrentEditor().getCode(), Player.currentServer, Player.getCurrentServer().scripts);
// s.scripts.push(script);
// If the current script does NOT exist, create a new one
let script = new Script();
script.saveScript(code, props.player.currentServer, props.player.getCurrentServer().scripts);
s.scripts.push(script);
// return iTutorialNextStep();
// }
return iTutorialNextStep();
}
if (filename == "") {
dialogBoxCreate("You must specify a filename!");
@@ -154,7 +163,7 @@ export function Root(props: IProps): React.ReactElement {
const textFile = new TextFile(filename, code);
s.textFiles.push(textFile);
} else {
dialogBoxCreate("Invalid filename. Must be either a script (.script) or " +
dialogBoxCreate("Invalid filename. Must be either a script (.script, .js, or .ns) or " +
" or text file (.txt)")
return;
}
@@ -226,6 +235,19 @@ export function Root(props: IProps): React.ReactElement {
return () => clearInterval(id);
}, [code]);
useEffect(() => {
function maybeSave(event: KeyboardEvent) {
if (Settings.DisableHotkeys) return;
//Ctrl + b
if (event.keyCode == 66 && (event.ctrlKey || event.metaKey)) {
event.preventDefault();
save();
}
}
document.addEventListener('keydown', maybeSave);
return () => document.removeEventListener('keydown', maybeSave);
})
function onMount(editor: IStandaloneCodeEditor): void {
editorRef.current = editor;
if(editorRef.current === null) return;
@@ -253,7 +275,6 @@ export function Root(props: IProps): React.ReactElement {
monaco.languages.typescript.typescriptDefaults.addExtraLib(libSource, 'netscript.d.ts');
}
console.log(options);
return (<div id="script-editor-wrapper">
<div id="script-editor-filename-wrapper">
<p id="script-editor-filename-tag" className="noselect"> <strong style={{backgroundColor:'#555'}}>Script name: </strong></p>

View File

@@ -145,7 +145,6 @@ export const Settings: ISettings & ISelfInitializer & ISelfLoading = {
Object.assign(Settings, defaultSettings);
},
load(saveString: string) {
console.log(saveString);
Object.assign(Settings, JSON.parse(saveString));
},
};

View File

@@ -55,12 +55,11 @@ function ScriptLogPopup(props: IProps): React.ReactElement {
function drag(event: React.MouseEvent<HTMLElement, MouseEvent>): void {
event.preventDefault();
//console.log(props.container.clientWidth);
//console.log(props.container.clientHeight);
let x = event.clientX;
let y = event.clientY;
console.log(props.container.clientWidth);
let left = props.container.offsetLeft+props.container.clientWidth/2;
let top = props.container.offsetTop+props.container.clientHeight/2;
let top = props.container.offsetTop+props.container.clientWidth/5;
function mouseMove(event: MouseEvent): void {
left+=event.clientX-x;
top+=event.clientY-y;
@@ -95,7 +94,8 @@ function ScriptLogPopup(props: IProps): React.ReactElement {
}
export function logBoxCreate(script: RunningScript): void {
const id = script.filename+script.args.map((x: any): string => `${x}`).join('');
const id = script.server+"-"+script.filename+script.args.map((x: any): string => `${x}`).join('-');
if(document.getElementById(id) !== null) return;
const container = createElement("div", {
class: "log-box-container",
id: id,