mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-22 14:12:27 +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 { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { HacknetServer } from "../Hacknet/HacknetServer";
|
||||
import { ISkillProgress } from "./formulas/skill";
|
||||
|
||||
export interface IPlayer {
|
||||
// Class members
|
||||
@ -259,6 +260,7 @@ export interface IPlayer {
|
||||
prestigeAugmentation(): void;
|
||||
prestigeSourceFile(): void;
|
||||
calculateSkill(exp: number, mult?: number): number;
|
||||
calculateSkillProgress(exp: number, mult?: number): ISkillProgress;
|
||||
resetWorkStatus(generalType?: string, group?: string, workType?: string): void;
|
||||
getWorkHackExpGain(): number;
|
||||
getWorkStrExpGain(): number;
|
||||
|
@ -34,6 +34,7 @@ import { CityName } from "../../Locations/data/CityNames";
|
||||
|
||||
import { MoneySourceTracker } from "../../utils/MoneySourceTracker";
|
||||
import { Reviver, Generic_toJSON, Generic_fromJSON } from "../../utils/JSONReviver";
|
||||
import { ISkillProgress } from "../formulas/skill";
|
||||
|
||||
export class PlayerObject implements IPlayer {
|
||||
// Class members
|
||||
@ -265,6 +266,7 @@ export class PlayerObject implements IPlayer {
|
||||
prestigeAugmentation: () => void;
|
||||
prestigeSourceFile: () => void;
|
||||
calculateSkill: (exp: number, mult?: number) => number;
|
||||
calculateSkillProgress: (exp: number, mult?: number) => ISkillProgress;
|
||||
resetWorkStatus: (generalType?: string, group?: string, workType?: string) => void;
|
||||
getWorkHackExpGain: () => number;
|
||||
getWorkStrExpGain: () => number;
|
||||
@ -470,6 +472,7 @@ export class PlayerObject implements IPlayer {
|
||||
this.prestigeSourceFile = generalMethods.prestigeSourceFile;
|
||||
this.receiveInvite = generalMethods.receiveInvite;
|
||||
this.calculateSkill = generalMethods.calculateSkill;
|
||||
this.calculateSkillProgress = generalMethods.calculateSkillProgress;
|
||||
this.updateSkillLevels = generalMethods.updateSkillLevels;
|
||||
this.resetMultipliers = generalMethods.resetMultipliers;
|
||||
this.hasProgram = generalMethods.hasProgram;
|
||||
|
@ -26,7 +26,7 @@ import { Locations } from "../../Locations/Locations";
|
||||
import { CityName } from "../../Locations/data/CityNames";
|
||||
import { LocationName } from "../../Locations/data/LocationNames";
|
||||
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 {
|
||||
getHackingWorkRepGain,
|
||||
@ -226,6 +226,11 @@ export function calculateSkill(this: IPlayer, exp: number, mult = 1): number {
|
||||
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 {
|
||||
this.hacking = Math.max(
|
||||
1,
|
||||
|
@ -5,3 +5,37 @@ export function calculateSkill(exp: number, mult = 1): number {
|
||||
export function calculateExp(skill: number, mult = 1): number {
|
||||
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
|
||||
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 createStyles from "@mui/styles/createStyles";
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
@ -20,6 +20,8 @@ import ClearAllIcon from "@mui/icons-material/ClearAll";
|
||||
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
import { use } from "../Context";
|
||||
import { StatsProgressOverviewCell } from "./StatsProgressBar";
|
||||
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
||||
|
||||
interface IProps {
|
||||
save: () => void;
|
||||
@ -139,6 +141,8 @@ const useStyles = makeStyles((theme: Theme) =>
|
||||
}),
|
||||
);
|
||||
|
||||
export { useStyles as characterOverviewStyles };
|
||||
|
||||
export function CharacterOverview({ save, killScripts }: IProps): React.ReactElement {
|
||||
const [killOpen, setKillOpen] = useState(false);
|
||||
const player = use.Player();
|
||||
@ -151,6 +155,21 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
|
||||
}, []);
|
||||
|
||||
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 (
|
||||
<>
|
||||
<Table sx={{ display: "block", m: 1 }}>
|
||||
@ -186,12 +205,20 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
|
||||
</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>
|
||||
</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>
|
||||
</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 }}>
|
||||
<Typography id="overview-hack-hook" classes={{ root: classes.hack }}>
|
||||
{/*Hook for player scripts*/}
|
||||
@ -212,6 +239,9 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
|
||||
</Typography>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<StatsProgressOverviewCell progress={strengthProgress} color={theme.colors.combat} />
|
||||
</TableRow>
|
||||
|
||||
<TableRow>
|
||||
<TableCell component="th" scope="row" classes={{ root: classes.cellNone }}>
|
||||
@ -226,6 +256,9 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
|
||||
</Typography>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<StatsProgressOverviewCell progress={defenseProgress} color={theme.colors.combat} />
|
||||
</TableRow>
|
||||
|
||||
<TableRow>
|
||||
<TableCell component="th" scope="row" classes={{ root: classes.cellNone }}>
|
||||
@ -240,6 +273,10 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
|
||||
</Typography>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<StatsProgressOverviewCell progress={dexterityProgress} color={theme.colors.combat} />
|
||||
</TableRow>
|
||||
|
||||
<TableRow>
|
||||
<TableCell component="th" scope="row" classes={{ root: classes.cell }}>
|
||||
<Typography classes={{ root: classes.combat }}>Agi </Typography>
|
||||
@ -253,6 +290,9 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
|
||||
</Typography>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<StatsProgressOverviewCell progress={agilityProgress} color={theme.colors.combat} />
|
||||
</TableRow>
|
||||
|
||||
<TableRow>
|
||||
<TableCell component="th" scope="row" classes={{ root: classes.cellNone }}>
|
||||
@ -267,6 +307,10 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
|
||||
</Typography>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<StatsProgressOverviewCell progress={charismaProgress} color={theme.colors.cha} />
|
||||
</TableRow>
|
||||
|
||||
<Intelligence />
|
||||
|
||||
<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