mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-26 01:23:49 +01:00
fix a bunch of small v2 related bugs
This commit is contained in:
parent
5d2b81053d
commit
faa3e212f3
@ -30,6 +30,7 @@ secrets that you've been searching for.
|
|||||||
Tools & Resources <toolsandresources>
|
Tools & Resources <toolsandresources>
|
||||||
Changelog <changelog>
|
Changelog <changelog>
|
||||||
v1.0.0 script migration guide <v1.0.0_migration.rst>
|
v1.0.0 script migration guide <v1.0.0_migration.rst>
|
||||||
|
v2.0.0 script migration guide <v2.0.0_migration.rst>
|
||||||
404 <404.rst>
|
404 <404.rst>
|
||||||
Donate <https://paypal.me/danielyxie>
|
Donate <https://paypal.me/danielyxie>
|
||||||
|
|
||||||
|
93
doc/source/v2.0.0_migration.rst
Normal file
93
doc/source/v2.0.0_migration.rst
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
v2.0.0 Migration Guide
|
||||||
|
======================
|
||||||
|
|
||||||
|
In v2.0.0 a few more API have been broken.
|
||||||
|
|
||||||
|
Working
|
||||||
|
-------
|
||||||
|
|
||||||
|
Working has been rebuilt from the grounds up. The motivation for that change is that all
|
||||||
|
different types of work all required different cached variables on the main Player object.
|
||||||
|
This caused a lot of bugs and crashes. It's been reworked in such a way as to prevent bugs
|
||||||
|
and make it nearly trivial to add new kinds of work.
|
||||||
|
All work type give their reward immediately. No need to stop work to bank rewards like reputation.
|
||||||
|
Faction and Company work no longer have a time limit.
|
||||||
|
Company work no longer reduces rep gain by half for quitting early.
|
||||||
|
Company faction require 400k rep to join (from 200k)
|
||||||
|
Backdooring company server reduces faction requirement to 300k.
|
||||||
|
All types of work generally no longer keep track of cumulative gains like exp and reputation since it's applied instantly.
|
||||||
|
|
||||||
|
commitCrime
|
||||||
|
-----------
|
||||||
|
|
||||||
|
crime now loops, meaning after finishing one shoplift you start the next one with no input. While the signature
|
||||||
|
has not changed its behavior has. It also has a new 'focus' parameters.
|
||||||
|
|
||||||
|
getPlayer
|
||||||
|
---------
|
||||||
|
|
||||||
|
The following work-related fields are not longer included:
|
||||||
|
|
||||||
|
* workChaExpGained
|
||||||
|
* currentWorkFactionName
|
||||||
|
* workDexExpGained
|
||||||
|
* workHackExpGained
|
||||||
|
* createProgramReqLvl
|
||||||
|
* workStrExpGained
|
||||||
|
* companyName
|
||||||
|
* crimeType
|
||||||
|
* workRepGained
|
||||||
|
* workChaExpGainRate
|
||||||
|
* workType
|
||||||
|
* workStrExpGainRate
|
||||||
|
* isWorking
|
||||||
|
* workRepGainRate
|
||||||
|
* workDefExpGained
|
||||||
|
* currentWorkFactionDescription
|
||||||
|
* workHackExpGainRate
|
||||||
|
* workAgiExpGainRate
|
||||||
|
* workDexExpGainRate
|
||||||
|
* workMoneyGained
|
||||||
|
* workMoneyLossRate
|
||||||
|
* workMoneyGainRate
|
||||||
|
* createProgramName
|
||||||
|
* workDefExpGainRate
|
||||||
|
* workAgiExpGained
|
||||||
|
* className
|
||||||
|
|
||||||
|
The reason for that is that these fields are all, in one way or another, included in the new work field 'currentWork'.
|
||||||
|
Some of these values are also irrelevant.
|
||||||
|
'currentWork' will be one of many different kind of value. For example when creating a program it will have a programName field.
|
||||||
|
One field that all kinds of work have in common is 'type' which denotes the current kind of work.
|
||||||
|
|
||||||
|
All fields ending in _mult have been moved to the 'mults' struct.
|
||||||
|
For example: getPlayer().hacking_skill_mult is now getPlayer().mults.hacking_skill
|
||||||
|
|
||||||
|
workForCompany
|
||||||
|
--------------
|
||||||
|
|
||||||
|
The argument 'companyName' is now not-optional.
|
||||||
|
|
||||||
|
|
||||||
|
getScriptIncome & getScriptExpGain
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
Those 2 functions used to have a call where no arguments would return the total for all scripts. This caused weird signature.
|
||||||
|
If you want to get the total income/exp for all scripts used the new getTotalScriptIncome / getTotalScriptExpGain instead.
|
||||||
|
|
||||||
|
scp
|
||||||
|
---
|
||||||
|
|
||||||
|
scp has it's 2 last argument reversed, the signature is now scp(files, destination, optional_source)
|
||||||
|
|
||||||
|
Singularity
|
||||||
|
-----------
|
||||||
|
|
||||||
|
A while ago top level singularity function were deprecated in favor of the singularity namespace.
|
||||||
|
This means calls like 'ns.connect' need to be changed to 'ns.singularity.connect'
|
||||||
|
|
||||||
|
|
||||||
|
stock.buy and stock.sell
|
||||||
|
------------------------
|
||||||
|
These 2 functions were renamed to stock.buyStock and stock.sellStock because 'buy' and 'sell'
|
||||||
|
are very common tokens that would trick the ram calculation.
|
10
src/Alias.ts
10
src/Alias.ts
@ -36,16 +36,18 @@ export function printAliases(): void {
|
|||||||
|
|
||||||
// Returns true if successful, false otherwise
|
// Returns true if successful, false otherwise
|
||||||
export function parseAliasDeclaration(dec: string, global = false): boolean {
|
export function parseAliasDeclaration(dec: string, global = false): boolean {
|
||||||
const re = /^([\w|!%,@-]+)=(("(.+)")|('(.+)'))$/;
|
console.log(dec);
|
||||||
|
const re = /^([\w|!%,@-]+)=(.+)$/;
|
||||||
const matches = dec.match(re);
|
const matches = dec.match(re);
|
||||||
if (matches == null || matches.length != 7) {
|
console.log(matches);
|
||||||
|
if (matches == null || matches.length != 3) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (global) {
|
if (global) {
|
||||||
addGlobalAlias(matches[1], matches[4] || matches[6]);
|
addGlobalAlias(matches[1], matches[2]);
|
||||||
} else {
|
} else {
|
||||||
addAlias(matches[1], matches[4] || matches[6]);
|
addAlias(matches[1], matches[2]);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -107,12 +107,7 @@ export const CurrentOptionsPage = (props: IProps): React.ReactElement => {
|
|||||||
step={25}
|
step={25}
|
||||||
min={0}
|
min={0}
|
||||||
max={500}
|
max={500}
|
||||||
tooltip={
|
tooltip={<>The maximum number of recently killed scripts the game will keep.</>}
|
||||||
<>
|
|
||||||
The maximum number of lines a script's logs can hold. Setting this too high can cause the game to use a
|
|
||||||
lot of memory if you have many scripts running.
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<OptionsSlider
|
<OptionsSlider
|
||||||
label="Netscript log size"
|
label="Netscript log size"
|
||||||
|
@ -84,7 +84,6 @@ import {
|
|||||||
Infiltration as IInfiltration,
|
Infiltration as IInfiltration,
|
||||||
RunningScript as IRunningScript,
|
RunningScript as IRunningScript,
|
||||||
RecentScript as IRecentScript,
|
RecentScript as IRecentScript,
|
||||||
SourceFileLvl,
|
|
||||||
BasicHGWOptions,
|
BasicHGWOptions,
|
||||||
ProcessInfo,
|
ProcessInfo,
|
||||||
HackingMultipliers,
|
HackingMultipliers,
|
||||||
@ -2470,6 +2469,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
|||||||
inBladeburner: Player.inBladeburner(),
|
inBladeburner: Player.inBladeburner(),
|
||||||
hasCorporation: Player.hasCorporation(),
|
hasCorporation: Player.hasCorporation(),
|
||||||
entropy: Player.entropy,
|
entropy: Player.entropy,
|
||||||
|
currentWork: Player.currentWork,
|
||||||
};
|
};
|
||||||
Object.assign(data.jobs, Player.jobs);
|
Object.assign(data.jobs, Player.jobs);
|
||||||
return data;
|
return data;
|
||||||
|
@ -11,7 +11,6 @@ import { LocationName } from "../../../Locations/data/LocationNames";
|
|||||||
import { Locations } from "../../../Locations/Locations";
|
import { Locations } from "../../../Locations/Locations";
|
||||||
import { PurchaseAugmentationsOrderSetting } from "../../../Settings/SettingEnums";
|
import { PurchaseAugmentationsOrderSetting } from "../../../Settings/SettingEnums";
|
||||||
import { Settings } from "../../../Settings/Settings";
|
import { Settings } from "../../../Settings/Settings";
|
||||||
import { IMap } from "../../../types";
|
|
||||||
import { use } from "../../../ui/Context";
|
import { use } from "../../../ui/Context";
|
||||||
import { ConfirmationModal } from "../../../ui/React/ConfirmationModal";
|
import { ConfirmationModal } from "../../../ui/React/ConfirmationModal";
|
||||||
import { Money } from "../../../ui/React/Money";
|
import { Money } from "../../../ui/React/Money";
|
||||||
@ -20,7 +19,15 @@ import { IPlayer } from "../../IPlayer";
|
|||||||
import { GraftableAugmentation } from "../GraftableAugmentation";
|
import { GraftableAugmentation } from "../GraftableAugmentation";
|
||||||
import { calculateGraftingTimeWithBonus, getGraftingAvailableAugs } from "../GraftingHelpers";
|
import { calculateGraftingTimeWithBonus, getGraftingAvailableAugs } from "../GraftingHelpers";
|
||||||
|
|
||||||
export const GraftableAugmentations: IMap<GraftableAugmentation> = {};
|
export const GraftableAugmentations = (): Record<string, GraftableAugmentation> => {
|
||||||
|
const gAugs: Record<string, GraftableAugmentation> = {};
|
||||||
|
for (const aug of Object.values(StaticAugmentations)) {
|
||||||
|
const name = aug.name;
|
||||||
|
const graftableAug = new GraftableAugmentation(aug);
|
||||||
|
gAugs[name] = graftableAug;
|
||||||
|
}
|
||||||
|
return gAugs;
|
||||||
|
};
|
||||||
|
|
||||||
const canGraft = (player: IPlayer, aug: GraftableAugmentation): boolean => {
|
const canGraft = (player: IPlayer, aug: GraftableAugmentation): boolean => {
|
||||||
if (player.money < aug.cost) {
|
if (player.money < aug.cost) {
|
||||||
@ -56,11 +63,7 @@ export const GraftingRoot = (): React.ReactElement => {
|
|||||||
const player = use.Player();
|
const player = use.Player();
|
||||||
const router = use.Router();
|
const router = use.Router();
|
||||||
|
|
||||||
for (const aug of Object.values(StaticAugmentations)) {
|
const graftableAugmentations = useState(GraftableAugmentations())[0];
|
||||||
const name = aug.name;
|
|
||||||
const graftableAug = new GraftableAugmentation(aug);
|
|
||||||
GraftableAugmentations[name] = graftableAug;
|
|
||||||
}
|
|
||||||
|
|
||||||
const [selectedAug, setSelectedAug] = useState(getGraftingAvailableAugs(player)[0]);
|
const [selectedAug, setSelectedAug] = useState(getGraftingAvailableAugs(player)[0]);
|
||||||
const [graftOpen, setGraftOpen] = useState(false);
|
const [graftOpen, setGraftOpen] = useState(false);
|
||||||
@ -75,7 +78,7 @@ export const GraftingRoot = (): React.ReactElement => {
|
|||||||
const augs = getGraftingAvailableAugs(player);
|
const augs = getGraftingAvailableAugs(player);
|
||||||
switch (Settings.PurchaseAugmentationsOrder) {
|
switch (Settings.PurchaseAugmentationsOrder) {
|
||||||
case PurchaseAugmentationsOrderSetting.Cost:
|
case PurchaseAugmentationsOrderSetting.Cost:
|
||||||
return augs.sort((a, b) => GraftableAugmentations[a].cost - GraftableAugmentations[b].cost);
|
return augs.sort((a, b) => graftableAugmentations[a].cost - graftableAugmentations[b].cost);
|
||||||
default:
|
default:
|
||||||
return augs;
|
return augs;
|
||||||
}
|
}
|
||||||
@ -126,7 +129,7 @@ export const GraftingRoot = (): React.ReactElement => {
|
|||||||
<ListItemButton key={i + 1} onClick={() => setSelectedAug(k)} selected={selectedAug === k}>
|
<ListItemButton key={i + 1} onClick={() => setSelectedAug(k)} selected={selectedAug === k}>
|
||||||
<Typography
|
<Typography
|
||||||
sx={{
|
sx={{
|
||||||
color: canGraft(player, GraftableAugmentations[k])
|
color: canGraft(player, graftableAugmentations[k])
|
||||||
? Settings.theme.primary
|
? Settings.theme.primary
|
||||||
: Settings.theme.disabled,
|
: Settings.theme.disabled,
|
||||||
}}
|
}}
|
||||||
@ -143,11 +146,11 @@ export const GraftingRoot = (): React.ReactElement => {
|
|||||||
<Button
|
<Button
|
||||||
onClick={() => setGraftOpen(true)}
|
onClick={() => setGraftOpen(true)}
|
||||||
sx={{ width: "100%" }}
|
sx={{ width: "100%" }}
|
||||||
disabled={!canGraft(player, GraftableAugmentations[selectedAug])}
|
disabled={!canGraft(player, graftableAugmentations[selectedAug])}
|
||||||
>
|
>
|
||||||
Graft Augmentation (
|
Graft Augmentation (
|
||||||
<Typography>
|
<Typography>
|
||||||
<Money money={GraftableAugmentations[selectedAug].cost} player={player} />
|
<Money money={graftableAugmentations[selectedAug].cost} player={player} />
|
||||||
</Typography>
|
</Typography>
|
||||||
)
|
)
|
||||||
</Button>
|
</Button>
|
||||||
@ -183,7 +186,7 @@ export const GraftingRoot = (): React.ReactElement => {
|
|||||||
<Typography color={Settings.theme.info}>
|
<Typography color={Settings.theme.info}>
|
||||||
<b>Time to Graft:</b>{" "}
|
<b>Time to Graft:</b>{" "}
|
||||||
{convertTimeMsToTimeElapsedString(
|
{convertTimeMsToTimeElapsedString(
|
||||||
calculateGraftingTimeWithBonus(player, GraftableAugmentations[selectedAug]),
|
calculateGraftingTimeWithBonus(player, graftableAugmentations[selectedAug]),
|
||||||
)}
|
)}
|
||||||
{/* Use formula so the displayed creation time is accurate to player bonus */}
|
{/* Use formula so the displayed creation time is accurate to player bonus */}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
2
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
2
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
@ -4471,7 +4471,7 @@ export interface NS {
|
|||||||
readonly infiltration: Infiltration;
|
readonly infiltration: Infiltration;
|
||||||
/**
|
/**
|
||||||
* Namespace for corporation functions.
|
* Namespace for corporation functions.
|
||||||
* RAM cost: 0 GB
|
* RAM cost: 1022.4 GB
|
||||||
*/
|
*/
|
||||||
readonly corporation: Corporation;
|
readonly corporation: Corporation;
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ export function buyStock(
|
|||||||
}
|
}
|
||||||
if (stock == null || isNaN(shares)) {
|
if (stock == null || isNaN(shares)) {
|
||||||
if (workerScript) {
|
if (workerScript) {
|
||||||
workerScript.log("stock.buy", () => `Invalid arguments: stock='${stock}' shares='${shares}'`);
|
workerScript.log("stock.buyStock", () => `Invalid arguments: stock='${stock}' shares='${shares}'`);
|
||||||
} else if (opts.suppressDialog !== true) {
|
} else if (opts.suppressDialog !== true) {
|
||||||
dialogBoxCreate("Failed to buy stock. This may be a bug, contact developer");
|
dialogBoxCreate("Failed to buy stock. This may be a bug, contact developer");
|
||||||
}
|
}
|
||||||
@ -67,7 +67,7 @@ export function buyStock(
|
|||||||
if (Player.money < totalPrice) {
|
if (Player.money < totalPrice) {
|
||||||
if (workerScript) {
|
if (workerScript) {
|
||||||
workerScript.log(
|
workerScript.log(
|
||||||
"stock.buy",
|
"stock.buyStock",
|
||||||
() =>
|
() =>
|
||||||
`You do not have enough money to purchase this position. You need ${numeralWrapper.formatMoney(totalPrice)}.`,
|
`You do not have enough money to purchase this position. You need ${numeralWrapper.formatMoney(totalPrice)}.`,
|
||||||
);
|
);
|
||||||
@ -86,7 +86,7 @@ export function buyStock(
|
|||||||
if (shares + stock.playerShares + stock.playerShortShares > stock.maxShares) {
|
if (shares + stock.playerShares + stock.playerShortShares > stock.maxShares) {
|
||||||
if (workerScript) {
|
if (workerScript) {
|
||||||
workerScript.log(
|
workerScript.log(
|
||||||
"stock.buy",
|
"stock.buyStock",
|
||||||
() =>
|
() =>
|
||||||
`Purchasing '${shares + stock.playerShares + stock.playerShortShares}' shares would exceed ${
|
`Purchasing '${shares + stock.playerShares + stock.playerShortShares}' shares would exceed ${
|
||||||
stock.symbol
|
stock.symbol
|
||||||
@ -119,7 +119,7 @@ export function buyStock(
|
|||||||
} for ${numeralWrapper.formatMoney(totalPrice)}. Paid ${numeralWrapper.formatMoney(
|
} for ${numeralWrapper.formatMoney(totalPrice)}. Paid ${numeralWrapper.formatMoney(
|
||||||
CONSTANTS.StockMarketCommission,
|
CONSTANTS.StockMarketCommission,
|
||||||
)} in commission fees.`;
|
)} in commission fees.`;
|
||||||
workerScript.log("stock.buy", () => resultTxt);
|
workerScript.log("stock.buyStock", () => resultTxt);
|
||||||
} else if (opts.suppressDialog !== true) {
|
} else if (opts.suppressDialog !== true) {
|
||||||
dialogBoxCreate(
|
dialogBoxCreate(
|
||||||
<>
|
<>
|
||||||
@ -149,7 +149,7 @@ export function sellStock(
|
|||||||
// Sanitize/Validate arguments
|
// Sanitize/Validate arguments
|
||||||
if (stock == null || shares < 0 || isNaN(shares)) {
|
if (stock == null || shares < 0 || isNaN(shares)) {
|
||||||
if (workerScript) {
|
if (workerScript) {
|
||||||
workerScript.log("stock.sell", () => `Invalid arguments: stock='${stock}' shares='${shares}'`);
|
workerScript.log("stock.sellStock", () => `Invalid arguments: stock='${stock}' shares='${shares}'`);
|
||||||
} else if (opts.suppressDialog !== true) {
|
} else if (opts.suppressDialog !== true) {
|
||||||
dialogBoxCreate(
|
dialogBoxCreate(
|
||||||
"Failed to sell stock. This is probably due to an invalid quantity. Otherwise, this may be a bug, contact developer",
|
"Failed to sell stock. This is probably due to an invalid quantity. Otherwise, this may be a bug, contact developer",
|
||||||
@ -195,7 +195,7 @@ export function sellStock(
|
|||||||
const resultTxt =
|
const resultTxt =
|
||||||
`Sold ${numeralWrapper.formatShares(shares)} shares of ${stock.symbol}. ` +
|
`Sold ${numeralWrapper.formatShares(shares)} shares of ${stock.symbol}. ` +
|
||||||
`After commissions, you gained a total of ${numeralWrapper.formatMoney(gains)}.`;
|
`After commissions, you gained a total of ${numeralWrapper.formatMoney(gains)}.`;
|
||||||
workerScript.log("stock.sell", () => resultTxt);
|
workerScript.log("stock.sellStock", () => resultTxt);
|
||||||
} else if (opts.suppressDialog !== true) {
|
} else if (opts.suppressDialog !== true) {
|
||||||
dialogBoxCreate(
|
dialogBoxCreate(
|
||||||
<>
|
<>
|
||||||
|
@ -7,6 +7,7 @@ import { IPlayer } from "../PersonObjects/IPlayer";
|
|||||||
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||||
import { CrimeType } from "../utils/WorkType";
|
import { CrimeType } from "../utils/WorkType";
|
||||||
import { Work, WorkType } from "./Work";
|
import { Work, WorkType } from "./Work";
|
||||||
|
import { newWorkStats, scaleWorkStats, WorkStats } from "./WorkStats";
|
||||||
|
|
||||||
interface CrimeWorkParams {
|
interface CrimeWorkParams {
|
||||||
crimeType: CrimeType;
|
crimeType: CrimeType;
|
||||||
@ -42,14 +43,22 @@ export class CrimeWork extends Work {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
earnings(): WorkStats {
|
||||||
|
const crime = this.getCrime();
|
||||||
|
return newWorkStats({
|
||||||
|
money: crime.money,
|
||||||
|
hackExp: crime.hacking_exp * 2,
|
||||||
|
strExp: crime.strength_exp * 2,
|
||||||
|
defExp: crime.defense_exp * 2,
|
||||||
|
dexExp: crime.dexterity_exp * 2,
|
||||||
|
agiExp: crime.agility_exp * 2,
|
||||||
|
chaExp: crime.charisma_exp * 2,
|
||||||
|
intExp: crime.intelligence_exp * 2,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
commit(player: IPlayer): void {
|
commit(player: IPlayer): void {
|
||||||
let crime = null;
|
const crime = this.getCrime();
|
||||||
for (const i of Object.keys(Crimes)) {
|
|
||||||
if (Crimes[i].type == this.crimeType) {
|
|
||||||
crime = Crimes[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (crime == null) {
|
if (crime == null) {
|
||||||
dialogBoxCreate(
|
dialogBoxCreate(
|
||||||
`ERR: Unrecognized crime type (${this.crimeType}). This is probably a bug please contact the developer`,
|
`ERR: Unrecognized crime type (${this.crimeType}). This is probably a bug please contact the developer`,
|
||||||
@ -59,33 +68,23 @@ export class CrimeWork extends Work {
|
|||||||
const focusPenalty = player.focusPenalty();
|
const focusPenalty = player.focusPenalty();
|
||||||
// exp times 2 because were trying to maintain the same numbers as before the conversion
|
// exp times 2 because were trying to maintain the same numbers as before the conversion
|
||||||
// Technically the definition of Crimes should have the success numbers and failure should divide by 4
|
// Technically the definition of Crimes should have the success numbers and failure should divide by 4
|
||||||
let hackExp = crime.hacking_exp * 2;
|
let gains = scaleWorkStats(this.earnings(), focusPenalty);
|
||||||
let StrExp = crime.strength_exp * 2;
|
|
||||||
let DefExp = crime.defense_exp * 2;
|
|
||||||
let DexExp = crime.dexterity_exp * 2;
|
|
||||||
let AgiExp = crime.agility_exp * 2;
|
|
||||||
let ChaExp = crime.charisma_exp * 2;
|
|
||||||
let karma = crime.karma;
|
let karma = crime.karma;
|
||||||
const success = determineCrimeSuccess(player, crime.type);
|
const success = determineCrimeSuccess(player, crime.type);
|
||||||
if (success) {
|
if (success) {
|
||||||
player.gainMoney(crime.money * focusPenalty, "crime");
|
player.gainMoney(gains.money, "crime");
|
||||||
player.numPeopleKilled += crime.kills;
|
player.numPeopleKilled += crime.kills;
|
||||||
player.gainIntelligenceExp(crime.intelligence_exp * focusPenalty);
|
player.gainIntelligenceExp(gains.intExp);
|
||||||
} else {
|
} else {
|
||||||
hackExp /= 4;
|
gains = scaleWorkStats(gains, 0.25);
|
||||||
StrExp /= 4;
|
|
||||||
DefExp /= 4;
|
|
||||||
DexExp /= 4;
|
|
||||||
AgiExp /= 4;
|
|
||||||
ChaExp /= 4;
|
|
||||||
karma /= 4;
|
karma /= 4;
|
||||||
}
|
}
|
||||||
player.gainHackingExp(hackExp * focusPenalty);
|
player.gainHackingExp(gains.hackExp);
|
||||||
player.gainStrengthExp(StrExp * focusPenalty);
|
player.gainStrengthExp(gains.strExp);
|
||||||
player.gainDefenseExp(DefExp * focusPenalty);
|
player.gainDefenseExp(gains.defExp);
|
||||||
player.gainDexterityExp(DexExp * focusPenalty);
|
player.gainDexterityExp(gains.dexExp);
|
||||||
player.gainAgilityExp(AgiExp * focusPenalty);
|
player.gainAgilityExp(gains.agiExp);
|
||||||
player.gainCharismaExp(ChaExp * focusPenalty);
|
player.gainCharismaExp(gains.chaExp);
|
||||||
player.karma -= karma * focusPenalty;
|
player.karma -= karma * focusPenalty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,8 +27,8 @@ export class GraftingWork extends Work {
|
|||||||
super(WorkType.GRAFTING, params?.singularity ?? true);
|
super(WorkType.GRAFTING, params?.singularity ?? true);
|
||||||
this.unitCompleted = 0;
|
this.unitCompleted = 0;
|
||||||
this.augmentation = params?.augmentation ?? AugmentationNames.Targeting1;
|
this.augmentation = params?.augmentation ?? AugmentationNames.Targeting1;
|
||||||
|
const gAugs = GraftableAugmentations();
|
||||||
if (params?.player) params.player.loseMoney(GraftableAugmentations[this.augmentation].cost, "augmentations");
|
if (params?.player) params.player.loseMoney(gAugs[this.augmentation].cost, "augmentations");
|
||||||
}
|
}
|
||||||
|
|
||||||
unitNeeded(): number {
|
unitNeeded(): number {
|
||||||
|
@ -48,7 +48,7 @@ interface IWorkInfo {
|
|||||||
stopTooltip?: string | React.ReactElement;
|
stopTooltip?: string | React.ReactElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ExpRows(rate: WorkStats): React.ReactElement[] {
|
function ExpRows(rate: WorkStats): React.ReactElement[] {
|
||||||
return [
|
return [
|
||||||
rate.hackExp > 0 ? (
|
rate.hackExp > 0 ? (
|
||||||
<StatsRow
|
<StatsRow
|
||||||
@ -119,6 +119,77 @@ export function ExpRows(rate: WorkStats): React.ReactElement[] {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function CrimeExpRows(rate: WorkStats): React.ReactElement[] {
|
||||||
|
return [
|
||||||
|
rate.hackExp > 0 ? (
|
||||||
|
<StatsRow
|
||||||
|
name="Hacking Exp"
|
||||||
|
color={Settings.theme.hack}
|
||||||
|
data={{
|
||||||
|
content: `${numeralWrapper.formatExp(rate.hackExp * CYCLES_PER_SEC)}`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
),
|
||||||
|
rate.strExp > 0 ? (
|
||||||
|
<StatsRow
|
||||||
|
name="Strength Exp"
|
||||||
|
color={Settings.theme.combat}
|
||||||
|
data={{
|
||||||
|
content: `${numeralWrapper.formatExp(rate.strExp * CYCLES_PER_SEC)}`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
),
|
||||||
|
rate.defExp > 0 ? (
|
||||||
|
<StatsRow
|
||||||
|
name="Defense Exp"
|
||||||
|
color={Settings.theme.combat}
|
||||||
|
data={{
|
||||||
|
content: `${numeralWrapper.formatExp(rate.defExp * CYCLES_PER_SEC)}`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
),
|
||||||
|
rate.dexExp > 0 ? (
|
||||||
|
<StatsRow
|
||||||
|
name="Dexterity Exp"
|
||||||
|
color={Settings.theme.combat}
|
||||||
|
data={{
|
||||||
|
content: `${numeralWrapper.formatExp(rate.dexExp * CYCLES_PER_SEC)}`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
),
|
||||||
|
rate.agiExp > 0 ? (
|
||||||
|
<StatsRow
|
||||||
|
name="Agility Exp"
|
||||||
|
color={Settings.theme.combat}
|
||||||
|
data={{
|
||||||
|
content: `${numeralWrapper.formatExp(rate.agiExp * CYCLES_PER_SEC)}`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
),
|
||||||
|
rate.chaExp > 0 ? (
|
||||||
|
<StatsRow
|
||||||
|
name="Charisma Exp"
|
||||||
|
color={Settings.theme.cha}
|
||||||
|
data={{
|
||||||
|
content: `${numeralWrapper.formatExp(rate.chaExp * CYCLES_PER_SEC)}`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
export function WorkInProgressRoot(): React.ReactElement {
|
export function WorkInProgressRoot(): React.ReactElement {
|
||||||
const setRerender = useState(false)[1];
|
const setRerender = useState(false)[1];
|
||||||
function rerender(): void {
|
function rerender(): void {
|
||||||
@ -149,7 +220,7 @@ export function WorkInProgressRoot(): React.ReactElement {
|
|||||||
if (isCrimeWork(player.currentWork)) {
|
if (isCrimeWork(player.currentWork)) {
|
||||||
const crime = player.currentWork.getCrime();
|
const crime = player.currentWork.getCrime();
|
||||||
const completion = (player.currentWork.unitCompleted / crime.time) * 100;
|
const completion = (player.currentWork.unitCompleted / crime.time) * 100;
|
||||||
|
const gains = player.currentWork.earnings();
|
||||||
workInfo = {
|
workInfo = {
|
||||||
buttons: {
|
buttons: {
|
||||||
cancel: () => {
|
cancel: () => {
|
||||||
@ -163,6 +234,15 @@ export function WorkInProgressRoot(): React.ReactElement {
|
|||||||
},
|
},
|
||||||
title: `You are attempting to ${crime.type}`,
|
title: `You are attempting to ${crime.type}`,
|
||||||
|
|
||||||
|
gains: [
|
||||||
|
<Typography>Gains (on success)</Typography>,
|
||||||
|
<StatsRow name="Money:" color={Settings.theme.money}>
|
||||||
|
<Typography>
|
||||||
|
<Money money={gains.money} />
|
||||||
|
</Typography>
|
||||||
|
</StatsRow>,
|
||||||
|
...CrimeExpRows(gains),
|
||||||
|
],
|
||||||
progress: {
|
progress: {
|
||||||
remaining: crime.time - player.currentWork.unitCompleted,
|
remaining: crime.time - player.currentWork.unitCompleted,
|
||||||
percentage: completion,
|
percentage: completion,
|
||||||
|
Loading…
Reference in New Issue
Block a user