mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-04-17 06:48:42 +02:00
IPVGO: Improve favor gain from wins to balance around the rep value of favor (#2131)
This commit is contained in:
committed by
GitHub
parent
2b8c008be1
commit
4749acdd4f
@@ -13,7 +13,7 @@ type SimpleOpponentStats = {
|
||||
losses: number;
|
||||
winStreak: number;
|
||||
highestWinStreak: number;
|
||||
favor: number;
|
||||
rep: number;
|
||||
bonusPercent: number;
|
||||
bonusDescription: string;
|
||||
};
|
||||
|
||||
@@ -525,11 +525,17 @@ export function initBitNodes() {
|
||||
<li>Level 2: Permanently unlocks the go.cheat API</li>
|
||||
<li>Level 3: 25% additive increased success rate for the go.cheat API</li>
|
||||
</ul>
|
||||
This Source-File also increases the maximum favor you can gain for each faction from IPvGO to:
|
||||
This Source-File also increases the maximum favor from winstreaks you can gain for each faction to:
|
||||
<ul>
|
||||
<li>Level 1: 80</li>
|
||||
<li>Level 2: 100</li>
|
||||
<li>Level 3: 120</li>
|
||||
<li>Level 1: 200k rep equivalent</li>
|
||||
<li>Level 2: 300k rep equivalent</li>
|
||||
<li>Level 3: 400k rep equivalent</li>
|
||||
</ul>
|
||||
and increases the reputation converted to favor for winning two games in a row to:
|
||||
<ul>
|
||||
<li>Level 1: 1000 rep to favor</li>
|
||||
<li>Level 2: 1500 rep to favor</li>
|
||||
<li>Level 3: 2000 rep to favor</li>
|
||||
</ul>
|
||||
</>
|
||||
),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { CompanyPosition } from "./CompanyPosition";
|
||||
|
||||
import { CompanyName, JobName, FactionName } from "@enums";
|
||||
import { MaxFavor, calculateFavorAfterResetting } from "../Faction/formulas/favor";
|
||||
import { MaxFavor, addRepToFavor } from "../Faction/formulas/favor";
|
||||
import { clampNumber } from "../utils/helpers/clampNumber";
|
||||
|
||||
export interface CompanyCtorParams {
|
||||
@@ -75,7 +75,7 @@ export class Company {
|
||||
}
|
||||
|
||||
prestigeAugmentation(): void {
|
||||
this.setFavor(calculateFavorAfterResetting(this.favor, this.playerReputation));
|
||||
this.setFavor(addRepToFavor(this.favor, this.playerReputation));
|
||||
this.playerReputation = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { AugmentationName, FactionName, FactionDiscovery } from "@enums";
|
||||
import { FactionInfo, FactionInfos } from "./FactionInfo";
|
||||
import { MaxFavor, calculateFavorAfterResetting } from "./formulas/favor";
|
||||
import { MaxFavor, addRepToFavor } from "./formulas/favor";
|
||||
import { clampNumber } from "../utils/helpers/clampNumber";
|
||||
|
||||
export class Faction {
|
||||
@@ -76,7 +76,7 @@ export class Faction {
|
||||
|
||||
prestigeAugmentation(): void {
|
||||
// Gain favor
|
||||
this.setFavor(calculateFavorAfterResetting(this.favor, this.playerReputation));
|
||||
this.setFavor(addRepToFavor(this.favor, this.playerReputation));
|
||||
// Reset reputation and flags
|
||||
this.playerReputation = 0;
|
||||
this.alreadyInvited = false;
|
||||
|
||||
@@ -19,6 +19,6 @@ export function repToFavor(r: number): number {
|
||||
return clampNumber(Math.log1p(r / 25000) / log1point02, 0, MaxFavor);
|
||||
}
|
||||
|
||||
export function calculateFavorAfterResetting(favor: number, playerReputation: number) {
|
||||
export function addRepToFavor(favor: number, playerReputation: number) {
|
||||
return repToFavor(favorToRep(favor) + playerReputation);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import Tooltip from "@mui/material/Tooltip";
|
||||
import Box from "@mui/material/Box";
|
||||
import InfoIcon from "@mui/icons-material/Info";
|
||||
import { useCycleRerender } from "../../ui/React/hooks";
|
||||
import { calculateFavorAfterResetting } from "../formulas/favor";
|
||||
import { addRepToFavor } from "../formulas/favor";
|
||||
import { knowAboutBitverse } from "../../BitNode/BitNodeUtils";
|
||||
|
||||
interface IProps {
|
||||
@@ -74,8 +74,7 @@ export function Info(props: IProps): React.ReactElement {
|
||||
title={
|
||||
<>
|
||||
<Typography>
|
||||
You will have{" "}
|
||||
<Favor favor={calculateFavorAfterResetting(props.faction.favor, props.faction.playerReputation)} />{" "}
|
||||
You will have <Favor favor={addRepToFavor(props.faction.favor, props.faction.playerReputation)} />{" "}
|
||||
faction favor after installing an Augmentation.
|
||||
</Typography>
|
||||
<MathJax>{"\\(\\huge{r = \\text{total faction reputation}}\\)"}</MathJax>
|
||||
|
||||
@@ -81,7 +81,7 @@ export function newOpponentStats(): OpponentStats {
|
||||
winStreak: 0,
|
||||
oldWinStreak: 0,
|
||||
highestWinStreak: 0,
|
||||
favor: 0,
|
||||
rep: 0,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -152,10 +152,10 @@ function loadStats(stats: unknown): PartialRecord<GoOpponent, OpponentStats> | s
|
||||
if (!getEnumHelper("GoOpponent").isMember(opponent)) return `Invalid opponent in Go.stats: ${opponent}`;
|
||||
if (!opponentStats || typeof opponentStats !== "object") return "Non-object encountered for an opponent's stats";
|
||||
assertLoadingType<OpponentStats>(opponentStats as object);
|
||||
const { favor, highestWinStreak, losses, nodes, wins, oldWinStreak, winStreak, nodePower } =
|
||||
const { rep, highestWinStreak, losses, nodes, wins, oldWinStreak, winStreak, nodePower } =
|
||||
opponentStats as OpponentStats;
|
||||
// Integers >= 0. Todo: make a better helper for this.
|
||||
if (!isInteger(favor) || favor < 0) return "A favor entry in Go.stats was invalid";
|
||||
if (!isInteger(rep) || rep < 0) return "A rep entry in Go.stats was invalid";
|
||||
if (!isInteger(highestWinStreak) || highestWinStreak < 0) return "A highestWinStreak entry in Go.stats was invalid";
|
||||
if (!isInteger(losses) || losses < 0) return "A losses entry in Go.stats was invalid";
|
||||
if (!isInteger(nodes) || nodes < 0) return "A nodes entry in Go.stats was invalid";
|
||||
@@ -167,7 +167,7 @@ function loadStats(stats: unknown): PartialRecord<GoOpponent, OpponentStats> | s
|
||||
|
||||
// Numbers >= 0
|
||||
if (!isNumber(nodePower) || nodePower < 0) return "A nodePower entry in Go.stats was invalid";
|
||||
finalStats[opponent] = { favor, highestWinStreak, losses, nodes, wins, oldWinStreak, winStreak, nodePower };
|
||||
finalStats[opponent] = { rep, highestWinStreak, losses, nodes, wins, oldWinStreak, winStreak, nodePower };
|
||||
}
|
||||
return finalStats;
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ export type OpponentStats = {
|
||||
winStreak: number;
|
||||
oldWinStreak: number;
|
||||
highestWinStreak: number;
|
||||
favor: number;
|
||||
rep: number;
|
||||
};
|
||||
|
||||
export type SimpleOpponentStats = {
|
||||
@@ -106,7 +106,7 @@ export type SimpleOpponentStats = {
|
||||
losses: number;
|
||||
winStreak: number;
|
||||
highestWinStreak: number;
|
||||
favor: number;
|
||||
rep: number;
|
||||
bonusPercent: number;
|
||||
bonusDescription: string;
|
||||
};
|
||||
|
||||
@@ -5,11 +5,12 @@ import { GoOpponent, GoColor } from "@enums";
|
||||
import { newOpponentStats } from "../Constants";
|
||||
import { getAllChains, getPlayerNeighbors } from "./boardAnalysis";
|
||||
import { getKomi, resetAI } from "./goAI";
|
||||
import { getDifficultyMultiplier, getMaxFavor, getWinstreakMultiplier } from "../effects/effect";
|
||||
import { getDifficultyMultiplier, getMaxRep, getWinstreakMultiplier } from "../effects/effect";
|
||||
import { isNotNullish } from "../boardState/boardState";
|
||||
import { Factions } from "../../Faction/Factions";
|
||||
import { getEnumHelper } from "../../utils/EnumHelper";
|
||||
import { Go, GoEvents } from "../Go";
|
||||
import { addRepToFavor } from "../../Faction/formulas/favor";
|
||||
|
||||
/**
|
||||
* Returns the score of the current board.
|
||||
@@ -49,7 +50,7 @@ export function endGoGame(boardState: BoardState) {
|
||||
|
||||
boardState.previousPlayer = null;
|
||||
const statusToUpdate = getOpponentStats(boardState.ai);
|
||||
statusToUpdate.favor = statusToUpdate.favor ?? 0;
|
||||
statusToUpdate.rep = statusToUpdate.rep ?? 0;
|
||||
const score = getScore(boardState);
|
||||
|
||||
if (score[GoColor.black].sum < score[GoColor.white].sum) {
|
||||
@@ -68,10 +69,13 @@ export function endGoGame(boardState: BoardState) {
|
||||
factionName &&
|
||||
statusToUpdate.winStreak % 2 === 0 &&
|
||||
Player.factions.includes(factionName) &&
|
||||
statusToUpdate.favor < getMaxFavor()
|
||||
statusToUpdate.rep < getMaxRep()
|
||||
) {
|
||||
Factions[factionName].setFavor(Factions[factionName].favor + 1);
|
||||
statusToUpdate.favor++;
|
||||
const currentFavor = Factions[factionName].favor;
|
||||
const repToAdd = getMaxRep() / 200;
|
||||
const newFavor = addRepToFavor(currentFavor, repToAdd);
|
||||
Factions[factionName].setFavor(newFavor);
|
||||
statusToUpdate.rep += repToAdd;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,22 +23,24 @@ export function CalculateEffect(nodes: number, faction: GoOpponent): number {
|
||||
|
||||
/**
|
||||
* Get maximum favor that you can gain from IPvGO win streaks
|
||||
* for factions you are a member of
|
||||
* for factions you are a member of.
|
||||
*
|
||||
* This is added as converted rep to avoid making the equivalent value of the favor in rep very different as you approach 150 favor
|
||||
*/
|
||||
export function getMaxFavor() {
|
||||
export function getMaxRep() {
|
||||
const sourceFileLevel = Player.activeSourceFileLvl(14);
|
||||
|
||||
if (sourceFileLevel === 1) {
|
||||
return 80;
|
||||
return 200_000;
|
||||
}
|
||||
if (sourceFileLevel === 2) {
|
||||
return 100;
|
||||
return 300_000;
|
||||
}
|
||||
if (sourceFileLevel >= 3) {
|
||||
return 120;
|
||||
return 400_000;
|
||||
}
|
||||
|
||||
return 40;
|
||||
return 100_000;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -378,7 +378,7 @@ export function getStats() {
|
||||
losses: details.losses,
|
||||
winStreak: details.winStreak,
|
||||
highestWinStreak: details.highestWinStreak,
|
||||
favor: details.favor,
|
||||
rep: details.rep,
|
||||
bonusPercent: effectPercent,
|
||||
bonusDescription: effectDescription,
|
||||
};
|
||||
|
||||
@@ -7,7 +7,7 @@ import { getOpponentStats, getScore } from "../boardAnalysis/scoring";
|
||||
import { GoGameboard } from "./GoGameboard";
|
||||
import { boardStyles } from "../boardState/goStyles";
|
||||
import { useRerender } from "../../ui/React/hooks";
|
||||
import { getBonusText, getMaxFavor } from "../effects/effect";
|
||||
import { getBonusText, getMaxRep } from "../effects/effect";
|
||||
import { formatNumber } from "../../ui/formatNumber";
|
||||
import { GoScoreSummaryTable } from "./GoScoreSummaryTable";
|
||||
import { getNewBoardState } from "../boardState/boardState";
|
||||
@@ -115,15 +115,18 @@ export const GoHistoryPage = (): React.ReactElement => {
|
||||
<Tooltip
|
||||
title={
|
||||
<>
|
||||
Two wins in a row against a faction will give you +1 favor to that faction <br />
|
||||
(up to a max of {getMaxFavor()} favor), if you are a member of that faction <br />
|
||||
Two wins in a row against an opponent will give you {getMaxRep() / 200} rep converted to favor
|
||||
with that faction (up to a max of {getMaxRep()} favor), if you are a member of that faction.
|
||||
<br />
|
||||
The rep is immediately applied as favor, meaning it will increase reputation gain right away
|
||||
without needing an install.
|
||||
</>
|
||||
}
|
||||
>
|
||||
<TableRow>
|
||||
<TableCell className={classes.cellNone}>Favor from winstreaks:</TableCell>
|
||||
<TableCell className={classes.cellNone}>
|
||||
{data.favor ?? 0} {data.favor === getMaxFavor() ? "(max)" : ""}
|
||||
{data.rep ?? 0} {data.rep === getMaxRep() ? "(max)" : ""}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</Tooltip>
|
||||
|
||||
@@ -7,7 +7,7 @@ import { boardStateFromSimpleBoard } from "../boardAnalysis/boardAnalysis";
|
||||
import { GoTutorialChallenge } from "./GoTutorialChallenge";
|
||||
import { Router } from "../../ui/GameRoot";
|
||||
import { Page } from "../../ui/Router";
|
||||
import { getMaxFavor } from "../effects/effect";
|
||||
import { getMaxRep } from "../effects/effect";
|
||||
|
||||
const captureChallenge = (
|
||||
<GoTutorialChallenge
|
||||
@@ -149,8 +149,11 @@ export const GoInstructionsPage = (): React.ReactElement => {
|
||||
will increase the amount gained, but is not required.
|
||||
<br />
|
||||
<br />
|
||||
Two wins in a row against a faction will give you +1 favor to that faction (up to a max of
|
||||
{getMaxFavor()} favor), if you are a member of that faction.
|
||||
Two wins in a row against an opponent will give you {getMaxRep() / 200} rep converted to favor with that
|
||||
faction (up to a max of {getMaxRep()} favor), if you are a member of that faction.
|
||||
<br />
|
||||
The rep is immediately applied as favor, meaning it will increase reputation gain right away without
|
||||
needing an install.
|
||||
<br />
|
||||
<br />
|
||||
For experienced Go players: IPvGO uses the old traditional Go score rules, area scoring, rather than the
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Table, TableBody, TableCell, TableRow, Typography, Tooltip } from "@mui
|
||||
import { Player } from "@player";
|
||||
import { GoOpponent, GoColor } from "@enums";
|
||||
import { Go } from "../Go";
|
||||
import { getBonusText, getDifficultyMultiplier, getMaxFavor, getWinstreakMultiplier } from "../effects/effect";
|
||||
import { getBonusText, getDifficultyMultiplier, getMaxRep, getWinstreakMultiplier } from "../effects/effect";
|
||||
import { boardStyles } from "../boardState/goStyles";
|
||||
import { formatNumber } from "../../ui/formatNumber";
|
||||
import { getOpponentStats } from "../boardAnalysis/scoring";
|
||||
@@ -99,14 +99,19 @@ export const GoScorePowerSummary = ({ finalScore, opponent }: Props) => {
|
||||
<Tooltip
|
||||
title={
|
||||
<>
|
||||
Two wins in a row against a faction will give you +1 favor to that faction <br />
|
||||
(up to a max of {getMaxFavor()} favor), if you are a member of that faction
|
||||
Two wins in a row against an opponent will give you {getMaxRep() / 200} rep converted to favor with that
|
||||
faction (up to a max of {getMaxRep()} favor), if you are a member of that faction.
|
||||
<br />
|
||||
The rep is immediately applied as favor, meaning it will increase reputation gain right away without
|
||||
needing an install.
|
||||
</>
|
||||
}
|
||||
>
|
||||
<Typography className={`${classes.inlineFlexBox} ${classes.keyText}`}>
|
||||
<span>Winstreak Bonus: </span>
|
||||
<span>+1 favor to {opponent}</span>
|
||||
<span>
|
||||
{getMaxRep() / 200} reputation converted to favor with {opponent}
|
||||
</span>
|
||||
</Typography>
|
||||
</Tooltip>
|
||||
) : (
|
||||
|
||||
@@ -24,7 +24,7 @@ import { companyNameAsLocationName } from "../../Company/utils";
|
||||
import { JobSummary } from "../../Company/ui/JobSummary";
|
||||
import { StatsTable } from "../../ui/React/StatsTable";
|
||||
import { JobListings } from "../../Company/ui/JobListings";
|
||||
import { calculateFavorAfterResetting } from "../../Faction/formulas/favor";
|
||||
import { addRepToFavor } from "../../Faction/formulas/favor";
|
||||
|
||||
interface IProps {
|
||||
companyName: CompanyName;
|
||||
@@ -101,8 +101,7 @@ export function CompanyLocation(props: IProps): React.ReactElement {
|
||||
key="repLabel"
|
||||
title={
|
||||
<>
|
||||
You will have{" "}
|
||||
<Favor favor={calculateFavorAfterResetting(company.favor, company.playerReputation)} /> company
|
||||
You will have <Favor favor={addRepToFavor(company.favor, company.playerReputation)} /> company
|
||||
favor upon resetting after installing Augmentations
|
||||
</>
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ import { JobTracks } from "../Company/data/JobTracks";
|
||||
import { ServerConstants } from "../Server/data/Constants";
|
||||
import { blackOpsArray } from "../Bladeburner/data/BlackOperations";
|
||||
import { calculateEffectiveRequiredReputation } from "../Company/utils";
|
||||
import { calculateFavorAfterResetting } from "../Faction/formulas/favor";
|
||||
import { addRepToFavor } from "../Faction/formulas/favor";
|
||||
import { validBitNodes } from "../BitNode/BitNodeUtils";
|
||||
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
||||
import { cat } from "../Terminal/commands/cat";
|
||||
@@ -754,7 +754,7 @@ export function NetscriptSingularity(): InternalAPI<ISingularity> {
|
||||
helpers.checkSingularityAccess(ctx);
|
||||
const companyName = getEnumHelper("CompanyName").nsGetMember(ctx, _companyName);
|
||||
const company = Companies[companyName];
|
||||
return calculateFavorAfterResetting(company.favor, company.playerReputation) - company.favor;
|
||||
return addRepToFavor(company.favor, company.playerReputation) - company.favor;
|
||||
},
|
||||
getFactionInviteRequirements: (ctx) => (_facName) => {
|
||||
helpers.checkSingularityAccess(ctx);
|
||||
@@ -924,7 +924,7 @@ export function NetscriptSingularity(): InternalAPI<ISingularity> {
|
||||
helpers.checkSingularityAccess(ctx);
|
||||
const facName = getEnumHelper("FactionName").nsGetMember(ctx, _facName);
|
||||
const faction = Factions[facName];
|
||||
return calculateFavorAfterResetting(faction.favor, faction.playerReputation) - faction.favor;
|
||||
return addRepToFavor(faction.favor, faction.playerReputation) - faction.favor;
|
||||
},
|
||||
donateToFaction: (ctx) => (_facName, _amt) => {
|
||||
helpers.checkSingularityAccess(ctx);
|
||||
|
||||
9
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
9
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
@@ -4442,12 +4442,19 @@ type GoOpponent =
|
||||
|
||||
/** @public */
|
||||
type SimpleOpponentStats = {
|
||||
/** Number of wins since last reset */
|
||||
wins: number;
|
||||
/** Number of losses since last reset*/
|
||||
losses: number;
|
||||
/** Current winstreak */
|
||||
winStreak: number;
|
||||
/** Highest winstreak since last reset*/
|
||||
highestWinStreak: number;
|
||||
favor: number;
|
||||
/** Favor gain from winstreaks, calculated as converted rep */
|
||||
rep: number;
|
||||
/** Stat boost*/
|
||||
bonusPercent: number;
|
||||
/** Description of stat boost */
|
||||
bonusDescription: string;
|
||||
};
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import { Money } from "./React/Money";
|
||||
import { StatsRow } from "./React/StatsRow";
|
||||
import { StatsTable } from "./React/StatsTable";
|
||||
import { useCycleRerender } from "./React/hooks";
|
||||
import { getMaxFavor } from "../Go/effects/effect";
|
||||
import { getMaxRep } from "../Go/effects/effect";
|
||||
import { canAccessBitNodeFeature, knowAboutBitverse } from "../BitNode/BitNodeUtils";
|
||||
|
||||
interface EmployersModalProps {
|
||||
@@ -566,7 +566,7 @@ export function CharacterStats(): React.ReactElement {
|
||||
},
|
||||
{
|
||||
mult: "IPvGO Max Favor",
|
||||
value: getMaxFavor(),
|
||||
value: getMaxRep(),
|
||||
isNumber: true,
|
||||
},
|
||||
]}
|
||||
|
||||
Reference in New Issue
Block a user