Move player skills and exp to their struct

This commit is contained in:
Olivier Gagnon
2022-07-26 23:54:17 -04:00
parent 3e4f26ac0a
commit 326d9fd7ef
45 changed files with 546 additions and 487 deletions

View File

@@ -26,7 +26,7 @@ v2.0.0 - 2022-07-19 Work rework
* Company faction require 400k rep to join (from 200k) * Company faction require 400k rep to join (from 200k)
* Backdooring company server reduces faction requirement to 300k. * Backdooring company server reduces faction requirement to 300k.
* All work generally no longer keep track of cumulative gains like exp and reputation since it's applied instantly. * All work generally no longer keep track of cumulative gains like exp and reputation since it's applied instantly.
* getPlayer returns way less fields but does return the new 'currentWork' field. * getPlayer returns way less fields but does return the new 'currentWork' field, some fields are moved around.
API breaks API breaks

View File

@@ -60,7 +60,16 @@ getPlayer
Take a look at the new singularity.getCurrentWork function. Take a look at the new singularity.getCurrentWork function.
All fields ending in _mult have been moved to the 'mults' struct. All fields ending in _mult have been moved to the 'mults' struct.
For example: getPlayer().hacking_skill_mult is now getPlayer().mults.hacking_skill For example: getPlayer().hacking_skill_mult => getPlayer().mults.hacking_skill
skills have been moved to the skills struct
For example: getPlayer().hacking => getPlayer().skills.hacking
exp have been moved to the exp struct
For example: getPlayer().hacking_exp => getPlayer().exp.hacking
hp have been moved to the hp struct
For example: getPlayer().max_hp => getPlayer().hp.max or hp.current
workForCompany workForCompany
-------------- --------------

View File

@@ -254,13 +254,16 @@ export const achievements: IMap<Achievement> = {
HACKING_100000: { HACKING_100000: {
...achievementData["HACKING_100000"], ...achievementData["HACKING_100000"],
Icon: "hack100000", Icon: "hack100000",
Condition: () => Player.hacking >= 100000, Condition: () => Player.skills.hacking >= 100000,
}, },
COMBAT_3000: { COMBAT_3000: {
...achievementData["COMBAT_3000"], ...achievementData["COMBAT_3000"],
Icon: "combat3000", Icon: "combat3000",
Condition: () => Condition: () =>
Player.strength >= 3000 && Player.defense >= 3000 && Player.dexterity >= 3000 && Player.agility >= 3000, Player.skills.strength >= 3000 &&
Player.skills.defense >= 3000 &&
Player.skills.dexterity >= 3000 &&
Player.skills.agility >= 3000,
}, },
NEUROFLUX_255: { NEUROFLUX_255: {
...achievementData["NEUROFLUX_255"], ...achievementData["NEUROFLUX_255"],
@@ -477,7 +480,7 @@ export const achievements: IMap<Achievement> = {
...achievementData["INTELLIGENCE_255"], ...achievementData["INTELLIGENCE_255"],
Icon: "INT255", Icon: "INT255",
Visible: () => hasAccessToSF(Player, 5), Visible: () => hasAccessToSF(Player, 5),
Condition: () => Player.intelligence >= 255, Condition: () => Player.skills.intelligence >= 255,
}, },
BLADEBURNER_DIVISION: { BLADEBURNER_DIVISION: {
...achievementData["BLADEBURNER_DIVISION"], ...achievementData["BLADEBURNER_DIVISION"],
@@ -644,12 +647,12 @@ export const achievements: IMap<Achievement> = {
!Player.sleeves.some( !Player.sleeves.some(
(s) => (s) =>
s.augmentations.length > 0 || s.augmentations.length > 0 ||
s.hacking_exp > 0 || s.exp.hacking > 0 ||
s.strength_exp > 0 || s.exp.strength > 0 ||
s.defense_exp > 0 || s.exp.defense > 0 ||
s.agility_exp > 0 || s.exp.agility > 0 ||
s.dexterity_exp > 0 || s.exp.dexterity > 0 ||
s.charisma_exp > 0, s.exp.charisma > 0,
), ),
}, },
CHALLENGE_BN12: { CHALLENGE_BN12: {

View File

@@ -167,8 +167,8 @@ export class Action implements IAction {
let baseTime = difficulty / BladeburnerConstants.DifficultyToTimeFactor; let baseTime = difficulty / BladeburnerConstants.DifficultyToTimeFactor;
const skillFac = inst.skillMultipliers.actionTime; // Always < 1 const skillFac = inst.skillMultipliers.actionTime; // Always < 1
const effAgility = person.agility * inst.skillMultipliers.effAgi; const effAgility = person.skills.agility * inst.skillMultipliers.effAgi;
const effDexterity = person.dexterity * inst.skillMultipliers.effDex; const effDexterity = person.skills.dexterity * inst.skillMultipliers.effDex;
const statFac = const statFac =
0.5 * 0.5 *
(Math.pow(effAgility, BladeburnerConstants.EffAgiExponentialFactor) + (Math.pow(effAgility, BladeburnerConstants.EffAgiExponentialFactor) +

View File

@@ -1027,16 +1027,17 @@ export class Bladeburner implements IBladeburner {
const CharismaLinearFactor = 1e3; const CharismaLinearFactor = 1e3;
const CharismaExponentialFactor = 0.045; const CharismaExponentialFactor = 0.045;
const charismaEff = Math.pow(person.charisma, CharismaExponentialFactor) + person.charisma / CharismaLinearFactor; const charismaEff =
Math.pow(person.skills.charisma, CharismaExponentialFactor) + person.skills.charisma / CharismaLinearFactor;
return (100 - charismaEff) / 100; return (100 - charismaEff) / 100;
} }
getRecruitmentSuccessChance(person: IPerson): number { getRecruitmentSuccessChance(person: IPerson): number {
return Math.pow(person.charisma, 0.45) / (this.teamSize - this.sleeveSize + 1); return Math.pow(person.skills.charisma, 0.45) / (this.teamSize - this.sleeveSize + 1);
} }
getRecruitmentTime(person: IPerson): number { getRecruitmentTime(person: IPerson): number {
const effCharisma = person.charisma * this.skillMultipliers.effCha; const effCharisma = person.skills.charisma * this.skillMultipliers.effCha;
const charismaFactor = Math.pow(effCharisma, 0.81) + effCharisma / 90; const charismaFactor = Math.pow(effCharisma, 0.81) + effCharisma / 90;
return Math.max(10, Math.round(BladeburnerConstants.BaseRecruitmentTimeNeeded - charismaFactor)); return Math.max(10, Math.round(BladeburnerConstants.BaseRecruitmentTimeNeeded - charismaFactor));
} }
@@ -1126,7 +1127,7 @@ export class Bladeburner implements IBladeburner {
const sup = player.sleeves.filter((x) => x.bbAction == "Support main sleeve"); const sup = player.sleeves.filter((x) => x.bbAction == "Support main sleeve");
for (let i = 0; i > this.teamSize - this.sleeveSize; i--) { for (let i = 0; i > this.teamSize - this.sleeveSize; i--) {
const r = Math.floor(Math.random() * sup.length); const r = Math.floor(Math.random() * sup.length);
sup[r].takeDamage(sup[r].max_hp); sup[r].takeDamage(sup[r].hp.max);
sup.splice(r, 1); sup.splice(r, 1);
} }
this.teamSize += this.sleeveSize; this.teamSize += this.sleeveSize;
@@ -1440,7 +1441,7 @@ export class Bladeburner implements IBladeburner {
const sup = player.sleeves.filter((x) => x.bbAction == "Support main sleeve"); const sup = player.sleeves.filter((x) => x.bbAction == "Support main sleeve");
for (let i = 0; i > this.teamSize - this.sleeveSize; i--) { for (let i = 0; i > this.teamSize - this.sleeveSize; i--) {
const r = Math.floor(Math.random() * sup.length); const r = Math.floor(Math.random() * sup.length);
sup[r].takeDamage(sup[r].max_hp); sup[r].takeDamage(sup[r].hp.max);
sup.splice(r, 1); sup.splice(r, 1);
} }
this.teamSize += this.sleeveSize; this.teamSize += this.sleeveSize;
@@ -1489,9 +1490,9 @@ export class Bladeburner implements IBladeburner {
case ActionTypes["Field Analysis"]: { case ActionTypes["Field Analysis"]: {
// Does not use stamina. Effectiveness depends on hacking, int, and cha // Does not use stamina. Effectiveness depends on hacking, int, and cha
let eff = let eff =
0.04 * Math.pow(person.hacking, 0.3) + 0.04 * Math.pow(person.skills.hacking, 0.3) +
0.04 * Math.pow(person.intelligence, 0.9) + 0.04 * Math.pow(person.skills.intelligence, 0.9) +
0.02 * Math.pow(person.charisma, 0.3); 0.02 * Math.pow(person.skills.charisma, 0.3);
eff *= person.mults.bladeburner_analysis; eff *= person.mults.bladeburner_analysis;
if (isNaN(eff) || eff < 0) { if (isNaN(eff) || eff < 0) {
throw new Error("Field Analysis Effectiveness calculated to be NaN or negative"); throw new Error("Field Analysis Effectiveness calculated to be NaN or negative");
@@ -1680,14 +1681,14 @@ export class Bladeburner implements IBladeburner {
} }
calculateStaminaGainPerSecond(player: IPlayer): number { calculateStaminaGainPerSecond(player: IPlayer): number {
const effAgility = player.agility * this.skillMultipliers.effAgi; const effAgility = player.skills.agility * this.skillMultipliers.effAgi;
const maxStaminaBonus = this.maxStamina / BladeburnerConstants.MaxStaminaToGainFactor; const maxStaminaBonus = this.maxStamina / BladeburnerConstants.MaxStaminaToGainFactor;
const gain = (BladeburnerConstants.StaminaGainPerSecond + maxStaminaBonus) * Math.pow(effAgility, 0.17); const gain = (BladeburnerConstants.StaminaGainPerSecond + maxStaminaBonus) * Math.pow(effAgility, 0.17);
return gain * (this.skillMultipliers.stamina * player.mults.bladeburner_stamina_gain); return gain * (this.skillMultipliers.stamina * player.mults.bladeburner_stamina_gain);
} }
calculateMaxStamina(player: IPlayer): void { calculateMaxStamina(player: IPlayer): void {
const effAgility = player.agility * this.skillMultipliers.effAgi; const effAgility = player.skills.agility * this.skillMultipliers.effAgi;
const maxStamina = const maxStamina =
(Math.pow(effAgility, 0.8) + this.staminaBonus) * (Math.pow(effAgility, 0.8) + this.staminaBonus) *
this.skillMultipliers.stamina * this.skillMultipliers.stamina *

View File

@@ -89,7 +89,7 @@ export const CONSTANTS: {
LatestUpdate: string; LatestUpdate: string;
} = { } = {
VersionString: "2.0.0", VersionString: "2.0.0",
VersionNumber: 21, VersionNumber: 22,
// Speed (in ms) at which the main loop is updated // Speed (in ms) at which the main loop is updated
_idleSpeed: 200, _idleSpeed: 200,
@@ -255,7 +255,7 @@ v2.0.0 - 2022-07-19 Work rework
* Company faction require 400k rep to join (from 200k) * Company faction require 400k rep to join (from 200k)
* Backdooring company server reduces faction requirement to 300k. * Backdooring company server reduces faction requirement to 300k.
* All work generally no longer keep track of cumulative gains like exp and reputation since it's applied instantly. * All work generally no longer keep track of cumulative gains like exp and reputation since it's applied instantly.
* getPlayer returns way less fields but does return the new 'currentWork' field. * getPlayer returns way less fields but does return the new 'currentWork' field, some fields are moved around.
API breaks API breaks

View File

@@ -112,13 +112,13 @@ export class Crime {
successRate(p: IPerson): number { successRate(p: IPerson): number {
let chance: number = let chance: number =
this.hacking_success_weight * p.hacking + this.hacking_success_weight * p.skills.hacking +
this.strength_success_weight * p.strength + this.strength_success_weight * p.skills.strength +
this.defense_success_weight * p.defense + this.defense_success_weight * p.skills.defense +
this.dexterity_success_weight * p.dexterity + this.dexterity_success_weight * p.skills.dexterity +
this.agility_success_weight * p.agility + this.agility_success_weight * p.skills.agility +
this.charisma_success_weight * p.charisma + this.charisma_success_weight * p.skills.charisma +
CONSTANTS.IntelligenceCrimeWeight * p.intelligence; CONSTANTS.IntelligenceCrimeWeight * p.skills.intelligence;
chance /= CONSTANTS.MaxSkillLevel; chance /= CONSTANTS.MaxSkillLevel;
chance /= this.difficulty; chance /= this.difficulty;
chance *= p.mults.crime_success; chance *= p.mults.crime_success;

View File

@@ -78,13 +78,13 @@ export function Stats(props: IProps): React.ReactElement {
} }
function resetAllExp(): void { function resetAllExp(): void {
props.player.hacking_exp = 0; props.player.exp.hacking = 0;
props.player.strength_exp = 0; props.player.exp.strength = 0;
props.player.defense_exp = 0; props.player.exp.defense = 0;
props.player.dexterity_exp = 0; props.player.exp.dexterity = 0;
props.player.agility_exp = 0; props.player.exp.agility = 0;
props.player.charisma_exp = 0; props.player.exp.charisma = 0;
props.player.intelligence_exp = 0; props.player.exp.intelligence = 0;
props.player.updateSkillLevels(); props.player.updateSkillLevels();
} }
@@ -92,25 +92,25 @@ export function Stats(props: IProps): React.ReactElement {
return function () { return function () {
switch (stat) { switch (stat) {
case "hacking": case "hacking":
props.player.hacking_exp = 0; props.player.exp.hacking = 0;
break; break;
case "strength": case "strength":
props.player.strength_exp = 0; props.player.exp.strength = 0;
break; break;
case "defense": case "defense":
props.player.defense_exp = 0; props.player.exp.defense = 0;
break; break;
case "dexterity": case "dexterity":
props.player.dexterity_exp = 0; props.player.exp.dexterity = 0;
break; break;
case "agility": case "agility":
props.player.agility_exp = 0; props.player.exp.agility = 0;
break; break;
case "charisma": case "charisma":
props.player.charisma_exp = 0; props.player.exp.charisma = 0;
break; break;
case "intelligence": case "intelligence":
props.player.intelligence_exp = 0; props.player.exp.intelligence = 0;
break; break;
} }
props.player.updateSkillLevels(); props.player.updateSkillLevels();
@@ -124,15 +124,15 @@ export function Stats(props: IProps): React.ReactElement {
} }
function enableIntelligence(): void { function enableIntelligence(): void {
if (props.player.intelligence === 0) { if (props.player.skills.intelligence === 0) {
props.player.intelligence = 1; props.player.skills.intelligence = 1;
props.player.updateSkillLevels(); props.player.updateSkillLevels();
} }
} }
function disableIntelligence(): void { function disableIntelligence(): void {
props.player.intelligence_exp = 0; props.player.exp.intelligence = 0;
props.player.intelligence = 0; props.player.skills.intelligence = 0;
props.player.updateSkillLevels(); props.player.updateSkillLevels();
} }

View File

@@ -9,10 +9,13 @@ import { Server } from "./Server/Server";
export function calculateHackingChance(server: Server, player: IPlayer): number { export function calculateHackingChance(server: Server, player: IPlayer): number {
const hackFactor = 1.75; const hackFactor = 1.75;
const difficultyMult = (100 - server.hackDifficulty) / 100; const difficultyMult = (100 - server.hackDifficulty) / 100;
const skillMult = hackFactor * player.hacking; const skillMult = hackFactor * player.skills.hacking;
const skillChance = (skillMult - server.requiredHackingSkill) / skillMult; const skillChance = (skillMult - server.requiredHackingSkill) / skillMult;
const chance = const chance =
skillChance * difficultyMult * player.mults.hacking_chance * calculateIntelligenceBonus(player.intelligence, 1); skillChance *
difficultyMult *
player.mults.hacking_chance *
calculateIntelligenceBonus(player.skills.intelligence, 1);
if (chance > 1) { if (chance > 1) {
return 1; return 1;
} }
@@ -48,7 +51,7 @@ export function calculatePercentMoneyHacked(server: Server, player: IPlayer): nu
const balanceFactor = 240; const balanceFactor = 240;
const difficultyMult = (100 - server.hackDifficulty) / 100; const difficultyMult = (100 - server.hackDifficulty) / 100;
const skillMult = (player.hacking - (server.requiredHackingSkill - 1)) / player.hacking; const skillMult = (player.skills.hacking - (server.requiredHackingSkill - 1)) / player.skills.hacking;
const percentMoneyHacked = const percentMoneyHacked =
(difficultyMult * skillMult * player.mults.hacking_money * BitNodeMultipliers.ScriptHackMoney) / balanceFactor; (difficultyMult * skillMult * player.mults.hacking_money * BitNodeMultipliers.ScriptHackMoney) / balanceFactor;
if (percentMoneyHacked < 0) { if (percentMoneyHacked < 0) {
@@ -72,12 +75,12 @@ export function calculateHackingTime(server: Server, player: IPlayer): number {
const diffFactor = 2.5; const diffFactor = 2.5;
let skillFactor = diffFactor * difficultyMult + baseDiff; let skillFactor = diffFactor * difficultyMult + baseDiff;
// tslint:disable-next-line // tslint:disable-next-line
skillFactor /= player.hacking + baseSkill; skillFactor /= player.skills.hacking + baseSkill;
const hackTimeMultiplier = 5; const hackTimeMultiplier = 5;
const hackingTime = const hackingTime =
(hackTimeMultiplier * skillFactor) / (hackTimeMultiplier * skillFactor) /
(player.mults.hacking_speed * calculateIntelligenceBonus(player.intelligence, 1)); (player.mults.hacking_speed * calculateIntelligenceBonus(player.skills.intelligence, 1));
return hackingTime; return hackingTime;
} }

View File

@@ -36,7 +36,7 @@ export function netscriptCanHack(server: Server, p: IPlayer): IReturnStatus {
} }
const s = server; const s = server;
if (s.requiredHackingSkill > p.hacking) { if (s.requiredHackingSkill > p.skills.hacking) {
return { return {
res: false, res: false,
msg: `Cannot hack ${server.hostname} server because your hacking skill is not high enough`, msg: `Cannot hack ${server.hostname} server because your hacking skill is not high enough`,

View File

@@ -6,13 +6,13 @@ export function getHospitalizationCost(p: IPlayer): number {
return 0; return 0;
} }
return Math.min(p.money * 0.1, (p.max_hp - p.hp) * CONSTANTS.HospitalCostPerHp); return Math.min(p.money * 0.1, (p.hp.max - p.hp.current) * CONSTANTS.HospitalCostPerHp);
} }
export function calculateHospitalizationCost(p: IPlayer, damage: number): number { export function calculateHospitalizationCost(p: IPlayer, damage: number): number {
const oldhp = p.hp; const oldhp = p.hp.current;
p.hp -= damage; p.hp.current -= damage;
const cost = getHospitalizationCost(p); const cost = getHospitalizationCost(p);
p.hp = oldhp; p.hp.current = oldhp;
return cost; return cost;
} }

View File

@@ -2,14 +2,19 @@ import { IPlayer } from "../../PersonObjects/IPlayer";
import { calculateSkill } from "../../PersonObjects/formulas/skill"; import { calculateSkill } from "../../PersonObjects/formulas/skill";
function calculateRawDiff(player: IPlayer, stats: number, startingDifficulty: number): number { function calculateRawDiff(player: IPlayer, stats: number, startingDifficulty: number): number {
const difficulty = startingDifficulty - Math.pow(stats, 0.9) / 250 - player.intelligence / 1600; const difficulty = startingDifficulty - Math.pow(stats, 0.9) / 250 - player.skills.intelligence / 1600;
if (difficulty < 0) return 0; if (difficulty < 0) return 0;
if (difficulty > 3) return 3; if (difficulty > 3) return 3;
return difficulty; return difficulty;
} }
export function calculateDifficulty(player: IPlayer, startingSecurityLevel: number): number { export function calculateDifficulty(player: IPlayer, startingSecurityLevel: number): number {
const totalStats = player.strength + player.defense + player.dexterity + player.agility + player.charisma; const totalStats =
player.skills.strength +
player.skills.defense +
player.skills.dexterity +
player.skills.agility +
player.skills.charisma;
return calculateRawDiff(player, totalStats, startingSecurityLevel); return calculateRawDiff(player, totalStats, startingSecurityLevel);
} }

View File

@@ -91,7 +91,7 @@ export function Game(props: IProps): React.ReactElement {
// Kill the player immediately if they use automation, so // Kill the player immediately if they use automation, so
// it's clear they're not meant to // it's clear they're not meant to
const damage = options?.automated const damage = options?.automated
? player.hp ? player.hp.current
: props.StartingDifficulty * 3 * (player.hasAugmentation(AugmentationNames.WKSharmonizer, true) ? 0.5 : 1); : props.StartingDifficulty * 3 * (player.hasAugmentation(AugmentationNames.WKSharmonizer, true) ? 0.5 : 1);
if (player.takeDamage(damage)) { if (player.takeDamage(damage)) {
router.toCity(); router.toCity();

View File

@@ -34,7 +34,7 @@ export class HospitalLocation extends React.Component<IProps, IState> {
this.getHealed = this.getHealed.bind(this); this.getHealed = this.getHealed.bind(this);
this.state = { this.state = {
currHp: this.props.p.hp, currHp: this.props.p.hp.current,
}; };
} }
@@ -47,20 +47,20 @@ export class HospitalLocation extends React.Component<IProps, IState> {
return; return;
} }
if (this.props.p.hp < 0) { if (this.props.p.hp.current < 0) {
this.props.p.hp = 0; this.props.p.hp.current = 0;
} }
if (this.props.p.hp >= this.props.p.max_hp) { if (this.props.p.hp.current >= this.props.p.hp.max) {
return; return;
} }
const cost = this.getCost(); const cost = this.getCost();
this.props.p.loseMoney(cost, "hospitalization"); this.props.p.loseMoney(cost, "hospitalization");
this.props.p.hp = this.props.p.max_hp; this.props.p.hp.current = this.props.p.hp.max;
// This just forces a re-render to update the cost // This just forces a re-render to update the cost
this.setState({ this.setState({
currHp: this.props.p.hp, currHp: this.props.p.hp.current,
}); });
dialogBoxCreate( dialogBoxCreate(

View File

@@ -54,7 +54,12 @@ export function SpecialLocation(props: IProps): React.ReactElement {
if (p.inBladeburner()) { if (p.inBladeburner()) {
// Enter Bladeburner division // Enter Bladeburner division
router.toBladeburner(); router.toBladeburner();
} else if (p.strength >= 100 && p.defense >= 100 && p.dexterity >= 100 && p.agility >= 100) { } else if (
p.skills.strength >= 100 &&
p.skills.defense >= 100 &&
p.skills.dexterity >= 100 &&
p.skills.agility >= 100
) {
// Apply for Bladeburner division // Apply for Bladeburner division
p.startBladeburner(); p.startBladeburner();
dialogBoxCreate("You have been accepted into the Bladeburner division!"); dialogBoxCreate("You have been accepted into the Bladeburner division!");
@@ -96,14 +101,14 @@ export function SpecialLocation(props: IProps): React.ReactElement {
N00dles(); // This is the true power of the noodles. N00dles(); // This is the true power of the noodles.
if (player.sourceFiles.length > 0) player.giveExploit(Exploit.N00dles); if (player.sourceFiles.length > 0) player.giveExploit(Exploit.N00dles);
if (player.sourceFileLvl(5) > 0 || player.bitNodeN === 5) { if (player.sourceFileLvl(5) > 0 || player.bitNodeN === 5) {
player.intelligence_exp *= 1.0000000000000002; player.exp.intelligence *= 1.0000000000000002;
} }
player.hacking_exp *= 1.0000000000000002; player.exp.hacking *= 1.0000000000000002;
player.strength_exp *= 1.0000000000000002; player.exp.strength *= 1.0000000000000002;
player.defense_exp *= 1.0000000000000002; player.exp.defense *= 1.0000000000000002;
player.agility_exp *= 1.0000000000000002; player.exp.agility *= 1.0000000000000002;
player.dexterity_exp *= 1.0000000000000002; player.exp.dexterity *= 1.0000000000000002;
player.charisma_exp *= 1.0000000000000002; player.exp.charisma *= 1.0000000000000002;
for (const node of player.hacknetNodes) { for (const node of player.hacknetNodes) {
if (node instanceof HacknetNode) { if (node instanceof HacknetNode) {
player.gainMoney(node.moneyGainRatePerSecond * 0.001, "other"); player.gainMoney(node.moneyGainRatePerSecond * 0.001, "other");

View File

@@ -76,33 +76,33 @@ function checkForMessagesToSend(): void {
throw new Error("The world daemon is not a server???? Please un-break reality"); throw new Error("The world daemon is not a server???? Please un-break reality");
} }
//If the daemon can be hacked, send the player icarus.msg //If the daemon can be hacked, send the player icarus.msg
if (Player.hacking >= worldDaemon.requiredHackingSkill) { if (Player.skills.hacking >= worldDaemon.requiredHackingSkill) {
sendMessage(redpill, Player.sourceFiles.length === 0); sendMessage(redpill, Player.sourceFiles.length === 0);
} }
//If the daemon cannot be hacked, send the player truthgazer.msg a single time. //If the daemon cannot be hacked, send the player truthgazer.msg a single time.
else if (!recvd(truthGazer)) { else if (!recvd(truthGazer)) {
sendMessage(truthGazer); sendMessage(truthGazer);
} }
} else if (!recvd(jumper0) && Player.hacking >= 25) { } else if (!recvd(jumper0) && Player.skills.hacking >= 25) {
sendMessage(jumper0); sendMessage(jumper0);
const flightName = Programs.Flight.name; const flightName = Programs.Flight.name;
const homeComp = Player.getHomeComputer(); const homeComp = Player.getHomeComputer();
if (!homeComp.programs.includes(flightName)) { if (!homeComp.programs.includes(flightName)) {
homeComp.programs.push(flightName); homeComp.programs.push(flightName);
} }
} else if (!recvd(jumper1) && Player.hacking >= 40) { } else if (!recvd(jumper1) && Player.skills.hacking >= 40) {
sendMessage(jumper1); sendMessage(jumper1);
} else if (!recvd(cybersecTest) && Player.hacking >= 50) { } else if (!recvd(cybersecTest) && Player.skills.hacking >= 50) {
sendMessage(cybersecTest); sendMessage(cybersecTest);
} else if (!recvd(jumper2) && Player.hacking >= 175) { } else if (!recvd(jumper2) && Player.skills.hacking >= 175) {
sendMessage(jumper2); sendMessage(jumper2);
} else if (!recvd(nitesecTest) && Player.hacking >= 200) { } else if (!recvd(nitesecTest) && Player.skills.hacking >= 200) {
sendMessage(nitesecTest); sendMessage(nitesecTest);
} else if (!recvd(jumper3) && Player.hacking >= 350) { } else if (!recvd(jumper3) && Player.skills.hacking >= 350) {
sendMessage(jumper3); sendMessage(jumper3);
} else if (!recvd(jumper4) && Player.hacking >= 490) { } else if (!recvd(jumper4) && Player.skills.hacking >= 490) {
sendMessage(jumper4); sendMessage(jumper4);
} else if (!recvd(bitrunnersTest) && Player.hacking >= 500) { } else if (!recvd(bitrunnersTest) && Player.skills.hacking >= 500) {
sendMessage(bitrunnersTest); sendMessage(bitrunnersTest);
} }
} }

View File

@@ -941,7 +941,9 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
}, },
share: (ctx: NetscriptContext) => async (): Promise<void> => { share: (ctx: NetscriptContext) => async (): Promise<void> => {
ctx.log(() => "Sharing this computer."); ctx.log(() => "Sharing this computer.");
const end = StartSharing(workerScript.scriptRef.threads * calculateIntelligenceBonus(Player.intelligence, 2)); const end = StartSharing(
workerScript.scriptRef.threads * calculateIntelligenceBonus(Player.skills.intelligence, 2),
);
return netscriptDelay(10000, workerScript).finally(function () { return netscriptDelay(10000, workerScript).finally(function () {
ctx.log(() => "Finished sharing this computer."); ctx.log(() => "Finished sharing this computer.");
end(); end();
@@ -1614,8 +1616,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
}, },
getHackingLevel: (ctx: NetscriptContext) => (): number => { getHackingLevel: (ctx: NetscriptContext) => (): number => {
Player.updateSkillLevels(); Player.updateSkillLevels();
ctx.log(() => `returned ${Player.hacking}`); ctx.log(() => `returned ${Player.skills.hacking}`);
return Player.hacking; return Player.skills.hacking;
}, },
getHackingMultipliers: () => (): HackingMultipliers => { getHackingMultipliers: () => (): HackingMultipliers => {
return { return {
@@ -2434,21 +2436,9 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
}, },
getPlayer: () => (): INetscriptPlayer => { getPlayer: () => (): INetscriptPlayer => {
const data = { const data = {
hacking: Player.hacking,
hp: Player.hp, hp: Player.hp,
max_hp: Player.max_hp, skills: Player.skills,
strength: Player.strength, exp: Player.exp,
defense: Player.defense,
dexterity: Player.dexterity,
agility: Player.agility,
charisma: Player.charisma,
intelligence: Player.intelligence,
hacking_exp: Player.hacking_exp,
strength_exp: Player.strength_exp,
defense_exp: Player.defense_exp,
dexterity_exp: Player.dexterity_exp,
agility_exp: Player.agility_exp,
charisma_exp: Player.charisma_exp,
hacking_chance_mult: Player.mults.hacking_chance, hacking_chance_mult: Player.mults.hacking_chance,
mults: JSON.parse(JSON.stringify(Player.mults)), mults: JSON.parse(JSON.stringify(Player.mults)),
numPeopleKilled: Player.numPeopleKilled, numPeopleKilled: Player.numPeopleKilled,
@@ -2469,7 +2459,6 @@ 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;

View File

@@ -403,10 +403,10 @@ export function NetscriptBladeburner(player: IPlayer, workerScript: WorkerScript
if (player.bladeburner instanceof Bladeburner) { if (player.bladeburner instanceof Bladeburner) {
return true; // Already member return true; // Already member
} else if ( } else if (
player.strength >= 100 && player.skills.strength >= 100 &&
player.defense >= 100 && player.skills.defense >= 100 &&
player.dexterity >= 100 && player.skills.dexterity >= 100 &&
player.agility >= 100 player.skills.agility >= 100
) { ) {
player.bladeburner = new Bladeburner(player); player.bladeburner = new Bladeburner(player);
ctx.log(() => "You have been accepted into the Bladeburner division"); ctx.log(() => "You have been accepted into the Bladeburner division");

View File

@@ -1257,7 +1257,7 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
const wd = GetServer(SpecialServers.WorldDaemon); const wd = GetServer(SpecialServers.WorldDaemon);
if (!(wd instanceof Server)) if (!(wd instanceof Server))
throw new Error("WorldDaemon was not a normal server. This is a bug contact dev."); throw new Error("WorldDaemon was not a normal server. This is a bug contact dev.");
if (player.hacking < wd.requiredHackingSkill) return false; if (player.skills.hacking < wd.requiredHackingSkill) return false;
if (!wd.hasAdminRights) return false; if (!wd.hasAdminRights) return false;
return true; return true;
}; };

View File

@@ -40,12 +40,12 @@ export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
shock: 100 - sl.shock, shock: 100 - sl.shock,
sync: sl.sync, sync: sl.sync,
memory: sl.memory, memory: sl.memory,
hacking: sl.hacking, hacking: sl.skills.hacking,
strength: sl.strength, strength: sl.skills.strength,
defense: sl.defense, defense: sl.skills.defense,
dexterity: sl.dexterity, dexterity: sl.skills.dexterity,
agility: sl.agility, agility: sl.skills.agility,
charisma: sl.charisma, charisma: sl.skills.charisma,
}; };
}; };
@@ -206,10 +206,10 @@ export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
return { return {
tor: false, tor: false,
city: sl.city, city: sl.city,
hp: sl.hp, hp: sl.hp.current,
jobs: Object.keys(player.jobs), // technically sleeves have the same jobs as the player. jobs: Object.keys(player.jobs), // technically sleeves have the same jobs as the player.
jobTitle: Object.values(player.jobs), jobTitle: Object.values(player.jobs),
maxHp: sl.max_hp, maxHp: sl.hp.max,
mult: { mult: {
agility: sl.mults.agility, agility: sl.mults.agility,

4
src/PersonObjects/HP.ts Normal file
View File

@@ -0,0 +1,4 @@
export interface HP {
current: number;
max: number;
}

View File

@@ -2,29 +2,15 @@
// a Sleeve. Used for functions that need to take in both. // a Sleeve. Used for functions that need to take in both.
import { IPlayerOwnedAugmentation } from "../Augmentation/PlayerOwnedAugmentation"; import { IPlayerOwnedAugmentation } from "../Augmentation/PlayerOwnedAugmentation";
import { HP } from "./HP";
import { ITaskTracker } from "./ITaskTracker"; import { ITaskTracker } from "./ITaskTracker";
import { Multipliers } from "./Multipliers"; import { Multipliers } from "./Multipliers";
import { Skills } from "./Skills";
export interface IPerson { export interface IPerson {
// Stats hp: HP;
hacking: number; skills: Skills;
strength: number; exp: Skills;
defense: number;
dexterity: number;
agility: number;
charisma: number;
intelligence: number;
hp: number;
max_hp: number;
// Experience
hacking_exp: number;
strength_exp: number;
defense_exp: number;
dexterity_exp: number;
agility_exp: number;
charisma_exp: number;
intelligence_exp: number;
mults: Multipliers; mults: Multipliers;

View File

@@ -31,6 +31,8 @@ import { PlayerAchievement } from "../Achievements/Achievements";
import { IPerson } from "./IPerson"; import { IPerson } from "./IPerson";
import { Work } from "../Work/Work"; import { Work } from "../Work/Work";
import { Multipliers } from "./Multipliers"; import { Multipliers } from "./Multipliers";
import { Skills } from "./Skills";
import { HP } from "./HP";
export interface IPlayer extends IPerson { export interface IPlayer extends IPerson {
bitNodeN: number; bitNodeN: number;
@@ -47,12 +49,10 @@ export interface IPlayer extends IPerson {
hashManager: HashManager; hashManager: HashManager;
hasTixApiAccess: boolean; hasTixApiAccess: boolean;
hasWseAccount: boolean; hasWseAccount: boolean;
hp: number;
jobs: IMap<string>; jobs: IMap<string>;
karma: number; karma: number;
numPeopleKilled: number; numPeopleKilled: number;
location: LocationName; location: LocationName;
max_hp: number;
readonly money: number; readonly money: number;
moneySourceA: MoneySourceTracker; moneySourceA: MoneySourceTracker;
moneySourceB: MoneySourceTracker; moneySourceB: MoneySourceTracker;
@@ -70,23 +70,9 @@ export interface IPlayer extends IPerson {
lastUpdate: number; lastUpdate: number;
totalPlaytime: number; totalPlaytime: number;
// Stats hp: HP;
hacking: number; skills: Skills;
strength: number; exp: Skills;
defense: number;
dexterity: number;
agility: number;
charisma: number;
intelligence: number;
// Experience
hacking_exp: number;
strength_exp: number;
defense_exp: number;
dexterity_exp: number;
agility_exp: number;
charisma_exp: number;
intelligence_exp: number;
mults: Multipliers; mults: Multipliers;

View File

@@ -8,32 +8,30 @@ import { calculateSkill } from "./formulas/skill";
import { calculateIntelligenceBonus } from "./formulas/intelligence"; import { calculateIntelligenceBonus } from "./formulas/intelligence";
import { IPerson } from "./IPerson"; import { IPerson } from "./IPerson";
import { defaultMultipliers, mergeMultipliers } from "./Multipliers"; import { defaultMultipliers, mergeMultipliers } from "./Multipliers";
import { Skills } from "./Skills";
import { HP } from "./HP";
// Base class representing a person-like object // Base class representing a person-like object
export abstract class Person implements IPerson { export abstract class Person implements IPerson {
/** hp: HP = { current: 10, max: 10 };
* Stats skills: Skills = {
*/ hacking: 1,
hacking = 1; strength: 1,
strength = 1; defense: 1,
defense = 1; dexterity: 1,
dexterity = 1; agility: 1,
agility = 1; charisma: 1,
charisma = 1; intelligence: 1,
intelligence = 0; };
hp = 10; exp: Skills = {
max_hp = 10; hacking: 0,
strength: 0,
/** defense: 0,
* Experience dexterity: 0,
*/ agility: 0,
hacking_exp = 0; charisma: 0,
strength_exp = 0; intelligence: 0,
defense_exp = 0; };
dexterity_exp = 0;
agility_exp = 0;
charisma_exp = 0;
intelligence_exp = 0;
mults = defaultMultipliers(); mults = defaultMultipliers();
@@ -81,12 +79,12 @@ export abstract class Person implements IPerson {
getFactionFieldWorkRepGain(): number { getFactionFieldWorkRepGain(): number {
const t = const t =
(0.9 * (0.9 *
(this.hacking / CONSTANTS.MaxSkillLevel + (this.skills.hacking / CONSTANTS.MaxSkillLevel +
this.strength / CONSTANTS.MaxSkillLevel + this.skills.strength / CONSTANTS.MaxSkillLevel +
this.defense / CONSTANTS.MaxSkillLevel + this.skills.defense / CONSTANTS.MaxSkillLevel +
this.dexterity / CONSTANTS.MaxSkillLevel + this.skills.dexterity / CONSTANTS.MaxSkillLevel +
this.agility / CONSTANTS.MaxSkillLevel + this.skills.agility / CONSTANTS.MaxSkillLevel +
this.charisma / CONSTANTS.MaxSkillLevel)) / this.skills.charisma / CONSTANTS.MaxSkillLevel)) /
5.5; 5.5;
return t * this.mults.faction_rep; return t * this.mults.faction_rep;
} }
@@ -96,7 +94,7 @@ export abstract class Person implements IPerson {
* when doing Hacking Work for a faction * when doing Hacking Work for a faction
*/ */
getFactionHackingWorkRepGain(): number { getFactionHackingWorkRepGain(): number {
return (this.hacking / CONSTANTS.MaxSkillLevel) * this.mults.faction_rep; return (this.skills.hacking / CONSTANTS.MaxSkillLevel) * this.mults.faction_rep;
} }
/** /**
@@ -106,11 +104,11 @@ export abstract class Person implements IPerson {
getFactionSecurityWorkRepGain(): number { getFactionSecurityWorkRepGain(): number {
const t = const t =
(0.9 * (0.9 *
(this.hacking / CONSTANTS.MaxSkillLevel + (this.skills.hacking / CONSTANTS.MaxSkillLevel +
this.strength / CONSTANTS.MaxSkillLevel + this.skills.strength / CONSTANTS.MaxSkillLevel +
this.defense / CONSTANTS.MaxSkillLevel + this.skills.defense / CONSTANTS.MaxSkillLevel +
this.dexterity / CONSTANTS.MaxSkillLevel + this.skills.dexterity / CONSTANTS.MaxSkillLevel +
this.agility / CONSTANTS.MaxSkillLevel)) / this.skills.agility / CONSTANTS.MaxSkillLevel)) /
4.5; 4.5;
return t * this.mults.faction_rep; return t * this.mults.faction_rep;
} }
@@ -126,44 +124,44 @@ export abstract class Person implements IPerson {
* Update all stat levels * Update all stat levels
*/ */
updateStatLevels(): void { updateStatLevels(): void {
this.hacking = Math.max( this.skills.hacking = Math.max(
1, 1,
Math.floor(this.calculateStat(this.hacking_exp, this.mults.hacking * BitNodeMultipliers.HackingLevelMultiplier)), Math.floor(this.calculateStat(this.exp.hacking, this.mults.hacking * BitNodeMultipliers.HackingLevelMultiplier)),
); );
this.strength = Math.max( this.skills.strength = Math.max(
1, 1,
Math.floor( Math.floor(
this.calculateStat(this.strength_exp, this.mults.strength * BitNodeMultipliers.StrengthLevelMultiplier), this.calculateStat(this.exp.strength, this.mults.strength * BitNodeMultipliers.StrengthLevelMultiplier),
), ),
); );
this.defense = Math.max( this.skills.defense = Math.max(
1, 1,
Math.floor(this.calculateStat(this.defense_exp, this.mults.defense * BitNodeMultipliers.DefenseLevelMultiplier)), Math.floor(this.calculateStat(this.exp.defense, this.mults.defense * BitNodeMultipliers.DefenseLevelMultiplier)),
); );
this.dexterity = Math.max( this.skills.dexterity = Math.max(
1, 1,
Math.floor( Math.floor(
this.calculateStat(this.dexterity_exp, this.mults.dexterity * BitNodeMultipliers.DexterityLevelMultiplier), this.calculateStat(this.exp.dexterity, this.mults.dexterity * BitNodeMultipliers.DexterityLevelMultiplier),
), ),
); );
this.agility = Math.max( this.skills.agility = Math.max(
1, 1,
Math.floor(this.calculateStat(this.agility_exp, this.mults.agility * BitNodeMultipliers.AgilityLevelMultiplier)), Math.floor(this.calculateStat(this.exp.agility, this.mults.agility * BitNodeMultipliers.AgilityLevelMultiplier)),
); );
this.charisma = Math.max( this.skills.charisma = Math.max(
1, 1,
Math.floor( Math.floor(
this.calculateStat(this.charisma_exp, this.mults.charisma * BitNodeMultipliers.CharismaLevelMultiplier), this.calculateStat(this.exp.charisma, this.mults.charisma * BitNodeMultipliers.CharismaLevelMultiplier),
), ),
); );
const ratio: number = this.hp / this.max_hp; const ratio: number = this.hp.current / this.hp.max;
this.max_hp = Math.floor(10 + this.defense / 10); this.hp.max = Math.floor(10 + this.skills.defense / 10);
this.hp = Math.round(this.max_hp * ratio); this.hp.current = Math.round(this.hp.max * ratio);
} }
getIntelligenceBonus(weight: number): number { getIntelligenceBonus(weight: number): number {
return calculateIntelligenceBonus(this.intelligence, weight); return calculateIntelligenceBonus(this.skills.intelligence, weight);
} }
abstract takeDamage(amt: number): boolean; abstract takeDamage(amt: number): boolean;

View File

@@ -40,6 +40,8 @@ import { ITaskTracker } from "../ITaskTracker";
import { CONSTANTS } from "../../Constants"; import { CONSTANTS } from "../../Constants";
import { Work } from "src/Work/Work"; import { Work } from "src/Work/Work";
import { defaultMultipliers, Multipliers } from "../Multipliers"; import { defaultMultipliers, Multipliers } from "../Multipliers";
import { HP } from "../HP";
import { Skills } from "../Skills";
export class PlayerObject implements IPlayer { export class PlayerObject implements IPlayer {
// Class members // Class members
@@ -58,13 +60,11 @@ export class PlayerObject implements IPlayer {
hashManager: HashManager; hashManager: HashManager;
hasTixApiAccess: boolean; hasTixApiAccess: boolean;
hasWseAccount: boolean; hasWseAccount: boolean;
hp: number;
jobs: IMap<string>; jobs: IMap<string>;
init: () => void; init: () => void;
karma: number; karma: number;
numPeopleKilled: number; numPeopleKilled: number;
location: LocationName; location: LocationName;
max_hp: number;
money: number; money: number;
moneySourceA: MoneySourceTracker; moneySourceA: MoneySourceTracker;
moneySourceB: MoneySourceTracker; moneySourceB: MoneySourceTracker;
@@ -84,23 +84,9 @@ export class PlayerObject implements IPlayer {
lastSave: number; lastSave: number;
totalPlaytime: number; totalPlaytime: number;
// Stats hp: HP;
hacking: number; skills: Skills;
strength: number; exp: Skills;
defense: number;
dexterity: number;
agility: number;
charisma: number;
intelligence: number;
// Experience
hacking_exp: number;
strength_exp: number;
defense_exp: number;
dexterity_exp: number;
agility_exp: number;
charisma_exp: number;
intelligence_exp: number;
mults: Multipliers; mults: Multipliers;
@@ -197,31 +183,25 @@ export class PlayerObject implements IPlayer {
focusPenalty: () => number; focusPenalty: () => number;
constructor() { constructor() {
//Skills and stats this.hp = { current: 10, max: 10 };
this.hacking = 1; this.skills = {
hacking: 1,
//Combat stats strength: 1,
this.hp = 10; defense: 1,
this.max_hp = 10; dexterity: 1,
this.strength = 1; agility: 1,
this.defense = 1; charisma: 1,
this.dexterity = 1; intelligence: 1,
this.agility = 1; };
this.exp = {
//Labor stats hacking: 0,
this.charisma = 1; strength: 0,
defense: 0,
//Special stats dexterity: 0,
this.intelligence = 0; agility: 0,
charisma: 0,
//Experience and multipliers intelligence: 0,
this.hacking_exp = 0; };
this.strength_exp = 0;
this.defense_exp = 0;
this.dexterity_exp = 0;
this.agility_exp = 0;
this.charisma_exp = 0;
this.intelligence_exp = 0;
this.mults = defaultMultipliers(); this.mults = defaultMultipliers();

View File

@@ -78,21 +78,21 @@ export function prestigeAugmentation(this: PlayerObject): void {
this.numPeopleKilled = 0; this.numPeopleKilled = 0;
//Reset stats //Reset stats
this.hacking = 1; this.skills.hacking = 1;
this.strength = 1; this.skills.strength = 1;
this.defense = 1; this.skills.defense = 1;
this.dexterity = 1; this.skills.dexterity = 1;
this.agility = 1; this.skills.agility = 1;
this.charisma = 1; this.skills.charisma = 1;
this.hacking_exp = 0; this.exp.hacking = 0;
this.strength_exp = 0; this.exp.strength = 0;
this.defense_exp = 0; this.exp.defense = 0;
this.dexterity_exp = 0; this.exp.dexterity = 0;
this.agility_exp = 0; this.exp.agility = 0;
this.charisma_exp = 0; this.exp.charisma = 0;
this.money = 1000 + CONSTANTS.Donations; this.money = 1000 + CONSTANTS.Donations;
@@ -136,7 +136,7 @@ export function prestigeAugmentation(this: PlayerObject): void {
// Reapply augs, re-calculate skills and reset HP // Reapply augs, re-calculate skills and reset HP
this.reapplyAllAugmentations(true); this.reapplyAllAugmentations(true);
this.hp = this.max_hp; this.hp.current = this.hp.max;
this.finishWork(true); this.finishWork(true);
} }
@@ -197,46 +197,46 @@ export function calculateSkillProgress(this: IPlayer, exp: number, mult = 1): IS
} }
export function updateSkillLevels(this: IPlayer): void { export function updateSkillLevels(this: IPlayer): void {
this.hacking = Math.max( this.skills.hacking = Math.max(
1, 1,
Math.floor(this.calculateSkill(this.hacking_exp, this.mults.hacking * BitNodeMultipliers.HackingLevelMultiplier)), Math.floor(this.calculateSkill(this.exp.hacking, this.mults.hacking * BitNodeMultipliers.HackingLevelMultiplier)),
); );
this.strength = Math.max( this.skills.strength = Math.max(
1, 1,
Math.floor( Math.floor(
this.calculateSkill(this.strength_exp, this.mults.strength * BitNodeMultipliers.StrengthLevelMultiplier), this.calculateSkill(this.exp.strength, this.mults.strength * BitNodeMultipliers.StrengthLevelMultiplier),
), ),
); );
this.defense = Math.max( this.skills.defense = Math.max(
1, 1,
Math.floor(this.calculateSkill(this.defense_exp, this.mults.defense * BitNodeMultipliers.DefenseLevelMultiplier)), Math.floor(this.calculateSkill(this.exp.defense, this.mults.defense * BitNodeMultipliers.DefenseLevelMultiplier)),
); );
this.dexterity = Math.max( this.skills.dexterity = Math.max(
1, 1,
Math.floor( Math.floor(
this.calculateSkill(this.dexterity_exp, this.mults.dexterity * BitNodeMultipliers.DexterityLevelMultiplier), this.calculateSkill(this.exp.dexterity, this.mults.dexterity * BitNodeMultipliers.DexterityLevelMultiplier),
), ),
); );
this.agility = Math.max( this.skills.agility = Math.max(
1, 1,
Math.floor(this.calculateSkill(this.agility_exp, this.mults.agility * BitNodeMultipliers.AgilityLevelMultiplier)), Math.floor(this.calculateSkill(this.exp.agility, this.mults.agility * BitNodeMultipliers.AgilityLevelMultiplier)),
); );
this.charisma = Math.max( this.skills.charisma = Math.max(
1, 1,
Math.floor( Math.floor(
this.calculateSkill(this.charisma_exp, this.mults.charisma * BitNodeMultipliers.CharismaLevelMultiplier), this.calculateSkill(this.exp.charisma, this.mults.charisma * BitNodeMultipliers.CharismaLevelMultiplier),
), ),
); );
if (this.intelligence > 0) { if (this.skills.intelligence > 0) {
this.intelligence = Math.floor(this.calculateSkill(this.intelligence_exp)); this.skills.intelligence = Math.floor(this.calculateSkill(this.exp.intelligence));
} else { } else {
this.intelligence = 0; this.skills.intelligence = 0;
} }
const ratio = this.hp / this.max_hp; const ratio = this.hp.current / this.hp.max;
this.max_hp = Math.floor(10 + this.defense / 10); this.hp.max = Math.floor(10 + this.skills.defense / 10);
this.hp = Math.round(this.max_hp * ratio); this.hp.current = Math.round(this.hp.max * ratio);
} }
export function resetMultipliers(this: IPlayer): void { export function resetMultipliers(this: IPlayer): void {
@@ -311,12 +311,15 @@ export function gainHackingExp(this: IPerson, exp: number): void {
console.error("ERR: NaN passed into Player.gainHackingExp()"); console.error("ERR: NaN passed into Player.gainHackingExp()");
return; return;
} }
this.hacking_exp += exp; this.exp.hacking += exp;
if (this.hacking_exp < 0) { if (this.exp.hacking < 0) {
this.hacking_exp = 0; this.exp.hacking = 0;
} }
this.hacking = calculateSkillF(this.hacking_exp, this.mults.hacking * BitNodeMultipliers.HackingLevelMultiplier); this.skills.hacking = calculateSkillF(
this.exp.hacking,
this.mults.hacking * BitNodeMultipliers.HackingLevelMultiplier,
);
} }
export function gainStrengthExp(this: IPerson, exp: number): void { export function gainStrengthExp(this: IPerson, exp: number): void {
@@ -324,12 +327,15 @@ export function gainStrengthExp(this: IPerson, exp: number): void {
console.error("ERR: NaN passed into Player.gainStrengthExp()"); console.error("ERR: NaN passed into Player.gainStrengthExp()");
return; return;
} }
this.strength_exp += exp; this.exp.strength += exp;
if (this.strength_exp < 0) { if (this.exp.strength < 0) {
this.strength_exp = 0; this.exp.strength = 0;
} }
this.strength = calculateSkillF(this.strength_exp, this.mults.strength * BitNodeMultipliers.StrengthLevelMultiplier); this.skills.strength = calculateSkillF(
this.exp.strength,
this.mults.strength * BitNodeMultipliers.StrengthLevelMultiplier,
);
} }
export function gainDefenseExp(this: IPerson, exp: number): void { export function gainDefenseExp(this: IPerson, exp: number): void {
@@ -337,15 +343,18 @@ export function gainDefenseExp(this: IPerson, exp: number): void {
console.error("ERR: NaN passed into player.gainDefenseExp()"); console.error("ERR: NaN passed into player.gainDefenseExp()");
return; return;
} }
this.defense_exp += exp; this.exp.defense += exp;
if (this.defense_exp < 0) { if (this.exp.defense < 0) {
this.defense_exp = 0; this.exp.defense = 0;
} }
this.defense = calculateSkillF(this.defense_exp, this.mults.defense * BitNodeMultipliers.DefenseLevelMultiplier); this.skills.defense = calculateSkillF(
const ratio = this.hp / this.max_hp; this.exp.defense,
this.max_hp = Math.floor(10 + this.defense / 10); this.mults.defense * BitNodeMultipliers.DefenseLevelMultiplier,
this.hp = Math.round(this.max_hp * ratio); );
const ratio = this.hp.current / this.hp.max;
this.hp.max = Math.floor(10 + this.skills.defense / 10);
this.hp.current = Math.round(this.hp.max * ratio);
} }
export function gainDexterityExp(this: IPerson, exp: number): void { export function gainDexterityExp(this: IPerson, exp: number): void {
@@ -353,13 +362,13 @@ export function gainDexterityExp(this: IPerson, exp: number): void {
console.error("ERR: NaN passed into Player.gainDexterityExp()"); console.error("ERR: NaN passed into Player.gainDexterityExp()");
return; return;
} }
this.dexterity_exp += exp; this.exp.dexterity += exp;
if (this.dexterity_exp < 0) { if (this.exp.dexterity < 0) {
this.dexterity_exp = 0; this.exp.dexterity = 0;
} }
this.dexterity = calculateSkillF( this.skills.dexterity = calculateSkillF(
this.dexterity_exp, this.exp.dexterity,
this.mults.dexterity * BitNodeMultipliers.DexterityLevelMultiplier, this.mults.dexterity * BitNodeMultipliers.DexterityLevelMultiplier,
); );
} }
@@ -369,12 +378,15 @@ export function gainAgilityExp(this: IPerson, exp: number): void {
console.error("ERR: NaN passed into Player.gainAgilityExp()"); console.error("ERR: NaN passed into Player.gainAgilityExp()");
return; return;
} }
this.agility_exp += exp; this.exp.agility += exp;
if (this.agility_exp < 0) { if (this.exp.agility < 0) {
this.agility_exp = 0; this.exp.agility = 0;
} }
this.agility = calculateSkillF(this.agility_exp, this.mults.agility * BitNodeMultipliers.AgilityLevelMultiplier); this.skills.agility = calculateSkillF(
this.exp.agility,
this.mults.agility * BitNodeMultipliers.AgilityLevelMultiplier,
);
} }
export function gainCharismaExp(this: IPerson, exp: number): void { export function gainCharismaExp(this: IPerson, exp: number): void {
@@ -382,12 +394,15 @@ export function gainCharismaExp(this: IPerson, exp: number): void {
console.error("ERR: NaN passed into Player.gainCharismaExp()"); console.error("ERR: NaN passed into Player.gainCharismaExp()");
return; return;
} }
this.charisma_exp += exp; this.exp.charisma += exp;
if (this.charisma_exp < 0) { if (this.exp.charisma < 0) {
this.charisma_exp = 0; this.exp.charisma = 0;
} }
this.charisma = calculateSkillF(this.charisma_exp, this.mults.charisma * BitNodeMultipliers.CharismaLevelMultiplier); this.skills.charisma = calculateSkillF(
this.exp.charisma,
this.mults.charisma * BitNodeMultipliers.CharismaLevelMultiplier,
);
} }
export function gainIntelligenceExp(this: IPerson, exp: number): void { export function gainIntelligenceExp(this: IPerson, exp: number): void {
@@ -395,9 +410,9 @@ export function gainIntelligenceExp(this: IPerson, exp: number): void {
console.error("ERROR: NaN passed into Player.gainIntelligenceExp()"); console.error("ERROR: NaN passed into Player.gainIntelligenceExp()");
return; return;
} }
if (Player.sourceFileLvl(5) > 0 || this.intelligence > 0) { if (Player.sourceFileLvl(5) > 0 || this.skills.intelligence > 0) {
this.intelligence_exp += exp; this.exp.intelligence += exp;
this.intelligence = Math.floor(this.calculateSkill(this.intelligence_exp, 1)); this.skills.intelligence = Math.floor(this.calculateSkill(this.exp.intelligence, 1));
} }
} }
@@ -415,25 +430,25 @@ export function gainStats(this: IPerson, retValue: ITaskTracker): void {
export function queryStatFromString(this: IPlayer, str: string): number { export function queryStatFromString(this: IPlayer, str: string): number {
const tempStr = str.toLowerCase(); const tempStr = str.toLowerCase();
if (tempStr.includes("hack")) { if (tempStr.includes("hack")) {
return this.hacking; return this.skills.hacking;
} }
if (tempStr.includes("str")) { if (tempStr.includes("str")) {
return this.strength; return this.skills.strength;
} }
if (tempStr.includes("def")) { if (tempStr.includes("def")) {
return this.defense; return this.skills.defense;
} }
if (tempStr.includes("dex")) { if (tempStr.includes("dex")) {
return this.dexterity; return this.skills.dexterity;
} }
if (tempStr.includes("agi")) { if (tempStr.includes("agi")) {
return this.agility; return this.skills.agility;
} }
if (tempStr.includes("cha")) { if (tempStr.includes("cha")) {
return this.charisma; return this.skills.charisma;
} }
if (tempStr.includes("int")) { if (tempStr.includes("int")) {
return this.intelligence; return this.skills.intelligence;
} }
return 0; return 0;
} }
@@ -453,8 +468,8 @@ export function takeDamage(this: IPlayer, amt: number): boolean {
return false; return false;
} }
this.hp -= amt; this.hp.current -= amt;
if (this.hp <= 0) { if (this.hp.current <= 0) {
this.hospitalize(); this.hospitalize();
return true; return true;
} else { } else {
@@ -467,9 +482,9 @@ export function regenerateHp(this: IPerson, amt: number): void {
console.warn(`Player.regenerateHp() called without a numeric argument: ${amt}`); console.warn(`Player.regenerateHp() called without a numeric argument: ${amt}`);
return; return;
} }
this.hp += amt; this.hp.current += amt;
if (this.hp > this.max_hp) { if (this.hp.current > this.hp.max) {
this.hp = this.max_hp; this.hp.current = this.hp.max;
} }
} }
@@ -478,7 +493,7 @@ export function hospitalize(this: IPlayer): number {
SnackbarEvents.emit(`You've been Hospitalized for ${numeralWrapper.formatMoney(cost)}`, ToastVariant.WARNING, 2000); SnackbarEvents.emit(`You've been Hospitalized for ${numeralWrapper.formatMoney(cost)}`, ToastVariant.WARNING, 2000);
this.loseMoney(cost, "hospitalization"); this.loseMoney(cost, "hospitalization");
this.hp = this.max_hp; this.hp.current = this.hp.max;
return cost; return cost;
} }
@@ -754,12 +769,12 @@ export function isQualified(this: IPlayer, company: Company, position: CompanyPo
const reqCharisma = position.requiredCharisma > 0 ? position.requiredCharisma + offset : 0; const reqCharisma = position.requiredCharisma > 0 ? position.requiredCharisma + offset : 0;
return ( return (
this.hacking >= reqHacking && this.skills.hacking >= reqHacking &&
this.strength >= reqStrength && this.skills.strength >= reqStrength &&
this.defense >= reqDefense && this.skills.defense >= reqDefense &&
this.dexterity >= reqDexterity && this.skills.dexterity >= reqDexterity &&
this.agility >= reqAgility && this.skills.agility >= reqAgility &&
this.charisma >= reqCharisma && this.skills.charisma >= reqCharisma &&
company.playerReputation >= position.requiredReputation company.playerReputation >= position.requiredReputation
); );
} }
@@ -851,11 +866,11 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
!illuminatiFac.alreadyInvited && !illuminatiFac.alreadyInvited &&
numAugmentations >= 30 && numAugmentations >= 30 &&
this.money >= 150000000000 && this.money >= 150000000000 &&
this.hacking >= 1500 && this.skills.hacking >= 1500 &&
this.strength >= 1200 && this.skills.strength >= 1200 &&
this.defense >= 1200 && this.skills.defense >= 1200 &&
this.dexterity >= 1200 && this.skills.dexterity >= 1200 &&
this.agility >= 1200 this.skills.agility >= 1200
) { ) {
invitedFactions.push(illuminatiFac); invitedFactions.push(illuminatiFac);
} }
@@ -868,8 +883,11 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
!daedalusFac.alreadyInvited && !daedalusFac.alreadyInvited &&
numAugmentations >= BitNodeMultipliers.DaedalusAugsRequirement && numAugmentations >= BitNodeMultipliers.DaedalusAugsRequirement &&
this.money >= 100000000000 && this.money >= 100000000000 &&
(this.hacking >= 2500 || (this.skills.hacking >= 2500 ||
(this.strength >= 1500 && this.defense >= 1500 && this.dexterity >= 1500 && this.agility >= 1500)) (this.skills.strength >= 1500 &&
this.skills.defense >= 1500 &&
this.skills.dexterity >= 1500 &&
this.skills.agility >= 1500))
) { ) {
invitedFactions.push(daedalusFac); invitedFactions.push(daedalusFac);
} }
@@ -882,11 +900,11 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
!covenantFac.alreadyInvited && !covenantFac.alreadyInvited &&
numAugmentations >= 20 && numAugmentations >= 20 &&
this.money >= 75000000000 && this.money >= 75000000000 &&
this.hacking >= 850 && this.skills.hacking >= 850 &&
this.strength >= 850 && this.skills.strength >= 850 &&
this.defense >= 850 && this.skills.defense >= 850 &&
this.dexterity >= 850 && this.skills.dexterity >= 850 &&
this.agility >= 850 this.skills.agility >= 850
) { ) {
invitedFactions.push(covenantFac); invitedFactions.push(covenantFac);
} }
@@ -1131,11 +1149,11 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
!speakersforthedeadFac.isBanned && !speakersforthedeadFac.isBanned &&
!speakersforthedeadFac.isMember && !speakersforthedeadFac.isMember &&
!speakersforthedeadFac.alreadyInvited && !speakersforthedeadFac.alreadyInvited &&
this.hacking >= 100 && this.skills.hacking >= 100 &&
this.strength >= 300 && this.skills.strength >= 300 &&
this.defense >= 300 && this.skills.defense >= 300 &&
this.dexterity >= 300 && this.skills.dexterity >= 300 &&
this.agility >= 300 && this.skills.agility >= 300 &&
this.numPeopleKilled >= 30 && this.numPeopleKilled >= 30 &&
this.karma <= -45 && this.karma <= -45 &&
!allCompanies.includes(LocationName.Sector12CIA) && !allCompanies.includes(LocationName.Sector12CIA) &&
@@ -1150,11 +1168,11 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
!thedarkarmyFac.isBanned && !thedarkarmyFac.isBanned &&
!thedarkarmyFac.isMember && !thedarkarmyFac.isMember &&
!thedarkarmyFac.alreadyInvited && !thedarkarmyFac.alreadyInvited &&
this.hacking >= 300 && this.skills.hacking >= 300 &&
this.strength >= 300 && this.skills.strength >= 300 &&
this.defense >= 300 && this.skills.defense >= 300 &&
this.dexterity >= 300 && this.skills.dexterity >= 300 &&
this.agility >= 300 && this.skills.agility >= 300 &&
this.city == CityName.Chongqing && this.city == CityName.Chongqing &&
this.numPeopleKilled >= 5 && this.numPeopleKilled >= 5 &&
this.karma <= -45 && this.karma <= -45 &&
@@ -1170,11 +1188,11 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
!thesyndicateFac.isBanned && !thesyndicateFac.isBanned &&
!thesyndicateFac.isMember && !thesyndicateFac.isMember &&
!thesyndicateFac.alreadyInvited && !thesyndicateFac.alreadyInvited &&
this.hacking >= 200 && this.skills.hacking >= 200 &&
this.strength >= 200 && this.skills.strength >= 200 &&
this.defense >= 200 && this.skills.defense >= 200 &&
this.dexterity >= 200 && this.skills.dexterity >= 200 &&
this.agility >= 200 && this.skills.agility >= 200 &&
(this.city == CityName.Aevum || this.city == CityName.Sector12) && (this.city == CityName.Aevum || this.city == CityName.Sector12) &&
this.money >= 10000000 && this.money >= 10000000 &&
this.karma <= -90 && this.karma <= -90 &&
@@ -1206,10 +1224,10 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
!tetradsFac.isMember && !tetradsFac.isMember &&
!tetradsFac.alreadyInvited && !tetradsFac.alreadyInvited &&
(this.city == CityName.Chongqing || this.city == CityName.NewTokyo || this.city == CityName.Ishima) && (this.city == CityName.Chongqing || this.city == CityName.NewTokyo || this.city == CityName.Ishima) &&
this.strength >= 75 && this.skills.strength >= 75 &&
this.defense >= 75 && this.skills.defense >= 75 &&
this.dexterity >= 75 && this.skills.dexterity >= 75 &&
this.agility >= 75 && this.skills.agility >= 75 &&
this.karma <= -18 this.karma <= -18
) { ) {
invitedFactions.push(tetradsFac); invitedFactions.push(tetradsFac);
@@ -1221,10 +1239,10 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
!slumsnakesFac.isBanned && !slumsnakesFac.isBanned &&
!slumsnakesFac.isMember && !slumsnakesFac.isMember &&
!slumsnakesFac.alreadyInvited && !slumsnakesFac.alreadyInvited &&
this.strength >= 30 && this.skills.strength >= 30 &&
this.defense >= 30 && this.skills.defense >= 30 &&
this.dexterity >= 30 && this.skills.dexterity >= 30 &&
this.agility >= 30 && this.skills.agility >= 30 &&
this.karma <= -9 && this.karma <= -9 &&
this.money >= 1000000 this.money >= 1000000
) { ) {
@@ -1255,7 +1273,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
!netburnersFac.isBanned && !netburnersFac.isBanned &&
!netburnersFac.isMember && !netburnersFac.isMember &&
!netburnersFac.alreadyInvited && !netburnersFac.alreadyInvited &&
this.hacking >= 80 && this.skills.hacking >= 80 &&
totalHacknetRam >= 8 && totalHacknetRam >= 8 &&
totalHacknetCores >= 4 && totalHacknetCores >= 4 &&
totalHacknetLevels >= 100 totalHacknetLevels >= 100
@@ -1270,7 +1288,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
!tiandihuiFac.isMember && !tiandihuiFac.isMember &&
!tiandihuiFac.alreadyInvited && !tiandihuiFac.alreadyInvited &&
this.money >= 1000000 && this.money >= 1000000 &&
this.hacking >= 50 && this.skills.hacking >= 50 &&
(this.city == CityName.Chongqing || this.city == CityName.NewTokyo || this.city == CityName.Ishima) (this.city == CityName.Chongqing || this.city == CityName.NewTokyo || this.city == CityName.Ishima)
) { ) {
invitedFactions.push(tiandihuiFac); invitedFactions.push(tiandihuiFac);
@@ -1418,7 +1436,7 @@ export function giveAchievement(this: IPlayer, achievementId: string): void {
} }
export function getIntelligenceBonus(this: IPlayer, weight: number): number { export function getIntelligenceBonus(this: IPlayer, weight: number): number {
return calculateIntelligenceBonus(this.intelligence, weight); return calculateIntelligenceBonus(this.skills.intelligence, weight);
} }
export function getCasinoWinnings(this: IPlayer): number { export function getCasinoWinnings(this: IPlayer): number {

View File

@@ -0,0 +1,9 @@
export interface Skills {
hacking: number;
strength: number;
defense: number;
dexterity: number;
agility: number;
charisma: number;
intelligence: number;
}

View File

@@ -289,27 +289,27 @@ export class Sleeve extends Person {
// Also the player does not earn anything // Also the player does not earn anything
if (fromOtherSleeve) { if (fromOtherSleeve) {
if (exp.hack > 0) { if (exp.hack > 0) {
this.hacking_exp += exp.hack; this.exp.hacking += exp.hack;
} }
if (exp.str > 0) { if (exp.str > 0) {
this.strength_exp += exp.str; this.exp.strength += exp.str;
} }
if (exp.def > 0) { if (exp.def > 0) {
this.defense_exp += exp.def; this.exp.defense += exp.def;
} }
if (exp.dex > 0) { if (exp.dex > 0) {
this.dexterity_exp += exp.dex; this.exp.dexterity += exp.dex;
} }
if (exp.agi > 0) { if (exp.agi > 0) {
this.agility_exp += exp.agi; this.exp.agility += exp.agi;
} }
if (exp.cha > 0) { if (exp.cha > 0) {
this.charisma_exp += exp.cha; this.exp.charisma += exp.cha;
} }
return createTaskTracker(); return createTaskTracker();
@@ -469,12 +469,12 @@ export class Sleeve extends Person {
} }
const jobPerformance: number = companyPosition.calculateJobPerformance( const jobPerformance: number = companyPosition.calculateJobPerformance(
this.hacking, this.skills.hacking,
this.strength, this.skills.strength,
this.defense, this.skills.defense,
this.dexterity, this.skills.dexterity,
this.agility, this.skills.agility,
this.charisma, this.skills.charisma,
); );
const favorMult = 1 + company.favor / 100; const favorMult = 1 + company.favor / 100;
@@ -485,12 +485,12 @@ export class Sleeve extends Person {
} }
installAugmentation(aug: Augmentation): void { installAugmentation(aug: Augmentation): void {
this.hacking_exp = 0; this.exp.hacking = 0;
this.strength_exp = 0; this.exp.strength = 0;
this.defense_exp = 0; this.exp.defense = 0;
this.dexterity_exp = 0; this.exp.dexterity = 0;
this.agility_exp = 0; this.exp.agility = 0;
this.charisma_exp = 0; this.exp.charisma = 0;
this.applyAugmentation(aug); this.applyAugmentation(aug);
this.augmentations.push({ name: aug.name, level: 1 }); this.augmentations.push({ name: aug.name, level: 1 });
this.updateStatLevels(); this.updateStatLevels();
@@ -509,12 +509,12 @@ export class Sleeve extends Person {
*/ */
prestige(p: IPlayer): void { prestige(p: IPlayer): void {
// Reset exp // Reset exp
this.hacking_exp = 0; this.exp.hacking = 0;
this.strength_exp = 0; this.exp.strength = 0;
this.defense_exp = 0; this.exp.defense = 0;
this.dexterity_exp = 0; this.exp.dexterity = 0;
this.agility_exp = 0; this.exp.agility = 0;
this.charisma_exp = 0; this.exp.charisma = 0;
// Reset task-related stuff // Reset task-related stuff
this.resetTaskStatus(p); this.resetTaskStatus(p);
@@ -1232,10 +1232,10 @@ export class Sleeve extends Person {
return false; return false;
} }
this.hp -= amt; this.hp.current -= amt;
if (this.hp <= 0) { if (this.hp.current <= 0) {
this.shock = Math.min(1, this.shock - 0.5); this.shock = Math.min(1, this.shock - 0.5);
this.hp = this.max_hp; this.hp.current = this.hp.max;
return true; return true;
} else { } else {
return false; return false;

View File

@@ -20,33 +20,33 @@ export function MoreStatsModal(props: IProps): React.ReactElement {
rows={[ rows={[
[ [
<>Hacking:&nbsp;</>, <>Hacking:&nbsp;</>,
props.sleeve.hacking, props.sleeve.skills.hacking,
<>&nbsp;({numeralWrapper.formatExp(props.sleeve.hacking_exp)} exp)</>, <>&nbsp;({numeralWrapper.formatExp(props.sleeve.exp.hacking)} exp)</>,
], ],
[ [
<>Strength:&nbsp;</>, <>Strength:&nbsp;</>,
props.sleeve.strength, props.sleeve.skills.strength,
<>&nbsp;({numeralWrapper.formatExp(props.sleeve.strength_exp)} exp)</>, <>&nbsp;({numeralWrapper.formatExp(props.sleeve.exp.strength)} exp)</>,
], ],
[ [
<>Defense:&nbsp;</>, <>Defense:&nbsp;</>,
props.sleeve.defense, props.sleeve.skills.defense,
<>&nbsp;({numeralWrapper.formatExp(props.sleeve.defense_exp)} exp)</>, <>&nbsp;({numeralWrapper.formatExp(props.sleeve.exp.defense)} exp)</>,
], ],
[ [
<>Dexterity:&nbsp;</>, <>Dexterity:&nbsp;</>,
props.sleeve.dexterity, props.sleeve.skills.dexterity,
<>&nbsp;({numeralWrapper.formatExp(props.sleeve.dexterity_exp)} exp)</>, <>&nbsp;({numeralWrapper.formatExp(props.sleeve.exp.dexterity)} exp)</>,
], ],
[ [
<>Agility:&nbsp;</>, <>Agility:&nbsp;</>,
props.sleeve.agility, props.sleeve.skills.agility,
<>&nbsp;({numeralWrapper.formatExp(props.sleeve.agility_exp)} exp)</>, <>&nbsp;({numeralWrapper.formatExp(props.sleeve.exp.agility)} exp)</>,
], ],
[ [
<>Charisma:&nbsp;</>, <>Charisma:&nbsp;</>,
props.sleeve.charisma, props.sleeve.skills.charisma,
<>&nbsp;({numeralWrapper.formatExp(props.sleeve.charisma_exp)} exp)</>, <>&nbsp;({numeralWrapper.formatExp(props.sleeve.exp.charisma)} exp)</>,
], ],
]} ]}
title="Stats:" title="Stats:"

View File

@@ -29,38 +29,40 @@ export function StatsElement(props: IProps): React.ReactElement {
name="HP" name="HP"
color={Settings.theme.hp} color={Settings.theme.hp}
data={{ data={{
content: `${numeralWrapper.formatHp(props.sleeve.hp)} / ${numeralWrapper.formatHp(props.sleeve.max_hp)}`, content: `${numeralWrapper.formatHp(props.sleeve.hp.current)} / ${numeralWrapper.formatHp(
props.sleeve.hp.max,
)}`,
}} }}
/> />
<StatsRow <StatsRow
name="Hacking" name="Hacking"
color={Settings.theme.hack} color={Settings.theme.hack}
data={{ level: props.sleeve.hacking, exp: props.sleeve.hacking_exp }} data={{ level: props.sleeve.skills.hacking, exp: props.sleeve.exp.hacking }}
/> />
<StatsRow <StatsRow
name="Strength" name="Strength"
color={Settings.theme.combat} color={Settings.theme.combat}
data={{ level: props.sleeve.strength, exp: props.sleeve.strength_exp }} data={{ level: props.sleeve.skills.strength, exp: props.sleeve.exp.strength }}
/> />
<StatsRow <StatsRow
name="Defense" name="Defense"
color={Settings.theme.combat} color={Settings.theme.combat}
data={{ level: props.sleeve.defense, exp: props.sleeve.defense_exp }} data={{ level: props.sleeve.skills.defense, exp: props.sleeve.exp.defense }}
/> />
<StatsRow <StatsRow
name="Dexterity" name="Dexterity"
color={Settings.theme.combat} color={Settings.theme.combat}
data={{ level: props.sleeve.dexterity, exp: props.sleeve.dexterity_exp }} data={{ level: props.sleeve.skills.dexterity, exp: props.sleeve.exp.dexterity }}
/> />
<StatsRow <StatsRow
name="Agility" name="Agility"
color={Settings.theme.combat} color={Settings.theme.combat}
data={{ level: props.sleeve.agility, exp: props.sleeve.agility_exp }} data={{ level: props.sleeve.skills.agility, exp: props.sleeve.exp.agility }}
/> />
<StatsRow <StatsRow
name="Charisma" name="Charisma"
color={Settings.theme.cha} color={Settings.theme.cha}
data={{ level: props.sleeve.charisma, exp: props.sleeve.charisma_exp }} data={{ level: props.sleeve.skills.charisma, exp: props.sleeve.exp.charisma }}
/> />
<TableRow> <TableRow>
<TableCell classes={{ root: classes.cellNone }}> <TableCell classes={{ root: classes.cellNone }}>

View File

@@ -14,7 +14,7 @@ function mult(f: Faction): number {
export function getHackingWorkRepGain(p: IPlayer, f: Faction): number { export function getHackingWorkRepGain(p: IPlayer, f: Faction): number {
return ( return (
((p.hacking + p.intelligence / 3) / CONSTANTS.MaxSkillLevel) * ((p.skills.hacking + p.skills.intelligence / 3) / CONSTANTS.MaxSkillLevel) *
p.mults.faction_rep * p.mults.faction_rep *
p.getIntelligenceBonus(1) * p.getIntelligenceBonus(1) *
mult(f) * mult(f) *
@@ -24,7 +24,12 @@ export function getHackingWorkRepGain(p: IPlayer, f: Faction): number {
export function getFactionSecurityWorkRepGain(p: IPlayer, f: Faction): number { export function getFactionSecurityWorkRepGain(p: IPlayer, f: Faction): number {
const t = const t =
(0.9 * (p.strength + p.defense + p.dexterity + p.agility + (p.hacking + p.intelligence) * CalculateShareMult())) / (0.9 *
(p.skills.strength +
p.skills.defense +
p.skills.dexterity +
p.skills.agility +
(p.skills.hacking + p.skills.intelligence) * CalculateShareMult())) /
CONSTANTS.MaxSkillLevel / CONSTANTS.MaxSkillLevel /
4.5; 4.5;
return t * p.mults.faction_rep * mult(f) * p.getIntelligenceBonus(1); return t * p.mults.faction_rep * mult(f) * p.getIntelligenceBonus(1);
@@ -33,12 +38,12 @@ export function getFactionSecurityWorkRepGain(p: IPlayer, f: Faction): number {
export function getFactionFieldWorkRepGain(p: IPlayer, f: Faction): number { export function getFactionFieldWorkRepGain(p: IPlayer, f: Faction): number {
const t = const t =
(0.9 * (0.9 *
(p.strength + (p.skills.strength +
p.defense + p.skills.defense +
p.dexterity + p.skills.dexterity +
p.agility + p.skills.agility +
p.charisma + p.skills.charisma +
(p.hacking + p.intelligence) * CalculateShareMult())) / (p.skills.hacking + p.skills.intelligence) * CalculateShareMult())) /
CONSTANTS.MaxSkillLevel / CONSTANTS.MaxSkillLevel /
5.5; 5.5;
return t * p.mults.faction_rep * mult(f) * p.getIntelligenceBonus(1); return t * p.mults.faction_rep * mult(f) * p.getIntelligenceBonus(1);

View File

@@ -15,13 +15,13 @@ import { FactionNames } from "../../Faction/data/FactionNames";
function requireHackingLevel(lvl: number) { function requireHackingLevel(lvl: number) {
return function (p: IPlayer) { return function (p: IPlayer) {
return p.hacking + p.intelligence / 2 >= lvl; return p.skills.hacking + p.skills.intelligence / 2 >= lvl;
}; };
} }
function bitFlumeRequirements() { function bitFlumeRequirements() {
return function (p: IPlayer) { return function (p: IPlayer) {
return p.sourceFiles.length > 0 && p.hacking >= 1; return p.sourceFiles.length > 0 && p.skills.hacking >= 1;
}; };
} }
@@ -308,11 +308,12 @@ export const programsMetadata: IProgramCreationParams[] = [
create: null, create: null,
run: (router: IRouter, terminal: ITerminal, player: IPlayer): void => { run: (router: IRouter, terminal: ITerminal, player: IPlayer): void => {
const numAugReq = BitNodeMultipliers.DaedalusAugsRequirement; const numAugReq = BitNodeMultipliers.DaedalusAugsRequirement;
const fulfilled = player.augmentations.length >= numAugReq && player.money > 1e11 && player.hacking >= 2500; const fulfilled =
player.augmentations.length >= numAugReq && player.money > 1e11 && player.skills.hacking >= 2500;
if (!fulfilled) { if (!fulfilled) {
terminal.print(`Augmentations: ${player.augmentations.length} / ${numAugReq}`); terminal.print(`Augmentations: ${player.augmentations.length} / ${numAugReq}`);
terminal.print(`Money: ${numeralWrapper.formatMoney(player.money)} / $100b`); terminal.print(`Money: ${numeralWrapper.formatMoney(player.money)} / $100b`);
terminal.print(`Hacking skill: ${player.hacking} / 2500`); terminal.print(`Hacking skill: ${player.skills.hacking} / 2500`);
return; return;
} }

View File

@@ -48,7 +48,7 @@ export function ProgramsRoot(): React.ReactElement {
}, []); }, []);
const getHackingLevelRemaining = (lvl: number): number => { const getHackingLevelRemaining = (lvl: number): number => {
return Math.ceil(Math.max(lvl - (player.hacking + player.intelligence / 2), 0)); return Math.ceil(Math.max(lvl - (player.skills.hacking + player.skills.intelligence / 2), 0));
}; };
const getProgCompletion = (name: string): number => { const getProgCompletion = (name: string): number => {

View File

@@ -47,9 +47,9 @@ function giveSourceFile(bitNodeNumber: number): void {
} else { } else {
const playerSrcFile = new PlayerOwnedSourceFile(bitNodeNumber, 1); const playerSrcFile = new PlayerOwnedSourceFile(bitNodeNumber, 1);
Player.sourceFiles.push(playerSrcFile); Player.sourceFiles.push(playerSrcFile);
if (bitNodeNumber === 5 && Player.intelligence === 0) { if (bitNodeNumber === 5 && Player.skills.intelligence === 0) {
// Artificial Intelligence // Artificial Intelligence
Player.intelligence = 1; Player.skills.intelligence = 1;
} }
dialogBoxCreate( dialogBoxCreate(
<> <>
@@ -69,11 +69,11 @@ export function enterBitNode(router: IRouter, flume: boolean, destroyedBitNode:
if (!flume) { if (!flume) {
giveSourceFile(destroyedBitNode); giveSourceFile(destroyedBitNode);
} else if (Player.sourceFileLvl(5) === 0 && newBitNode !== 5) { } else if (Player.sourceFileLvl(5) === 0 && newBitNode !== 5) {
Player.intelligence = 0; Player.skills.intelligence = 0;
Player.intelligence_exp = 0; Player.exp.intelligence = 0;
} }
if (newBitNode === 5 && Player.intelligence === 0) { if (newBitNode === 5 && Player.skills.intelligence === 0) {
Player.intelligence = 1; Player.skills.intelligence = 1;
} }
// Set new Bit Node // Set new Bit Node
Player.bitNodeN = newBitNode; Player.bitNodeN = newBitNode;

View File

@@ -218,7 +218,7 @@ class BitburnerSaveObject {
totalPlaytime: importedPlayer.totalPlaytime, totalPlaytime: importedPlayer.totalPlaytime,
money: importedPlayer.money, money: importedPlayer.money,
hacking: importedPlayer.hacking, hacking: importedPlayer.skills.hacking,
augmentations: importedPlayer.augmentations?.reduce<number>((total, current) => (total += current.level), 0) ?? 0, augmentations: importedPlayer.augmentations?.reduce<number>((total, current) => (total += current.level), 0) ?? 0,
factions: importedPlayer.factions?.length ?? 0, factions: importedPlayer.factions?.length ?? 0,
@@ -462,6 +462,22 @@ function evaluateVersionCompatibility(ver: string | number): void {
if (create) Player.getHomeComputer().pushProgram(create); if (create) Player.getHomeComputer().pushProgram(create);
const graft = anyPlayer["graftAugmentationName"]; const graft = anyPlayer["graftAugmentationName"];
if (graft) Player.augmentations.push({ name: graft, level: 1 }); if (graft) Player.augmentations.push({ name: graft, level: 1 });
}
if (ver < 22) {
// reset HP correctly to avoid crash
anyPlayer.hp = { current: 1, max: 1 };
for (const sleeve of anyPlayer.sleeves) {
sleeve.hp = { current: 1, max: 1 };
}
// transfer over old exp to new struct
anyPlayer.exp.hacking = anyPlayer.hacking_exp;
anyPlayer.exp.strength = anyPlayer.strength_exp;
anyPlayer.exp.defense = anyPlayer.defense_exp;
anyPlayer.exp.dexterity = anyPlayer.dexterity_exp;
anyPlayer.exp.agility = anyPlayer.agility_exp;
anyPlayer.exp.charisma = anyPlayer.charisma_exp;
anyPlayer.exp.intelligence = anyPlayer.intelligence_exp;
v2APIBreak(); v2APIBreak();
} }
} }

View File

@@ -1,3 +1,24 @@
/**
* @public
*/
export interface HP {
current: number;
max: number;
}
/**
* @public
*/
export interface Skills {
hacking: number;
strength: number;
defense: number;
dexterity: number;
agility: number;
charisma: number;
intelligence: number;
}
/** /**
* @public * @public
*/ */
@@ -31,21 +52,9 @@ type FilenameOrPID = number | string;
* @public * @public
*/ */
interface Player { interface Player {
hacking: number; hp: HP;
hp: number; skills: Skills;
max_hp: number; exp: Skills;
strength: number;
defense: number;
dexterity: number;
agility: number;
charisma: number;
intelligence: number;
hacking_exp: number;
strength_exp: number;
defense_exp: number;
dexterity_exp: number;
agility_exp: number;
charisma_exp: number;
mults: Multipliers; mults: Multipliers;
numPeopleKilled: number; numPeopleKilled: number;
money: number; money: number;

View File

@@ -29,7 +29,7 @@ export function backdoor(
); );
} else if (!normalServer.hasAdminRights) { } else if (!normalServer.hasAdminRights) {
terminal.error("You do not have admin rights for this machine! Cannot backdoor"); terminal.error("You do not have admin rights for this machine! Cannot backdoor");
} else if (normalServer.requiredHackingSkill > player.hacking) { } else if (normalServer.requiredHackingSkill > player.skills.hacking) {
terminal.error( terminal.error(
"Your hacking skill is not high enough to use backdoor on this machine. Try analyzing the machine to determine the required hacking skill", "Your hacking skill is not high enough to use backdoor on this machine. Try analyzing the machine to determine the required hacking skill",
); );

View File

@@ -34,7 +34,7 @@ export function grow(
terminal.error("You do not have admin rights for this machine! Cannot grow"); terminal.error("You do not have admin rights for this machine! Cannot grow");
return; return;
} }
if (normalServer.requiredHackingSkill > player.hacking) { if (normalServer.requiredHackingSkill > player.skills.hacking) {
terminal.error( terminal.error(
"Your hacking skill is not high enough to attempt hacking this machine. Try analyzing the machine to determine the required hacking skill", "Your hacking skill is not high enough to attempt hacking this machine. Try analyzing the machine to determine the required hacking skill",
); );

View File

@@ -34,7 +34,7 @@ export function hack(
terminal.error("You do not have admin rights for this machine! Cannot hack"); terminal.error("You do not have admin rights for this machine! Cannot hack");
return; return;
} }
if (normalServer.requiredHackingSkill > player.hacking) { if (normalServer.requiredHackingSkill > player.skills.hacking) {
terminal.error( terminal.error(
"Your hacking skill is not high enough to attempt hacking this machine. Try analyzing the machine to determine the required hacking skill", "Your hacking skill is not high enough to attempt hacking this machine. Try analyzing the machine to determine the required hacking skill",
); );

View File

@@ -34,7 +34,7 @@ export function weaken(
terminal.error("You do not have admin rights for this machine! Cannot weaken"); terminal.error("You do not have admin rights for this machine! Cannot weaken");
return; return;
} }
if (normalServer.requiredHackingSkill > player.hacking) { if (normalServer.requiredHackingSkill > player.skills.hacking) {
terminal.error( terminal.error(
"Your hacking skill is not high enough to attempt hacking this machine. Try analyzing the machine to determine the required hacking skill", "Your hacking skill is not high enough to attempt hacking this machine. Try analyzing the machine to determine the required hacking skill",
); );

View File

@@ -63,7 +63,7 @@ export class CreateProgramWork extends Work {
} }
//Higher hacking skill will allow you to create programs faster //Higher hacking skill will allow you to create programs faster
const reqLvl = this.getProgram().create?.level ?? 0; const reqLvl = this.getProgram().create?.level ?? 0;
let skillMult = (player.hacking / reqLvl) * player.getIntelligenceBonus(3); //This should always be greater than 1; let skillMult = (player.skills.hacking / reqLvl) * player.getIntelligenceBonus(3); //This should always be greater than 1;
skillMult = 1 + (skillMult - 1) / 5; //The divider constant can be adjusted as necessary skillMult = 1 + (skillMult - 1) / 5; //The divider constant can be adjusted as necessary
skillMult *= focusBonus; skillMult *= focusBonus;
//Skill multiplier directly applied to "time worked" //Skill multiplier directly applied to "time worked"

View File

@@ -27,15 +27,15 @@ export const calculateCompanyWorkStats = (player: IPlayer, company: Company): Wo
} }
let jobPerformance = companyPosition.calculateJobPerformance( let jobPerformance = companyPosition.calculateJobPerformance(
player.hacking, player.skills.hacking,
player.strength, player.skills.strength,
player.defense, player.skills.defense,
player.dexterity, player.skills.dexterity,
player.agility, player.skills.agility,
player.charisma, player.skills.charisma,
); );
jobPerformance += player.intelligence / CONSTANTS.MaxSkillLevel; jobPerformance += player.skills.intelligence / CONSTANTS.MaxSkillLevel;
return { return {
money: money:

View File

@@ -293,38 +293,38 @@ export function CharacterStats(): React.ReactElement {
<StatsRow <StatsRow
name="Hacking" name="Hacking"
color={Settings.theme.hack} color={Settings.theme.hack}
data={{ level: player.hacking, exp: player.hacking_exp }} data={{ level: player.skills.hacking, exp: player.exp.hacking }}
/> />
<StatsRow <StatsRow
name="Strength" name="Strength"
color={Settings.theme.combat} color={Settings.theme.combat}
data={{ level: player.strength, exp: player.strength_exp }} data={{ level: player.skills.strength, exp: player.exp.strength }}
/> />
<StatsRow <StatsRow
name="Defense" name="Defense"
color={Settings.theme.combat} color={Settings.theme.combat}
data={{ level: player.defense, exp: player.defense_exp }} data={{ level: player.skills.defense, exp: player.exp.defense }}
/> />
<StatsRow <StatsRow
name="Dexterity" name="Dexterity"
color={Settings.theme.combat} color={Settings.theme.combat}
data={{ level: player.dexterity, exp: player.dexterity_exp }} data={{ level: player.skills.dexterity, exp: player.exp.dexterity }}
/> />
<StatsRow <StatsRow
name="Agility" name="Agility"
color={Settings.theme.combat} color={Settings.theme.combat}
data={{ level: player.agility, exp: player.agility_exp }} data={{ level: player.skills.agility, exp: player.exp.agility }}
/> />
<StatsRow <StatsRow
name="Charisma" name="Charisma"
color={Settings.theme.cha} color={Settings.theme.cha}
data={{ level: player.charisma, exp: player.charisma_exp }} data={{ level: player.skills.charisma, exp: player.exp.charisma }}
/> />
{player.intelligence > 0 && (player.bitNodeN === 5 || player.sourceFileLvl(5) > 0) && ( {player.skills.intelligence > 0 && (player.bitNodeN === 5 || player.sourceFileLvl(5) > 0) && (
<StatsRow <StatsRow
name="Intelligence" name="Intelligence"
color={Settings.theme.int} color={Settings.theme.int}
data={{ level: player.intelligence, exp: player.intelligence_exp }} data={{ level: player.skills.intelligence, exp: player.exp.intelligence }}
/> />
)} )}
</TableBody> </TableBody>

View File

@@ -44,8 +44,8 @@ function Intelligence(): React.ReactElement {
const theme = useTheme(); const theme = useTheme();
const player = use.Player(); const player = use.Player();
const classes = useStyles(); const classes = useStyles();
if (player.intelligence === 0) return <></>; if (player.skills.intelligence === 0) return <></>;
const progress = player.calculateSkillProgress(player.intelligence_exp); const progress = player.calculateSkillProgress(player.exp.intelligence);
return ( return (
<> <>
@@ -54,7 +54,9 @@ function Intelligence(): React.ReactElement {
<Typography classes={{ root: classes.int }}>Int&nbsp;</Typography> <Typography classes={{ root: classes.int }}>Int&nbsp;</Typography>
</TableCell> </TableCell>
<TableCell align="right" classes={{ root: classes.cell }}> <TableCell align="right" classes={{ root: classes.cell }}>
<Typography classes={{ root: classes.int }}>{numeralWrapper.formatSkill(player.intelligence)}</Typography> <Typography classes={{ root: classes.int }}>
{numeralWrapper.formatSkill(player.skills.intelligence)}
</Typography>
</TableCell> </TableCell>
<TableCell align="right" classes={{ root: classes.cell }}> <TableCell align="right" classes={{ root: classes.cell }}>
<Typography id="overview-int-hook" classes={{ root: classes.int }}> <Typography id="overview-int-hook" classes={{ root: classes.int }}>
@@ -292,27 +294,27 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
const theme = useTheme(); const theme = useTheme();
const hackingProgress = player.calculateSkillProgress( const hackingProgress = player.calculateSkillProgress(
player.hacking_exp, player.exp.hacking,
player.mults.hacking * BitNodeMultipliers.HackingLevelMultiplier, player.mults.hacking * BitNodeMultipliers.HackingLevelMultiplier,
); );
const strengthProgress = player.calculateSkillProgress( const strengthProgress = player.calculateSkillProgress(
player.strength_exp, player.exp.strength,
player.mults.strength * BitNodeMultipliers.StrengthLevelMultiplier, player.mults.strength * BitNodeMultipliers.StrengthLevelMultiplier,
); );
const defenseProgress = player.calculateSkillProgress( const defenseProgress = player.calculateSkillProgress(
player.defense_exp, player.exp.defense,
player.mults.defense * BitNodeMultipliers.DefenseLevelMultiplier, player.mults.defense * BitNodeMultipliers.DefenseLevelMultiplier,
); );
const dexterityProgress = player.calculateSkillProgress( const dexterityProgress = player.calculateSkillProgress(
player.dexterity_exp, player.exp.dexterity,
player.mults.dexterity * BitNodeMultipliers.DexterityLevelMultiplier, player.mults.dexterity * BitNodeMultipliers.DexterityLevelMultiplier,
); );
const agilityProgress = player.calculateSkillProgress( const agilityProgress = player.calculateSkillProgress(
player.agility_exp, player.exp.agility,
player.mults.agility * BitNodeMultipliers.AgilityLevelMultiplier, player.mults.agility * BitNodeMultipliers.AgilityLevelMultiplier,
); );
const charismaProgress = player.calculateSkillProgress( const charismaProgress = player.calculateSkillProgress(
player.charisma_exp, player.exp.charisma,
player.mults.charisma * BitNodeMultipliers.CharismaLevelMultiplier, player.mults.charisma * BitNodeMultipliers.CharismaLevelMultiplier,
); );
@@ -326,7 +328,7 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
</TableCell> </TableCell>
<TableCell align="right" classes={{ root: classes.cellNone }}> <TableCell align="right" classes={{ root: classes.cellNone }}>
<Typography classes={{ root: classes.hp }}> <Typography classes={{ root: classes.hp }}>
{numeralWrapper.formatHp(player.hp)}&nbsp;/&nbsp;{numeralWrapper.formatHp(player.max_hp)} {numeralWrapper.formatHp(player.hp.current)}&nbsp;/&nbsp;{numeralWrapper.formatHp(player.hp.max)}
</Typography> </Typography>
</TableCell> </TableCell>
<TableCell align="right" classes={{ root: classes.cellNone }}> <TableCell align="right" classes={{ root: classes.cellNone }}>
@@ -355,7 +357,9 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
<Typography classes={{ root: classes.hack }}>Hack&nbsp;</Typography> <Typography classes={{ root: classes.hack }}>Hack&nbsp;</Typography>
</TableCell> </TableCell>
<TableCell align="right" classes={{ root: classes.cellNone }}> <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.skills.hacking)}
</Typography>
</TableCell> </TableCell>
</TableRow> </TableRow>
<TableRow> <TableRow>
@@ -379,7 +383,9 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
<Typography classes={{ root: classes.combat }}>Str&nbsp;</Typography> <Typography classes={{ root: classes.combat }}>Str&nbsp;</Typography>
</TableCell> </TableCell>
<TableCell align="right" classes={{ root: classes.cellNone }}> <TableCell align="right" classes={{ root: classes.cellNone }}>
<Typography classes={{ root: classes.combat }}>{numeralWrapper.formatSkill(player.strength)}</Typography> <Typography classes={{ root: classes.combat }}>
{numeralWrapper.formatSkill(player.skills.strength)}
</Typography>
</TableCell> </TableCell>
<TableCell align="right" classes={{ root: classes.cellNone }}> <TableCell align="right" classes={{ root: classes.cellNone }}>
<Typography id="overview-str-hook" classes={{ root: classes.combat }}> <Typography id="overview-str-hook" classes={{ root: classes.combat }}>
@@ -398,7 +404,9 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
<Typography classes={{ root: classes.combat }}>Def&nbsp;</Typography> <Typography classes={{ root: classes.combat }}>Def&nbsp;</Typography>
</TableCell> </TableCell>
<TableCell align="right" classes={{ root: classes.cellNone }}> <TableCell align="right" classes={{ root: classes.cellNone }}>
<Typography classes={{ root: classes.combat }}>{numeralWrapper.formatSkill(player.defense)}</Typography> <Typography classes={{ root: classes.combat }}>
{numeralWrapper.formatSkill(player.skills.defense)}
</Typography>
</TableCell> </TableCell>
<TableCell align="right" classes={{ root: classes.cellNone }}> <TableCell align="right" classes={{ root: classes.cellNone }}>
<Typography id="overview-def-hook" classes={{ root: classes.combat }}> <Typography id="overview-def-hook" classes={{ root: classes.combat }}>
@@ -417,7 +425,9 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
<Typography classes={{ root: classes.combat }}>Dex&nbsp;</Typography> <Typography classes={{ root: classes.combat }}>Dex&nbsp;</Typography>
</TableCell> </TableCell>
<TableCell align="right" classes={{ root: classes.cellNone }}> <TableCell align="right" classes={{ root: classes.cellNone }}>
<Typography classes={{ root: classes.combat }}>{numeralWrapper.formatSkill(player.dexterity)}</Typography> <Typography classes={{ root: classes.combat }}>
{numeralWrapper.formatSkill(player.skills.dexterity)}
</Typography>
</TableCell> </TableCell>
<TableCell align="right" classes={{ root: classes.cellNone }}> <TableCell align="right" classes={{ root: classes.cellNone }}>
<Typography id="overview-dex-hook" classes={{ root: classes.combat }}> <Typography id="overview-dex-hook" classes={{ root: classes.combat }}>
@@ -436,7 +446,9 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
<Typography classes={{ root: classes.combat }}>Agi&nbsp;</Typography> <Typography classes={{ root: classes.combat }}>Agi&nbsp;</Typography>
</TableCell> </TableCell>
<TableCell align="right" classes={{ root: classes.cell }}> <TableCell align="right" classes={{ root: classes.cell }}>
<Typography classes={{ root: classes.combat }}>{numeralWrapper.formatSkill(player.agility)}</Typography> <Typography classes={{ root: classes.combat }}>
{numeralWrapper.formatSkill(player.skills.agility)}
</Typography>
</TableCell> </TableCell>
<TableCell align="right" classes={{ root: classes.cell }}> <TableCell align="right" classes={{ root: classes.cell }}>
<Typography id="overview-agi-hook" classes={{ root: classes.combat }}> <Typography id="overview-agi-hook" classes={{ root: classes.combat }}>
@@ -455,7 +467,9 @@ export function CharacterOverview({ save, killScripts }: IProps): React.ReactEle
<Typography classes={{ root: classes.cha }}>Cha&nbsp;</Typography> <Typography classes={{ root: classes.cha }}>Cha&nbsp;</Typography>
</TableCell> </TableCell>
<TableCell align="right" classes={{ root: classes.cellNone }}> <TableCell align="right" classes={{ root: classes.cellNone }}>
<Typography classes={{ root: classes.cha }}>{numeralWrapper.formatSkill(player.charisma)}</Typography> <Typography classes={{ root: classes.cha }}>
{numeralWrapper.formatSkill(player.skills.charisma)}
</Typography>
</TableCell> </TableCell>
<TableCell align="right" classes={{ root: classes.cellNone }}> <TableCell align="right" classes={{ root: classes.cellNone }}>
<Typography id="overview-cha-hook" classes={{ root: classes.cha }}> <Typography id="overview-cha-hook" classes={{ root: classes.cha }}>

View File

@@ -86,6 +86,22 @@ const getPlayerFields = [
"workDefExpGainRate", "workDefExpGainRate",
"workAgiExpGained", "workAgiExpGained",
"className", "className",
"hacking",
"strength",
"defense",
"dexterity",
"agility",
"charisma",
"intelligence",
"hacking_exp",
"strength_exp",
"defense_exp",
"dexterity_exp",
"agility_exp",
"charisma_exp",
"intelligence_exp",
"hp",
"max_hp",
]; ];
const mults = [ const mults = [
@@ -188,7 +204,7 @@ export const v2APIBreak = () => {
for (const f of getPlayerFields) { for (const f of getPlayerFields) {
rules.push({ rules.push({
match: new RegExp(f, "g"), match: new RegExp(f, "g"),
reason: `The work system is completely reworked and ns.getPlayer().${f} no longer exists. This data is likely available inside ns.getPlayer().currentWork`, reason: `The work system is completely reworked and ns.getPlayer().${f} no longer exists. This data is likely available inside ns.getPlayer().currentWork, skills, exp, or hp`,
offenders: [], offenders: [],
}); });
} }