Fixed bugs with Location code refactor

This commit is contained in:
danielyxie 2019-04-03 17:08:11 -07:00
parent 4b95ba9ed1
commit bf9b837e31
24 changed files with 2897 additions and 2571 deletions

@ -3,7 +3,7 @@
import { CompanyPosition } from "./CompanyPosition"; import { CompanyPosition } from "./CompanyPosition";
import { CompanyPositions } from "./CompanyPositions"; import { CompanyPositions } from "./CompanyPositions";
export function getNextCompanyPosition(currPos: CompanyPosition | null): CompanyPosition | null { export function getNextCompanyPositionHelper(currPos: CompanyPosition | null): CompanyPosition | null {
if (currPos == null) { return null; } if (currPos == null) { return null; }
const nextPosName: string | null = currPos.nextPosition; const nextPosName: string | null = currPos.nextPosition;

@ -107,7 +107,7 @@ export function createPurchaseServerPopup(ram: number, p: IPlayer) {
* Create a popup that lets the player start a Corporation * Create a popup that lets the player start a Corporation
*/ */
export function createStartCorporationPopup(p: IPlayer) { export function createStartCorporationPopup(p: IPlayer) {
if (p.hasCorporation) { return; } if (!p.canAccessCorporation() || p.hasCorporation) { return; }
const popupId = "create-corporation-popup"; const popupId = "create-corporation-popup";
const txt = createElement("p", { const txt = createElement("p", {

@ -15,6 +15,7 @@ type IProps = {
entryPosType: CompanyPosition; entryPosType: CompanyPosition;
onClick: (e: React.MouseEvent<HTMLElement>) => void; onClick: (e: React.MouseEvent<HTMLElement>) => void;
p: IPlayer; p: IPlayer;
style?: object;
text: string; text: string;
} }
@ -38,6 +39,7 @@ export class ApplyToJobButton extends React.Component<IProps, any> {
return ( return (
<StdButton <StdButton
onClick={this.props.onClick} onClick={this.props.onClick}
style={this.props.style}
text={this.props.text} text={this.props.text}
tooltip={this.getJobRequirementTooltip()} tooltip={this.getJobRequirementTooltip()}
/> />

@ -19,8 +19,8 @@ export class LocationCity extends React.Component<IProps, any> {
render() { render() {
const locationButtons = this.props.city.locations.map((locName) => { const locationButtons = this.props.city.locations.map((locName) => {
return ( return (
<li> <li key={locName}>
<StdButton onClick={this.props.enterLocation.bind(this, locName)} text={locName} key={locName} /> <StdButton onClick={this.props.enterLocation.bind(this, locName)} text={locName} />
</li> </li>
) )
}); });

@ -16,10 +16,12 @@ import { beginInfiltration } from "../../Infiltration";
import { Companies } from "../../Company/Companies"; import { Companies } from "../../Company/Companies";
import { Company } from "../../Company/Company"; import { Company } from "../../Company/Company";
import { CompanyPosition } from "../../Company/CompanyPosition";
import { CompanyPositions } from "../../Company/CompanyPositions"; import { CompanyPositions } from "../../Company/CompanyPositions";
import * as posNames from "../../Company/data/companypositionnames"; import * as posNames from "../../Company/data/companypositionnames";
import { IPlayer } from "../../PersonObjects/IPlayer"; import { IPlayer } from "../../PersonObjects/IPlayer";
import { numeralWrapper } from "../../ui/numeralFormat";
import { StdButton } from "../../ui/React/StdButton"; import { StdButton } from "../../ui/React/StdButton";
type IProps = { type IProps = {
@ -28,21 +30,43 @@ type IProps = {
p: IPlayer; p: IPlayer;
} }
export class CompanyLocation extends React.Component<IProps, any> { type IState = {
employedHere: boolean;
}
export class CompanyLocation extends React.Component<IProps, IState> {
/** /**
* We'll keep a reference to the Company that this component is being rendered for, * We'll keep a reference to the Company that this component is being rendered for,
* so we don't have to look it up every time * so we don't have to look it up every time
*/ */
company: Company; company: Company;
/**
* CompanyPosition object for the job that the player holds at this company
* (if he has one)
*/
companyPosition: CompanyPosition | null = null;
/**
* Stores button styling that sets them all to block display
*/
btnStyle: object;
/** /**
* Reference to the Location that this component is being rendered for * Reference to the Location that this component is being rendered for
*/ */
location: Location; location: Location;
/**
* Name of company position that player holds, if applicable
*/
jobTitle: string | null = null;
constructor(props: IProps) { constructor(props: IProps) {
super(props); super(props);
this.btnStyle = { display: "block" };
this.applyForAgentJob = this.applyForAgentJob.bind(this); this.applyForAgentJob = this.applyForAgentJob.bind(this);
this.applyForBusinessConsultantJob = this.applyForBusinessConsultantJob.bind(this); this.applyForBusinessConsultantJob = this.applyForBusinessConsultantJob.bind(this);
this.applyForBusinessJob = this.applyForBusinessJob.bind(this); this.applyForBusinessJob = this.applyForBusinessJob.bind(this);
@ -54,7 +78,9 @@ export class CompanyLocation extends React.Component<IProps, any> {
this.applyForSoftwareConsultantJob = this.applyForSoftwareConsultantJob.bind(this); this.applyForSoftwareConsultantJob = this.applyForSoftwareConsultantJob.bind(this);
this.applyForSoftwareJob = this.applyForSoftwareJob.bind(this); this.applyForSoftwareJob = this.applyForSoftwareJob.bind(this);
this.applyForWaiterJob = this.applyForWaiterJob.bind(this); this.applyForWaiterJob = this.applyForWaiterJob.bind(this);
this.checkIfEmployedHere = this.checkIfEmployedHere.bind(this);
this.startInfiltration = this.startInfiltration.bind(this); this.startInfiltration = this.startInfiltration.bind(this);
this.work = this.work.bind(this);
this.location = Locations[props.locName]; this.location = Locations[props.locName];
if (this.location == null) { if (this.location == null) {
@ -65,61 +91,91 @@ export class CompanyLocation extends React.Component<IProps, any> {
if (this.company == null) { if (this.company == null) {
throw new Error(`CompanyLocation component constructed with invalid company: ${props.locName}`); throw new Error(`CompanyLocation component constructed with invalid company: ${props.locName}`);
} }
this.state = {
employedHere: false,
}
this.checkIfEmployedHere(false);
} }
applyForAgentJob(e: React.MouseEvent<HTMLElement>) { applyForAgentJob(e: React.MouseEvent<HTMLElement>) {
if (!e.isTrusted) { return false; } if (!e.isTrusted) { return false; }
this.props.p.applyForAgentJob(); this.props.p.applyForAgentJob();
this.checkIfEmployedHere();
} }
applyForBusinessConsultantJob(e: React.MouseEvent<HTMLElement>) { applyForBusinessConsultantJob(e: React.MouseEvent<HTMLElement>) {
if (!e.isTrusted) { return false; } if (!e.isTrusted) { return false; }
this.props.p.applyForBusinessConsultantJob(); this.props.p.applyForBusinessConsultantJob();
this.checkIfEmployedHere();
} }
applyForBusinessJob(e: React.MouseEvent<HTMLElement>) { applyForBusinessJob(e: React.MouseEvent<HTMLElement>) {
if (!e.isTrusted) { return false; } if (!e.isTrusted) { return false; }
this.props.p.applyForBusinessJob(); this.props.p.applyForBusinessJob();
this.checkIfEmployedHere();
} }
applyForEmployeeJob(e: React.MouseEvent<HTMLElement>) { applyForEmployeeJob(e: React.MouseEvent<HTMLElement>) {
if (!e.isTrusted) { return false; } if (!e.isTrusted) { return false; }
this.props.p.applyForEmployeeJob(); this.props.p.applyForEmployeeJob();
this.checkIfEmployedHere();
} }
applyForItJob(e: React.MouseEvent<HTMLElement>) { applyForItJob(e: React.MouseEvent<HTMLElement>) {
if (!e.isTrusted) { return false; } if (!e.isTrusted) { return false; }
this.props.p.applyForItJob(); this.props.p.applyForItJob();
this.checkIfEmployedHere();
} }
applyForPartTimeEmployeeJob(e: React.MouseEvent<HTMLElement>) { applyForPartTimeEmployeeJob(e: React.MouseEvent<HTMLElement>) {
if (!e.isTrusted) { return false; } if (!e.isTrusted) { return false; }
this.props.p.applyForPartTimeEmployeeJob(); this.props.p.applyForPartTimeEmployeeJob();
this.checkIfEmployedHere();
} }
applyForPartTimeWaiterJob(e: React.MouseEvent<HTMLElement>) { applyForPartTimeWaiterJob(e: React.MouseEvent<HTMLElement>) {
if (!e.isTrusted) { return false; } if (!e.isTrusted) { return false; }
this.props.p.applyForPartTimeWaiterJob(); this.props.p.applyForPartTimeWaiterJob();
this.checkIfEmployedHere();
} }
applyForSecurityJob(e: React.MouseEvent<HTMLElement>) { applyForSecurityJob(e: React.MouseEvent<HTMLElement>) {
if (!e.isTrusted) { return false; } if (!e.isTrusted) { return false; }
this.props.p.applyForSecurityJob(); this.props.p.applyForSecurityJob();
this.checkIfEmployedHere();
} }
applyForSoftwareConsultantJob(e: React.MouseEvent<HTMLElement>) { applyForSoftwareConsultantJob(e: React.MouseEvent<HTMLElement>) {
if (!e.isTrusted) { return false; } if (!e.isTrusted) { return false; }
this.props.p.applyForSoftwareConsultantJob(); this.props.p.applyForSoftwareConsultantJob();
this.checkIfEmployedHere();
} }
applyForSoftwareJob(e: React.MouseEvent<HTMLElement>) { applyForSoftwareJob(e: React.MouseEvent<HTMLElement>) {
if (!e.isTrusted) { return false; } if (!e.isTrusted) { return false; }
this.props.p.applyForSoftwareJob(); this.props.p.applyForSoftwareJob();
this.checkIfEmployedHere();
} }
applyForWaiterJob(e: React.MouseEvent<HTMLElement>) { applyForWaiterJob(e: React.MouseEvent<HTMLElement>) {
if (!e.isTrusted) { return false; } if (!e.isTrusted) { return false; }
this.props.p.applyForWaiterJob(); this.props.p.applyForWaiterJob();
this.checkIfEmployedHere();
}
checkIfEmployedHere(updateState=true) {
this.jobTitle = this.props.p.jobs[this.props.locName];
if (this.jobTitle != null) {
this.companyPosition = CompanyPositions[this.jobTitle];
}
if (updateState) {
this.setState({
employedHere: this.jobTitle != null
});
}
} }
startInfiltration(e: React.MouseEvent<HTMLElement>) { startInfiltration(e: React.MouseEvent<HTMLElement>) {
@ -133,9 +189,54 @@ export class CompanyLocation extends React.Component<IProps, any> {
beginInfiltration(this.props.locName, data.startingSecurityLevel, data.baseRewardValue, data.maxClearanceLevel, data.difficulty); beginInfiltration(this.props.locName, data.startingSecurityLevel, data.baseRewardValue, data.maxClearanceLevel, data.difficulty);
} }
work(e: React.MouseEvent<HTMLElement>) {
if (!e.isTrusted) { return false; }
const pos = this.companyPosition;
if (pos instanceof CompanyPosition) {
if (pos.isPartTimeJob() || pos.isSoftwareConsultantJob() || pos.isBusinessConsultantJob()) {
this.props.p.startWorkPartTime(this.props.locName);
} else {
this.props.p.startWork(this.props.locName);
}
}
}
render() { render() {
const isEmployedHere = this.jobTitle != null;
const favorGain = this.company.getFavorGain();
return ( return (
<div> <div>
{
isEmployedHere &&
<div>
<p>Job Title: {this.jobTitle}</p>
<p>--------------------</p>
<p className={"tooltip"}>
Company reputation: {numeralWrapper.format(this.company.playerReputation, "0,0.000")}
<span className={"tooltiptext"}>
You will earn ${numeralWrapper.format(favorGain[0], "0,0")} company
favor upon resetting after installing Augmentations
</span>
</p>
<p>--------------------</p>
<p className={"tooltip"}>
Company Favor: {numeralWrapper.format(this.company.favor, "0,0")}
<span className={"tooltiptext"}>
Company favor increases the rate at which you earn reputation for this company by
1% per favor. Company favor is gained whenever you reset after installing Augmentations. The amount
of favor you gain depends on how much reputation you have with the comapny.
</span>
</p>
<StdButton
id={"foo-work-button-id"}
onClick={this.work}
style={this.btnStyle}
text={"Work"}
/>
</div>
}
{ {
this.company.hasAgentPositions() && this.company.hasAgentPositions() &&
<ApplyToJobButton <ApplyToJobButton
@ -143,6 +244,7 @@ export class CompanyLocation extends React.Component<IProps, any> {
entryPosType={CompanyPositions[posNames.AgentCompanyPositions[0]]} entryPosType={CompanyPositions[posNames.AgentCompanyPositions[0]]}
onClick={this.applyForAgentJob} onClick={this.applyForAgentJob}
p={this.props.p} p={this.props.p}
style={this.btnStyle}
text={"Apply for Agent Job"} text={"Apply for Agent Job"}
/> />
} }
@ -153,6 +255,7 @@ export class CompanyLocation extends React.Component<IProps, any> {
entryPosType={CompanyPositions[posNames.BusinessConsultantCompanyPositions[0]]} entryPosType={CompanyPositions[posNames.BusinessConsultantCompanyPositions[0]]}
onClick={this.applyForBusinessConsultantJob} onClick={this.applyForBusinessConsultantJob}
p={this.props.p} p={this.props.p}
style={this.btnStyle}
text={"Apply for Business Consultant Job"} text={"Apply for Business Consultant Job"}
/> />
} }
@ -163,6 +266,7 @@ export class CompanyLocation extends React.Component<IProps, any> {
entryPosType={CompanyPositions[posNames.BusinessCompanyPositions[0]]} entryPosType={CompanyPositions[posNames.BusinessCompanyPositions[0]]}
onClick={this.applyForBusinessJob} onClick={this.applyForBusinessJob}
p={this.props.p} p={this.props.p}
style={this.btnStyle}
text={"Apply for Business Job"} text={"Apply for Business Job"}
/> />
} }
@ -173,6 +277,7 @@ export class CompanyLocation extends React.Component<IProps, any> {
entryPosType={CompanyPositions[posNames.MiscCompanyPositions[1]]} entryPosType={CompanyPositions[posNames.MiscCompanyPositions[1]]}
onClick={this.applyForEmployeeJob} onClick={this.applyForEmployeeJob}
p={this.props.p} p={this.props.p}
style={this.btnStyle}
text={"Apply to be an Employee"} text={"Apply to be an Employee"}
/> />
} }
@ -183,6 +288,7 @@ export class CompanyLocation extends React.Component<IProps, any> {
entryPosType={CompanyPositions[posNames.PartTimeCompanyPositions[1]]} entryPosType={CompanyPositions[posNames.PartTimeCompanyPositions[1]]}
onClick={this.applyForPartTimeEmployeeJob} onClick={this.applyForPartTimeEmployeeJob}
p={this.props.p} p={this.props.p}
style={this.btnStyle}
text={"Apply to be a part-time Employee"} text={"Apply to be a part-time Employee"}
/> />
} }
@ -193,6 +299,7 @@ export class CompanyLocation extends React.Component<IProps, any> {
entryPosType={CompanyPositions[posNames.ITCompanyPositions[0]]} entryPosType={CompanyPositions[posNames.ITCompanyPositions[0]]}
onClick={this.applyForItJob} onClick={this.applyForItJob}
p={this.props.p} p={this.props.p}
style={this.btnStyle}
text={"Apply for IT Job"} text={"Apply for IT Job"}
/> />
} }
@ -203,6 +310,7 @@ export class CompanyLocation extends React.Component<IProps, any> {
entryPosType={CompanyPositions[posNames.SecurityCompanyPositions[2]]} entryPosType={CompanyPositions[posNames.SecurityCompanyPositions[2]]}
onClick={this.applyForSecurityJob} onClick={this.applyForSecurityJob}
p={this.props.p} p={this.props.p}
style={this.btnStyle}
text={"Apply for Security Job"} text={"Apply for Security Job"}
/> />
} }
@ -213,6 +321,7 @@ export class CompanyLocation extends React.Component<IProps, any> {
entryPosType={CompanyPositions[posNames.SoftwareConsultantCompanyPositions[0]]} entryPosType={CompanyPositions[posNames.SoftwareConsultantCompanyPositions[0]]}
onClick={this.applyForSoftwareConsultantJob} onClick={this.applyForSoftwareConsultantJob}
p={this.props.p} p={this.props.p}
style={this.btnStyle}
text={"Apply for Software Consultant Job"} text={"Apply for Software Consultant Job"}
/> />
} }
@ -223,6 +332,7 @@ export class CompanyLocation extends React.Component<IProps, any> {
entryPosType={CompanyPositions[posNames.SoftwareCompanyPositions[0]]} entryPosType={CompanyPositions[posNames.SoftwareCompanyPositions[0]]}
onClick={this.applyForSoftwareJob} onClick={this.applyForSoftwareJob}
p={this.props.p} p={this.props.p}
style={this.btnStyle}
text={"Apply for Software Job"} text={"Apply for Software Job"}
/> />
} }
@ -233,6 +343,7 @@ export class CompanyLocation extends React.Component<IProps, any> {
entryPosType={CompanyPositions[posNames.MiscCompanyPositions[0]]} entryPosType={CompanyPositions[posNames.MiscCompanyPositions[0]]}
onClick={this.applyForWaiterJob} onClick={this.applyForWaiterJob}
p={this.props.p} p={this.props.p}
style={this.btnStyle}
text={"Apply to be a Waiter"} text={"Apply to be a Waiter"}
/> />
} }
@ -243,6 +354,7 @@ export class CompanyLocation extends React.Component<IProps, any> {
entryPosType={CompanyPositions[posNames.PartTimeCompanyPositions[0]]} entryPosType={CompanyPositions[posNames.PartTimeCompanyPositions[0]]}
onClick={this.applyForPartTimeWaiterJob} onClick={this.applyForPartTimeWaiterJob}
p={this.props.p} p={this.props.p}
style={this.btnStyle}
text={"Apply to be a part-time Waiter"} text={"Apply to be a part-time Waiter"}
/> />
} }
@ -250,6 +362,7 @@ export class CompanyLocation extends React.Component<IProps, any> {
(this.location.infiltrationData != null) && (this.location.infiltrationData != null) &&
<StdButton <StdButton
onClick={this.startInfiltration} onClick={this.startInfiltration}
style={this.btnStyle}
text={"Infiltration Company"} text={"Infiltration Company"}
/> />
} }

@ -33,6 +33,17 @@ type IProps = {
} }
export class GenericLocation extends React.Component<IProps, any> { export class GenericLocation extends React.Component<IProps, any> {
/**
* Stores button styling that sets them all to block display
*/
btnStyle: object;
constructor(props: IProps) {
super(props);
this.btnStyle = { display: "block" };
}
/** /**
* Determine what needs to be rendered for this location based on the locations * Determine what needs to be rendered for this location based on the locations
* type. Returns an array of React components that should be rendered * type. Returns an array of React components that should be rendered
@ -44,6 +55,7 @@ export class GenericLocation extends React.Component<IProps, any> {
content.push( content.push(
<CompanyLocation <CompanyLocation
engine={this.props.engine} engine={this.props.engine}
key={"companylocation"}
locName={this.props.loc.name} locName={this.props.loc.name}
p={this.props.p} p={this.props.p}
/> />
@ -53,6 +65,7 @@ export class GenericLocation extends React.Component<IProps, any> {
if (this.props.loc.types.includes(LocationType.Gym)) { if (this.props.loc.types.includes(LocationType.Gym)) {
content.push( content.push(
<GymLocation <GymLocation
key={"gymlocation"}
loc={this.props.loc} loc={this.props.loc}
p={this.props.p} p={this.props.p}
/> />
@ -62,6 +75,7 @@ export class GenericLocation extends React.Component<IProps, any> {
if (this.props.loc.types.includes(LocationType.Hospital)) { if (this.props.loc.types.includes(LocationType.Hospital)) {
content.push( content.push(
<HospitalLocation <HospitalLocation
key={"hospitallocation"}
p={this.props.p} p={this.props.p}
/> />
) )
@ -70,6 +84,7 @@ export class GenericLocation extends React.Component<IProps, any> {
if (this.props.loc.types.includes(LocationType.Slums)) { if (this.props.loc.types.includes(LocationType.Slums)) {
content.push( content.push(
<SlumsLocation <SlumsLocation
key={"slumslocation"}
p={this.props.p} p={this.props.p}
/> />
) )
@ -79,6 +94,7 @@ export class GenericLocation extends React.Component<IProps, any> {
content.push( content.push(
<SpecialLocation <SpecialLocation
engine={this.props.engine} engine={this.props.engine}
key={"speciallocation"}
loc={this.props.loc} loc={this.props.loc}
p={this.props.p} p={this.props.p}
/> />
@ -88,6 +104,7 @@ export class GenericLocation extends React.Component<IProps, any> {
if (this.props.loc.types.includes(LocationType.TechVendor)) { if (this.props.loc.types.includes(LocationType.TechVendor)) {
content.push( content.push(
<TechVendorLocation <TechVendorLocation
key={"techvendorlocation"}
loc={this.props.loc} loc={this.props.loc}
p={this.props.p} p={this.props.p}
/> />
@ -97,6 +114,7 @@ export class GenericLocation extends React.Component<IProps, any> {
if (this.props.loc.types.includes(LocationType.TravelAgency)) { if (this.props.loc.types.includes(LocationType.TravelAgency)) {
content.push( content.push(
<TravelAgencyLocation <TravelAgencyLocation
key={"travelagencylocation"}
p={this.props.p} p={this.props.p}
travel={this.props.travel} travel={this.props.travel}
/> />
@ -106,6 +124,7 @@ export class GenericLocation extends React.Component<IProps, any> {
if (this.props.loc.types.includes(LocationType.University)) { if (this.props.loc.types.includes(LocationType.University)) {
content.push( content.push(
<UniversityLocation <UniversityLocation
key={"universitylocation"}
loc={this.props.loc} loc={this.props.loc}
p={this.props.p} p={this.props.p}
/> />
@ -120,8 +139,7 @@ export class GenericLocation extends React.Component<IProps, any> {
return ( return (
<div> <div>
<StdButton onClick={this.props.returnToCity} text={"Return to world"} /> <StdButton onClick={this.props.returnToCity} style={this.btnStyle} text={"Return to World"} />
<br />
<h1>{this.props.loc.name}</h1> <h1>{this.props.loc.name}</h1>
{locContent} {locContent}
</div> </div>

@ -19,9 +19,16 @@ type IProps = {
} }
export class GymLocation extends React.Component<IProps, any> { export class GymLocation extends React.Component<IProps, any> {
/**
* Stores button styling that sets them all to block display
*/
btnStyle: object;
constructor(props: IProps) { constructor(props: IProps) {
super(props); super(props);
this.btnStyle = { display: "block" };
this.trainStrength = this.trainStrength.bind(this); this.trainStrength = this.trainStrength.bind(this);
this.trainDefense = this.trainDefense.bind(this); this.trainDefense = this.trainDefense.bind(this);
this.trainDexterity = this.trainDexterity.bind(this); this.trainDexterity = this.trainDexterity.bind(this);
@ -58,18 +65,22 @@ export class GymLocation extends React.Component<IProps, any> {
<div> <div>
<StdButton <StdButton
onClick={this.trainStrength} onClick={this.trainStrength}
style={this.btnStyle}
text={`Train Strength (${numeralWrapper.formatMoney(cost)} / sec)`} text={`Train Strength (${numeralWrapper.formatMoney(cost)} / sec)`}
/> />
<StdButton <StdButton
onClick={this.trainDefense} onClick={this.trainDefense}
style={this.btnStyle}
text={`Train Defense (${numeralWrapper.formatMoney(cost)} / sec)`} text={`Train Defense (${numeralWrapper.formatMoney(cost)} / sec)`}
/> />
<StdButton <StdButton
onClick={this.trainDexterity} onClick={this.trainDexterity}
style={this.btnStyle}
text={`Train Dexterity (${numeralWrapper.formatMoney(cost)} / sec)`} text={`Train Dexterity (${numeralWrapper.formatMoney(cost)} / sec)`}
/> />
<StdButton <StdButton
onClick={this.trainAgility} onClick={this.trainAgility}
style={this.btnStyle}
text={`Train Agility (${numeralWrapper.formatMoney(cost)} / sec)`} text={`Train Agility (${numeralWrapper.formatMoney(cost)} / sec)`}
/> />
</div> </div>

@ -18,9 +18,16 @@ type IProps = {
} }
export class HospitalLocation extends React.Component<IProps, any> { export class HospitalLocation extends React.Component<IProps, any> {
/**
* Stores button styling that sets them all to block display
*/
btnStyle: object;
constructor(props: IProps) { constructor(props: IProps) {
super(props); super(props);
this.btnStyle = { display: "block" };
this.getCost = this.getCost.bind(this); this.getCost = this.getCost.bind(this);
this.getHealed = this.getHealed.bind(this); this.getHealed = this.getHealed.bind(this);
} }
@ -48,6 +55,7 @@ export class HospitalLocation extends React.Component<IProps, any> {
return ( return (
<AutoupdatingStdButton <AutoupdatingStdButton
onClick={this.getHealed} onClick={this.getHealed}
style={this.btnStyle}
text={`Get treatment for wounds - ${numeralWrapper.formatMoney(cost)}`} text={`Get treatment for wounds - ${numeralWrapper.formatMoney(cost)}`}
/> />
) )

@ -20,6 +20,7 @@ import { IPlayer } from "../../PersonObjects/IPlayer";
import { dialogBoxCreate } from "../../../utils/DialogBox"; import { dialogBoxCreate } from "../../../utils/DialogBox";
type IProps = { type IProps = {
initiallyInCity?: boolean;
engine: IEngine; engine: IEngine;
p: IPlayer; p: IPlayer;
} }
@ -36,16 +37,17 @@ export class LocationRoot extends React.Component<IProps, IState> {
this.state = { this.state = {
city: props.p.city, city: props.p.city,
inCity: true, inCity: props.initiallyInCity == null ? true : props.initiallyInCity,
location: props.p.location, location: props.p.location,
} }
this.enterLocation = this.enterLocation.bind(this);
this.returnToCity = this.returnToCity.bind(this); this.returnToCity = this.returnToCity.bind(this);
this.travel = this.travel.bind(this); this.travel = this.travel.bind(this);
} }
enterLocation(to: LocationName): void { enterLocation(to: LocationName): void {
this.props.p.location = to; this.props.p.gotoLocation(to);
this.setState({ this.setState({
inCity: false, inCity: false,
location: to, location: to,
@ -133,6 +135,7 @@ export class LocationRoot extends React.Component<IProps, IState> {
if (this.props.p.travel(to)) { if (this.props.p.travel(to)) {
this.setState({ this.setState({
inCity: true,
city: to city: to
}); });
} }

@ -16,9 +16,16 @@ type IProps = {
} }
export class SlumsLocation extends React.Component<IProps, any> { export class SlumsLocation extends React.Component<IProps, any> {
/**
* Stores button styling that sets them all to block display
*/
btnStyle: object;
constructor(props: IProps) { constructor(props: IProps) {
super(props); super(props);
this.btnStyle = { display: "block" };
this.shoplift = this.shoplift.bind(this); this.shoplift = this.shoplift.bind(this);
this.robStore = this.robStore.bind(this); this.robStore = this.robStore.bind(this);
this.mug = this.mug.bind(this); this.mug = this.mug.bind(this);
@ -40,12 +47,12 @@ export class SlumsLocation extends React.Component<IProps, any> {
robStore(e: React.MouseEvent<HTMLElement>): void { robStore(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) { return; } if (!e.isTrusted) { return; }
Crimes.RobSTore.commit(this.props.p); Crimes.RobStore.commit(this.props.p);
} }
mug(e: React.MouseEvent<HTMLElement>): void { mug(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) { return; } if (!e.isTrusted) { return; }
Crimes.mug.commit(this.props.p); Crimes.Mug.commit(this.props.p);
} }
larceny(e: React.MouseEvent<HTMLElement>): void { larceny(e: React.MouseEvent<HTMLElement>): void {
@ -112,72 +119,84 @@ export class SlumsLocation extends React.Component<IProps, any> {
<AutoupdatingStdButton <AutoupdatingStdButton
intervalTime={5e3} intervalTime={5e3}
onClick={this.shoplift} onClick={this.shoplift}
style={this.btnStyle}
text={`Shoplift (${numeralWrapper.formatPercentage(shopliftChance)} chance of success)`} text={`Shoplift (${numeralWrapper.formatPercentage(shopliftChance)} chance of success)`}
tooltip={"Attempt to shoplift from a low-end retailer"} tooltip={"Attempt to shoplift from a low-end retailer"}
/> />
<AutoupdatingStdButton <AutoupdatingStdButton
intervalTime={5e3} intervalTime={5e3}
onClick={this.robStore} onClick={this.robStore}
style={this.btnStyle}
text={`Rob store (${numeralWrapper.formatPercentage(robStoreChance)} chance of success)`} text={`Rob store (${numeralWrapper.formatPercentage(robStoreChance)} chance of success)`}
tooltip={"Attempt to commit armed robbery on a high-end store"} tooltip={"Attempt to commit armed robbery on a high-end store"}
/> />
<AutoupdatingStdButton <AutoupdatingStdButton
intervalTime={5e3} intervalTime={5e3}
onClick={this.mug} onClick={this.mug}
style={this.btnStyle}
text={`Mug someone (${numeralWrapper.formatPercentage(mugChance)} chance of success)`} text={`Mug someone (${numeralWrapper.formatPercentage(mugChance)} chance of success)`}
tooltip={"Attempt to mug a random person on the street"} tooltip={"Attempt to mug a random person on the street"}
/> />
<AutoupdatingStdButton <AutoupdatingStdButton
intervalTime={5e3} intervalTime={5e3}
onClick={this.larceny} onClick={this.larceny}
style={this.btnStyle}
text={`Larceny (${numeralWrapper.formatPercentage(larcenyChance)} chance of success)`} text={`Larceny (${numeralWrapper.formatPercentage(larcenyChance)} chance of success)`}
tooltip={"Attempt to rob property from someone's house"} tooltip={"Attempt to rob property from someone's house"}
/> />
<AutoupdatingStdButton <AutoupdatingStdButton
intervalTime={5e3} intervalTime={5e3}
onClick={this.dealDrugs} onClick={this.dealDrugs}
style={this.btnStyle}
text={`Deal Drugs (${numeralWrapper.formatPercentage(drugsChance)} chance of success)`} text={`Deal Drugs (${numeralWrapper.formatPercentage(drugsChance)} chance of success)`}
tooltip={"Attempt to deal drugs"} tooltip={"Attempt to deal drugs"}
/> />
<AutoupdatingStdButton <AutoupdatingStdButton
intervalTime={5e3} intervalTime={5e3}
onClick={this.bondForgery} onClick={this.bondForgery}
style={this.btnStyle}
text={`Bond Forgery (${numeralWrapper.formatPercentage(bondChance)} chance of success)`} text={`Bond Forgery (${numeralWrapper.formatPercentage(bondChance)} chance of success)`}
tooltip={"Attempt to forge corporate bonds"} tooltip={"Attempt to forge corporate bonds"}
/> />
<AutoupdatingStdButton <AutoupdatingStdButton
intervalTime={5e3} intervalTime={5e3}
onClick={this.traffickArms} onClick={this.traffickArms}
style={this.btnStyle}
text={`Traffick illegal Arms (${numeralWrapper.formatPercentage(armsChance)} chance of success)`} text={`Traffick illegal Arms (${numeralWrapper.formatPercentage(armsChance)} chance of success)`}
tooltip={"Attempt to smuggle illegal arms into the city"} tooltip={"Attempt to smuggle illegal arms into the city"}
/> />
<AutoupdatingStdButton <AutoupdatingStdButton
intervalTime={5e3} intervalTime={5e3}
onClick={this.homicide} onClick={this.homicide}
style={this.btnStyle}
text={`Homicide (${numeralWrapper.formatPercentage(homicideChance)} chance of success)`} text={`Homicide (${numeralWrapper.formatPercentage(homicideChance)} chance of success)`}
tooltip={"Attempt to murder a random person on the street"} tooltip={"Attempt to murder a random person on the street"}
/> />
<AutoupdatingStdButton <AutoupdatingStdButton
intervalTime={5e3} intervalTime={5e3}
onClick={this.grandTheftAuto} onClick={this.grandTheftAuto}
style={this.btnStyle}
text={`Grand theft Auto (${numeralWrapper.formatPercentage(gtaChance)} chance of success)`} text={`Grand theft Auto (${numeralWrapper.formatPercentage(gtaChance)} chance of success)`}
tooltip={"Attempt to commit grand theft auto"} tooltip={"Attempt to commit grand theft auto"}
/> />
<AutoupdatingStdButton <AutoupdatingStdButton
intervalTime={5e3} intervalTime={5e3}
onClick={this.kidnap} onClick={this.kidnap}
style={this.btnStyle}
text={`Kidnap and Ransom (${numeralWrapper.formatPercentage(kidnapChance)} chance of success)`} text={`Kidnap and Ransom (${numeralWrapper.formatPercentage(kidnapChance)} chance of success)`}
tooltip={"Attempt to kidnap and ransom a high-profile-target"} tooltip={"Attempt to kidnap and ransom a high-profile-target"}
/> />
<AutoupdatingStdButton <AutoupdatingStdButton
intervalTime={5e3} intervalTime={5e3}
onClick={this.assassinate} onClick={this.assassinate}
style={this.btnStyle}
text={`Assassinate (${numeralWrapper.formatPercentage(assassinateChance)} chance of success)`} text={`Assassinate (${numeralWrapper.formatPercentage(assassinateChance)} chance of success)`}
tooltip={"Attempt to assassinate a high-profile target"} tooltip={"Attempt to assassinate a high-profile target"}
/> />
<AutoupdatingStdButton <AutoupdatingStdButton
intervalTime={5e3} intervalTime={5e3}
onClick={this.heist} onClick={this.heist}
style={this.btnStyle}
text={`Heist (${numeralWrapper.formatPercentage(heistChance)} chance of success)`} text={`Heist (${numeralWrapper.formatPercentage(heistChance)} chance of success)`}
tooltip={"Attempt to pull off the ultimate heist"} tooltip={"Attempt to pull off the ultimate heist"}
/> />

@ -35,9 +35,16 @@ type IState = {
} }
export class SpecialLocation extends React.Component<IProps, IState> { export class SpecialLocation extends React.Component<IProps, IState> {
/**
* Stores button styling that sets them all to block display
*/
btnStyle: object;
constructor(props: IProps) { constructor(props: IProps) {
super(props); super(props);
this.btnStyle = { display: "block" };
this.createCorporationPopup = this.createCorporationPopup.bind(this); this.createCorporationPopup = this.createCorporationPopup.bind(this);
this.handleBladeburner = this.handleBladeburner.bind(this); this.handleBladeburner = this.handleBladeburner.bind(this);
this.handleResleeving = this.handleResleeving.bind(this); this.handleResleeving = this.handleResleeving.bind(this);
@ -89,29 +96,35 @@ export class SpecialLocation extends React.Component<IProps, IState> {
} }
renderBladeburner(): React.ReactNode { renderBladeburner(): React.ReactNode {
if (!this.props.p.canAccessBladeburner()) { return null; }
const text = this.state.inBladeburner ? "Enter Bladeburner Headquarters" : "Apply to Bladeburner Division"; const text = this.state.inBladeburner ? "Enter Bladeburner Headquarters" : "Apply to Bladeburner Division";
return ( return (
<StdButton <StdButton
onClick={this.handleBladeburner} onClick={this.handleBladeburner}
style={this.btnStyle}
text={text} text={text}
/> />
) )
} }
renderCreateCorporation(): React.ReactNode { renderCreateCorporation(): React.ReactNode {
if (!this.props.p.canAccessCorporation()) { return null; }
return ( return (
<AutoupdatingStdButton <AutoupdatingStdButton
disabled={this.props.p.hasCorporation()} disabled={!this.props.p.canAccessCorporation() || this.props.p.hasCorporation()}
onClick={this.createCorporationPopup} onClick={this.createCorporationPopup}
style={this.btnStyle}
text={"Create a Corporation"} text={"Create a Corporation"}
/> />
) )
} }
renderResleeving(): React.ReactNode { renderResleeving(): React.ReactNode {
if (!this.props.p.canAccessResleeving()) { return null; }
return ( return (
<StdButton <StdButton
onClick={this.handleResleeving} onClick={this.handleResleeving}
style={this.btnStyle}
text={"Re-Sleeve"} text={"Re-Sleeve"}
/> />
) )

@ -25,9 +25,16 @@ type IProps = {
} }
export class TechVendorLocation extends React.Component<IProps, any> { export class TechVendorLocation extends React.Component<IProps, any> {
/**
* Stores button styling that sets them all to block display
*/
btnStyle: object;
constructor(props: IProps) { constructor(props: IProps) {
super(props); super(props);
this.btnStyle = { display: "block" };
this.state = { this.state = {
torPurchased: props.p.hasTorRouter(), torPurchased: props.p.hasTorRouter(),
} }
@ -59,6 +66,7 @@ export class TechVendorLocation extends React.Component<IProps, any> {
<StdButton <StdButton
key={i} key={i}
onClick={() => createPurchaseServerPopup(i, this.props.p)} onClick={() => createPurchaseServerPopup(i, this.props.p)}
style={this.btnStyle}
text={`Purchase ${i}GB Server - ${numeralWrapper.formatMoney(cost)}`} text={`Purchase ${i}GB Server - ${numeralWrapper.formatMoney(cost)}`}
/> />
) )
@ -70,11 +78,13 @@ export class TechVendorLocation extends React.Component<IProps, any> {
{ {
this.state.torPurchased ? ( this.state.torPurchased ? (
<StdButtonPurchased <StdButtonPurchased
style={this.btnStyle}
text={"TOR Router - Purchased"} text={"TOR Router - Purchased"}
/> />
) : ( ) : (
<StdButton <StdButton
onClick={this.purchaseTorRouter} onClick={this.purchaseTorRouter}
style={this.btnStyle}
text={`Purchase TOR Router - ${numeralWrapper.formatMoney(CONSTANTS.TorRouterCost)}`} text={`Purchase TOR Router - ${numeralWrapper.formatMoney(CONSTANTS.TorRouterCost)}`}
/> />
) )
@ -82,10 +92,12 @@ export class TechVendorLocation extends React.Component<IProps, any> {
} }
<StdButton <StdButton
onClick={this.createUpgradeHomeRamPopup} onClick={this.createUpgradeHomeRamPopup}
style={this.btnStyle}
text={`Purchase additional RAM for Home computer`} text={`Purchase additional RAM for Home computer`}
/> />
<StdButton <StdButton
onClick={this.createUpgradeHomeCoresPopup} onClick={this.createUpgradeHomeCoresPopup}
style={this.btnStyle}
text={`Purchase additional Core for Home computer`} text={`Purchase additional Core for Home computer`}
/> />
</div> </div>

@ -20,8 +20,15 @@ type IProps = {
} }
export class TravelAgencyLocation extends React.Component<IProps, any> { export class TravelAgencyLocation extends React.Component<IProps, any> {
/**
* Stores button styling that sets them all to block display
*/
btnStyle: object;
constructor(props: IProps) { constructor(props: IProps) {
super(props); super(props);
this.btnStyle = { display: "block" };
} }
render() { render() {
@ -36,6 +43,7 @@ export class TravelAgencyLocation extends React.Component<IProps, any> {
<StdButton <StdButton
key={city} key={city}
onClick={createTravelPopup.bind(null, city, this.props.travel)} onClick={createTravelPopup.bind(null, city, this.props.travel)}
style={this.btnStyle}
text={`Travel to ${city}`} text={`Travel to ${city}`}
/> />
) )
@ -44,8 +52,8 @@ export class TravelAgencyLocation extends React.Component<IProps, any> {
return ( return (
<div> <div>
<p> <p>
From here, you can travel to any other city! A ticket costs From here, you can travel to any other city! A ticket
{numeralWrapper.formatMoney(CONSTANTS.TravelCost)} costs {numeralWrapper.formatMoney(CONSTANTS.TravelCost)}
</p> </p>
{travelBtns} {travelBtns}
</div> </div>

@ -19,10 +19,18 @@ type IProps = {
} }
export class UniversityLocation extends React.Component<IProps, any> { export class UniversityLocation extends React.Component<IProps, any> {
/**
* Stores button styling that sets them all to block display
*/
btnStyle: object;
constructor(props: IProps) { constructor(props: IProps) {
super(props); super(props);
this.btnStyle = { display: "block" };
this.take = this.take.bind(this); this.take = this.take.bind(this);
this.study = this.study.bind(this);
this.dataStructures = this.dataStructures.bind(this); this.dataStructures = this.dataStructures.bind(this);
this.networks = this.networks.bind(this); this.networks = this.networks.bind(this);
this.algorithms = this.algorithms.bind(this); this.algorithms = this.algorithms.bind(this);
@ -72,26 +80,32 @@ export class UniversityLocation extends React.Component<IProps, any> {
<div> <div>
<StdButton <StdButton
onClick={this.study} onClick={this.study}
style={this.btnStyle}
text={`Study Computer Science (free)`} text={`Study Computer Science (free)`}
/> />
<StdButton <StdButton
onClick={this.dataStructures} onClick={this.dataStructures}
style={this.btnStyle}
text={`Take Data Structures course (${numeralWrapper.formatMoney(dataStructuresCost)} / sec)`} text={`Take Data Structures course (${numeralWrapper.formatMoney(dataStructuresCost)} / sec)`}
/> />
<StdButton <StdButton
onClick={this.networks} onClick={this.networks}
style={this.btnStyle}
text={`Take Networks course (${numeralWrapper.formatMoney(networksCost)} / sec)`} text={`Take Networks course (${numeralWrapper.formatMoney(networksCost)} / sec)`}
/> />
<StdButton <StdButton
onClick={this.algorithms} onClick={this.algorithms}
style={this.btnStyle}
text={`Take Algorithms course (${numeralWrapper.formatMoney(algorithmsCost)} / sec)`} text={`Take Algorithms course (${numeralWrapper.formatMoney(algorithmsCost)} / sec)`}
/> />
<StdButton <StdButton
onClick={this.management} onClick={this.management}
style={this.btnStyle}
text={`Take Management course (${numeralWrapper.formatMoney(managementCost)} / sec)`} text={`Take Management course (${numeralWrapper.formatMoney(managementCost)} / sec)`}
/> />
<StdButton <StdButton
onClick={this.leadership} onClick={this.leadership}
style={this.btnStyle}
text={`Take Leadership course (${numeralWrapper.formatMoney(leadershipCost)} / sec)`} text={`Take Leadership course (${numeralWrapper.formatMoney(leadershipCost)} / sec)`}
/> />
</div> </div>

@ -33,6 +33,7 @@ export interface IPlayer {
hacknetNodes: (HacknetNode | string)[]; // HacknetNode object or IP of Hacknet Server hacknetNodes: (HacknetNode | string)[]; // HacknetNode object or IP of Hacknet Server
hashManager: HashManager; hashManager: HashManager;
hasWseAccount: boolean; hasWseAccount: boolean;
homeComputer: string;
hp: number; hp: number;
jobs: IMap<string>; jobs: IMap<string>;
karma: number; karma: number;
@ -111,6 +112,9 @@ export interface IPlayer {
applyForSoftwareConsultantJob(sing?: boolean): boolean | void; applyForSoftwareConsultantJob(sing?: boolean): boolean | void;
applyForSoftwareJob(sing?: boolean): boolean | void; applyForSoftwareJob(sing?: boolean): boolean | void;
applyForWaiterJob(sing?: boolean): boolean | void; applyForWaiterJob(sing?: boolean): boolean | void;
canAccessBladeburner(): boolean;
canAccessCorporation(): boolean;
canAccessResleeving(): boolean;
canAfford(cost: number): boolean; canAfford(cost: number): boolean;
gainHackingExp(exp: number): void; gainHackingExp(exp: number): void;
gainStrengthExp(exp: number): void; gainStrengthExp(exp: number): void;
@ -122,6 +126,7 @@ export interface IPlayer {
getHomeComputer(): Server; getHomeComputer(): Server;
getNextCompanyPosition(company: Company, entryPosType: CompanyPosition): CompanyPosition; getNextCompanyPosition(company: Company, entryPosType: CompanyPosition): CompanyPosition;
getUpgradeHomeRamCost(): number; getUpgradeHomeRamCost(): number;
gotoLocation(to: LocationName): boolean;
hasCorporation(): boolean; hasCorporation(): boolean;
hasTorRouter(): boolean; hasTorRouter(): boolean;
inBladeburner(): boolean; inBladeburner(): boolean;
@ -145,5 +150,7 @@ export interface IPlayer {
money: number, money: number,
time: number, time: number,
singParams: any): void; singParams: any): void;
startWork(companyName: string): void;
startWorkPartTime(companyName: string): void;
travel(to: CityName): boolean; travel(to: CityName): boolean;
} }

@ -0,0 +1,212 @@
import * as generalMethods from "./PlayerObjectGeneralMethods";
import * as serverMethods from "./PlayerObjectServerMethods";
import * as bladeburnerMethods from "./PlayerObjectBladeburnerMethods";
import * as corporationMethods from "./PlayerObjectCorporationMethods";
import { HashManager } from "../../Hacknet/HashManager";
import { CityName } from "../../Locations/data/CityNames";
import { MoneySourceTracker } from "../../utils/MoneySourceTracker";
import { Reviver,
Generic_toJSON,
Generic_fromJSON } from "../../../utils/JSONReviver";
import Decimal from "decimal.js";
export function PlayerObject() {
//Skills and stats
this.hacking_skill = 1;
//Combat stats
this.hp = 10;
this.max_hp = 10;
this.strength = 1;
this.defense = 1;
this.dexterity = 1;
this.agility = 1;
//Labor stats
this.charisma = 1;
//Special stats
this.intelligence = 0;
//Hacking multipliers
this.hacking_chance_mult = 1;
this.hacking_speed_mult = 1;
this.hacking_money_mult = 1;
this.hacking_grow_mult = 1;
//Experience and multipliers
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.hacking_mult = 1;
this.strength_mult = 1;
this.defense_mult = 1;
this.dexterity_mult = 1;
this.agility_mult = 1;
this.charisma_mult = 1;
this.hacking_exp_mult = 1;
this.strength_exp_mult = 1;
this.defense_exp_mult = 1;
this.dexterity_exp_mult = 1;
this.agility_exp_mult = 1;
this.charisma_exp_mult = 1;
this.company_rep_mult = 1;
this.faction_rep_mult = 1;
//Money
this.money = new Decimal(1000);
//IP Address of Starting (home) computer
this.homeComputer = "";
//Location information
this.city = CityName.Sector12;
this.location = "";
// Jobs that the player holds
// Map of company name (key) -> name of company position (value. Just the name, not the CompanyPosition object)
// The CompanyPosition name must match a key value in CompanyPositions
this.jobs = {};
// Company at which player is CURRENTLY working (only valid when the player is actively working)
this.companyName = ""; // Name of Company. Must match a key value in Companies map
// Servers
this.currentServer = ""; //IP address of Server currently being accessed through terminal
this.purchasedServers = []; //IP Addresses of purchased servers
// Hacknet Nodes/Servers
this.hacknetNodes = []; // Note: For Hacknet Servers, this array holds the IP addresses of the servers
this.hashManager = new HashManager();
//Factions
this.factions = []; //Names of all factions player has joined
this.factionInvitations = []; //Outstanding faction invitations
//Augmentations
this.queuedAugmentations = [];
this.augmentations = [];
this.sourceFiles = [];
//Crime statistics
this.numPeopleKilled = 0;
this.karma = 0;
this.crime_money_mult = 1;
this.crime_success_mult = 1;
//Flags/variables for working (Company, Faction, Creating Program, Taking Class)
this.isWorking = false;
this.workType = "";
this.currentWorkFactionName = "";
this.currentWorkFactionDescription = "";
this.workHackExpGainRate = 0;
this.workStrExpGainRate = 0;
this.workDefExpGainRate = 0;
this.workDexExpGainRate = 0;
this.workAgiExpGainRate = 0;
this.workChaExpGainRate = 0;
this.workRepGainRate = 0;
this.workMoneyGainRate = 0;
this.workMoneyLossRate = 0;
this.workHackExpGained = 0;
this.workStrExpGained = 0;
this.workDefExpGained = 0;
this.workDexExpGained = 0;
this.workAgiExpGained = 0;
this.workChaExpGained = 0;
this.workRepGained = 0;
this.workMoneyGained = 0;
this.createProgramName = "";
this.createProgramReqLvl = 0;
this.className = "";
this.crimeType = "";
this.timeWorked = 0; //in ms
this.timeWorkedCreateProgram = 0;
this.timeNeededToCompleteWork = 0;
this.work_money_mult = 1;
//Hacknet Node multipliers
this.hacknet_node_money_mult = 1;
this.hacknet_node_purchase_cost_mult = 1;
this.hacknet_node_ram_cost_mult = 1;
this.hacknet_node_core_cost_mult = 1;
this.hacknet_node_level_cost_mult = 1;
//Stock Market
this.hasWseAccount = false;
this.hasTixApiAccess = false;
this.has4SData = false;
this.has4SDataTixApi = false;
//Gang
this.gang = 0;
//Corporation
this.corporation = 0;
//Bladeburner
this.bladeburner = 0;
this.bladeburner_max_stamina_mult = 1;
this.bladeburner_stamina_gain_mult = 1;
this.bladeburner_analysis_mult = 1; //Field Analysis Only
this.bladeburner_success_chance_mult = 1;
// Sleeves & Re-sleeving
this.sleeves = [];
this.resleeves = [];
this.sleevesFromCovenant = 0; // # of Duplicate sleeves purchased from the covenant
//bitnode
this.bitNodeN = 1;
//Flags for determining whether certain "thresholds" have been achieved
this.firstFacInvRecvd = false;
this.firstAugPurchased = false;
this.firstTimeTraveled = false;
this.firstProgramAvailable = false;
//Used to store the last update time.
this.lastUpdate = 0;
this.totalPlaytime = 0;
this.playtimeSinceLastAug = 0;
this.playtimeSinceLastBitnode = 0;
// Keep track of where money comes from
this.moneySourceA = new MoneySourceTracker(); // Where money comes from since last-installed Augmentation
this.moneySourceB = new MoneySourceTracker(); // Where money comes from for this entire BitNode run
// Production since last Augmentation installation
this.scriptProdSinceLastAug = 0;
};
Object.assign(PlayerObject.prototype, generalMethods, serverMethods, bladeburnerMethods, corporationMethods);
PlayerObject.prototype.toJSON = function() {
return Generic_toJSON("PlayerObject", this);
}
PlayerObject.fromJSON = function(value) {
return Generic_fromJSON(PlayerObject, value.data);
}
Reviver.constructors.PlayerObject = PlayerObject;

@ -0,0 +1,17 @@
import { Bladeburner } from "../../Bladeburner";
import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
export function canAccessBladeburner() {
if (this.bitNodeN === 8) { return false; }
return (this.bitNodeN === 6) || (this.bitNodeN === 7) || (SourceFileFlags[6] > 0);
}
export function inBladeburner() {
if (this.bladeburner == null) { return false; }
return (this.bladeburner instanceof Bladeburner);
}
export function startBladeburner() {
this.bladeburner = new Bladeburner({ new: true });
}

@ -0,0 +1,19 @@
import { Corporation } from "../../Corporation/Corporation";
import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
export function canAccessCorporation() {
return this.bitNodeN === 3 || (SourceFileFlags[3] > 0);
}
export function hasCorporation() {
if (this.corporation == null) { return false; }
return (this.corporation instanceof Corporation);
}
export function startCorporation(corpName, additionalShares=0) {
this.corporation = new Corporation({
name: corpName
});
this.corporation.totalShares += additionalShares;
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,30 @@
import { IPlayer } from "../IPlayer";
import { CONSTANTS } from "../../Constants";
import { AllServers } from "../../Server/AllServers";
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
import { SpecialServerIps } from "../../Server/SpecialServerIps";
export function hasTorRouter(this: IPlayer) {
return SpecialServerIps.hasOwnProperty("Darkweb Server");
}
export function getCurrentServer(this: IPlayer) {
return AllServers[this.currentServer];
}
export function getHomeComputer(this: IPlayer) {
return AllServers[this.homeComputer];
}
export function getUpgradeHomeRamCost(this: IPlayer) {
//Calculate how many times ram has been upgraded (doubled)
const currentRam = this.getHomeComputer().maxRam;
const numUpgrades = Math.log2(currentRam);
//Calculate cost
//Have cost increase by some percentage each time RAM has been upgraded
const mult = Math.pow(1.58, numUpgrades);
var cost = currentRam * CONSTANTS.BaseCostFor1GBOfRamHome * mult * BitNodeMultipliers.HomeComputerRamCost;
return cost;
}

File diff suppressed because it is too large Load Diff

@ -33,6 +33,7 @@ import { hasHacknetServers,
processHacknetEarnings } from "./Hacknet/HacknetHelpers"; processHacknetEarnings } from "./Hacknet/HacknetHelpers";
import {iTutorialStart} from "./InteractiveTutorial"; import {iTutorialStart} from "./InteractiveTutorial";
import {initLiterature} from "./Literature"; import {initLiterature} from "./Literature";
import { LocationName } from "./Locations/data/LocationNames";
import { LocationRoot } from "./Locations/ui/Root"; import { LocationRoot } from "./Locations/ui/Root";
import { checkForMessagesToSend, initMessages } from "./Message/MessageHelpers"; import { checkForMessagesToSend, initMessages } from "./Message/MessageHelpers";
import {inMission, currMission} from "./Missions"; import {inMission, currMission} from "./Missions";
@ -343,12 +344,14 @@ const Engine = {
MainMenuLinks.DevMenu.classList.add("active"); MainMenuLinks.DevMenu.classList.add("active");
}, },
loadLocationContent: function() { loadLocationContent: function(initiallyInCity=true) {
Engine.hideAllContent(); Engine.hideAllContent();
Engine.Display.locationContent.style.display = "block"; Engine.Display.locationContent.style.display = "block";
MainMenuLinks.City.classList.add("active");
routing.navigateTo(Page.Location); routing.navigateTo(Page.Location);
const rootComponent = <LocationRoot const rootComponent = <LocationRoot
initiallyInCity={initiallyInCity}
engine={Engine} engine={Engine}
p={Player} p={Player}
/> />
@ -356,18 +359,42 @@ const Engine = {
}, },
loadTravelContent: function() { loadTravelContent: function() {
// Same as loadLocationContent() except first set the location to the travel agency,
// and make sure that the 'City' main menu link doesnt become 'active'
Engine.hideAllContent();
Player.gotoLocation(LocationName.TravelAgency); Player.gotoLocation(LocationName.TravelAgency);
Engine.loadLocationContent(); Engine.Display.locationContent.style.display = "block";
MainMenuLinks.Travel.classList.add("active");
routing.navigateTo(Page.Location);
const rootComponent = <LocationRoot
initiallyInCity={false}
engine={Engine}
p={Player}
/>
ReactDOM.render(rootComponent, Engine.Display.locationContent);
}, },
loadJobContent: function() { loadJobContent: function() {
// Same as loadLocationContent(), except first set the location to the job.
// Make sure that the 'City' main menu link doesnt become 'active'
if (Player.companyName == "") { if (Player.companyName == "") {
dialogBoxCreate("You do not currently have a job! You can visit various companies " + dialogBoxCreate("You do not currently have a job! You can visit various companies " +
"in the city and try to find a job."); "in the city and try to find a job.");
return; return;
} }
Player.location = Player.companyName; Engine.hideAllContent();
Engine.loadLocationContent(); Player.gotoLocation(Player.companyName);
Engine.Display.locationContent.style.display = "block";
MainMenuLinks.Job.classList.add("active");
routing.navigateTo(Page.Location);
const rootComponent = <LocationRoot
initiallyInCity={false}
engine={Engine}
p={Player}
/>
ReactDOM.render(rootComponent, Engine.Display.locationContent);
}, },
loadWorkInProgressContent: function() { loadWorkInProgressContent: function() {
@ -469,7 +496,7 @@ const Engine = {
} }
}, },
//Helper function that hides all content // Helper function that hides all content
hideAllContent: function() { hideAllContent: function() {
Engine.Display.terminalContent.style.display = "none"; Engine.Display.terminalContent.style.display = "none";
Engine.Display.characterContent.style.display = "none"; Engine.Display.characterContent.style.display = "none";
@ -483,6 +510,7 @@ const Engine = {
Engine.Display.augmentationsContent.style.display = "none"; Engine.Display.augmentationsContent.style.display = "none";
Engine.Display.tutorialContent.style.display = "none"; Engine.Display.tutorialContent.style.display = "none";
Engine.Display.locationContent.style.display = "none"; Engine.Display.locationContent.style.display = "none";
ReactDOM.unmountComponentAtNode(Engine.Display.locationContent);
Engine.Display.workInProgressContent.style.display = "none"; Engine.Display.workInProgressContent.style.display = "none";
Engine.Display.redPillContent.style.display = "none"; Engine.Display.redPillContent.style.display = "none";
Engine.Display.cinematicTextContent.style.display = "none"; Engine.Display.cinematicTextContent.style.display = "none";
@ -507,7 +535,15 @@ const Engine = {
clearResleevesPage(); clearResleevesPage();
clearSleevesPage(); clearSleevesPage();
//Make nav menu tabs inactive // Make nav menu tabs inactive
Engine.inactivateMainMenuLinks();
// Close dev menu
closeDevMenu();
},
// Remove 'active' css class from all main menu links
inactivateMainMenuLinks: function() {
MainMenuLinks.Terminal.classList.remove("active"); MainMenuLinks.Terminal.classList.remove("active");
MainMenuLinks.ScriptEditor.classList.remove("active"); MainMenuLinks.ScriptEditor.classList.remove("active");
MainMenuLinks.ActiveScripts.classList.remove("active"); MainMenuLinks.ActiveScripts.classList.remove("active");
@ -527,9 +563,6 @@ const Engine = {
MainMenuLinks.Tutorial.classList.remove("active"); MainMenuLinks.Tutorial.classList.remove("active");
MainMenuLinks.Options.classList.remove("active"); MainMenuLinks.Options.classList.remove("active");
MainMenuLinks.DevMenu.classList.remove("active"); MainMenuLinks.DevMenu.classList.remove("active");
// Close dev menu
closeDevMenu();
}, },
displayCharacterOverviewInfo: function() { displayCharacterOverviewInfo: function() {
@ -1334,13 +1367,11 @@ const Engine = {
MainMenuLinks.Travel.addEventListener("click", function() { MainMenuLinks.Travel.addEventListener("click", function() {
Engine.loadTravelContent(); Engine.loadTravelContent();
MainMenuLinks.Travel.classList.add("active");
return false; return false;
}); });
MainMenuLinks.Job.addEventListener("click", function() { MainMenuLinks.Job.addEventListener("click", function() {
Engine.loadJobContent(); Engine.loadJobContent();
MainMenuLinks.Job.classList.add("active");
return false; return false;
}); });

@ -19,6 +19,10 @@ interface IState {
i: number; i: number;
} }
type IInnerHTMLMarkup = {
__html: string;
}
export class AutoupdatingStdButton extends React.Component<IProps, IState> { export class AutoupdatingStdButton extends React.Component<IProps, IState> {
/** /**
* Timer ID for auto-updating implementation (returned value from setInterval()) * Timer ID for auto-updating implementation (returned value from setInterval())
@ -48,21 +52,27 @@ export class AutoupdatingStdButton extends React.Component<IProps, IState> {
} }
render() { render() {
const hasTooltip = this.props.tooltip !== ""; const hasTooltip = this.props.tooltip != null && this.props.tooltip !== "";
let className = this.props.disabled ? "std-button-disabled" : "std-button"; let className = this.props.disabled ? "std-button-disabled" : "std-button";
if (hasTooltip) { if (hasTooltip) {
className += " tooltip" className += " tooltip"
} }
// Tooltip will eb set using inner HTML
let tooltipMarkup: IInnerHTMLMarkup | null;
if (hasTooltip) {
tooltipMarkup = {
__html: this.props.tooltip!
}
}
return ( return (
<button className={className} onClick={this.props.onClick} style={this.props.style}> <button className={className} onClick={this.props.onClick} style={this.props.style}>
{this.props.text} {this.props.text}
{ {
hasTooltip && hasTooltip &&
<span className={"tooltiptext"}> <span className={"tooltiptext"} dangerouslySetInnerHTML={tooltipMarkup!}></span>
{this.props.tooltip}
</span>
} }
</button> </button>
) )

@ -6,28 +6,39 @@ import * as React from "react";
interface IStdButtonProps { interface IStdButtonProps {
disabled?: boolean; disabled?: boolean;
id?: string;
onClick?: (e: React.MouseEvent<HTMLElement>) => any; onClick?: (e: React.MouseEvent<HTMLElement>) => any;
style?: object; style?: object;
text: string; text: string;
tooltip?: string; tooltip?: string;
} }
type IInnerHTMLMarkup = {
__html: string;
}
export class StdButton extends React.Component<IStdButtonProps, any> { export class StdButton extends React.Component<IStdButtonProps, any> {
render() { render() {
const hasTooltip = this.props.tooltip !== ""; const hasTooltip = this.props.tooltip != null && this.props.tooltip !== "";
let className = this.props.disabled ? "std-button-disabled" : "std-button"; let className = this.props.disabled ? "std-button-disabled" : "std-button";
if (hasTooltip) { if (hasTooltip) {
className += " tooltip"; className += " tooltip";
} }
// Tooltip will be set using inner HTML
let tooltipMarkup: IInnerHTMLMarkup | null;
if (hasTooltip) {
tooltipMarkup = {
__html: this.props.tooltip!
}
}
return ( return (
<button className={className} onClick={this.props.onClick} style={this.props.style}> <button className={className} id={this.props.id} onClick={this.props.onClick} style={this.props.style}>
{this.props.text} {this.props.text}
{ {
hasTooltip && hasTooltip &&
<span className={"tooltiptext"}> <span className={"tooltiptext"} dangerouslySetInnerHTML={tooltipMarkup!}></span>
{this.props.tooltip}
</span>
} }
</button> </button>
) )