HASHNET: Company Favor (#469)

This commit is contained in:
T.J. Eckman 2023-04-08 23:24:09 -04:00 committed by GitHub
parent ed9e6d5ea3
commit 751fe82f92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 94 additions and 3 deletions

@ -21,6 +21,7 @@ import { iTutorialSteps, iTutorialNextStep, ITutorial } from "../InteractiveTuto
import { Player } from "@player"; import { Player } from "@player";
import { GetServer } from "../Server/AllServers"; import { GetServer } from "../Server/AllServers";
import { Server } from "../Server/Server"; import { Server } from "../Server/Server";
import { Companies } from "../Company/Companies";
// Returns a boolean indicating whether the player has Hacknet Servers // Returns a boolean indicating whether the player has Hacknet Servers
// (the upgraded form of Hacknet Nodes) // (the upgraded form of Hacknet Nodes)
@ -562,6 +563,14 @@ export function purchaseHashUpgrade(upgName: string, upgTarget: string, count =
} }
break; break;
} }
case "Company Favor": {
if (!(upgTarget in Companies)) {
console.error(`Invalid target specified in purchaseHashUpgrade(): ${upgTarget}`);
throw new Error(`'${upgTarget}' is not a company.`);
}
Companies[upgTarget].favor += 5;
break;
}
default: default:
console.warn(`Unrecognized upgrade name ${upgName}. Upgrade has no effect`); console.warn(`Unrecognized upgrade name ${upgName}. Upgrade has no effect`);
return false; return false;

@ -4,6 +4,7 @@ export interface IConstructorParams {
costPerLevel: number; costPerLevel: number;
desc: string; desc: string;
hasTargetServer?: boolean; hasTargetServer?: boolean;
hasTargetCompany?: boolean;
name: string; name: string;
value: number; value: number;
effectText?: (level: number) => JSX.Element | null; effectText?: (level: number) => JSX.Element | null;
@ -33,6 +34,12 @@ export class HashUpgrade {
*/ */
hasTargetServer = false; hasTargetServer = false;
/**
* Boolean indicating that this upgrade's effect affects a single company,
* the "target" company
*/
hasTargetCompany = false;
/** Name of upgrade */ /** Name of upgrade */
name = ""; name = "";
@ -51,6 +58,7 @@ export class HashUpgrade {
this.costPerLevel = p.costPerLevel; this.costPerLevel = p.costPerLevel;
this.desc = p.desc; this.desc = p.desc;
this.hasTargetServer = p.hasTargetServer ? p.hasTargetServer : false; this.hasTargetServer = p.hasTargetServer ? p.hasTargetServer : false;
this.hasTargetCompany = p.hasTargetCompany ? p.hasTargetCompany : false;
this.name = p.name; this.name = p.name;
this.value = p.value; this.value = p.value;
} }

@ -101,4 +101,11 @@ export const HashUpgradesMetadata: IConstructorParams[] = [
effectText: (level: number): JSX.Element | null => <>Generated {level} contracts.</>, effectText: (level: number): JSX.Element | null => <>Generated {level} contracts.</>,
value: 1, value: 1,
}, },
{
costPerLevel: 200,
desc: "Use hashes to increase the favor with a company by 5. This effect is permanent.",
hasTargetCompany: true,
name: "Company Favor",
value: 5,
},
]; ];

@ -5,6 +5,7 @@ import { HashManager } from "../HashManager";
import { HashUpgrade } from "../HashUpgrade"; import { HashUpgrade } from "../HashUpgrade";
import { ServerDropdown, ServerType } from "../../ui/React/ServerDropdown"; import { ServerDropdown, ServerType } from "../../ui/React/ServerDropdown";
import { CompanyDropdown } from "../../ui/React/CompanyDropdown";
import { dialogBoxCreate } from "../../ui/React/DialogBox"; import { dialogBoxCreate } from "../../ui/React/DialogBox";
import { CopyableText } from "../../ui/React/CopyableText"; import { CopyableText } from "../../ui/React/CopyableText";
@ -15,6 +16,7 @@ import Paper from "@mui/material/Paper";
import Button from "@mui/material/Button"; import Button from "@mui/material/Button";
import { SelectChangeEvent } from "@mui/material/Select"; import { SelectChangeEvent } from "@mui/material/Select";
import { FactionNames } from "../../Faction/data/FactionNames"; import { FactionNames } from "../../Faction/data/FactionNames";
import { companiesMetadata } from "../../Company/data/CompaniesMetadata";
interface IProps { interface IProps {
hashManager: HashManager; hashManager: HashManager;
@ -23,6 +25,7 @@ interface IProps {
} }
const serversMap: { [key: string]: string } = {}; const serversMap: { [key: string]: string } = {};
const companiesMap: { [key: string]: string } = {};
export function HacknetUpgradeElem(props: IProps): React.ReactElement { export function HacknetUpgradeElem(props: IProps): React.ReactElement {
const [selectedServer, setSelectedServer] = useState( const [selectedServer, setSelectedServer] = useState(
@ -32,11 +35,20 @@ export function HacknetUpgradeElem(props: IProps): React.ReactElement {
setSelectedServer(event.target.value); setSelectedServer(event.target.value);
serversMap[props.upg.name] = event.target.value; serversMap[props.upg.name] = event.target.value;
} }
const [selectedCompany, setSelectedCompany] = useState(
companiesMap[props.upg.name] ? companiesMap[props.upg.name] : companiesMetadata[0].name,
);
function changeTargetCompany(event: SelectChangeEvent<string>): void {
setSelectedCompany(event.target.value);
companiesMap[props.upg.name] = event.target.value;
}
function purchase(): void { function purchase(): void {
const canPurchase = props.hashManager.hashes >= props.hashManager.getUpgradeCost(props.upg.name); const canPurchase = props.hashManager.hashes >= props.hashManager.getUpgradeCost(props.upg.name);
if (canPurchase) { if (canPurchase) {
const res = purchaseHashUpgrade(props.upg.name, selectedServer); const res = purchaseHashUpgrade(
props.upg.name,
props.upg.name === "Company Favor" ? selectedCompany : selectedServer,
);
if (!res) { if (!res) {
dialogBoxCreate( dialogBoxCreate(
"Failed to purchase upgrade. This may be because you do not have enough hashes, " + "Failed to purchase upgrade. This may be because you do not have enough hashes, " +
@ -67,7 +79,7 @@ export function HacknetUpgradeElem(props: IProps): React.ReactElement {
</Typography> </Typography>
<Typography>{upg.desc}</Typography> <Typography>{upg.desc}</Typography>
{!upg.hasTargetServer && ( {!upg.hasTargetServer && !upg.hasTargetCompany && (
<Button onClick={purchase} disabled={!canPurchase}> <Button onClick={purchase} disabled={!canPurchase}>
Buy Buy
</Button> </Button>
@ -81,6 +93,14 @@ export function HacknetUpgradeElem(props: IProps): React.ReactElement {
onChange={changeTargetServer} onChange={changeTargetServer}
/> />
)} )}
{upg.hasTargetCompany && (
<CompanyDropdown
purchase={purchase}
canPurchase={canPurchase}
value={selectedCompany}
onChange={changeTargetCompany}
/>
)}
{level > 0 && effect && <Typography>{effect}</Typography>} {level > 0 && effect && <Typography>{effect}</Typography>}
</Paper> </Paper>
); );

@ -657,6 +657,9 @@ function evaluateVersionCompatibility(ver: string | number): void {
// Prior to v2.2.0, sleeve shock was 0 to 100 internally but displayed as 100 to 0. This unifies them as 100 to 0. // Prior to v2.2.0, sleeve shock was 0 to 100 internally but displayed as 100 to 0. This unifies them as 100 to 0.
for (const sleeve of Player.sleeves) sleeve.shock = 100 - sleeve.shock; for (const sleeve of Player.sleeves) sleeve.shock = 100 - sleeve.shock;
} }
if (anyPlayer.hashManager !== undefined) {
anyPlayer.hashManager.upgrades["Company Favor"] ??= 0;
}
} }
function loadGame(saveString: string): boolean { function loadGame(saveString: string): boolean {

@ -0,0 +1,44 @@
/**
* Creates a dropdown (select HTML element) with company names as options
*/
import React from "react";
import { companiesMetadata } from "../../Company/data/CompaniesMetadata";
import Select, { SelectChangeEvent } from "@mui/material/Select";
import MenuItem from "@mui/material/MenuItem";
import Button from "@mui/material/Button";
interface IProps {
purchase: () => void;
canPurchase: boolean;
onChange: (event: SelectChangeEvent<string>) => void;
value: string;
}
const sortedCompanies = companiesMetadata.sort((a, b) => a.name.localeCompare(b.name));
export function CompanyDropdown(props: IProps): React.ReactElement {
const companies = [];
for (const company of sortedCompanies) {
companies.push(
<MenuItem key={company.name} value={company.name}>
{company.name}
</MenuItem>,
);
}
return (
<Select
startAdornment={
<Button onClick={props.purchase} disabled={!props.canPurchase}>
Buy
</Button>
}
sx={{ mx: 1 }}
value={props.value}
onChange={props.onChange}
>
{companies}
</Select>
);
}