mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-26 17:43:48 +01:00
Merge pull request #1979 from MartinFournier/feature/skill-progress-bars
Fix #1889: Add skill progress to overview
This commit is contained in:
commit
b739d60490
@ -29,6 +29,7 @@ import { ICodingContractReward } from "../CodingContracts";
|
|||||||
import { IRouter } from "../ui/Router";
|
import { IRouter } from "../ui/Router";
|
||||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||||
import { HacknetServer } from "../Hacknet/HacknetServer";
|
import { HacknetServer } from "../Hacknet/HacknetServer";
|
||||||
|
import { ISkillProgress } from "./formulas/skill";
|
||||||
|
|
||||||
export interface IPlayer {
|
export interface IPlayer {
|
||||||
// Class members
|
// Class members
|
||||||
@ -259,6 +260,7 @@ export interface IPlayer {
|
|||||||
prestigeAugmentation(): void;
|
prestigeAugmentation(): void;
|
||||||
prestigeSourceFile(): void;
|
prestigeSourceFile(): void;
|
||||||
calculateSkill(exp: number, mult?: number): number;
|
calculateSkill(exp: number, mult?: number): number;
|
||||||
|
calculateSkillProgress(exp: number, mult?: number): ISkillProgress;
|
||||||
resetWorkStatus(generalType?: string, group?: string, workType?: string): void;
|
resetWorkStatus(generalType?: string, group?: string, workType?: string): void;
|
||||||
getWorkHackExpGain(): number;
|
getWorkHackExpGain(): number;
|
||||||
getWorkStrExpGain(): number;
|
getWorkStrExpGain(): number;
|
||||||
|
@ -34,6 +34,7 @@ import { CityName } from "../../Locations/data/CityNames";
|
|||||||
|
|
||||||
import { MoneySourceTracker } from "../../utils/MoneySourceTracker";
|
import { MoneySourceTracker } from "../../utils/MoneySourceTracker";
|
||||||
import { Reviver, Generic_toJSON, Generic_fromJSON } from "../../utils/JSONReviver";
|
import { Reviver, Generic_toJSON, Generic_fromJSON } from "../../utils/JSONReviver";
|
||||||
|
import { ISkillProgress } from "../formulas/skill";
|
||||||
|
|
||||||
export class PlayerObject implements IPlayer {
|
export class PlayerObject implements IPlayer {
|
||||||
// Class members
|
// Class members
|
||||||
@ -265,6 +266,7 @@ export class PlayerObject implements IPlayer {
|
|||||||
prestigeAugmentation: () => void;
|
prestigeAugmentation: () => void;
|
||||||
prestigeSourceFile: () => void;
|
prestigeSourceFile: () => void;
|
||||||
calculateSkill: (exp: number, mult?: number) => number;
|
calculateSkill: (exp: number, mult?: number) => number;
|
||||||
|
calculateSkillProgress: (exp: number, mult?: number) => ISkillProgress;
|
||||||
resetWorkStatus: (generalType?: string, group?: string, workType?: string) => void;
|
resetWorkStatus: (generalType?: string, group?: string, workType?: string) => void;
|
||||||
getWorkHackExpGain: () => number;
|
getWorkHackExpGain: () => number;
|
||||||
getWorkStrExpGain: () => number;
|
getWorkStrExpGain: () => number;
|
||||||
@ -470,6 +472,7 @@ export class PlayerObject implements IPlayer {
|
|||||||
this.prestigeSourceFile = generalMethods.prestigeSourceFile;
|
this.prestigeSourceFile = generalMethods.prestigeSourceFile;
|
||||||
this.receiveInvite = generalMethods.receiveInvite;
|
this.receiveInvite = generalMethods.receiveInvite;
|
||||||
this.calculateSkill = generalMethods.calculateSkill;
|
this.calculateSkill = generalMethods.calculateSkill;
|
||||||
|
this.calculateSkillProgress = generalMethods.calculateSkillProgress;
|
||||||
this.updateSkillLevels = generalMethods.updateSkillLevels;
|
this.updateSkillLevels = generalMethods.updateSkillLevels;
|
||||||
this.resetMultipliers = generalMethods.resetMultipliers;
|
this.resetMultipliers = generalMethods.resetMultipliers;
|
||||||
this.hasProgram = generalMethods.hasProgram;
|
this.hasProgram = generalMethods.hasProgram;
|
||||||
|
@ -26,7 +26,7 @@ import { Locations } from "../../Locations/Locations";
|
|||||||
import { CityName } from "../../Locations/data/CityNames";
|
import { CityName } from "../../Locations/data/CityNames";
|
||||||
import { LocationName } from "../../Locations/data/LocationNames";
|
import { LocationName } from "../../Locations/data/LocationNames";
|
||||||
import { Sleeve } from "../../PersonObjects/Sleeve/Sleeve";
|
import { Sleeve } from "../../PersonObjects/Sleeve/Sleeve";
|
||||||
import { calculateSkill as calculateSkillF } from "../formulas/skill";
|
import { calculateSkill as calculateSkillF, calculateSkillProgress as calculateSkillProgressF, getEmptySkillProgress, ISkillProgress } from "../formulas/skill";
|
||||||
import { calculateIntelligenceBonus } from "../formulas/intelligence";
|
import { calculateIntelligenceBonus } from "../formulas/intelligence";
|
||||||
import {
|
import {
|
||||||
getHackingWorkRepGain,
|
getHackingWorkRepGain,
|
||||||
@ -226,6 +226,11 @@ export function calculateSkill(this: IPlayer, exp: number, mult = 1): number {
|
|||||||
return calculateSkillF(exp, mult);
|
return calculateSkillF(exp, mult);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Calculates skill level progress based on experience. The same formula will be used for every skill
|
||||||
|
export function calculateSkillProgress(this: IPlayer, exp: number, mult = 1): ISkillProgress {
|
||||||
|
return calculateSkillProgressF(exp, mult);
|
||||||
|
}
|
||||||
|
|
||||||
export function updateSkillLevels(this: IPlayer): void {
|
export function updateSkillLevels(this: IPlayer): void {
|
||||||
this.hacking = Math.max(
|
this.hacking = Math.max(
|
||||||
1,
|
1,
|
||||||
|
@ -5,3 +5,37 @@ export function calculateSkill(exp: number, mult = 1): number {
|
|||||||
export function calculateExp(skill: number, mult = 1): number {
|
export function calculateExp(skill: number, mult = 1): number {
|
||||||
return Math.exp((skill / mult + 200) / 32) - 534.6;
|
return Math.exp((skill / mult + 200) / 32) - 534.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function calculateSkillProgress(exp: number, mult = 1): ISkillProgress {
|
||||||
|
const currentSkill = calculateSkill(exp, mult);
|
||||||
|
const nextSkill = currentSkill + 1;
|
||||||
|
let baseExperience = calculateExp(currentSkill, mult);
|
||||||
|
if (baseExperience < 0) baseExperience = 0;
|
||||||
|
const nextExperience = calculateExp(nextSkill, mult)
|
||||||
|
|
||||||
|
return {
|
||||||
|
currentSkill,
|
||||||
|
nextSkill,
|
||||||
|
baseExperience,
|
||||||
|
experience: exp,
|
||||||
|
nextExperience,
|
||||||
|
progress: exp / nextExperience,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ISkillProgress {
|
||||||
|
currentSkill: number;
|
||||||
|
nextSkill: number;
|
||||||
|
baseExperience: number;
|
||||||
|
experience: number;
|
||||||
|
nextExperience: number;
|
||||||
|
progress: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getEmptySkillProgress() {
|
||||||
|
return {
|
||||||
|
currentSkill: 0, nextSkill: 0,
|
||||||
|
baseExperience: 0, experience: 0, nextExperience: 0,
|
||||||
|
progress: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// Root React Component for the Corporation UI
|
// Root React Component for the Corporation UI
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
|
|
||||||
import { Theme } from "@mui/material/styles";
|
import { Theme, useTheme } from "@mui/material/styles";
|
||||||
import makeStyles from "@mui/styles/makeStyles";
|
import makeStyles from "@mui/styles/makeStyles";
|
||||||
import createStyles from "@mui/styles/createStyles";
|
import createStyles from "@mui/styles/createStyles";
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
@ -20,6 +20,8 @@ import ClearAllIcon from "@mui/icons-material/ClearAll";
|
|||||||
|
|
||||||
import { Settings } from "../../Settings/Settings";
|
import { Settings } from "../../Settings/Settings";
|
||||||
import { use } from "../Context";
|
import { use } from "../Context";
|
||||||
|
import { StatsProgressOverviewCell } from "./StatsProgressBar";
|
||||||
|
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
save: () => void;
|
save: () => void;
|
||||||
@ -139,6 +141,8 @@ const useStyles = makeStyles((theme: Theme) =>
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export { useStyles as characterOverviewStyles };
|
||||||
|
|
||||||
export function CharacterOverview({ save, killScripts }: IProps): React.ReactElement {
|
export function CharacterOverview({ save, killScripts }: IProps): React.ReactElement {
|
||||||
const [killOpen, setKillOpen] = useState(false);
|
const [killOpen, setKillOpen] = useState(false);
|
||||||
const player = use.Player();
|
const player = use.Player();
|
||||||
@ -151,6 +155,21 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
const theme = useTheme();
|
||||||
|
|
||||||
|
const hackingProgress = player.calculateSkillProgress(
|
||||||
|
player.hacking_exp, player.hacking_mult * BitNodeMultipliers.HackingLevelMultiplier);
|
||||||
|
const strengthProgress = player.calculateSkillProgress(
|
||||||
|
player.strength_exp, player.strength_mult * BitNodeMultipliers.StrengthLevelMultiplier);
|
||||||
|
const defenseProgress = player.calculateSkillProgress(
|
||||||
|
player.defense_exp, player.defense_mult * BitNodeMultipliers.DefenseLevelMultiplier);
|
||||||
|
const dexterityProgress = player.calculateSkillProgress(
|
||||||
|
player.dexterity_exp, player.dexterity_mult * BitNodeMultipliers.DexterityLevelMultiplier);
|
||||||
|
const agilityProgress = player.calculateSkillProgress(
|
||||||
|
player.agility_exp, player.agility_mult * BitNodeMultipliers.AgilityLevelMultiplier);
|
||||||
|
const charismaProgress = player.calculateSkillProgress(
|
||||||
|
player.charisma_exp, player.charisma_mult * BitNodeMultipliers.CharismaLevelMultiplier);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Table sx={{ display: "block", m: 1 }}>
|
<Table sx={{ display: "block", m: 1 }}>
|
||||||
@ -186,12 +205,20 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
|
|||||||
</TableRow>
|
</TableRow>
|
||||||
|
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell component="th" scope="row" classes={{ root: classes.cell }}>
|
<TableCell component="th" scope="row" classes={{ root: classes.cellNone }}>
|
||||||
<Typography classes={{ root: classes.hack }}>Hack </Typography>
|
<Typography classes={{ root: classes.hack }}>Hack </Typography>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell align="right" classes={{ root: classes.cell }}>
|
<TableCell align="right" classes={{ root: classes.cellNone }}>
|
||||||
<Typography classes={{ root: classes.hack }}>{numeralWrapper.formatSkill(player.hacking)}</Typography>
|
<Typography classes={{ root: classes.hack }}>{numeralWrapper.formatSkill(player.hacking)}</Typography>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
<TableRow>
|
||||||
|
<StatsProgressOverviewCell progress={hackingProgress} color={theme.colors.hack} />
|
||||||
|
</TableRow>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell component="th" scope="row" classes={{ root: classes.cell }}>
|
||||||
|
<Typography classes={{ root: classes.hack }}></Typography>
|
||||||
|
</TableCell>
|
||||||
<TableCell align="right" classes={{ root: classes.cell }}>
|
<TableCell align="right" classes={{ root: classes.cell }}>
|
||||||
<Typography id="overview-hack-hook" classes={{ root: classes.hack }}>
|
<Typography id="overview-hack-hook" classes={{ root: classes.hack }}>
|
||||||
{/*Hook for player scripts*/}
|
{/*Hook for player scripts*/}
|
||||||
@ -212,6 +239,9 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
|
|||||||
</Typography>
|
</Typography>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
<TableRow>
|
||||||
|
<StatsProgressOverviewCell progress={strengthProgress} color={theme.colors.combat} />
|
||||||
|
</TableRow>
|
||||||
|
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell component="th" scope="row" classes={{ root: classes.cellNone }}>
|
<TableCell component="th" scope="row" classes={{ root: classes.cellNone }}>
|
||||||
@ -226,6 +256,9 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
|
|||||||
</Typography>
|
</Typography>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
<TableRow>
|
||||||
|
<StatsProgressOverviewCell progress={defenseProgress} color={theme.colors.combat} />
|
||||||
|
</TableRow>
|
||||||
|
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell component="th" scope="row" classes={{ root: classes.cellNone }}>
|
<TableCell component="th" scope="row" classes={{ root: classes.cellNone }}>
|
||||||
@ -240,6 +273,10 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
|
|||||||
</Typography>
|
</Typography>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
<TableRow>
|
||||||
|
<StatsProgressOverviewCell progress={dexterityProgress} color={theme.colors.combat} />
|
||||||
|
</TableRow>
|
||||||
|
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell component="th" scope="row" classes={{ root: classes.cell }}>
|
<TableCell component="th" scope="row" classes={{ root: classes.cell }}>
|
||||||
<Typography classes={{ root: classes.combat }}>Agi </Typography>
|
<Typography classes={{ root: classes.combat }}>Agi </Typography>
|
||||||
@ -253,6 +290,9 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
|
|||||||
</Typography>
|
</Typography>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
<TableRow>
|
||||||
|
<StatsProgressOverviewCell progress={agilityProgress} color={theme.colors.combat} />
|
||||||
|
</TableRow>
|
||||||
|
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell component="th" scope="row" classes={{ root: classes.cellNone }}>
|
<TableCell component="th" scope="row" classes={{ root: classes.cellNone }}>
|
||||||
@ -267,6 +307,10 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
|
|||||||
</Typography>
|
</Typography>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
<TableRow>
|
||||||
|
<StatsProgressOverviewCell progress={charismaProgress} color={theme.colors.cha} />
|
||||||
|
</TableRow>
|
||||||
|
|
||||||
<Intelligence />
|
<Intelligence />
|
||||||
|
|
||||||
<TableRow>
|
<TableRow>
|
||||||
|
57
src/ui/React/StatsProgressBar.tsx
Normal file
57
src/ui/React/StatsProgressBar.tsx
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import LinearProgress from '@mui/material/LinearProgress';
|
||||||
|
import { TableCell, Tooltip } from '@mui/material';
|
||||||
|
import { characterOverviewStyles } from './CharacterOverview';
|
||||||
|
import { ISkillProgress } from 'src/PersonObjects/formulas/skill';
|
||||||
|
|
||||||
|
interface IProgressProps {
|
||||||
|
min: number;
|
||||||
|
max: number;
|
||||||
|
current: number;
|
||||||
|
color?: React.CSSProperties["color"];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IStatsOverviewCellProps {
|
||||||
|
progress: ISkillProgress;
|
||||||
|
color?: React.CSSProperties["color"];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function StatsProgressBar({ min, max, current, color }: IProgressProps): React.ReactElement {
|
||||||
|
const normalise = (value: number): number => ((value - min) * 100) / (max - min);
|
||||||
|
const tooltipText = <>
|
||||||
|
Experience: {current.toFixed(2)}/{max.toFixed(2)}
|
||||||
|
<br />
|
||||||
|
{normalise(current).toFixed(2)}%
|
||||||
|
</>;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tooltip title={tooltipText}>
|
||||||
|
<LinearProgress
|
||||||
|
variant="determinate"
|
||||||
|
value={normalise(current)}
|
||||||
|
sx={{
|
||||||
|
backgroundColor: '#111111',
|
||||||
|
'& .MuiLinearProgress-bar1Determinate': {
|
||||||
|
backgroundColor: color,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function StatsProgressOverviewCell({progress, color}: IStatsOverviewCellProps): React.ReactElement {
|
||||||
|
const classes = characterOverviewStyles();
|
||||||
|
return (
|
||||||
|
<TableCell component="th" scope="row" colSpan={2}
|
||||||
|
classes={{ root: classes.cellNone }}
|
||||||
|
style={{ paddingBottom: '2px', position: 'relative', top: '-3px' }}>
|
||||||
|
<StatsProgressBar
|
||||||
|
min={progress.baseExperience}
|
||||||
|
max={progress.nextExperience}
|
||||||
|
current={progress.experience}
|
||||||
|
color={color}
|
||||||
|
/>
|
||||||
|
</TableCell>
|
||||||
|
)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user