mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-05-07 16:17:49 +02:00
MISC: Refactor favor code (#1321)
This commit is contained in:
+24
-16
@@ -1,6 +1,7 @@
|
||||
import { AugmentationName, FactionName, FactionDiscovery } from "@enums";
|
||||
import { FactionInfo, FactionInfos } from "./FactionInfo";
|
||||
import { favorToRep, repToFavor } from "./formulas/favor";
|
||||
import { MaxFavor, calculateFavorAfterResetting } from "./formulas/favor";
|
||||
import { clampNumber } from "../utils/helpers/clampNumber";
|
||||
|
||||
export class Faction {
|
||||
/**
|
||||
@@ -13,7 +14,7 @@ export class Faction {
|
||||
augmentations: AugmentationName[] = [];
|
||||
|
||||
/** Amount of favor the player has with this faction. */
|
||||
favor = 0;
|
||||
#favor = 0;
|
||||
|
||||
/** Flag signalling whether player has been banned from this faction */
|
||||
isBanned = false;
|
||||
@@ -34,6 +35,25 @@ export class Faction {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
get favor() {
|
||||
return this.#favor;
|
||||
}
|
||||
|
||||
/**
|
||||
* There is no setter for this.#favor. This is intentional. Performing arithmetic operations on `favor` may lead to
|
||||
* the overflow error of `playerReputation`, so anything that wants to change `favor` must explicitly do that through
|
||||
* `setFavor`.
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
setFavor(value: number) {
|
||||
if (Number.isNaN(value)) {
|
||||
this.#favor = 0;
|
||||
return;
|
||||
}
|
||||
this.#favor = clampNumber(value, 0, MaxFavor);
|
||||
}
|
||||
|
||||
getInfo(): FactionInfo {
|
||||
const info = FactionInfos[this.name];
|
||||
if (info == null) {
|
||||
@@ -47,7 +67,7 @@ export class Faction {
|
||||
|
||||
prestigeSourceFile() {
|
||||
// Reset favor, reputation, and flags
|
||||
this.favor = 0;
|
||||
this.setFavor(0);
|
||||
this.playerReputation = 0;
|
||||
this.alreadyInvited = false;
|
||||
this.isMember = false;
|
||||
@@ -56,23 +76,11 @@ export class Faction {
|
||||
|
||||
prestigeAugmentation(): void {
|
||||
// Gain favor
|
||||
if (this.favor == null) this.favor = 0;
|
||||
this.favor += this.getFavorGain();
|
||||
this.setFavor(calculateFavorAfterResetting(this.favor, this.playerReputation));
|
||||
// Reset reputation and flags
|
||||
this.playerReputation = 0;
|
||||
this.alreadyInvited = false;
|
||||
this.isMember = false;
|
||||
this.isBanned = false;
|
||||
}
|
||||
|
||||
//Returns an array with [How much favor would be gained, how much rep would be left over]
|
||||
getFavorGain(): number {
|
||||
if (this.favor == null) {
|
||||
this.favor = 0;
|
||||
}
|
||||
const storedRep = Math.max(0, favorToRep(this.favor));
|
||||
const totalRep = storedRep + this.playerReputation;
|
||||
const newFavor = repToFavor(totalRep);
|
||||
return newFavor - this.favor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import { assertLoadingType } from "../utils/TypeAssertion";
|
||||
import { PartialRecord, createEnumKeyedRecord, getRecordValues } from "../Types/Record";
|
||||
import { Augmentations } from "../Augmentation/Augmentations";
|
||||
import { getEnumHelper } from "../utils/EnumHelper";
|
||||
import { clampNumber } from "../utils/helpers/clampNumber";
|
||||
|
||||
/** The static list of all factions. Initialized once and never modified. */
|
||||
export const Factions = createEnumKeyedRecord(FactionName, (name) => new Faction(name));
|
||||
@@ -33,8 +34,14 @@ export function loadFactions(saveString: string, player: PlayerObject): void {
|
||||
if (typeof loadedFaction !== "object") continue;
|
||||
assertLoadingType<SavegameFaction>(loadedFaction);
|
||||
const { playerReputation: loadedRep, favor: loadedFavor, discovery: loadedDiscovery } = loadedFaction;
|
||||
if (typeof loadedRep === "number" && loadedRep > 0) faction.playerReputation = loadedRep;
|
||||
if (typeof loadedFavor === "number" && loadedFavor > 0) faction.favor = loadedFavor;
|
||||
if (typeof loadedRep === "number" && loadedRep >= 0) {
|
||||
// `playerReputation` must be in [0, Number.MAX_VALUE].
|
||||
faction.playerReputation = clampNumber(loadedRep, 0);
|
||||
}
|
||||
if (typeof loadedFavor === "number" && loadedFavor >= 0) {
|
||||
// `favor` must be in [0, MaxFavor]. This rule will be enforced in the `setFavor` function.
|
||||
faction.setFavor(loadedFavor);
|
||||
}
|
||||
if (getEnumHelper("FactionDiscovery").isMember(loadedDiscovery)) faction.discovery = loadedDiscovery;
|
||||
}
|
||||
// Load joined factions from player save
|
||||
|
||||
@@ -2,12 +2,18 @@
|
||||
// see https://en.wikipedia.org/wiki/Geometric_series#Closed-form_formula
|
||||
// for information on how to calculate this
|
||||
|
||||
import { clampNumber } from "../../utils/helpers/clampNumber";
|
||||
|
||||
export const MaxFavor = 35331;
|
||||
|
||||
export function favorToRep(f: number): number {
|
||||
const raw = 25000 * (Math.pow(1.02, f) - 1);
|
||||
return Math.round(raw * 10000) / 10000; // round to make things easier.
|
||||
return clampNumber(25000 * (Math.pow(1.02, f) - 1), 0);
|
||||
}
|
||||
|
||||
export function repToFavor(r: number): number {
|
||||
const raw = Math.log(r / 25000 + 1) / Math.log(1.02);
|
||||
return Math.round(raw * 10000) / 10000; // round to make things easier.
|
||||
return clampNumber(Math.log(r / 25000 + 1) / Math.log(1.02), 0, MaxFavor);
|
||||
}
|
||||
|
||||
export function calculateFavorAfterResetting(favor: number, playerReputation: number) {
|
||||
return repToFavor(favorToRep(favor) + playerReputation);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import Typography from "@mui/material/Typography";
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
import Box from "@mui/material/Box";
|
||||
import { useRerender } from "../../ui/React/hooks";
|
||||
import { calculateFavorAfterResetting } from "../formulas/favor";
|
||||
|
||||
interface IProps {
|
||||
faction: Faction;
|
||||
@@ -49,8 +50,6 @@ export function Info(props: IProps): React.ReactElement {
|
||||
|
||||
const Assignment = props.factionInfo.assignment ?? DefaultAssignment;
|
||||
|
||||
const favorGain = props.faction.getFavorGain();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Typography classes={{ root: classes.noformat }}>{props.factionInfo.infoText}</Typography>
|
||||
@@ -60,8 +59,9 @@ export function Info(props: IProps): React.ReactElement {
|
||||
title={
|
||||
<>
|
||||
<Typography>
|
||||
You will have <Favor favor={Math.floor(props.faction.favor + favorGain)} /> faction favor after
|
||||
installing an Augmentation.
|
||||
You will have{" "}
|
||||
<Favor favor={calculateFavorAfterResetting(props.faction.favor, props.faction.playerReputation)} />{" "}
|
||||
faction favor after installing an Augmentation.
|
||||
</Typography>
|
||||
<MathJax>{"\\(\\huge{r = \\text{total faction reputation}}\\)"}</MathJax>
|
||||
<MathJax>
|
||||
|
||||
Reference in New Issue
Block a user