Merge pull request #591 from danielyxie/location-code-refactor

Location code refactor
This commit is contained in:
danielyxie 2019-04-03 20:38:02 -07:00 committed by GitHub
commit fb857642e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
60 changed files with 5730 additions and 5713 deletions

@ -6,7 +6,6 @@ import { Engine } from "./engine";
import { Faction } from "./Faction/Faction";
import { Factions, factionExists } from "./Faction/Factions";
import { joinFaction, displayFactionContent } from "./Faction/FactionHelpers";
import { Locations } from "./Locations";
import { Player } from "./Player";
import { hackWorldDaemon, redPillFlag } from "./RedPill";
import { numeralWrapper } from "./ui/numeralFormat";
@ -218,7 +217,7 @@ $(document).keydown(function(event) {
});
function City(params={}) {
this.name = params.name ? params.name : Locations.Sector12;
this.name = params.name ? params.name : CityNames[2]; // Sector-12
//Synthoid population and estimate
this.pop = params.pop ? params.pop : getRandomInt(PopulationThreshold, 1.5 * PopulationThreshold);
@ -690,7 +689,7 @@ function Bladeburner(params={}) {
for (var i = 0; i < CityNames.length; ++i) {
this.cities[CityNames[i]] = new City({name:CityNames[i]});
}
this.city = Locations.Sector12;
this.city = CityNames[2]; // Sector-12
//Map of SkillNames -> level
this.skills = {};

@ -1,8 +1,11 @@
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver";
import { CompanyPosition } from "./CompanyPosition";
import * as posNames from "./data/companypositionnames";
import { CONSTANTS } from "../Constants";
import { IMap } from "../types";
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver";
export interface IConstructorParams {
name: string;
info: string;
@ -93,6 +96,43 @@ export class Company {
}
}
hasAgentPositions(): boolean {
return (this.companyPositions[posNames.AgentCompanyPositions[0]] != null);
}
hasBusinessConsultantPositions(): boolean {
return (this.companyPositions[posNames.BusinessConsultantCompanyPositions[0]] != null);
}
hasBusinessPositions(): boolean {
return (this.companyPositions[posNames.BusinessCompanyPositions[0]] != null);
}
hasEmployeePositions(): boolean {
return (this.companyPositions[posNames.MiscCompanyPositions[1]] != null);
}
hasITPositions(): boolean {
return (this.companyPositions[posNames.ITCompanyPositions[0]] != null);
}
hasSecurityPositions(): boolean {
return (this.companyPositions[posNames.SecurityCompanyPositions[2]] != null);
}
hasSoftwareConsultantPositions(): boolean {
return (this.companyPositions[posNames.SoftwareConsultantCompanyPositions[0]] != null);
}
hasSoftwarePositions(): boolean {
return (this.companyPositions[posNames.SoftwareCompanyPositions[0]] != null);
}
hasWaiterPositions(): boolean {
return (this.companyPositions[posNames.MiscCompanyPositions[0]] != null);
}
gainFavor(): void {
if (this.favor == null) { this.favor = 0; }
if (this.rolloverRep == null) { this.rolloverRep = 0; }

@ -1,5 +1,5 @@
import { CONSTANTS } from "../Constants";
import * as names from "./data/CompanyPositionNames";
import * as names from "./data/companypositionnames";
/* tslint:disable:completed-docs */

@ -3,7 +3,7 @@
import { CompanyPosition } from "./CompanyPosition";
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; }
const nextPosName: string | null = currPos.nextPosition;

@ -1,7 +1,8 @@
import { IConstructorParams } from "../Company";
import { Locations } from "../../Locations";
import * as posNames from "./CompanyPositionNames";
import { IMap } from "../../types";
import * as posNames from "./companypositionnames";
import { IConstructorParams } from "../Company";
import { IMap } from "../../types";
import { LocationName } from "../../Locations/data/LocationNames";
// Create Objects containing Company Positions by category
// Will help in metadata construction later
@ -89,7 +90,7 @@ CEOOnly[posNames.BusinessCompanyPositions[5]] = true;
// Metadata
export const companiesMetadata: IConstructorParams[] = [
{
name: Locations.AevumECorp,
name: LocationName.AevumECorp,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -101,7 +102,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 249,
},
{
name: Locations.Sector12MegaCorp,
name: LocationName.Sector12MegaCorp,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -113,7 +114,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 249,
},
{
name: Locations.AevumBachmanAndAssociates,
name: LocationName.AevumBachmanAndAssociates,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -125,7 +126,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 224,
},
{
name: Locations.Sector12BladeIndustries,
name: LocationName.Sector12BladeIndustries,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -137,7 +138,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 224,
},
{
name: Locations.VolhavenNWO,
name: LocationName.VolhavenNWO,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -149,7 +150,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 249,
},
{
name: Locations.AevumClarkeIncorporated,
name: LocationName.AevumClarkeIncorporated,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -161,7 +162,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 224,
},
{
name: Locations.VolhavenOmniTekIncorporated,
name: LocationName.VolhavenOmniTekIncorporated,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -173,7 +174,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 224,
},
{
name: Locations.Sector12FourSigma,
name: LocationName.Sector12FourSigma,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -185,7 +186,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 224,
},
{
name: Locations.ChongqingKuaiGongInternational,
name: LocationName.ChongqingKuaiGongInternational,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -197,7 +198,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 224,
},
{
name: Locations.AevumFulcrumTechnologies,
name: LocationName.AevumFulcrumTechnologies,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -208,7 +209,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 224,
},
{
name: Locations.IshimaStormTechnologies,
name: LocationName.IshimaStormTechnologies,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -220,7 +221,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 199,
},
{
name: Locations.NewTokyoDefComm,
name: LocationName.NewTokyoDefComm,
info: "",
companyPositions: Object.assign({},
CEOOnly,
@ -232,7 +233,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 199,
},
{
name: Locations.VolhavenHeliosLabs,
name: LocationName.VolhavenHeliosLabs,
info: "",
companyPositions: Object.assign({},
CEOOnly,
@ -244,7 +245,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 199,
},
{
name: Locations.NewTokyoVitaLife,
name: LocationName.NewTokyoVitaLife,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -256,7 +257,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 199,
},
{
name: Locations.Sector12IcarusMicrosystems,
name: LocationName.Sector12IcarusMicrosystems,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -268,7 +269,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 199,
},
{
name: Locations.Sector12UniversalEnergy,
name: LocationName.Sector12UniversalEnergy,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -280,7 +281,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 199,
},
{
name: Locations.AevumGalacticCybersystems,
name: LocationName.AevumGalacticCybersystems,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -292,7 +293,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 199,
},
{
name: Locations.AevumAeroCorp,
name: LocationName.AevumAeroCorp,
info: "",
companyPositions: Object.assign({},
CEOOnly,
@ -305,7 +306,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 199,
},
{
name: Locations.VolhavenOmniaCybersystems,
name: LocationName.VolhavenOmniaCybersystems,
info: "",
companyPositions: Object.assign({},
CEOOnly,
@ -318,7 +319,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 199,
},
{
name: Locations.ChongqingSolarisSpaceSystems,
name: LocationName.ChongqingSolarisSpaceSystems,
info: "",
companyPositions: Object.assign({},
CEOOnly,
@ -331,7 +332,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 199,
},
{
name: Locations.Sector12DeltaOne,
name: LocationName.Sector12DeltaOne,
info: "",
companyPositions: Object.assign({},
CEOOnly,
@ -344,7 +345,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 199,
},
{
name: Locations.NewTokyoGlobalPharmaceuticals,
name: LocationName.NewTokyoGlobalPharmaceuticals,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -357,7 +358,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 224,
},
{
name: Locations.IshimaNovaMedical,
name: LocationName.IshimaNovaMedical,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -370,7 +371,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 199,
},
{
name: Locations.Sector12CIA,
name: LocationName.Sector12CIA,
info: "",
companyPositions: Object.assign({},
SoftwarePositionsUpToHeadOfEngineering,
@ -385,7 +386,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 149,
},
{
name: Locations.Sector12NSA,
name: LocationName.Sector12NSA,
info: "",
companyPositions: Object.assign({},
SoftwarePositionsUpToHeadOfEngineering,
@ -400,7 +401,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 149,
},
{
name: Locations.AevumWatchdogSecurity,
name: LocationName.AevumWatchdogSecurity,
info: "",
companyPositions: Object.assign({},
SoftwarePositionsUpToHeadOfEngineering,
@ -415,7 +416,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 124,
},
{
name: Locations.VolhavenLexoCorp,
name: LocationName.VolhavenLexoCorp,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -428,7 +429,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 99,
},
{
name: Locations.AevumRhoConstruction,
name: LocationName.AevumRhoConstruction,
info: "",
companyPositions: Object.assign({},
SoftwarePositionsUpToLeadDeveloper,
@ -439,7 +440,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 49,
},
{
name: Locations.Sector12AlphaEnterprises,
name: LocationName.Sector12AlphaEnterprises,
info: "",
companyPositions: Object.assign({},
SoftwarePositionsUpToLeadDeveloper,
@ -451,7 +452,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 99,
},
{
name: Locations.AevumPolice,
name: LocationName.AevumPolice,
info: "",
companyPositions: Object.assign({},
AllSecurityPositions,
@ -462,7 +463,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 99,
},
{
name: Locations.VolhavenSysCoreSecurities,
name: LocationName.VolhavenSysCoreSecurities,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions
@ -472,7 +473,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 124,
},
{
name: Locations.VolhavenCompuTek,
name: LocationName.VolhavenCompuTek,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions
@ -482,7 +483,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 74,
},
{
name: Locations.AevumNetLinkTechnologies,
name: LocationName.AevumNetLinkTechnologies,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions
@ -492,7 +493,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 99,
},
{
name: Locations.Sector12CarmichaelSecurity,
name: LocationName.Sector12CarmichaelSecurity,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
@ -505,7 +506,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 74,
},
{
name: Locations.Sector12FoodNStuff,
name: LocationName.Sector12FoodNStuff,
info: "",
companyPositions: Object.assign({},
EmployeeOnly, PartTimeEmployeeOnly
@ -515,7 +516,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 0,
},
{
name: Locations.Sector12JoesGuns,
name: LocationName.Sector12JoesGuns,
info: "",
companyPositions: Object.assign({},
EmployeeOnly, PartTimeEmployeeOnly
@ -525,7 +526,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 0,
},
{
name: Locations.IshimaOmegaSoftware,
name: LocationName.IshimaOmegaSoftware,
info: "",
companyPositions: Object.assign({},
AllSoftwarePositions,
@ -537,7 +538,7 @@ export const companiesMetadata: IConstructorParams[] = [
jobStatReqOffset: 49,
},
{
name: Locations.NewTokyoNoodleBar,
name: LocationName.NewTokyoNoodleBar,
info: "",
companyPositions: Object.assign({},
WaiterOnly, PartTimeWaiterOnly

@ -1,6 +1,6 @@
// Metadata used for constructing Company Positions
import { IConstructorParams } from "../CompanyPosition";
import * as posNames from "./CompanyPositionNames";
import * as posNames from "./companypositionnames";
export const companyPositionMetadata: IConstructorParams[] = [
{

@ -18,8 +18,8 @@ import { BitNodeMultipliers } from "../BitNode/BitNode
import { CONSTANTS } from "../Constants";
import { Factions } from "../Faction/Factions";
import { showLiterature } from "../Literature";
import { Locations } from "../Locations";
import { createCityMap } from "../Locations/Cities";
import { CityName } from "../Locations/data/CityNames";
import { Player } from "../Player";
import { numeralWrapper } from "../ui/numeralFormat";
@ -113,15 +113,15 @@ $(document).mousedown(function(event) {
var empManualAssignmentModeActive = false;
function Industry(params={}) {
this.offices = { //Maps locations to offices. 0 if no office at that location
[Locations.Aevum]: 0,
[Locations.Chongqing]: 0,
[Locations.Sector12]: new OfficeSpace({
loc:Locations.Sector12,
[CityName.Aevum]: 0,
[CityName.Chongqing]: 0,
[CityName.Sector12]: new OfficeSpace({
loc:CityName.Sector12,
size:OfficeInitialSize,
}),
[Locations.NewTokyo]: 0,
[Locations.Ishima]: 0,
[Locations.Volhaven]: 0
[CityName.NewTokyo]: 0,
[CityName.Ishima]: 0,
[CityName.Volhaven]: 0
};
this.name = params.name ? params.name : 0;
@ -172,17 +172,17 @@ function Industry(params={}) {
this.newInd = true;
this.warehouses = { //Maps locations to warehouses. 0 if no warehouse at that location
[Locations.Aevum]: 0,
[Locations.Chonqing]: 0,
[Locations.Sector12]: new Warehouse({
[CityName.Aevum]: 0,
[CityName.Chonqing]: 0,
[CityName.Sector12]: new Warehouse({
corp: params.corp,
industry: this,
loc: Locations.Sector12,
loc: CityName.Sector12,
size: WarehouseInitialSize,
}),
[Locations.NewTokyo]: 0,
[Locations.Ishima]: 0,
[Locations.Volhaven]: 0
[CityName.NewTokyo]: 0,
[CityName.Ishima]: 0,
[CityName.Volhaven]: 0
};
this.init();
@ -571,7 +571,7 @@ Industry.prototype.processProductMarket = function(marketCycles=1) {
const product = this.products[name];
let change = getRandomInt(0, 3) * 0.0004;
if (change === 0) { continue; }
if (this.type === Industries.Pharmaceutical || this.type === Industries.Software ||
this.type === Industries.Robotics) {
change *= 3;

@ -3,11 +3,9 @@ import { MaterialSizes } from "./MaterialSizes";
import { ProductRatingWeights,
IProductRatingWeight } from "./ProductRatingWeights";
import { Cities } from "../Locations/Cities";
import { createCityMap } from "../Locations/createCityMap";
import { IMap } from "../types";
import { Generic_fromJSON,
Generic_toJSON,
Reviver } from "../../utils/JSONReviver";

@ -11,7 +11,7 @@ import { overviewPage } from "./Routing";
import { OfficeSpace } from "../Corporation";
import { Cities } from "../../Locations/Cities";
import { CityName } from "../../Locations/data/CityNames";
export class MainPanel extends BaseReactComponent {
constructor(props) {
@ -19,7 +19,7 @@ export class MainPanel extends BaseReactComponent {
this.state = {
division: "",
city: Cities.Sector12,
city: CityName.Sector12,
}
}

@ -7,7 +7,6 @@ import { Engine } from "../engine";
import { Faction } from "./Faction";
import { Factions } from "./Factions";
import { FactionInfos } from "./FactionInfo";
import { Locations} from "../Location";
import { HackingMission, setInMission } from "../Missions";
import { Player } from "../Player";
import { PurchaseAugmentationsOrderSetting } from "../Settings/SettingEnums";

10
src/IEngine.ts Normal file

@ -0,0 +1,10 @@
/**
* TypeScript interface for the game engine (engine.js), which can't be converted
* to TypeScript at the moment
*/
export interface IEngine {
loadBladeburnerContent: () => void;
loadInfiltrationContent: () => void;
loadResleevingContent: () => void;
loadStockMarketContent: () => void;
}

7
src/Infiltration.d.ts vendored Normal file

@ -0,0 +1,7 @@
import { LocationName } from "./Locations/data/LocationNames";
export declare function beginInfiltration(companyName: LocationName,
startLevel: number,
rewardVal: number,
maxClearance: number,
diff: number): void;

@ -382,13 +382,13 @@ function iTutorialEvaluateStep() {
//Flash 'City' menu and set its tutorial click handler
cityMainMenu.setAttribute("class", "flashing-button");
cityMainMenu.addEventListener("click", function() {
Engine.loadWorldContent();
Engine.loadLocationContent();
iTutorialNextStep();
return false;
});
break;
case iTutorialSteps.WorldDescription:
Engine.loadWorldContent();
Engine.loadLocationContent();
iTutorialSetText("This page lists all of the different locations you can currently " +
"travel to. Each location has something that you can do. " +
"There's a lot of content out in the world, make sure " +

File diff suppressed because it is too large Load Diff

@ -1,90 +0,0 @@
import { IMap } from "./types";
/**
* Display Location Content when visiting somewhere in the World
*/
// tslint:disable-next-line:variable-name
export const Locations: IMap<string> = {
// Cities
Aevum: "Aevum",
Chongqing: "Chongqing",
Ishima: "Ishima",
NewTokyo: "New Tokyo",
Sector12: "Sector-12",
Volhaven: "Volhaven",
// Aevum Locations
AevumAeroCorp: "AeroCorp",
AevumBachmanAndAssociates: "Bachman & Associates",
AevumClarkeIncorporated: "Clarke Incorporated",
AevumCrushFitnessGym: "Crush Fitness Gym",
AevumECorp: "ECorp",
AevumFulcrumTechnologies: "Fulcrum Technologies",
AevumGalacticCybersystems: "Galactic Cybersystems",
AevumNetLinkTechnologies: "NetLink Technologies",
AevumPolice: "Aevum Police Headquarters",
AevumRhoConstruction: "Rho Construction",
AevumSlums: "Aevum Slums",
AevumSnapFitnessGym: "Snap Fitness Gym",
AevumSummitUniversity: "Summit University",
AevumTravelAgency: "Aevum Travel Agency",
AevumWatchdogSecurity: "Watchdog Security",
// Chongqing locations
ChongqingKuaiGongInternational: "KuaiGong International",
ChongqingSlums: "Chongqing Slums",
ChongqingSolarisSpaceSystems: "Solaris Space Systems",
ChongqingTravelAgency: "Chongqing Travel Agency",
// Sector 12
Sector12AlphaEnterprises: "Alpha Enterprises",
Sector12BladeIndustries: "Blade Industries",
Sector12CIA: "Central Intelligence Agency",
Sector12CarmichaelSecurity: "Carmichael Security",
Sector12CityHall: "Sector-12 City Hall",
Sector12DeltaOne: "DeltaOne",
Sector12FoodNStuff: "FoodNStuff",
Sector12FourSigma: "Four Sigma",
Sector12IcarusMicrosystems: "Icarus Microsystems",
Sector12IronGym: "Iron Gym",
Sector12JoesGuns: "Joe's Guns",
Sector12MegaCorp: "MegaCorp",
Sector12NSA: "National Security Agency",
Sector12PowerhouseGym: "Powerhouse Gym",
Sector12RothmanUniversity: "Rothman University",
Sector12Slums: "Sector-12 Slums",
Sector12TravelAgency: "Sector-12 Travel Agency",
Sector12UniversalEnergy: "Universal Energy",
// New Tokyo
NewTokyoDefComm: "DefComm",
NewTokyoGlobalPharmaceuticals: "Global Pharmaceuticals",
NewTokyoNoodleBar: "Noodle Bar",
NewTokyoSlums: "New Tokyo Slums",
NewTokyoTravelAgency: "New Tokyo Travel Agency",
NewTokyoVitaLife: "VitaLife",
// Ishima
IshimaNovaMedical: "Nova Medical",
IshimaOmegaSoftware: "Omega Software",
IshimaSlums: "Ishima Slums",
IshimaStormTechnologies: "Storm Technologies",
IshimaTravelAgency: "Ishima Travel Agency",
// Volhaven
VolhavenCompuTek: "CompuTek",
VolhavenHeliosLabs: "Helios Labs",
VolhavenLexoCorp: "LexoCorp",
VolhavenMilleniumFitnessGym: "Millenium Fitness Gym",
VolhavenNWO: "NWO",
VolhavenOmniTekIncorporated: "OmniTek Incorporated",
VolhavenOmniaCybersystems: "Omnia Cybersystems",
VolhavenSlums: "Volhaven Slums",
VolhavenSysCoreSecurities: "SysCore Securities",
VolhavenTravelAgency: "Volhaven Travel Agency",
VolhavenZBInstituteOfTechnology: "ZB Institute of Technology",
// Generic locations
Hospital: "Hospital",
WorldStockExchange: "World Stock Exchange",
};

@ -1,14 +1,8 @@
/**
* Map of all Cities in the game
* Key = City Name, Value = City object
*/
import { City } from "./City";
import { IMap } from "../types";
/**
* Display Location Content when visiting somewhere in the World
*/
// tslint:disable-next-line:variable-name
export const Cities: IMap<string> = {
Aevum: "Aevum",
Chongqing: "Chongqing",
Ishima: "Ishima",
NewTokyo: "New Tokyo",
Sector12: "Sector-12",
Volhaven: "Volhaven",
};
export const Cities: IMap<City> = {};

26
src/Locations/City.ts Normal file

@ -0,0 +1,26 @@
/**
* Class representing a City in the game
*/
import { CityName } from "./data/CityNames";
import { LocationName } from "./data/LocationNames";
export class City {
/**
* List of all locations in this city
*/
locations: LocationName[];
/**
* Name of this city
*/
name: CityName;
constructor(name: CityName, locations: LocationName[]=[]) {
this.name = name;
this.locations = locations;
}
addLocation(loc: LocationName): void {
this.locations.push(loc);
}
}

82
src/Locations/Location.ts Normal file

@ -0,0 +1,82 @@
/**
* Class representing a visitable location in the world
*/
import { CityName } from "./data/CityNames";
import { LocationName } from "./data/LocationNames";
import { LocationType } from "./LocationTypeEnum";
interface IInfiltrationMetadata {
baseRewardValue: number;
difficulty: number;
maxClearanceLevel: number;
startingSecurityLevel: number;
}
export interface IConstructorParams {
city?: CityName | null;
costMult?: number;
expMult?: number;
infiltrationData?: IInfiltrationMetadata;
name?: LocationName;
types?: LocationType[];
techVendorMaxRam?: number;
techVendorMinRam?: number;
}
export class Location {
/**
* Name of city this location is in. If this property is null, it means this i
* is a generic location that is available in all cities
*/
city: CityName | null = null;
/**
* Cost multiplier that influences how expensive a gym/university is
*/
costMult: number = 0;
/**
* Exp multiplier that influences how effective a gym/university is
*/
expMult: number = 0;
/**
* Companies can be infiltrated. This contains the data required for that
* infiltration event
*/
infiltrationData?: IInfiltrationMetadata;
/**
* Identifier for location
*/
name: LocationName = LocationName.Void;
/**
* List of what type(s) this location is. A location can be multiple types
* (e.g. company and tech vendor)
*/
types: LocationType[] = [];
/**
* Tech vendors allow you to purchase servers.
* This property defines the max RAM server you can purchase from this vendor
*/
techVendorMaxRam: number = 0;
/**
* Tech vendors allow you to purchase servers.
* This property defines the max RAM server you can purchase from this vendor
*/
techVendorMinRam: number = 0;
constructor(p: IConstructorParams) {
if (p.city) { this.city = p.city; }
if (p.costMult) { this.costMult = p.costMult; }
if (p.expMult) { this.expMult = p.expMult; }
if (p.infiltrationData) { this.infiltrationData = p.infiltrationData; }
if (p.name) { this.name = p.name; }
if (p.types) { this.types = p.types; }
if (p.techVendorMaxRam) { this.techVendorMaxRam = p.techVendorMaxRam; }
if (p.techVendorMinRam) { this.techVendorMinRam = p.techVendorMinRam; }
}
}

@ -0,0 +1,14 @@
/**
* Enum defining the different types of possible locations
*/
export enum LocationType {
Company,
Gym,
Hospital,
Slums,
Special, // This location has special options/activities (e.g. Bladeburner, Re-sleeving)
StockMarket,
TechVendor,
TravelAgency,
University,
}

@ -0,0 +1,56 @@
/**
* Map of all Locations in the game
* Key = Location name, value = Location object
*/
import { City } from "./City";
import { Cities } from "./Cities";
import { Location,
IConstructorParams } from "./Location";
import { CityName } from "./data/CityNames";
import { LocationsMetadata } from "./data/LocationsMetadata";
import { IMap } from "../types";
export const Locations: IMap<Location> = {};
/**
* Here, we'll initialize both Locations and Cities data. These can both
* be initialized from the `LocationsMetadata`
*/
function constructLocation(p: IConstructorParams): Location {
if (!p.name) {
throw new Error(`Invalid constructor parameters for Location. No 'name' property`);
}
if (Locations[p.name] instanceof Location) {
console.warn(`Property with name ${p.name} already exists and is being overwritten`);
}
Locations[p.name] = new Location(p);
return Locations[p.name];
}
// First construct all cities
Cities[CityName.Aevum] = new City(CityName.Aevum);
Cities[CityName.Chongqing] = new City(CityName.Chongqing);
Cities[CityName.Ishima] = new City(CityName.Ishima);
Cities[CityName.NewTokyo] = new City(CityName.NewTokyo);
Cities[CityName.Sector12] = new City(CityName.Sector12);
Cities[CityName.Volhaven] = new City(CityName.Volhaven);
// Then construct all locations, and add them to the cities as we go.
for (const metadata of LocationsMetadata) {
const loc = constructLocation(metadata);
const cityName = loc.city;
if (cityName === null) {
// Generic location, add to all cities
for (const city in Cities) {
Cities[city].addLocation(loc.name);
}
} else {
Cities[cityName].addLocation(loc.name);
}
}

@ -0,0 +1,281 @@
/**
* Location and traveling-related helper functions.
* Mostly used for UI
*/
import { CONSTANTS } from "../Constants";
import { CityName } from "./data/CityNames";
import { IPlayer } from "../PersonObjects/IPlayer";
import { AllServers,
AddToAllServers } from "../Server/AllServers";
import { Server } from "../Server/Server";
import { getPurchaseServerCost,
purchaseRamForHomeComputer,
purchaseServer } from "../Server/ServerPurchases";
import { SpecialServerIps } from "../Server/SpecialServerIps";
import { Settings } from "../Settings/Settings";
import { numeralWrapper } from "../ui/numeralFormat";
import { dialogBoxCreate } from "../../utils/DialogBox";
import { createRandomIp } from "../../utils/IPAddress";
import { yesNoBoxGetYesButton,
yesNoBoxGetNoButton,
yesNoBoxClose,
yesNoBoxCreate,
yesNoTxtInpBoxGetYesButton,
yesNoTxtInpBoxGetNoButton,
yesNoTxtInpBoxClose,
yesNoTxtInpBoxCreate } from "../../utils/YesNoBox";
import { createElement } from "../../utils/uiHelpers/createElement";
import { createPopup } from "../../utils/uiHelpers/createPopup";
import { createPopupCloseButton } from "../../utils/uiHelpers/createPopupCloseButton";
import { removeElementById } from "../../utils/uiHelpers/removeElementById";
/**
* Create a pop-up box that lets the player confirm traveling to a different city
* If settings are configured to suppress this popup, just instantly travel
* The actual "Travel" implementation is implemented in the UI, and is passed in
* as an argument
*/
type TravelFunction = (to: CityName) => void;
export function createTravelPopup(destination: CityName, travelFn: TravelFunction) {
const cost = CONSTANTS.TravelCost;
if (Settings.SuppressTravelConfirmation) {
travelFn(destination);
return;
}
const yesBtn = yesNoBoxGetYesButton();
const noBtn = yesNoBoxGetNoButton();
if (yesBtn == null || noBtn == null) {
console.warn(`Could nto find YesNo pop-up box buttons`);
return;
}
yesBtn.innerHTML = "Yes";
yesBtn.addEventListener("click", () => {
yesNoBoxClose();
travelFn(destination);
return false;
});
noBtn.innerHTML = "No";
noBtn.addEventListener("click", () => {
yesNoBoxClose();
return false;
});
yesNoBoxCreate(`Would you like to travel to ${destination}? The trip will ` +
`cost ${numeralWrapper.formatMoney(cost)}`);
}
/**
* Create a pop-up box that lets the player purchase a server.
* @param ram - Amount of RAM (GB) on server
* @param p - Player object
*/
export function createPurchaseServerPopup(ram: number, p: IPlayer) {
const cost = getPurchaseServerCost(ram);
if (cost === Infinity) {
dialogBoxCreate("Something went wrong when trying to purchase this server. Please contact developer");
return;
}
var yesBtn = yesNoTxtInpBoxGetYesButton();
var noBtn = yesNoTxtInpBoxGetNoButton();
if (yesBtn == null || noBtn == null) { return; }
yesBtn.innerHTML = "Purchase Server";
noBtn.innerHTML = "Cancel";
yesBtn.addEventListener("click", function() {
purchaseServer(ram, p);
yesNoTxtInpBoxClose();
});
noBtn.addEventListener("click", function() {
yesNoTxtInpBoxClose();
});
yesNoTxtInpBoxCreate("Would you like to purchase a new server with " + ram +
"GB of RAM for $" + numeralWrapper.formatMoney(cost) + "?<br><br>" +
"Please enter the server hostname below:<br>");
}
/**
* Create a popup that lets the player start a Corporation
*/
export function createStartCorporationPopup(p: IPlayer) {
if (!p.canAccessCorporation() || p.hasCorporation) { return; }
const popupId = "create-corporation-popup";
const txt = createElement("p", {
innerHTML: "Would you like to start a corporation? This will require $150b for registration " +
"and initial funding. This $150b can either be self-funded, or you can obtain " +
"the seed money from the government in exchange for 500 million shares<br><br>" +
"If you would like to start one, please enter a name for your corporation below:",
});
const nameInput = createElement("input", {
placeholder: "Corporation Name",
}) as HTMLInputElement;
const selfFundedButton = createElement("button", {
class: "popup-box-button",
innerText: "Self-Fund",
clickListener: () => {
if (!p.canAfford(150e9)) {
dialogBoxCreate("You don't have enough money to create a corporation! You need $150b");
return false;
}
p.loseMoney(150e9);
const companyName = nameInput.value;
if (companyName == null || companyName == "") {
dialogBoxCreate("Invalid company name!");
return false;
}
p.startCorporation(companyName);
const worldHeader = document.getElementById("world-menu-header");
if (worldHeader instanceof HTMLElement) {
worldHeader.click(); worldHeader.click();
}
dialogBoxCreate("Congratulations! You just self-funded your own corporation. You can visit " +
"and manage your company in the City");
removeElementById(popupId);
return false;
}
});
const seedMoneyButton = createElement("button", {
class: "popup-box-button",
innerText: "Use Seed Money",
clickListener: () => {
const companyName = nameInput.value;
if (companyName == null || companyName == "") {
dialogBoxCreate("Invalid company name!");
return false;
}
p.startCorporation(companyName, 500e6);
const worldHeader = document.getElementById("world-menu-header");
if (worldHeader instanceof HTMLElement) {
worldHeader.click(); worldHeader.click();
}
dialogBoxCreate("Congratulations! You just started your own corporation with government seed money. " +
"You can visit and manage your company in the City");
removeElementById(popupId);
return false;
}
})
const cancelBtn = createPopupCloseButton(popupId, { class: "popup-box-button" });
createPopup(popupId, [txt, nameInput, cancelBtn, selfFundedButton, seedMoneyButton]);
nameInput.focus();
}
/**
* Create a popup that lets the player upgrade the cores on his/her home computer
* @param p - Player object
*/
export function createUpgradeHomeCoresPopup(p: IPlayer) {
const currentCores = p.getHomeComputer().cpuCores;
if (currentCores >= 8) { return; } // Max of 8 cores
//Cost of purchasing another cost is found by indexing this array with number of current cores
const allCosts = [0,
10e9, // 1->2 Cores - 10 bn
250e9, // 2->3 Cores - 250 bn
5e12, // 3->4 Cores - 5 trillion
100e12, // 4->5 Cores - 100 trillion
1e15, // 5->6 Cores - 1 quadrillion
20e15, // 6->7 Cores - 20 quadrillion
200e15]; // 7->8 Cores - 200 quadrillion
const cost: number = allCosts[currentCores];
const yesBtn = yesNoBoxGetYesButton();
const noBtn = yesNoBoxGetNoButton();
if (yesBtn == null || noBtn == null) { return; }
yesBtn.innerHTML = "Purchase";
yesBtn.addEventListener("click", ()=>{
if (!p.canAfford(cost)) {
dialogBoxCreate("You do not have enough money to purchase an additional CPU Core for your home computer!");
} else {
p.loseMoney(cost);
p.getHomeComputer().cpuCores++;
dialogBoxCreate("You purchased an additional CPU Core for your home computer! It now has " +
p.getHomeComputer().cpuCores + " cores.");
}
yesNoBoxClose();
});
noBtn.innerHTML = "Cancel";
noBtn.addEventListener("click", ()=>{
yesNoBoxClose();
});
yesNoBoxCreate("Would you like to purchase an additional CPU Core for your home computer? Each CPU Core " +
"lets you start with an additional Core Node in Hacking Missions.<br><br>" +
"Purchasing an additional core (for a total of " + (p.getHomeComputer().cpuCores + 1) + ") will " +
"cost " + numeralWrapper.formatMoney(cost));
}
/**
* Create a popup that lets the player upgrade the RAM on his/her home computer
* @param p - Player object
*/
export function createUpgradeHomeRamPopup(p: IPlayer) {
const cost: number = p.getUpgradeHomeRamCost();
const ram: number = p.getHomeComputer().maxRam;
const yesBtn = yesNoBoxGetYesButton();
const noBtn = yesNoBoxGetNoButton();
if (yesBtn == null || noBtn == null) { return; }
yesBtn.innerText = "Purchase";
yesBtn.addEventListener("click", ()=>{
purchaseRamForHomeComputer(cost, p);
yesNoBoxClose();
});
noBtn.innerText = "Cancel";
noBtn.addEventListener("click", ()=>{
yesNoBoxClose();
});
yesNoBoxCreate("Would you like to purchase additional RAM for your home computer? <br><br>" +
"This will upgrade your RAM from " + ram + "GB to " + ram*2 + "GB. <br><br>" +
"This will cost " + numeralWrapper.format(cost, '$0.000a'));
}
/**
* Attempt to purchase a TOR router
* @param p - Player object
*/
export function purchaseTorRouter(p: IPlayer) {
if (!p.canAfford(CONSTANTS.TorRouterCost)) {
dialogBoxCreate("You cannot afford to purchase the Tor router");
return;
}
p.loseMoney(CONSTANTS.TorRouterCost);
const darkweb = new Server({
ip: createRandomIp(), hostname:"darkweb", organizationName:"",
isConnectedTo:false, adminRights:false, purchasedByPlayer:false, maxRam:1
});
AddToAllServers(darkweb);
SpecialServerIps.addIp("Darkweb Server", darkweb.ip);
p.getHomeComputer().serversOnNetwork.push(darkweb.ip);
darkweb.serversOnNetwork.push(p.getHomeComputer().ip);
dialogBoxCreate("You have purchased a Tor router!<br>" +
"You now have access to the dark web from your home computer<br>" +
"Use the scan/scan-analyze commands to search for the dark web connection.");
}

@ -9,7 +9,7 @@ import { IMap } from "../types";
export function createCityMap<T>(initValue: T): IMap<T> {
const map: IMap<any> = {};
const cities = Object.values(Cities);
const cities = Object.keys(Cities);
for (let i = 0; i < cities.length; ++i) {
map[cities[i]] = initValue;
}

@ -0,0 +1,12 @@
/**
* All possible Cities in the game. Names only, not actual "City" object
* Implemented as an enum for typing purposes
*/
export enum CityName {
Aevum = "Aevum",
Chongqing = "Chongqing",
Ishima = "Ishima",
NewTokyo = "New Tokyo",
Sector12 = "Sector-12",
Volhaven = "Volhaven",
};

@ -0,0 +1,80 @@
/**
* Names of all locations
*/
export enum LocationName {
// Cities
Aevum = "Aevum",
Chongqing = "Chongqing",
Ishima = "Ishima",
NewTokyo = "New Tokyo",
Sector12 = "Sector-12",
Volhaven = "Volhaven",
// Aevum Locations
AevumAeroCorp = "AeroCorp",
AevumBachmanAndAssociates = "Bachman & Associates",
AevumClarkeIncorporated = "Clarke Incorporated",
AevumCrushFitnessGym = "Crush Fitness Gym",
AevumECorp = "ECorp",
AevumFulcrumTechnologies = "Fulcrum Technologies",
AevumGalacticCybersystems = "Galactic Cybersystems",
AevumNetLinkTechnologies = "NetLink Technologies",
AevumPolice = "Aevum Police Headquarters",
AevumRhoConstruction = "Rho Construction",
AevumSnapFitnessGym = "Snap Fitness Gym",
AevumSummitUniversity = "Summit University",
AevumWatchdogSecurity = "Watchdog Security",
// Chongqing locations
ChongqingKuaiGongInternational = "KuaiGong International",
ChongqingSolarisSpaceSystems = "Solaris Space Systems",
// Sector 12
Sector12AlphaEnterprises = "Alpha Enterprises",
Sector12BladeIndustries = "Blade Industries",
Sector12CIA = "Central Intelligence Agency",
Sector12CarmichaelSecurity = "Carmichael Security",
Sector12CityHall = "Sector-12 City Hall",
Sector12DeltaOne = "DeltaOne",
Sector12FoodNStuff = "FoodNStuff",
Sector12FourSigma = "Four Sigma",
Sector12IcarusMicrosystems = "Icarus Microsystems",
Sector12IronGym = "Iron Gym",
Sector12JoesGuns = "Joe's Guns",
Sector12MegaCorp = "MegaCorp",
Sector12NSA = "National Security Agency",
Sector12PowerhouseGym = "Powerhouse Gym",
Sector12RothmanUniversity = "Rothman University",
Sector12UniversalEnergy = "Universal Energy",
// New Tokyo
NewTokyoDefComm = "DefComm",
NewTokyoGlobalPharmaceuticals = "Global Pharmaceuticals",
NewTokyoNoodleBar = "Noodle Bar",
NewTokyoVitaLife = "VitaLife",
// Ishima
IshimaNovaMedical = "Nova Medical",
IshimaOmegaSoftware = "Omega Software",
IshimaStormTechnologies = "Storm Technologies",
// Volhaven
VolhavenCompuTek = "CompuTek",
VolhavenHeliosLabs = "Helios Labs",
VolhavenLexoCorp = "LexoCorp",
VolhavenMilleniumFitnessGym = "Millenium Fitness Gym",
VolhavenNWO = "NWO",
VolhavenOmniTekIncorporated = "OmniTek Incorporated",
VolhavenOmniaCybersystems = "Omnia Cybersystems",
VolhavenSysCoreSecurities = "SysCore Securities",
VolhavenZBInstituteOfTechnology = "ZB Institute of Technology",
// Generic locations
Hospital = "Hospital",
Slums = "The Slums",
TravelAgency = "Travel Agency",
WorldStockExchange = "World Stock Exchange",
// Default name for Location objects
Void = "The Void",
};

@ -0,0 +1,502 @@
/**
* Metadata for constructing Location objects for all Locations
* in the game
*/
import { CityName } from "./CityNames";
import { LocationName } from "./LocationNames";
import { IConstructorParams } from "../Location";
import { LocationType } from "../LocationTypeEnum";
export const LocationsMetadata: IConstructorParams[] = [
{
city: CityName.Aevum,
infiltrationData: {
baseRewardValue: 32,
difficulty: 4.4,
maxClearanceLevel: 50,
startingSecurityLevel: 1350,
},
name: LocationName.AevumAeroCorp,
types: [LocationType.Company],
},
{
city: CityName.Aevum,
infiltrationData: {
baseRewardValue: 42,
difficulty: 4.1,
maxClearanceLevel: 60,
startingSecurityLevel: 1350,
},
name: LocationName.AevumBachmanAndAssociates,
types: [LocationType.Company],
},
{
city: CityName.Aevum,
infiltrationData: {
baseRewardValue: 34,
difficulty: 3.6,
maxClearanceLevel: 75,
startingSecurityLevel: 1800,
},
name: LocationName.AevumClarkeIncorporated,
types: [LocationType.Company],
},
{
city: CityName.Aevum,
costMult: 3,
expMult: 2,
name: LocationName.AevumCrushFitnessGym,
types: [LocationType.Gym],
},
{
city: CityName.Aevum,
infiltrationData: {
baseRewardValue: 116,
difficulty: 6,
maxClearanceLevel: 150,
startingSecurityLevel: 4800,
},
name: LocationName.AevumECorp,
types: [LocationType.Company, LocationType.TechVendor],
techVendorMaxRam: 512,
techVendorMinRam: 128,
},
{
city: CityName.Aevum,
infiltrationData: {
baseRewardValue: 96,
difficulty: 6.2,
maxClearanceLevel: 100,
startingSecurityLevel: 4140,
},
name: LocationName.AevumFulcrumTechnologies,
types: [LocationType.Company, LocationType.TechVendor],
techVendorMaxRam: 1024,
techVendorMinRam: 256,
},
{
city: CityName.Aevum,
infiltrationData: {
baseRewardValue: 30,
difficulty: 3.95,
maxClearanceLevel: 50,
startingSecurityLevel: 1260,
},
name: LocationName.AevumGalacticCybersystems,
types: [LocationType.Company],
},
{
city: CityName.Aevum,
infiltrationData: {
baseRewardValue: 10,
difficulty: 1.4,
maxClearanceLevel: 25,
startingSecurityLevel: 144,
},
name: LocationName.AevumNetLinkTechnologies,
types: [LocationType.Company, LocationType.TechVendor],
techVendorMaxRam: 64,
techVendorMinRam: 8,
},
{
city: CityName.Aevum,
infiltrationData: {
baseRewardValue: 18,
difficulty: 2.2,
maxClearanceLevel: 25,
startingSecurityLevel: 565,
},
name: LocationName.AevumPolice,
types: [LocationType.Company],
},
{
city: CityName.Aevum,
infiltrationData: {
baseRewardValue: 16,
difficulty: 1.9,
maxClearanceLevel: 20,
startingSecurityLevel: 485,
},
name: LocationName.AevumRhoConstruction,
types: [LocationType.Company],
},
{
city: CityName.Aevum,
costMult: 10,
expMult: 5,
name: LocationName.AevumSnapFitnessGym,
types: [LocationType.Gym],
},
{
city: CityName.Aevum,
costMult: 4,
expMult: 3,
name: LocationName.AevumSummitUniversity,
types: [LocationType.University],
},
{
city: CityName.Aevum,
infiltrationData: {
baseRewardValue: 20,
difficulty: 3,
maxClearanceLevel: 30,
startingSecurityLevel: 690,
},
name: LocationName.AevumWatchdogSecurity,
types: [LocationType.Company],
},
{
city: CityName.Chongqing,
infiltrationData: {
baseRewardValue: 100,
difficulty: 6.1,
maxClearanceLevel: 100,
startingSecurityLevel: 4450,
},
name: LocationName.ChongqingKuaiGongInternational,
types: [LocationType.Company],
},
{
city: CityName.Chongqing,
infiltrationData: {
baseRewardValue: 52,
difficulty: 6,
maxClearanceLevel: 75,
startingSecurityLevel: 2915,
},
name: LocationName.ChongqingSolarisSpaceSystems,
types: [LocationType.Company],
},
{
city: CityName.Ishima,
infiltrationData: {
baseRewardValue: 20,
difficulty: 3.2,
maxClearanceLevel: 50,
startingSecurityLevel: 485,
},
name: LocationName.IshimaNovaMedical,
types: [LocationType.Company],
},
{
city: CityName.Ishima,
infiltrationData: {
baseRewardValue: 10,
difficulty: 1.6,
maxClearanceLevel: 40,
startingSecurityLevel: 130,
},
name: LocationName.IshimaOmegaSoftware,
types: [LocationType.Company, LocationType.TechVendor],
techVendorMaxRam: 128,
techVendorMinRam: 4,
},
{
city: CityName.Ishima,
infiltrationData: {
baseRewardValue: 24,
difficulty: 4.1,
maxClearanceLevel: 100,
startingSecurityLevel: 570,
},
name: LocationName.IshimaStormTechnologies,
types: [LocationType.Company, LocationType.TechVendor],
techVendorMaxRam: 512,
techVendorMinRam: 32,
},
{
city: CityName.NewTokyo,
infiltrationData: {
baseRewardValue: 28,
difficulty: 4,
maxClearanceLevel: 70,
startingSecurityLevel: 1050,
},
name: LocationName.NewTokyoDefComm,
types: [LocationType.Company],
},
{
city: CityName.NewTokyo,
infiltrationData: {
baseRewardValue: 24,
difficulty: 3.8,
maxClearanceLevel: 80,
startingSecurityLevel: 700,
},
name: LocationName.NewTokyoGlobalPharmaceuticals,
types: [LocationType.Company],
},
{
city: CityName.NewTokyo,
name: LocationName.NewTokyoNoodleBar,
types: [LocationType.Company],
},
{
city: CityName.NewTokyo,
infiltrationData: {
baseRewardValue: 22,
difficulty: 3.5,
maxClearanceLevel: 100,
startingSecurityLevel: 605,
},
name: LocationName.NewTokyoVitaLife,
types: [LocationType.Company, LocationType.Special],
},
{
city: CityName.Sector12,
infiltrationData: {
baseRewardValue: 14,
difficulty: 2.25,
maxClearanceLevel: 40,
startingSecurityLevel: 200,
},
name: LocationName.Sector12AlphaEnterprises,
types: [LocationType.Company, LocationType.TechVendor],
techVendorMaxRam: 8,
techVendorMinRam: 2,
},
{
city: CityName.Sector12,
infiltrationData: {
baseRewardValue: 46,
difficulty: 4.2,
maxClearanceLevel: 100,
startingSecurityLevel: 2160,
},
name: LocationName.Sector12BladeIndustries,
types: [LocationType.Company],
},
{
city: CityName.Sector12,
name: LocationName.Sector12CIA,
types: [LocationType.Company],
},
{
city: CityName.Sector12,
infiltrationData: {
baseRewardValue: 18,
difficulty: 2.5,
maxClearanceLevel: 60,
startingSecurityLevel: 405,
},
name: LocationName.Sector12CarmichaelSecurity,
types: [LocationType.Company],
},
{
city: CityName.Sector12,
name: LocationName.Sector12CityHall,
types: [LocationType.Special],
},
{
city: CityName.Sector12,
infiltrationData: {
baseRewardValue: 24,
difficulty: 4.3,
maxClearanceLevel: 50,
startingSecurityLevel: 700,
},
name: LocationName.Sector12DeltaOne,
types: [LocationType.Company],
},
{
city: CityName.Sector12,
name: LocationName.Sector12FoodNStuff,
types: [LocationType.Company],
},
{
city: CityName.Sector12,
infiltrationData: {
baseRewardValue: 58,
difficulty: 7,
maxClearanceLevel: 100,
startingSecurityLevel: 1350,
},
name: LocationName.Sector12FourSigma,
types: [LocationType.Company],
},
{
city: CityName.Sector12,
infiltrationData: {
baseRewardValue: 32,
difficulty: 5.4,
maxClearanceLevel: 70,
startingSecurityLevel: 730,
},
name: LocationName.Sector12IcarusMicrosystems,
types: [LocationType.Company],
},
{
city: CityName.Sector12,
expMult: 1,
costMult: 1,
name: LocationName.Sector12IronGym,
types: [LocationType.Gym],
},
{
city: CityName.Sector12,
infiltrationData: {
baseRewardValue: 8,
difficulty: 1.8,
maxClearanceLevel: 20,
startingSecurityLevel: 120,
},
name: LocationName.Sector12JoesGuns,
types: [LocationType.Company],
},
{
city: CityName.Sector12,
infiltrationData: {
baseRewardValue: 114,
difficulty: 6.75,
maxClearanceLevel: 125,
startingSecurityLevel: 4500,
},
name: LocationName.Sector12MegaCorp,
types: [LocationType.Company],
},
{
city: CityName.Sector12,
name: LocationName.Sector12NSA,
types: [LocationType.Company, LocationType.Special],
},
{
city: CityName.Sector12,
costMult: 20,
expMult: 10,
name: LocationName.Sector12PowerhouseGym,
types: [LocationType.Gym],
},
{
city: CityName.Sector12,
costMult: 3,
expMult: 2,
name: LocationName.Sector12RothmanUniversity,
types: [LocationType.University],
},
{
city: CityName.Sector12,
infiltrationData: {
baseRewardValue: 24,
difficulty: 4.3,
maxClearanceLevel: 50,
startingSecurityLevel: 700,
},
name: LocationName.Sector12UniversalEnergy,
types: [LocationType.Company],
},
{
city: CityName.Volhaven,
infiltrationData: {
baseRewardValue: 12,
difficulty: 2.1,
maxClearanceLevel: 60,
startingSecurityLevel: 195,
},
name: LocationName.VolhavenCompuTek,
types: [LocationType.Company, LocationType.TechVendor],
techVendorMaxRam: 256,
techVendorMinRam: 8,
},
{
city: CityName.Volhaven,
infiltrationData: {
baseRewardValue: 28,
difficulty: 3,
maxClearanceLevel: 75,
startingSecurityLevel: 1080,
},
name: LocationName.VolhavenHeliosLabs,
types: [LocationType.Company],
},
{
city: CityName.Volhaven,
infiltrationData: {
baseRewardValue: 14,
difficulty: 2,
maxClearanceLevel: 60,
startingSecurityLevel: 340,
},
name: LocationName.VolhavenLexoCorp,
types: [LocationType.Company],
},
{
city: CityName.Volhaven,
costMult: 7,
expMult: 4,
name: LocationName.VolhavenMilleniumFitnessGym,
types: [LocationType.Gym],
},
{
city: CityName.Volhaven,
infiltrationData: {
baseRewardValue: 56,
difficulty: 6.8,
maxClearanceLevel: 200,
startingSecurityLevel: 1460,
},
name: LocationName.VolhavenNWO,
types: [LocationType.Company],
},
{
city: CityName.Volhaven,
infiltrationData: {
baseRewardValue: 44,
difficulty: 4.4,
maxClearanceLevel: 100,
startingSecurityLevel: 1215,
},
name: LocationName.VolhavenOmniTekIncorporated,
types: [LocationType.Company, LocationType.TechVendor],
techVendorMaxRam: 1024,
techVendorMinRam: 128,
},
{
city: CityName.Volhaven,
infiltrationData: {
baseRewardValue: 28,
difficulty: 4.9,
maxClearanceLevel: 90,
startingSecurityLevel: 725,
},
name: LocationName.VolhavenOmniaCybersystems,
types: [LocationType.Company],
},
{
city: CityName.Volhaven,
infiltrationData: {
baseRewardValue: 18,
difficulty: 2.4,
maxClearanceLevel: 75,
startingSecurityLevel: 430,
},
name: LocationName.VolhavenSysCoreSecurities,
types: [LocationType.Company],
},
{
city: CityName.Volhaven,
costMult: 5,
expMult: 4,
name: LocationName.VolhavenZBInstituteOfTechnology,
types: [LocationType.University],
},
{
city: null,
name: LocationName.Hospital,
types: [LocationType.Hospital],
},
{
city: null,
name: LocationName.Slums,
types: [LocationType.Slums],
},
{
city: null,
name: LocationName.TravelAgency,
types: [LocationType.TravelAgency],
},
{
city: null,
name: LocationName.WorldStockExchange,
types: [LocationType.StockMarket],
},
];

@ -0,0 +1,48 @@
/**
* React Component for a button that's used to apply for a job
*/
import * as React from "react";
import { Company } from "../../Company/Company";
import { CompanyPosition } from "../../Company/CompanyPosition";
import { getJobRequirementText } from "../../Company/GetJobRequirementText";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { StdButton } from "../../ui/React/StdButton";
type IProps = {
company: Company;
entryPosType: CompanyPosition;
onClick: (e: React.MouseEvent<HTMLElement>) => void;
p: IPlayer;
style?: object;
text: string;
}
export class ApplyToJobButton extends React.Component<IProps, any> {
constructor(props: IProps) {
super(props);
this.getJobRequirementTooltip = this.getJobRequirementTooltip.bind(this);
}
getJobRequirementTooltip(): string {
const pos = this.props.p.getNextCompanyPosition(this.props.company, this.props.entryPosType);
if (pos == null) { return "" };
if (!this.props.company.hasPosition(pos)) { return ""; }
return getJobRequirementText(this.props.company, pos, true);
}
render() {
return (
<StdButton
onClick={this.props.onClick}
style={this.props.style}
text={this.props.text}
tooltip={this.getJobRequirementTooltip()}
/>
)
}
}

34
src/Locations/ui/City.tsx Normal file

@ -0,0 +1,34 @@
/**
* React Component for displaying a City's UI.
* This UI shows all of the available locations in the city, and lets the player
* visit those locations
*/
import * as React from "react";
import { City } from "../City";
import { LocationName } from "../data/LocationNames";
import { StdButton } from "../../ui/React/StdButton";
type IProps = {
city: City;
enterLocation: (to: LocationName) => void;
}
export class LocationCity extends React.Component<IProps, any> {
render() {
const locationButtons = this.props.city.locations.map((locName) => {
return (
<li key={locName}>
<StdButton onClick={this.props.enterLocation.bind(this, locName)} text={locName} />
</li>
)
});
return (
<ul>
{locationButtons}
</ul>
)
}
}

@ -0,0 +1,372 @@
/**
* React Subcomponent for displaying a location's UI, when that location is a company
*
* This subcomponent renders all of the buttons for applying to jobs at a company
*/
import * as React from "react";
import { ApplyToJobButton } from "./ApplyToJobButton";
import { Location } from "../Location";
import { Locations } from "../Locations";
import { LocationName } from "../data/LocationNames";
import { IEngine } from "../../IEngine";
import { beginInfiltration } from "../../Infiltration";
import { Companies } from "../../Company/Companies";
import { Company } from "../../Company/Company";
import { CompanyPosition } from "../../Company/CompanyPosition";
import { CompanyPositions } from "../../Company/CompanyPositions";
import * as posNames from "../../Company/data/companypositionnames";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { numeralWrapper } from "../../ui/numeralFormat";
import { StdButton } from "../../ui/React/StdButton";
type IProps = {
engine: IEngine;
locName: LocationName;
p: IPlayer;
}
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,
* so we don't have to look it up every time
*/
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
*/
location: Location;
/**
* Name of company position that player holds, if applicable
*/
jobTitle: string | null = null;
constructor(props: IProps) {
super(props);
this.btnStyle = { display: "block" };
this.applyForAgentJob = this.applyForAgentJob.bind(this);
this.applyForBusinessConsultantJob = this.applyForBusinessConsultantJob.bind(this);
this.applyForBusinessJob = this.applyForBusinessJob.bind(this);
this.applyForEmployeeJob = this.applyForEmployeeJob.bind(this);
this.applyForItJob = this.applyForItJob.bind(this);
this.applyForPartTimeEmployeeJob = this.applyForPartTimeEmployeeJob.bind(this);
this.applyForPartTimeWaiterJob = this.applyForPartTimeWaiterJob.bind(this);
this.applyForSecurityJob = this.applyForSecurityJob.bind(this);
this.applyForSoftwareConsultantJob = this.applyForSoftwareConsultantJob.bind(this);
this.applyForSoftwareJob = this.applyForSoftwareJob.bind(this);
this.applyForWaiterJob = this.applyForWaiterJob.bind(this);
this.checkIfEmployedHere = this.checkIfEmployedHere.bind(this);
this.startInfiltration = this.startInfiltration.bind(this);
this.work = this.work.bind(this);
this.location = Locations[props.locName];
if (this.location == null) {
throw new Error(`CompanyLocation component constructed with invalid location: ${props.locName}`);
}
this.company = Companies[props.locName];
if (this.company == null) {
throw new Error(`CompanyLocation component constructed with invalid company: ${props.locName}`);
}
this.state = {
employedHere: false,
}
this.checkIfEmployedHere(false);
}
applyForAgentJob(e: React.MouseEvent<HTMLElement>) {
if (!e.isTrusted) { return false; }
this.props.p.applyForAgentJob();
this.checkIfEmployedHere();
}
applyForBusinessConsultantJob(e: React.MouseEvent<HTMLElement>) {
if (!e.isTrusted) { return false; }
this.props.p.applyForBusinessConsultantJob();
this.checkIfEmployedHere();
}
applyForBusinessJob(e: React.MouseEvent<HTMLElement>) {
if (!e.isTrusted) { return false; }
this.props.p.applyForBusinessJob();
this.checkIfEmployedHere();
}
applyForEmployeeJob(e: React.MouseEvent<HTMLElement>) {
if (!e.isTrusted) { return false; }
this.props.p.applyForEmployeeJob();
this.checkIfEmployedHere();
}
applyForItJob(e: React.MouseEvent<HTMLElement>) {
if (!e.isTrusted) { return false; }
this.props.p.applyForItJob();
this.checkIfEmployedHere();
}
applyForPartTimeEmployeeJob(e: React.MouseEvent<HTMLElement>) {
if (!e.isTrusted) { return false; }
this.props.p.applyForPartTimeEmployeeJob();
this.checkIfEmployedHere();
}
applyForPartTimeWaiterJob(e: React.MouseEvent<HTMLElement>) {
if (!e.isTrusted) { return false; }
this.props.p.applyForPartTimeWaiterJob();
this.checkIfEmployedHere();
}
applyForSecurityJob(e: React.MouseEvent<HTMLElement>) {
if (!e.isTrusted) { return false; }
this.props.p.applyForSecurityJob();
this.checkIfEmployedHere();
}
applyForSoftwareConsultantJob(e: React.MouseEvent<HTMLElement>) {
if (!e.isTrusted) { return false; }
this.props.p.applyForSoftwareConsultantJob();
this.checkIfEmployedHere();
}
applyForSoftwareJob(e: React.MouseEvent<HTMLElement>) {
if (!e.isTrusted) { return false; }
this.props.p.applyForSoftwareJob();
this.checkIfEmployedHere();
}
applyForWaiterJob(e: React.MouseEvent<HTMLElement>) {
if (!e.isTrusted) { return false; }
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>) {
if (!e.isTrusted) { return false; }
const loc = this.location;
this.props.engine.loadInfiltrationContent();
const data = loc.infiltrationData;
if (data == null) { return false; }
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() {
const isEmployedHere = this.jobTitle != null;
const favorGain = this.company.getFavorGain();
return (
<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() &&
<ApplyToJobButton
company={this.company}
entryPosType={CompanyPositions[posNames.AgentCompanyPositions[0]]}
onClick={this.applyForAgentJob}
p={this.props.p}
style={this.btnStyle}
text={"Apply for Agent Job"}
/>
}
{
this.company.hasBusinessConsultantPositions() &&
<ApplyToJobButton
company={this.company}
entryPosType={CompanyPositions[posNames.BusinessConsultantCompanyPositions[0]]}
onClick={this.applyForBusinessConsultantJob}
p={this.props.p}
style={this.btnStyle}
text={"Apply for Business Consultant Job"}
/>
}
{
this.company.hasBusinessPositions() &&
<ApplyToJobButton
company={this.company}
entryPosType={CompanyPositions[posNames.BusinessCompanyPositions[0]]}
onClick={this.applyForBusinessJob}
p={this.props.p}
style={this.btnStyle}
text={"Apply for Business Job"}
/>
}
{
this.company.hasEmployeePositions() &&
<ApplyToJobButton
company={this.company}
entryPosType={CompanyPositions[posNames.MiscCompanyPositions[1]]}
onClick={this.applyForEmployeeJob}
p={this.props.p}
style={this.btnStyle}
text={"Apply to be an Employee"}
/>
}
{
this.company.hasEmployeePositions() &&
<ApplyToJobButton
company={this.company}
entryPosType={CompanyPositions[posNames.PartTimeCompanyPositions[1]]}
onClick={this.applyForPartTimeEmployeeJob}
p={this.props.p}
style={this.btnStyle}
text={"Apply to be a part-time Employee"}
/>
}
{
this.company.hasITPositions() &&
<ApplyToJobButton
company={this.company}
entryPosType={CompanyPositions[posNames.ITCompanyPositions[0]]}
onClick={this.applyForItJob}
p={this.props.p}
style={this.btnStyle}
text={"Apply for IT Job"}
/>
}
{
this.company.hasSecurityPositions() &&
<ApplyToJobButton
company={this.company}
entryPosType={CompanyPositions[posNames.SecurityCompanyPositions[2]]}
onClick={this.applyForSecurityJob}
p={this.props.p}
style={this.btnStyle}
text={"Apply for Security Job"}
/>
}
{
this.company.hasSoftwareConsultantPositions() &&
<ApplyToJobButton
company={this.company}
entryPosType={CompanyPositions[posNames.SoftwareConsultantCompanyPositions[0]]}
onClick={this.applyForSoftwareConsultantJob}
p={this.props.p}
style={this.btnStyle}
text={"Apply for Software Consultant Job"}
/>
}
{
this.company.hasSoftwarePositions() &&
<ApplyToJobButton
company={this.company}
entryPosType={CompanyPositions[posNames.SoftwareCompanyPositions[0]]}
onClick={this.applyForSoftwareJob}
p={this.props.p}
style={this.btnStyle}
text={"Apply for Software Job"}
/>
}
{
this.company.hasWaiterPositions() &&
<ApplyToJobButton
company={this.company}
entryPosType={CompanyPositions[posNames.MiscCompanyPositions[0]]}
onClick={this.applyForWaiterJob}
p={this.props.p}
style={this.btnStyle}
text={"Apply to be a Waiter"}
/>
}
{
this.company.hasWaiterPositions() &&
<ApplyToJobButton
company={this.company}
entryPosType={CompanyPositions[posNames.PartTimeCompanyPositions[0]]}
onClick={this.applyForPartTimeWaiterJob}
p={this.props.p}
style={this.btnStyle}
text={"Apply to be a part-time Waiter"}
/>
}
{
(this.location.infiltrationData != null) &&
<StdButton
onClick={this.startInfiltration}
style={this.btnStyle}
text={"Infiltration Company"}
/>
}
</div>
)
}
}

@ -0,0 +1,148 @@
/**
* React Component for displaying a location's UI
*
* This is a "router" component of sorts, meaning it deduces the type of
* location that is being rendered and then creates the proper component(s) for that.
*/
import * as React from "react";
import { CompanyLocation } from "./CompanyLocation";
import { GymLocation } from "./GymLocation";
import { HospitalLocation } from "./HospitalLocation";
import { SlumsLocation } from "./SlumsLocation";
import { SpecialLocation } from "./SpecialLocation";
import { TechVendorLocation } from "./TechVendorLocation";
import { TravelAgencyLocation } from "./TravelAgencyLocation";
import { UniversityLocation } from "./UniversityLocation";
import { Location } from "../Location";
import { LocationType } from "../LocationTypeEnum";
import { CityName } from "../data/CityNames";
import { IEngine } from "../../IEngine";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { StdButton } from "../../ui/React/StdButton";
type IProps = {
engine: IEngine;
loc: Location;
p: IPlayer;
returnToCity: () => void;
travel: (to: CityName) => void;
}
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
* type. Returns an array of React components that should be rendered
*/
getLocationSpecificContent(): React.ReactNode[] {
const content: React.ReactNode[] = [];
if (this.props.loc.types.includes(LocationType.Company)) {
content.push(
<CompanyLocation
engine={this.props.engine}
key={"companylocation"}
locName={this.props.loc.name}
p={this.props.p}
/>
)
}
if (this.props.loc.types.includes(LocationType.Gym)) {
content.push(
<GymLocation
key={"gymlocation"}
loc={this.props.loc}
p={this.props.p}
/>
)
}
if (this.props.loc.types.includes(LocationType.Hospital)) {
content.push(
<HospitalLocation
key={"hospitallocation"}
p={this.props.p}
/>
)
}
if (this.props.loc.types.includes(LocationType.Slums)) {
content.push(
<SlumsLocation
key={"slumslocation"}
p={this.props.p}
/>
)
}
if (this.props.loc.types.includes(LocationType.Special)) {
content.push(
<SpecialLocation
engine={this.props.engine}
key={"speciallocation"}
loc={this.props.loc}
p={this.props.p}
/>
)
}
if (this.props.loc.types.includes(LocationType.TechVendor)) {
content.push(
<TechVendorLocation
key={"techvendorlocation"}
loc={this.props.loc}
p={this.props.p}
/>
)
}
if (this.props.loc.types.includes(LocationType.TravelAgency)) {
content.push(
<TravelAgencyLocation
key={"travelagencylocation"}
p={this.props.p}
travel={this.props.travel}
/>
)
}
if (this.props.loc.types.includes(LocationType.University)) {
content.push(
<UniversityLocation
key={"universitylocation"}
loc={this.props.loc}
p={this.props.p}
/>
)
}
return content;
}
render() {
const locContent: React.ReactNode[] = this.getLocationSpecificContent();
return (
<div>
<StdButton onClick={this.props.returnToCity} style={this.btnStyle} text={"Return to World"} />
<h1>{this.props.loc.name}</h1>
{locContent}
</div>
)
}
}

@ -0,0 +1,89 @@
/**
* React Subcomponent for displaying a location's UI, when that location is a gym
*
* This subcomponent renders all of the buttons for training at the gym
*/
import * as React from "react";
import { Location } from "../Location";
import { CONSTANTS } from "../../Constants";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { numeralWrapper } from "../../ui/numeralFormat";
import { StdButton } from "../../ui/React/StdButton";
type IProps = {
loc: Location;
p: IPlayer;
}
export class GymLocation 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" };
this.trainStrength = this.trainStrength.bind(this);
this.trainDefense = this.trainDefense.bind(this);
this.trainDexterity = this.trainDexterity.bind(this);
this.trainAgility = this.trainAgility.bind(this);
}
train(stat: string) {
const loc = this.props.loc;
this.props.p.startClass(loc.costMult, loc.expMult, stat);
}
trainStrength() {
return this.train(CONSTANTS.ClassGymStrength);
}
trainDefense() {
return this.train(CONSTANTS.ClassGymDefense);
}
trainDexterity() {
return this.train(CONSTANTS.ClassGymDexterity);
}
trainAgility() {
return this.train(CONSTANTS.ClassGymAgility);
}
render() {
const costMult: number = this.props.loc.costMult;
const cost = CONSTANTS.ClassGymBaseCost * costMult;
return (
<div>
<StdButton
onClick={this.trainStrength}
style={this.btnStyle}
text={`Train Strength (${numeralWrapper.formatMoney(cost)} / sec)`}
/>
<StdButton
onClick={this.trainDefense}
style={this.btnStyle}
text={`Train Defense (${numeralWrapper.formatMoney(cost)} / sec)`}
/>
<StdButton
onClick={this.trainDexterity}
style={this.btnStyle}
text={`Train Dexterity (${numeralWrapper.formatMoney(cost)} / sec)`}
/>
<StdButton
onClick={this.trainAgility}
style={this.btnStyle}
text={`Train Agility (${numeralWrapper.formatMoney(cost)} / sec)`}
/>
</div>
)
}
}

@ -0,0 +1,63 @@
/**
* React Subcomponent for displaying a location's UI, when that location is a hospital
*
* This subcomponent renders all of the buttons for hospital options
*/
import * as React from "react";
import { CONSTANTS } from "../../Constants";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { numeralWrapper } from "../../ui/numeralFormat";
import { AutoupdatingStdButton } from "../../ui/React/AutoupdatingStdButton";
import { dialogBoxCreate } from "../../../utils/DialogBox";
type IProps = {
p: IPlayer;
}
export class HospitalLocation 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" };
this.getCost = this.getCost.bind(this);
this.getHealed = this.getHealed.bind(this);
}
getCost(): number {
return (this.props.p.max_hp - this.props.p.hp) * CONSTANTS.HospitalCostPerHp;
}
getHealed(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) { return; }
if (this.props.p.hp < 0) { this.props.p.hp = 0; }
if (this.props.p.hp >= this.props.p.max_hp) { return; }
const cost = this.getCost();
this.props.p.loseMoney(cost);
this.props.p.hp = this.props.p.max_hp;
dialogBoxCreate(`You were healed to full health! The hospital billed you for ${numeralWrapper.formatMoney(cost)}`);
}
render() {
const cost = this.getCost();
return (
<AutoupdatingStdButton
onClick={this.getHealed}
style={this.btnStyle}
text={`Get treatment for wounds - ${numeralWrapper.formatMoney(cost)}`}
/>
)
}
}

151
src/Locations/ui/Root.tsx Normal file

@ -0,0 +1,151 @@
/**
* Root React Component for displaying overall Location UI
*/
import * as React from "react";
import { LocationCity } from "./City";
import { GenericLocation } from "./GenericLocation";
import { Cities } from "../Cities";
import { Locations } from "../Locations";
import { LocationType } from "../LocationTypeEnum";
import { CityName } from "../data/CityNames";
import { LocationName } from "../data/LocationNames";
import { CONSTANTS } from "../../Constants";
import { IEngine } from "../../IEngine";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { dialogBoxCreate } from "../../../utils/DialogBox";
type IProps = {
initiallyInCity?: boolean;
engine: IEngine;
p: IPlayer;
}
type IState = {
city: CityName;
inCity: boolean;
location: LocationName;
}
export class LocationRoot extends React.Component<IProps, IState> {
constructor(props: IProps) {
super(props);
this.state = {
city: props.p.city,
inCity: props.initiallyInCity == null ? true : props.initiallyInCity,
location: props.p.location,
}
this.enterLocation = this.enterLocation.bind(this);
this.returnToCity = this.returnToCity.bind(this);
this.travel = this.travel.bind(this);
}
enterLocation(to: LocationName): void {
this.props.p.gotoLocation(to);
this.setState({
inCity: false,
location: to,
});
}
/**
* Click listener for a button that lets the player go from a specific location
* back to the city
*/
returnToCity(): void {
this.setState({
inCity: true,
});
}
/**
* Render UI for a city
*/
renderCity(): React.ReactNode {
const city = Cities[this.state.city];
if (city == null) {
throw new Error(`Invalid city when rendering UI: ${this.state.city}`);
}
return (
<div>
<h2>{this.state.city}</h2>
<LocationCity city={city} enterLocation={this.enterLocation} />
</div>
)
}
/**
* Render UI for a specific location
*/
renderLocation(): React.ReactNode {
const loc = Locations[this.state.location];
if (loc == null) {
throw new Error(`Invalid location when rendering UI: ${this.state.location}`);
}
if (loc.types.includes(LocationType.StockMarket)) {
this.props.engine.loadStockMarketContent();
}
return (
<GenericLocation
engine={this.props.engine}
loc={loc}
p={this.props.p}
returnToCity={this.returnToCity}
travel={this.travel}
/>
)
}
/**
* Travel to a different city
* @param {CityName} to - Destination city
*/
travel(to: CityName): void {
const p = this.props.p;
const cost = CONSTANTS.TravelCost;
if (!p.canAfford(cost)) {
dialogBoxCreate(`You cannot afford to travel to ${to}`);
return;
}
p.loseMoney(cost);
p.travel(to);
dialogBoxCreate(`You are now in ${to}!`);
// Dynamically update main menu
if (p.firstTimeTraveled === false) {
p.firstTimeTraveled = true;
const travelTab = document.getElementById("travel-tab");
const worldHeader = document.getElementById("world-menu-header");
if (travelTab != null && worldHeader !== null) {
travelTab.style.display = "list-item";
worldHeader.click(); worldHeader.click();
}
}
if (this.props.p.travel(to)) {
this.setState({
inCity: true,
city: to
});
}
}
render() {
if (this.state.inCity) {
return this.renderCity();
} else {
return this.renderLocation();
}
}
}

@ -0,0 +1,206 @@
/**
* React Subcomponent for displaying a location's UI, when that location is a slum
*
* This subcomponent renders all of the buttons for committing crimes
*/
import * as React from "react";
import { Crimes } from "../../Crime/Crimes";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { numeralWrapper } from "../../ui/numeralFormat";
import { AutoupdatingStdButton } from "../../ui/React/AutoupdatingStdButton";
type IProps = {
p: IPlayer;
}
export class SlumsLocation 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" };
this.shoplift = this.shoplift.bind(this);
this.robStore = this.robStore.bind(this);
this.mug = this.mug.bind(this);
this.larceny = this.larceny.bind(this);
this.dealDrugs = this.dealDrugs.bind(this);
this.bondForgery = this.bondForgery.bind(this);
this.traffickArms = this.traffickArms.bind(this);
this.homicide = this.homicide.bind(this);
this.grandTheftAuto = this.grandTheftAuto.bind(this);
this.kidnap = this.kidnap.bind(this);
this.assassinate = this.assassinate.bind(this);
this.heist = this.heist.bind(this);
}
shoplift(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) { return; }
Crimes.Shoplift.commit(this.props.p);
}
robStore(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) { return; }
Crimes.RobStore.commit(this.props.p);
}
mug(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) { return; }
Crimes.Mug.commit(this.props.p);
}
larceny(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) { return; }
Crimes.Larceny.commit(this.props.p);
}
dealDrugs(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) { return; }
Crimes.DealDrugs.commit(this.props.p);
}
bondForgery(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) { return; }
Crimes.BondForgery.commit(this.props.p);
}
traffickArms(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) { return; }
Crimes.TraffickArms.commit(this.props.p);
}
homicide(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) { return; }
Crimes.Homicide.commit(this.props.p);
}
grandTheftAuto(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) { return; }
Crimes.GrandTheftAuto.commit(this.props.p);
}
kidnap(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) { return; }
Crimes.Kidnap.commit(this.props.p);
}
assassinate(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) { return; }
Crimes.Assassination.commit(this.props.p);
}
heist(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) { return; }
Crimes.Heist.commit(this.props.p);
}
render() {
const shopliftChance = Crimes.Shoplift.successRate(this.props.p);
const robStoreChance = Crimes.RobStore.successRate(this.props.p);
const mugChance = Crimes.Mug.successRate(this.props.p);
const larcenyChance = Crimes.Larceny.successRate(this.props.p);
const drugsChance = Crimes.DealDrugs.successRate(this.props.p);
const bondChance = Crimes.BondForgery.successRate(this.props.p);
const armsChance = Crimes.TraffickArms.successRate(this.props.p);
const homicideChance = Crimes.Homicide.successRate(this.props.p);
const gtaChance = Crimes.GrandTheftAuto.successRate(this.props.p);
const kidnapChance = Crimes.Kidnap.successRate(this.props.p);
const assassinateChance = Crimes.Assassination.successRate(this.props.p);
const heistChance = Crimes.Heist.successRate(this.props.p);
return (
<div>
<AutoupdatingStdButton
intervalTime={5e3}
onClick={this.shoplift}
style={this.btnStyle}
text={`Shoplift (${numeralWrapper.formatPercentage(shopliftChance)} chance of success)`}
tooltip={"Attempt to shoplift from a low-end retailer"}
/>
<AutoupdatingStdButton
intervalTime={5e3}
onClick={this.robStore}
style={this.btnStyle}
text={`Rob store (${numeralWrapper.formatPercentage(robStoreChance)} chance of success)`}
tooltip={"Attempt to commit armed robbery on a high-end store"}
/>
<AutoupdatingStdButton
intervalTime={5e3}
onClick={this.mug}
style={this.btnStyle}
text={`Mug someone (${numeralWrapper.formatPercentage(mugChance)} chance of success)`}
tooltip={"Attempt to mug a random person on the street"}
/>
<AutoupdatingStdButton
intervalTime={5e3}
onClick={this.larceny}
style={this.btnStyle}
text={`Larceny (${numeralWrapper.formatPercentage(larcenyChance)} chance of success)`}
tooltip={"Attempt to rob property from someone's house"}
/>
<AutoupdatingStdButton
intervalTime={5e3}
onClick={this.dealDrugs}
style={this.btnStyle}
text={`Deal Drugs (${numeralWrapper.formatPercentage(drugsChance)} chance of success)`}
tooltip={"Attempt to deal drugs"}
/>
<AutoupdatingStdButton
intervalTime={5e3}
onClick={this.bondForgery}
style={this.btnStyle}
text={`Bond Forgery (${numeralWrapper.formatPercentage(bondChance)} chance of success)`}
tooltip={"Attempt to forge corporate bonds"}
/>
<AutoupdatingStdButton
intervalTime={5e3}
onClick={this.traffickArms}
style={this.btnStyle}
text={`Traffick illegal Arms (${numeralWrapper.formatPercentage(armsChance)} chance of success)`}
tooltip={"Attempt to smuggle illegal arms into the city"}
/>
<AutoupdatingStdButton
intervalTime={5e3}
onClick={this.homicide}
style={this.btnStyle}
text={`Homicide (${numeralWrapper.formatPercentage(homicideChance)} chance of success)`}
tooltip={"Attempt to murder a random person on the street"}
/>
<AutoupdatingStdButton
intervalTime={5e3}
onClick={this.grandTheftAuto}
style={this.btnStyle}
text={`Grand theft Auto (${numeralWrapper.formatPercentage(gtaChance)} chance of success)`}
tooltip={"Attempt to commit grand theft auto"}
/>
<AutoupdatingStdButton
intervalTime={5e3}
onClick={this.kidnap}
style={this.btnStyle}
text={`Kidnap and Ransom (${numeralWrapper.formatPercentage(kidnapChance)} chance of success)`}
tooltip={"Attempt to kidnap and ransom a high-profile-target"}
/>
<AutoupdatingStdButton
intervalTime={5e3}
onClick={this.assassinate}
style={this.btnStyle}
text={`Assassinate (${numeralWrapper.formatPercentage(assassinateChance)} chance of success)`}
tooltip={"Attempt to assassinate a high-profile target"}
/>
<AutoupdatingStdButton
intervalTime={5e3}
onClick={this.heist}
style={this.btnStyle}
text={`Heist (${numeralWrapper.formatPercentage(heistChance)} chance of success)`}
tooltip={"Attempt to pull off the ultimate heist"}
/>
</div>
)
}
}

@ -0,0 +1,149 @@
/**
* React Subcomponent for displaying a location's UI, when that location has special
* actions/options/properties
*
* Examples:
* - Bladeburner @ NSA
* - Re-sleeving @ VitaLife
* - Create Corporation @ City Hall
*
* This subcomponent creates all of the buttons for interacting with those special
* properties
*/
import * as React from "react";
import { Location } from "../Location";
import { createStartCorporationPopup } from "../LocationsHelpers";
import { LocationName } from "../data/LocationNames";
import { IEngine } from "../../IEngine";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { AutoupdatingStdButton } from "../../ui/React/AutoupdatingStdButton";
import { StdButton } from "../../ui/React/StdButton";
import { dialogBoxCreate } from "../../../utils/DialogBox";
type IProps = {
engine: IEngine;
loc: Location;
p: IPlayer;
}
type IState = {
inBladeburner: boolean;
}
export class SpecialLocation extends React.Component<IProps, IState> {
/**
* Stores button styling that sets them all to block display
*/
btnStyle: object;
constructor(props: IProps) {
super(props);
this.btnStyle = { display: "block" };
this.createCorporationPopup = this.createCorporationPopup.bind(this);
this.handleBladeburner = this.handleBladeburner.bind(this);
this.handleResleeving = this.handleResleeving.bind(this);
this.state = {
inBladeburner: this.props.p.inBladeburner(),
}
}
/**
* Click handler for "Create Corporation" button at Sector-12 City Hall
*/
createCorporationPopup() {
createStartCorporationPopup(this.props.p);
}
/**
* Click handler for Bladeburner button at Sector-12 NSA
*/
handleBladeburner() {
const p = this.props.p;
if (p.inBladeburner()) {
// Enter Bladeburner division
this.props.engine.loadBladeburnerContent();
} else {
// Apply for Bladeburner division
if (p.strength >= 100 && p.defense >= 100 && p.dexterity >= 100 && p.agility >= 100) {
p.startBladeburner({ new: true });
dialogBoxCreate("You have been accepted into the Bladeburner division!");
this.setState({
inBladeburner: true,
});
const worldHeader = document.getElementById("world-menu-header");
if (worldHeader instanceof HTMLElement) {
worldHeader.click(); worldHeader.click();
}
} else {
dialogBoxCreate("Rejected! Please apply again when you have 100 of each combat stat (str, def, dex, agi)");
}
}
}
/**
* Click handler for Resleeving button at New Tokyo VitaLife
*/
handleResleeving() {
this.props.engine.loadResleevingContent();
}
renderBladeburner(): React.ReactNode {
if (!this.props.p.canAccessBladeburner()) { return null; }
const text = this.state.inBladeburner ? "Enter Bladeburner Headquarters" : "Apply to Bladeburner Division";
return (
<StdButton
onClick={this.handleBladeburner}
style={this.btnStyle}
text={text}
/>
)
}
renderCreateCorporation(): React.ReactNode {
if (!this.props.p.canAccessCorporation()) { return null; }
return (
<AutoupdatingStdButton
disabled={!this.props.p.canAccessCorporation() || this.props.p.hasCorporation()}
onClick={this.createCorporationPopup}
style={this.btnStyle}
text={"Create a Corporation"}
/>
)
}
renderResleeving(): React.ReactNode {
if (!this.props.p.canAccessResleeving()) { return null; }
return (
<StdButton
onClick={this.handleResleeving}
style={this.btnStyle}
text={"Re-Sleeve"}
/>
)
}
render() {
switch (this.props.loc.name) {
case LocationName.NewTokyoVitaLife: {
return this.renderResleeving();
}
case LocationName.Sector12CityHall: {
return this.renderCreateCorporation();
}
case LocationName.Sector12NSA: {
return this.renderBladeburner();
}
default:
console.error(`Location ${this.props.loc.name} doesn't have any special properties`);
break;
}
}
}

@ -0,0 +1,106 @@
/**
* React Subcomponent for displaying a location's UI, when that location is a tech vendor
*
* This subcomponent renders all of the buttons for purchasing things from tech vendors
*/
import * as React from "react";
import { Location } from "../Location";
import { createPurchaseServerPopup,
createUpgradeHomeCoresPopup,
createUpgradeHomeRamPopup,
purchaseTorRouter } from "../LocationsHelpers";
import { CONSTANTS } from "../../Constants";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { getPurchaseServerCost } from "../../Server/ServerPurchases";
import { numeralWrapper } from "../../ui/numeralFormat";
import { StdButtonPurchased } from "../../ui/React/StdButtonPurchased";
import { StdButton } from "../../ui/React/StdButton";
type IProps = {
loc: Location;
p: IPlayer;
}
export class TechVendorLocation 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" };
this.state = {
torPurchased: props.p.hasTorRouter(),
}
this.createUpgradeHomeCoresPopup = this.createUpgradeHomeCoresPopup.bind(this);
this.createUpgradeHomeRamPopup = this.createUpgradeHomeRamPopup.bind(this);
this.purchaseTorRouter = this.purchaseTorRouter.bind(this);
}
createUpgradeHomeCoresPopup() {
createUpgradeHomeCoresPopup(this.props.p);
}
createUpgradeHomeRamPopup() {
createUpgradeHomeRamPopup(this.props.p);
}
purchaseTorRouter() {
purchaseTorRouter(this.props.p);
}
render() {
const loc: Location = this.props.loc;
const purchaseServerButtons: React.ReactNode[] = [];
for (let i = loc.techVendorMinRam; i <= loc.techVendorMaxRam; i *= 2) {
const cost = getPurchaseServerCost(i);
purchaseServerButtons.push(
<StdButton
key={i}
onClick={() => createPurchaseServerPopup(i, this.props.p)}
style={this.btnStyle}
text={`Purchase ${i}GB Server - ${numeralWrapper.formatMoney(cost)}`}
/>
)
}
return (
<div>
{purchaseServerButtons}
{
this.state.torPurchased ? (
<StdButtonPurchased
style={this.btnStyle}
text={"TOR Router - Purchased"}
/>
) : (
<StdButton
onClick={this.purchaseTorRouter}
style={this.btnStyle}
text={`Purchase TOR Router - ${numeralWrapper.formatMoney(CONSTANTS.TorRouterCost)}`}
/>
)
}
<StdButton
onClick={this.createUpgradeHomeRamPopup}
style={this.btnStyle}
text={`Purchase additional RAM for Home computer`}
/>
<StdButton
onClick={this.createUpgradeHomeCoresPopup}
style={this.btnStyle}
text={`Purchase additional Core for Home computer`}
/>
</div>
)
}
}

@ -0,0 +1,62 @@
/**
* React Subcomponent for displaying a location's UI, when that location is a Travel Agency
*
* This subcomponent renders all of the buttons for traveling to different cities
*/
import * as React from "react";
import { CityName } from "../data/CityNames";
import { createTravelPopup } from "../LocationsHelpers";
import { CONSTANTS } from "../../Constants";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { numeralWrapper } from "../../ui/numeralFormat";
import { StdButton } from "../../ui/React/StdButton";
type IProps = {
p: IPlayer;
travel: (to: CityName) => void;
}
export class TravelAgencyLocation 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" };
}
render() {
const travelBtns: React.ReactNode[] = [];
for (const key in CityName) {
const city = CityName[key];
// Skip current city
if (city === this.props.p.city) { continue; }
travelBtns.push(
<StdButton
key={city}
onClick={createTravelPopup.bind(null, city, this.props.travel)}
style={this.btnStyle}
text={`Travel to ${city}`}
/>
)
}
return (
<div>
<p>
From here, you can travel to any other city! A ticket
costs {numeralWrapper.formatMoney(CONSTANTS.TravelCost)}
</p>
{travelBtns}
</div>
)
}
}

@ -0,0 +1,114 @@
/**
* React Subcomponent for displaying a location's UI, when that location is a university
*
* This subcomponent renders all of the buttons for studying/taking courses
*/
import * as React from "react";
import { Location } from "../Location";
import { CONSTANTS } from "../../Constants";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { numeralWrapper } from "../../ui/numeralFormat";
import { StdButton } from "../../ui/React/StdButton";
type IProps = {
loc: Location;
p: IPlayer;
}
export class UniversityLocation 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" };
this.take = this.take.bind(this);
this.study = this.study.bind(this);
this.dataStructures = this.dataStructures.bind(this);
this.networks = this.networks.bind(this);
this.algorithms = this.algorithms.bind(this);
this.management = this.management.bind(this);
this.leadership = this.leadership.bind(this);
}
take(stat: string) {
const loc = this.props.loc;
this.props.p.startClass(loc.costMult, loc.expMult, stat);
}
study() {
return this.take(CONSTANTS.ClassStudyComputerScience);
}
dataStructures() {
return this.take(CONSTANTS.ClassDataStructures);
}
networks() {
return this.take(CONSTANTS.ClassNetworks);
}
algorithms() {
return this.take(CONSTANTS.ClassAlgorithms);
}
management() {
return this.take(CONSTANTS.ClassManagement);
}
leadership() {
return this.take(CONSTANTS.ClassLeadership);
}
render() {
const costMult: number = this.props.loc.costMult;
const dataStructuresCost = CONSTANTS.ClassDataStructuresBaseCost * costMult;
const networksCost = CONSTANTS.ClassNetworksBaseCost * costMult;
const algorithmsCost = CONSTANTS.ClassAlgorithmsBaseCost * costMult;
const managementCost = CONSTANTS.ClassManagementBaseCost * costMult;
const leadershipCost = CONSTANTS.ClassLeadershipBaseCost * costMult;
return (
<div>
<StdButton
onClick={this.study}
style={this.btnStyle}
text={`Study Computer Science (free)`}
/>
<StdButton
onClick={this.dataStructures}
style={this.btnStyle}
text={`Take Data Structures course (${numeralWrapper.formatMoney(dataStructuresCost)} / sec)`}
/>
<StdButton
onClick={this.networks}
style={this.btnStyle}
text={`Take Networks course (${numeralWrapper.formatMoney(networksCost)} / sec)`}
/>
<StdButton
onClick={this.algorithms}
style={this.btnStyle}
text={`Take Algorithms course (${numeralWrapper.formatMoney(algorithmsCost)} / sec)`}
/>
<StdButton
onClick={this.management}
style={this.btnStyle}
text={`Take Management course (${numeralWrapper.formatMoney(managementCost)} / sec)`}
/>
<StdButton
onClick={this.leadership}
style={this.btnStyle}
text={`Take Leadership course (${numeralWrapper.formatMoney(leadershipCost)} / sec)`}
/>
</div>
)
}
}

@ -35,8 +35,11 @@ import { netscriptCanGrow,
import { getCostOfNextHacknetNode,
getCostOfNextHacknetServer,
hasHacknetServers,
purchaseHacknet } from "./Hacknet/HacknetHelpers";
purchaseHacknet,
hasHacknetServers } from "./Hacknet/HacknetHelpers";
import { CityName } from "./Locations/data/CityNames";
import { LocationName } from "./Locations/data/LocationNames";
import { HacknetServer } from "./Hacknet/HacknetServer";
import {Locations} from "./Locations";
import { Message } from "./Message/Message";
@ -2615,30 +2618,30 @@ function NetscriptFunctions(workerScript) {
var costMult, expMult;
switch(universityName.toLowerCase()) {
case Locations.AevumSummitUniversity.toLowerCase():
if (Player.city != Locations.Aevum) {
case LocationName.AevumSummitUniversity.toLowerCase():
if (Player.city != CityName.Aevum) {
workerScript.scriptRef.log("ERROR: You cannot study at Summit University because you are not in Aevum. universityCourse() failed");
return false;
}
Player.location = Locations.AevumSummitUniversity;
Player.gotoLocation(LocationName.AevumSummitUniversity);
costMult = 4;
expMult = 3;
break;
case Locations.Sector12RothmanUniversity.toLowerCase():
if (Player.city != Locations.Sector12) {
case LocationName.Sector12RothmanUniversity.toLowerCase():
if (Player.city != CityName.Sector12) {
workerScript.scriptRef.log("ERROR: You cannot study at Rothman University because you are not in Sector-12. universityCourse() failed");
return false;
}
Player.location = Locations.Sector12RothmanUniversity;
Player.location = LocationName.Sector12RothmanUniversity;
costMult = 3;
expMult = 2;
break;
case Locations.VolhavenZBInstituteOfTechnology.toLowerCase():
if (Player.city != Locations.Volhaven) {
case LocationName.VolhavenZBInstituteOfTechnology.toLowerCase():
if (Player.city != CityName.Volhaven) {
workerScript.scriptRef.log("ERROR: You cannot study at ZB Institute of Technology because you are not in Volhaven. universityCourse() failed");
return false;
}
Player.location = Locations.VolhavenZBInstituteOfTechnology;
Player.location = LocationName.VolhavenZBInstituteOfTechnology;
costMult = 5;
expMult = 4;
break;
@ -2703,48 +2706,48 @@ function NetscriptFunctions(workerScript) {
}
var costMult, expMult;
switch(gymName.toLowerCase()) {
case Locations.AevumCrushFitnessGym.toLowerCase():
if (Player.city != Locations.Aevum) {
case LocationName.AevumCrushFitnessGym.toLowerCase():
if (Player.city != CityName.Aevum) {
workerScript.scriptRef.log("ERROR: You cannot workout at Crush Fitness because you are not in Aevum. gymWorkout() failed");
return false;
}
Player.location = Locations.AevumCrushFitnessGym;
Player.location = LocationName.AevumCrushFitnessGym;
costMult = 3;
expMult = 2;
break;
case Locations.AevumSnapFitnessGym.toLowerCase():
if (Player.city != Locations.Aevum) {
case LocationName.AevumSnapFitnessGym.toLowerCase():
if (Player.city != CityName.Aevum) {
workerScript.scriptRef.log("ERROR: You cannot workout at Snap Fitness because you are not in Aevum. gymWorkout() failed");
return false;
}
Player.location = Locations.AevumSnapFitnessGym;
Player.location = LocationName.AevumSnapFitnessGym;
costMult = 10;
expMult = 5;
break;
case Locations.Sector12IronGym.toLowerCase():
if (Player.city != Locations.Sector12) {
case LocationName.Sector12IronGym.toLowerCase():
if (Player.city != CityName.Sector12) {
workerScript.scriptRef.log("ERROR: You cannot workout at Iron Gym because you are not in Sector-12. gymWorkout() failed");
return false;
}
Player.location = Locations.Sector12IronGym;
Player.location = LocationName.Sector12IronGym;
costMult = 1;
expMult = 1;
break;
case Locations.Sector12PowerhouseGym.toLowerCase():
if (Player.city != Locations.Sector12) {
case LocationName.Sector12PowerhouseGym.toLowerCase():
if (Player.city != CityName.Sector12) {
workerScript.scriptRef.log("ERROR: You cannot workout at Powerhouse Gym because you are not in Sector-12. gymWorkout() failed");
return false;
}
Player.location = Locations.Sector12PowerhouseGym;
Player.location = LocationName.Sector12PowerhouseGym;
costMult = 20;
expMult = 10;
break;
case Locations.VolhavenMilleniumFitnessGym.toLowerCase():
if (Player.city != Locations.Volhaven) {
case LocationName.VolhavenMilleniumFitnessGym.toLowerCase():
if (Player.city != CityName.Volhaven) {
workerScript.scriptRef.log("ERROR: You cannot workout at Millenium Fitness Gym because you are not in Volhaven. gymWorkout() failed");
return false;
}
Player.location = Locations.VolhavenMilleniumFitnessGym;
Player.location = LocationName.VolhavenMilleniumFitnessGym;
costMult = 7;
expMult = 4;
break;
@ -2795,12 +2798,12 @@ function NetscriptFunctions(workerScript) {
}
switch(cityname) {
case Locations.Aevum:
case Locations.Chongqing:
case Locations.Sector12:
case Locations.NewTokyo:
case Locations.Ishima:
case Locations.Volhaven:
case CityName.Aevum:
case CityName.Chongqing:
case CityName.Sector12:
case CityName.NewTokyo:
case CityName.Ishima:
case CityName.Volhaven:
if(Player.money.lt(CONSTANTS.TravelCost)) {
workerScript.scriptRef.log("ERROR: not enough money to travel with travelToCity().");
throw makeRuntimeRejectMsg(workerScript, "ERROR: not enough money to travel with travelToCity().");
@ -3618,29 +3621,8 @@ function NetscriptFunctions(workerScript) {
}
}
//Set Location to slums
switch(Player.city) {
case Locations.Aevum:
Player.location = Locations.AevumSlums;
break;
case Locations.Chongqing:
Player.location = Locations.ChongqingSlums;
break;
case Locations.Sector12:
Player.location = Locations.Sector12Slums;
break;
case Locations.NewTokyo:
Player.location = Locations.NewTokyoSlums;
break;
case Locations.Ishima:
Player.location = Locations.IshimaSlums;
break;
case Locations.Volhaven:
Player.location = Locations.VolhavenSlums;
break;
default:
console.log("Invalid Player.city value");
}
// Set Location to slums
Player.gotoLocation(LocationName.Slums);
const crime = findCrime(crimeRoughName.toLowerCase());
if(crime == null) { // couldn't find crime

@ -1,33 +1,44 @@
// Interface for an object that represents the player (PlayerObject)
// Used because at the time of implementation, the PlayerObject
// cant be converted to TypeScript.
//
// Only contains the needed properties for Sleeve implementation
/**
* Interface for an object that represents the player (PlayerObject)
* Used because at the time of implementation, the PlayerObject
* cant be converted to TypeScript.
*/
import { Resleeve } from "./Resleeving/Resleeve";
import { Sleeve } from "./Sleeve/Sleeve";
import { IMap } from "../types";
import { IPlayerOwnedAugmentation } from "../Augmentation/PlayerOwnedAugmentation";
import { HacknetNode } from "../Hacknet/HacknetNode";
import { HacknetServer } from "../Hacknet/HacknetServer";
import { IPlayerOwnedSourceFile } from "../SourceFile/PlayerOwnedSourceFile";
import { MoneySourceTracker } from "../utils/MoneySourceTracker";
import { IPlayerOwnedAugmentation } from "../Augmentation/PlayerOwnedAugmentation";
import { Company } from "../Company/Company";
import { CompanyPosition } from "../Company/CompanyPosition";
import { CityName } from "../Locations/data/CityNames";
import { HashManager } from "../Hacknet/HashManager";
import { HacknetNode } from "../Hacknet/HacknetNode";
import { LocationName } from "../Locations/data/LocationNames";
import { Server } from "../Server/Server";
import { IPlayerOwnedSourceFile } from "../SourceFile/PlayerOwnedSourceFile";
import { MoneySourceTracker } from "../utils/MoneySourceTracker";
export interface IPlayer {
// Class members
augmentations: IPlayerOwnedAugmentation[];
bladeburner: any;
bitNodeN: number;
city: string;
city: CityName;
companyName: string;
corporation: any;
currentServer: string;
factions: string[];
firstTimeTraveled: boolean;
hacknetNodes: (HacknetNode | string)[]; // HacknetNode object or IP of Hacknet Server
hashManager: HashManager;
hasWseAccount: boolean;
homeComputer: string;
hp: number;
jobs: IMap<string>;
karma: number;
location: LocationName;
max_hp: number;
money: any;
moneySourceA: MoneySourceTracker;
moneySourceB: MoneySourceTracker;
@ -87,6 +98,23 @@ export interface IPlayer {
crime_money_mult: number;
// Methods
applyForAgentJob(sing?: boolean): boolean | void;
applyForBusinessConsultantJob(sing?: boolean): boolean | void;
applyForBusinessJob(sing?: boolean): boolean | void;
applyForEmployeeJob(sing?: boolean): boolean | void;
applyForItJob(sing?: boolean): boolean | void;
applyForJob(entryPosType: CompanyPosition, sing?: boolean): boolean | void;
applyForNetworkEngineerJob(sing?: boolean): boolean | void;
applyForPartTimeEmployeeJob(sing?: boolean): boolean | void;
applyForPartTimeWaiterJob(sing?: boolean): boolean | void;
applyForSecurityEngineerJob(sing?: boolean): boolean | void;
applyForSecurityJob(sing?: boolean): boolean | void;
applyForSoftwareConsultantJob(sing?: boolean): boolean | void;
applyForSoftwareJob(sing?: boolean): boolean | void;
applyForWaiterJob(sing?: boolean): boolean | void;
canAccessBladeburner(): boolean;
canAccessCorporation(): boolean;
canAccessResleeving(): boolean;
canAfford(cost: number): boolean;
gainHackingExp(exp: number): void;
gainStrengthExp(exp: number): void;
@ -95,13 +123,23 @@ export interface IPlayer {
gainAgilityExp(exp: number): void;
gainCharismaExp(exp: number): void;
gainMoney(money: number): void;
getHomeComputer(): Server;
getNextCompanyPosition(company: Company, entryPosType: CompanyPosition): CompanyPosition;
getUpgradeHomeRamCost(): number;
gotoLocation(to: LocationName): boolean;
hasCorporation(): boolean;
hasTorRouter(): boolean;
inBladeburner(): boolean;
inGang(): boolean;
isQualified(company: Company, position: CompanyPosition): boolean;
loseMoney(money: number): void;
reapplyAllAugmentations(resetMultipliers: boolean): void;
reapplyAllSourceFiles(): void;
regenerateHp(amt: number): void;
recordMoneySource(amt: number, source: string): void;
startBladeburner(p: object): void;
startClass(costMult: number, expMult: number, className: string): void;
startCorporation(corpName: string, additionalShares?: number): void;
startCrime(crimeType: string,
hackExp: number,
strExp: number,
@ -112,4 +150,7 @@ export interface IPlayer {
money: number,
time: number,
singParams: any): void;
startWork(companyName: string): void;
startWorkPartTime(companyName: string): void;
travel(to: CityName): boolean;
}

@ -3,7 +3,7 @@ import { Augmentation } from "../Augmentation/Augmentation";
import { Augmentations } from "../Augmentation/Augmentations";
import { IPlayerOwnedAugmentation } from "../Augmentation/PlayerOwnedAugmentation";
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
import { Cities } from "../Locations/Cities";
import { CityName } from "../Locations/data/CityNames";
import { CONSTANTS } from "../Constants";
// Interface that defines a generic object used to track experience/money
@ -105,7 +105,7 @@ export abstract class Person {
/**
* City that the person is in
*/
city: string = Cities.Sector12;
city: CityName = CityName.Sector12;
constructor() {}

@ -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;
}

@ -22,8 +22,6 @@ import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
import { Crime } from "../../Crime/Crime";
import { Crimes } from "../../Crime/Crimes";
import { Cities } from "../../Locations/Cities";
import { Companies } from "../../Company/Companies";
import { Company } from "../../Company/Company";
import { CompanyPosition } from "../../Company/CompanyPosition";
@ -35,7 +33,8 @@ import { Faction } from "../../Faction/Faction";
import { Factions } from "../../Faction/Factions";
import { FactionWorkType } from "../../Faction/FactionWorkTypeEnum";
import { Locations } from "../../Locations";
import { CityName } from "../../Locations/data/CityNames";
import { LocationName } from "../../Locations/data/LocationNames";
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../../utils/JSONReviver";
@ -592,21 +591,21 @@ export class Sleeve extends Person {
let costMult: number = 1;
let expMult: number = 1;
switch (universityName.toLowerCase()) {
case Locations.AevumSummitUniversity.toLowerCase():
if (this.city !== Cities.Aevum) { return false; }
this.currentTaskLocation = Locations.AevumSummitUniversity;
case LocationName.AevumSummitUniversity.toLowerCase():
if (this.city !== CityName.Aevum) { return false; }
this.currentTaskLocation = LocationName.AevumSummitUniversity;
costMult = 4;
expMult = 3;
break;
case Locations.Sector12RothmanUniversity.toLowerCase():
if (this.city !== Cities.Sector12) { return false; }
this.currentTaskLocation = Locations.Sector12RothmanUniversity;
case LocationName.Sector12RothmanUniversity.toLowerCase():
if (this.city !== CityName.Sector12) { return false; }
this.currentTaskLocation = LocationName.Sector12RothmanUniversity;
costMult = 3;
expMult = 2;
break;
case Locations.VolhavenZBInstituteOfTechnology.toLowerCase():
if (this.city !== Cities.Volhaven) { return false; }
this.currentTaskLocation = Locations.VolhavenZBInstituteOfTechnology;
case LocationName.VolhavenZBInstituteOfTechnology.toLowerCase():
if (this.city !== CityName.Volhaven) { return false; }
this.currentTaskLocation = LocationName.VolhavenZBInstituteOfTechnology;
costMult = 5;
expMult = 4;
break;
@ -658,11 +657,7 @@ export class Sleeve extends Person {
/**
* Travel to another City. Costs money from player
*/
travel(p: IPlayer, newCity: string): boolean {
if (Cities[newCity] == null) {
return false;
}
travel(p: IPlayer, newCity: CityName): boolean {
p.loseMoney(CONSTANTS.TravelCost);
this.city = newCity;
@ -791,33 +786,33 @@ export class Sleeve extends Person {
let costMult: number = 1;
let expMult: number = 1;
switch (gymName.toLowerCase()) {
case Locations.AevumCrushFitnessGym.toLowerCase():
if (this.city != Cities.Aevum) { return false; }
this.currentTaskLocation = Locations.AevumCrushFitnessGym;
case LocationName.AevumCrushFitnessGym.toLowerCase():
if (this.city != CityName.Aevum) { return false; }
this.currentTaskLocation = LocationName.AevumCrushFitnessGym;
costMult = 3;
expMult = 2;
break;
case Locations.AevumSnapFitnessGym.toLowerCase():
if (this.city != Cities.Aevum) { return false; }
this.currentTaskLocation = Locations.AevumSnapFitnessGym;
case LocationName.AevumSnapFitnessGym.toLowerCase():
if (this.city != CityName.Aevum) { return false; }
this.currentTaskLocation = LocationName.AevumSnapFitnessGym;
costMult = 10;
expMult = 5;
break;
case Locations.Sector12IronGym.toLowerCase():
if (this.city != Cities.Sector12) { return false; }
this.currentTaskLocation = Locations.Sector12IronGym;
case LocationName.Sector12IronGym.toLowerCase():
if (this.city != CityName.Sector12) { return false; }
this.currentTaskLocation = LocationName.Sector12IronGym;
costMult = 1;
expMult = 1;
break;
case Locations.Sector12PowerhouseGym.toLowerCase():
if (this.city != Cities.Sector12) { return false; }
this.currentTaskLocation = Locations.Sector12PowerhouseGym;
case LocationName.Sector12PowerhouseGym.toLowerCase():
if (this.city != CityName.Sector12) { return false; }
this.currentTaskLocation = LocationName.Sector12PowerhouseGym;
costMult = 20;
expMult = 10;
break;
case Locations.VolhavenMilleniumFitnessGym:
if (this.city != Cities.Volhaven) { return false; }
this.currentTaskLocation = Locations.VolhavenMilleniumFitnessGym;
case LocationName.VolhavenMilleniumFitnessGym:
if (this.city != CityName.Volhaven) { return false; }
this.currentTaskLocation = LocationName.VolhavenMilleniumFitnessGym;
costMult = 7;
expMult = 4;
break;

@ -9,15 +9,16 @@ import { SleeveFaq } from "./data/SleeveFaq";
import { IPlayer } from "../IPlayer";
import { CONSTANTS } from "../../Constants";
import { Locations } from "../../Locations";
import { Faction } from "../../Faction/Faction";
import { Factions } from "../../Faction/Factions";
import { FactionWorkType } from "../../Faction/FactionWorkTypeEnum";
import { Cities } from "../../Locations/Cities";
import { Crime } from "../../Crime/Crime";
import { Crimes } from "../../Crime/Crimes";
import { Cities } from "../../Locations/Cities";
import { CityName } from "../../Locations/data/CityNames";
import { LocationName } from "../../Locations/data/LocationNames";
import { numeralWrapper } from "../../ui/numeralFormat";
import { Page,
@ -243,20 +244,20 @@ function createSleeveUi(sleeve: Sleeve, allSleeves: Sleeve[]): ISleeveUIElems {
`Traveling to a different city costs ${numeralWrapper.formatMoney(CONSTANTS.TravelCost)}. ` +
"It will also CANCEL the sleeve's current task (setting it to idle)",
}));
for (const label in Cities) {
if (sleeve.city === Cities[label]) { continue; }
(function(sleeve, label) {
for (const cityName in Cities) {
if (sleeve.city === cityName) { continue; }
(function(sleeve, cityName) {
popupArguments.push(createElement("div", {
// Reusing this css class. It adds a border and makes it so that
// the background color changes when you hover
class: "cmpy-mgmt-find-employee-option",
innerText: Cities[label],
innerText: cityName,
clickListener: () => {
if (!playerRef!.canAfford(CONSTANTS.TravelCost)) {
dialogBoxCreate("You cannot afford to have this sleeve travel to another city", false);
return false;
}
sleeve.city = Cities[label];
sleeve.city = <CityName>cityName;
playerRef!.loseMoney(CONSTANTS.TravelCost);
sleeve.resetTaskStatus();
removeElementById(popupId);
@ -265,7 +266,7 @@ function createSleeveUi(sleeve: Sleeve, allSleeves: Sleeve[]): ISleeveUIElems {
return false;
}
}));
})(sleeve, label);
})(sleeve, cityName);
}
createPopup(popupId, popupArguments);
@ -569,14 +570,14 @@ function updateSleeveTaskSelector(sleeve: Sleeve, elems: ISleeveUIElems, allSlee
// Second selector has which university
switch (sleeve.city) {
case Cities.Aevum:
elems.taskDetailsSelector2!.add(createOptionElement(Locations.AevumSummitUniversity));
case CityName.Aevum:
elems.taskDetailsSelector2!.add(createOptionElement(LocationName.AevumSummitUniversity));
break;
case Cities.Sector12:
elems.taskDetailsSelector2!.add(createOptionElement(Locations.Sector12RothmanUniversity));
case CityName.Sector12:
elems.taskDetailsSelector2!.add(createOptionElement(LocationName.Sector12RothmanUniversity));
break;
case Cities.Volhaven:
elems.taskDetailsSelector2!.add(createOptionElement(Locations.VolhavenZBInstituteOfTechnology));
case CityName.Volhaven:
elems.taskDetailsSelector2!.add(createOptionElement(LocationName.VolhavenZBInstituteOfTechnology));
break;
default:
elems.taskDetailsSelector2!.add(createOptionElement("No university available in city!"));
@ -597,30 +598,30 @@ function updateSleeveTaskSelector(sleeve: Sleeve, elems: ISleeveUIElems, allSlee
// Second selector has gym
// In this switch statement we also set the initial value of the second selector
switch (sleeve.city) {
case Cities.Aevum:
elems.taskDetailsSelector2!.add(createOptionElement(Locations.AevumCrushFitnessGym));
elems.taskDetailsSelector2!.add(createOptionElement(Locations.AevumSnapFitnessGym));
case CityName.Aevum:
elems.taskDetailsSelector2!.add(createOptionElement(LocationName.AevumCrushFitnessGym));
elems.taskDetailsSelector2!.add(createOptionElement(LocationName.AevumSnapFitnessGym));
// Set initial value
if (sleeve.currentTaskLocation === Locations.AevumCrushFitnessGym) {
if (sleeve.currentTaskLocation === LocationName.AevumCrushFitnessGym) {
elems.taskDetailsSelector2!.selectedIndex = 0;
} else if (sleeve.currentTaskLocation === Locations.AevumSnapFitnessGym) {
} else if (sleeve.currentTaskLocation === LocationName.AevumSnapFitnessGym) {
elems.taskDetailsSelector2!.selectedIndex = 1;
}
break;
case Cities.Sector12:
elems.taskDetailsSelector2!.add(createOptionElement(Locations.Sector12IronGym));
elems.taskDetailsSelector2!.add(createOptionElement(Locations.Sector12PowerhouseGym));
case CityName.Sector12:
elems.taskDetailsSelector2!.add(createOptionElement(LocationName.Sector12IronGym));
elems.taskDetailsSelector2!.add(createOptionElement(LocationName.Sector12PowerhouseGym));
// Set initial value
if (sleeve.currentTaskLocation === Locations.Sector12IronGym) {
if (sleeve.currentTaskLocation === LocationName.Sector12IronGym) {
elems.taskDetailsSelector2!.selectedIndex = 0;
} else if (sleeve.currentTaskLocation === Locations.Sector12PowerhouseGym) {
} else if (sleeve.currentTaskLocation === LocationName.Sector12PowerhouseGym) {
elems.taskDetailsSelector2!.selectedIndex = 1;
}
break;
case Cities.Volhaven:
elems.taskDetailsSelector2!.add(createOptionElement(Locations.VolhavenMilleniumFitnessGym));
case CityName.Volhaven:
elems.taskDetailsSelector2!.add(createOptionElement(LocationName.VolhavenMilleniumFitnessGym));
break;
default:
elems.taskDetailsSelector2!.add(createOptionElement("No gym available in city!"));

File diff suppressed because it is too large Load Diff

@ -16,7 +16,6 @@ import { Factions,
import { joinFaction } from "./Faction/FactionHelpers";
import { createHacknetServer } from "./Hacknet/HacknetHelpers";
import {deleteGangDisplayContent} from "./Gang";
import {Locations} from "./Location";
import { Message } from "./Message/Message";
import { initMessages,
Messages } from "./Message/MessageHelpers";

@ -20,7 +20,7 @@ interface IConstructorParams {
organizationName?: string;
}
export abstract class BaseServer {
export class BaseServer {
// Coding Contract files on this server
contracts: CodingContract[] = [];

@ -4,9 +4,8 @@
*/
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
import { CONSTANTS } from "../Constants";
import { Player } from "../Player";
import { AllServers,
AddToAllServers } from "../Server/AllServers";
import { IPlayer } from "../PersonObjects/IPlayer";
import { AddToAllServers } from "../Server/AllServers";
import { Server } from "../Server/Server";
import { dialogBoxCreate } from "../../utils/DialogBox";
import { createRandomIp } from "../../utils/IPAddress";
@ -15,7 +14,11 @@ import { isPowerOfTwo } from "../../utils/helpers/isPowerOfT
// Returns the cost of purchasing a server with the given RAM
// Returns Infinity for invalid 'ram' arguments
export function getPurchaseServerCost(ram) {
/**
* @param ram Amount of RAM on purchased server (GB)
* @returns Cost of purchasing the given server. Returns infinity for invalid arguments
*/
export function getPurchaseServerCost(ram: number) {
const sanitizedRam = Math.round(ram);
if (isNaN(sanitizedRam) || !isPowerOfTwo(sanitizedRam)) {
return Infinity;
@ -40,17 +43,17 @@ export function getPurchaseServerMaxRam() {
}
// Manually purchase a server (NOT through Netscript)
export function purchaseServer(ram) {
export function purchaseServer(ram: number, p: IPlayer) {
const cost = getPurchaseServerCost(ram);
//Check if player has enough money
if (Player.money.lt(cost)) {
dialogBoxCreate("You don't have enough money to purchase this server!");
if (!p.canAfford(cost)) {
dialogBoxCreate("You don't have enough money to purchase this server!", false);
return;
}
//Maximum server limit
if (Player.purchasedServers.length >= getPurchaseServerLimit()) {
if (p.purchasedServers.length >= getPurchaseServerLimit()) {
dialogBoxCreate("You have reached the maximum limit of " + getPurchaseServerLimit() + " servers. " +
"You cannot purchase any more. You can " +
"delete some of your purchased servers using the deleteServer() Netscript function in a script");
@ -71,26 +74,26 @@ export function purchaseServer(ram) {
AddToAllServers(newServ);
//Add to Player's purchasedServers array
Player.purchasedServers.push(newServ.ip);
p.purchasedServers.push(newServ.ip);
//Connect new server to home computer
var homeComputer = Player.getHomeComputer();
var homeComputer = p.getHomeComputer();
homeComputer.serversOnNetwork.push(newServ.ip);
newServ.serversOnNetwork.push(homeComputer.ip);
Player.loseMoney(cost);
p.loseMoney(cost);
dialogBoxCreate("Server successfully purchased with hostname " + hostname);
}
// Manually upgrade RAM on home computer (NOT through Netscript)
export function purchaseRamForHomeComputer(cost) {
if (Player.money.lt(cost)) {
export function purchaseRamForHomeComputer(cost: number, p: IPlayer) {
if (!p.canAfford(cost)) {
dialogBoxCreate("You do not have enough money to purchase additional RAM for your home computer");
return;
}
const homeComputer = Player.getHomeComputer();
const homeComputer = p.getHomeComputer();
if (homeComputer.maxRam >= CONSTANTS.HomeComputerMaxRam) {
dialogBoxCreate(`You cannot upgrade your home computer RAM because it is at its maximum possible value`);
return;
@ -98,7 +101,7 @@ export function purchaseRamForHomeComputer(cost) {
homeComputer.maxRam *= 2;
Player.loseMoney(cost);
p.loseMoney(cost);
dialogBoxCreate("Purchased additional RAM for home computer! It now has " + homeComputer.maxRam + "GB of RAM.");
}

@ -3,7 +3,7 @@ import { getStockMarket4SDataCost,
getStockMarket4STixApiCost } from "./StockMarketCosts";
import {CONSTANTS} from "../Constants";
import {Locations} from "../Locations";
import { LocationName } from "../Locations/data/LocationNames";
import {hasWallStreetSF, wallStreetSFLvl} from "../NetscriptFunctions";
import {WorkerScript} from "../NetscriptWorker";
import {Player} from "../Player";
@ -190,34 +190,34 @@ function loadStockMarket(saveString) {
function initStockSymbols() {
//Stocks for companies at which you can work
StockSymbols[Locations.AevumECorp] = "ECP";
StockSymbols[Locations.Sector12MegaCorp] = "MGCP";
StockSymbols[Locations.Sector12BladeIndustries] = "BLD";
StockSymbols[Locations.AevumClarkeIncorporated] = "CLRK";
StockSymbols[Locations.VolhavenOmniTekIncorporated] = "OMTK";
StockSymbols[Locations.Sector12FourSigma] = "FSIG";
StockSymbols[Locations.ChongqingKuaiGongInternational] = "KGI";
StockSymbols[Locations.AevumFulcrumTechnologies] = "FLCM";
StockSymbols[Locations.IshimaStormTechnologies] = "STM";
StockSymbols[Locations.NewTokyoDefComm] = "DCOMM";
StockSymbols[Locations.VolhavenHeliosLabs] = "HLS";
StockSymbols[Locations.NewTokyoVitaLife] = "VITA";
StockSymbols[Locations.Sector12IcarusMicrosystems] = "ICRS";
StockSymbols[Locations.Sector12UniversalEnergy] = "UNV";
StockSymbols[Locations.AevumAeroCorp] = "AERO";
StockSymbols[Locations.VolhavenOmniaCybersystems] = "OMN";
StockSymbols[Locations.ChongqingSolarisSpaceSystems] = "SLRS";
StockSymbols[Locations.NewTokyoGlobalPharmaceuticals] = "GPH";
StockSymbols[Locations.IshimaNovaMedical] = "NVMD";
StockSymbols[Locations.AevumWatchdogSecurity] = "WDS";
StockSymbols[Locations.VolhavenLexoCorp] = "LXO";
StockSymbols[Locations.AevumRhoConstruction] = "RHOC";
StockSymbols[Locations.Sector12AlphaEnterprises] = "APHE";
StockSymbols[Locations.VolhavenSysCoreSecurities] = "SYSC";
StockSymbols[Locations.VolhavenCompuTek] = "CTK";
StockSymbols[Locations.AevumNetLinkTechnologies] = "NTLK";
StockSymbols[Locations.IshimaOmegaSoftware] = "OMGA";
StockSymbols[Locations.Sector12FoodNStuff] = "FNS";
StockSymbols[LocationName.AevumECorp] = "ECP";
StockSymbols[LocationName.Sector12MegaCorp] = "MGCP";
StockSymbols[LocationName.Sector12BladeIndustries] = "BLD";
StockSymbols[LocationName.AevumClarkeIncorporated] = "CLRK";
StockSymbols[LocationName.VolhavenOmniTekIncorporated] = "OMTK";
StockSymbols[LocationName.Sector12FourSigma] = "FSIG";
StockSymbols[LocationName.ChongqingKuaiGongInternational] = "KGI";
StockSymbols[LocationName.AevumFulcrumTechnologies] = "FLCM";
StockSymbols[LocationName.IshimaStormTechnologies] = "STM";
StockSymbols[LocationName.NewTokyoDefComm] = "DCOMM";
StockSymbols[LocationName.VolhavenHeliosLabs] = "HLS";
StockSymbols[LocationName.NewTokyoVitaLife] = "VITA";
StockSymbols[LocationName.Sector12IcarusMicrosystems] = "ICRS";
StockSymbols[LocationName.Sector12UniversalEnergy] = "UNV";
StockSymbols[LocationName.AevumAeroCorp] = "AERO";
StockSymbols[LocationName.VolhavenOmniaCybersystems] = "OMN";
StockSymbols[LocationName.ChongqingSolarisSpaceSystems] = "SLRS";
StockSymbols[LocationName.NewTokyoGlobalPharmaceuticals] = "GPH";
StockSymbols[LocationName.IshimaNovaMedical] = "NVMD";
StockSymbols[LocationName.AevumWatchdogSecurity] = "WDS";
StockSymbols[LocationName.VolhavenLexoCorp] = "LXO";
StockSymbols[LocationName.AevumRhoConstruction] = "RHOC";
StockSymbols[LocationName.Sector12AlphaEnterprises] = "APHE";
StockSymbols[LocationName.VolhavenSysCoreSecurities] = "SYSC";
StockSymbols[LocationName.VolhavenCompuTek] = "CTK";
StockSymbols[LocationName.AevumNetLinkTechnologies] = "NTLK";
StockSymbols[LocationName.IshimaOmegaSoftware] = "OMGA";
StockSymbols[LocationName.Sector12FoodNStuff] = "FNS";
//Stocks for other companies
StockSymbols["Sigma Cosmetics"] = "SGC";
@ -241,115 +241,115 @@ function initStockMarket() {
const randInt = getRandomInt;
var ecorp = Locations.AevumECorp;
var ecorp = LocationName.AevumECorp;
var ecorpStk = new Stock(ecorp, StockSymbols[ecorp], randInt(40, 50) / 100, true, 19, randInt(17e3, 28e3), 2.4e12);
StockMarket[ecorp] = ecorpStk;
var megacorp = Locations.Sector12MegaCorp;
var megacorp = LocationName.Sector12MegaCorp;
var megacorpStk = new Stock(megacorp, StockSymbols[megacorp], randInt(40,50)/100, true, 19, randInt(24e3, 34e3), 2.4e12);
StockMarket[megacorp] = megacorpStk;
var blade = Locations.Sector12BladeIndustries;
var blade = LocationName.Sector12BladeIndustries;
var bladeStk = new Stock(blade, StockSymbols[blade], randInt(70, 80)/100, true, 13, randInt(12e3, 25e3), 1.6e12);
StockMarket[blade] = bladeStk;
var clarke = Locations.AevumClarkeIncorporated;
var clarke = LocationName.AevumClarkeIncorporated;
var clarkeStk = new Stock(clarke, StockSymbols[clarke], randInt(65, 75)/100, true, 12, randInt(10e3, 25e3), 1.5e12);
StockMarket[clarke] = clarkeStk;
var omnitek = Locations.VolhavenOmniTekIncorporated;
var omnitek = LocationName.VolhavenOmniTekIncorporated;
var omnitekStk = new Stock(omnitek, StockSymbols[omnitek], randInt(60, 70)/100, true, 12, randInt(32e3, 43e3), 1.8e12);
StockMarket[omnitek] = omnitekStk;
var foursigma = Locations.Sector12FourSigma;
var foursigma = LocationName.Sector12FourSigma;
var foursigmaStk = new Stock(foursigma, StockSymbols[foursigma], randInt(100, 110)/100, true, 17, randInt(50e3, 80e3), 2e12);
StockMarket[foursigma] = foursigmaStk;
var kuaigong = Locations.ChongqingKuaiGongInternational;
var kuaigong = LocationName.ChongqingKuaiGongInternational;
var kuaigongStk = new Stock(kuaigong, StockSymbols[kuaigong], randInt(75, 85)/100, true, 10, randInt(16e3, 28e3), 1.9e12);
StockMarket[kuaigong] = kuaigongStk;
var fulcrum = Locations.AevumFulcrumTechnologies;
var fulcrum = LocationName.AevumFulcrumTechnologies;
var fulcrumStk = new Stock(fulcrum, StockSymbols[fulcrum], randInt(120, 130)/100, true, 16, randInt(29e3, 36e3), 2e12);
StockMarket[fulcrum] = fulcrumStk;
var storm = Locations.IshimaStormTechnologies;
var storm = LocationName.IshimaStormTechnologies;
var stormStk = new Stock(storm, StockSymbols[storm], randInt(80, 90)/100, true, 7, randInt(20e3, 25e3), 1.2e12);
StockMarket[storm] = stormStk;
var defcomm = Locations.NewTokyoDefComm;
var defcomm = LocationName.NewTokyoDefComm;
var defcommStk = new Stock(defcomm, StockSymbols[defcomm], randInt(60, 70)/100, true, 10, randInt(6e3, 19e3), 900e9);
StockMarket[defcomm] = defcommStk;
var helios = Locations.VolhavenHeliosLabs;
var helios = LocationName.VolhavenHeliosLabs;
var heliosStk = new Stock(helios, StockSymbols[helios], randInt(55, 65)/100, true, 9, randInt(10e3, 18e3), 825e9);
StockMarket[helios] = heliosStk;
var vitalife = Locations.NewTokyoVitaLife;
var vitalife = LocationName.NewTokyoVitaLife;
var vitalifeStk = new Stock(vitalife, StockSymbols[vitalife], randInt(70, 80)/100, true, 7, randInt(8e3, 14e3), 1e12);
StockMarket[vitalife] = vitalifeStk;
var icarus = Locations.Sector12IcarusMicrosystems;
var icarus = LocationName.Sector12IcarusMicrosystems;
var icarusStk = new Stock(icarus, StockSymbols[icarus], randInt(60, 70)/100, true, 7.5, randInt(12e3, 24e3), 800e9);
StockMarket[icarus] = icarusStk;
var universalenergy = Locations.Sector12UniversalEnergy;
var universalenergy = LocationName.Sector12UniversalEnergy;
var universalenergyStk = new Stock(universalenergy, StockSymbols[universalenergy], randInt(50, 60)/100, true, 10, randInt(16e3, 29e3), 900e9);
StockMarket[universalenergy] = universalenergyStk;
var aerocorp = Locations.AevumAeroCorp;
var aerocorp = LocationName.AevumAeroCorp;
var aerocorpStk = new Stock(aerocorp, StockSymbols[aerocorp], randInt(55, 65)/100, true, 6, randInt(8e3, 17e3), 640e9);
StockMarket[aerocorp] = aerocorpStk;
var omnia = Locations.VolhavenOmniaCybersystems;
var omnia = LocationName.VolhavenOmniaCybersystems;
var omniaStk = new Stock(omnia, StockSymbols[omnia], randInt(65, 75)/100, true, 4.5, randInt(6e3, 15e3), 600e9);
StockMarket[omnia] = omniaStk;
var solaris = Locations.ChongqingSolarisSpaceSystems;
var solaris = LocationName.ChongqingSolarisSpaceSystems;
var solarisStk = new Stock(solaris, StockSymbols[solaris], randInt(70, 80)/100, true, 8.5, randInt(14e3, 28e3), 705e9);
StockMarket[solaris] = solarisStk;
var globalpharm = Locations.NewTokyoGlobalPharmaceuticals;
var globalpharm = LocationName.NewTokyoGlobalPharmaceuticals;
var globalpharmStk = new Stock(globalpharm, StockSymbols[globalpharm], randInt(55, 65)/100, true, 10.5, randInt(12e3, 30e3), 695e9);
StockMarket[globalpharm] = globalpharmStk;
var nova = Locations.IshimaNovaMedical;
var nova = LocationName.IshimaNovaMedical;
var novaStk = new Stock(nova, StockSymbols[nova], randInt(70, 80)/100, true, 5, randInt(15e3, 27e3), 600e9);
StockMarket[nova] = novaStk;
var watchdog = Locations.AevumWatchdogSecurity;
var watchdog = LocationName.AevumWatchdogSecurity;
var watchdogStk = new Stock(watchdog, StockSymbols[watchdog], randInt(240, 260)/100, true, 1.5, randInt(4e3, 8.5e3), 450e9);
StockMarket[watchdog] = watchdogStk;
var lexocorp = Locations.VolhavenLexoCorp;
var lexocorp = LocationName.VolhavenLexoCorp;
var lexocorpStk = new Stock(lexocorp, StockSymbols[lexocorp], randInt(115, 135)/100, true, 6, randInt(4.5e3, 8e3), 300e9);
StockMarket[lexocorp] = lexocorpStk;
var rho = Locations.AevumRhoConstruction;
var rho = LocationName.AevumRhoConstruction;
var rhoStk = new Stock(rho, StockSymbols[rho], randInt(50, 70)/100, true, 1, randInt(2e3, 7e3), 180e9);
StockMarket[rho] = rhoStk;
var alpha = Locations.Sector12AlphaEnterprises;
var alpha = LocationName.Sector12AlphaEnterprises;
var alphaStk = new Stock(alpha, StockSymbols[alpha], randInt(175, 205)/100, true, 10, randInt(4e3, 8.5e3), 240e9);
StockMarket[alpha] = alphaStk;
var syscore = Locations.VolhavenSysCoreSecurities;
var syscore = LocationName.VolhavenSysCoreSecurities;
var syscoreStk = new Stock(syscore, StockSymbols[syscore], randInt(150, 170)/100, true, 3, randInt(3e3, 8e3), 200e9);
StockMarket[syscore] = syscoreStk;
var computek = Locations.VolhavenCompuTek;
var computek = LocationName.VolhavenCompuTek;
var computekStk = new Stock(computek, StockSymbols[computek], randInt(80, 100)/100, true, 4, randInt(1e3, 6e3), 185e9);
StockMarket[computek] = computekStk;
var netlink = Locations.AevumNetLinkTechnologies;
var netlink = LocationName.AevumNetLinkTechnologies;
var netlinkStk = new Stock(netlink, StockSymbols[netlink], randInt(400, 430)/100, true, 1, randInt(1e3, 5e3), 58e9);
StockMarket[netlink] = netlinkStk;
var omega = Locations.IshimaOmegaSoftware;
var omega = LocationName.IshimaOmegaSoftware;
var omegaStk = new Stock(omega, StockSymbols[omega], randInt(90, 110)/100, true, 0.5, randInt(1e3, 8e3), 60e9);
StockMarket[omega] = omegaStk;
var fns = Locations.Sector12FoodNStuff;
var fns = LocationName.Sector12FoodNStuff;
var fnsStk = new Stock(fns, StockSymbols[fns], randInt(70, 80)/100, false, 1, randInt(500, 4.5e3), 45e9);
StockMarket[fns] = fnsStk;

@ -27,15 +27,14 @@ import { displayFactionContent, joinFaction,
processPassiveFactionRepGain,
inviteToFaction } from "./Faction/FactionHelpers";
import { FconfSettings } from "./Fconf/FconfSettings";
import {displayLocationContent,
initLocationButtons} from "./Location";
import {Locations} from "./Locations";
import { hasHacknetServers,
renderHacknetNodesUI,
clearHacknetNodesUI,
processHacknetEarnings } from "./Hacknet/HacknetHelpers";
import {iTutorialStart} from "./InteractiveTutorial";
import {initLiterature} from "./Literature";
import { LocationName } from "./Locations/data/LocationNames";
import { LocationRoot } from "./Locations/ui/Root";
import { checkForMessagesToSend, initMessages } from "./Message/MessageHelpers";
import {inMission, currMission} from "./Missions";
import {initSingularitySFFlags,
@ -174,7 +173,7 @@ $(document).keydown(function(e) {
Engine.loadHacknetNodesContent();
} else if (e.keyCode === KEY.W && e.altKey) {
e.preventDefault();
Engine.loadWorldContent();
Engine.loadLocationContent();
} else if (e.keyCode === KEY.J && e.altKey) {
e.preventDefault();
Engine.loadJobContent();
@ -233,7 +232,6 @@ const Engine = {
scriptEditorContent: null,
activeScriptsContent: null,
hacknetNodesContent: null,
worldContent: null,
createProgramContent: null,
factionsContent: null,
factionContent: null,
@ -302,14 +300,6 @@ const Engine = {
MainMenuLinks.HacknetNodes.classList.add("active");
},
loadWorldContent: function() {
Engine.hideAllContent();
Engine.Display.worldContent.style.display = "block";
Engine.displayWorldInfo();
routing.navigateTo(Page.World);
MainMenuLinks.City.classList.add("active");
},
loadCreateProgramContent: function() {
Engine.hideAllContent();
Engine.Display.createProgramContent.style.display = "block";
@ -354,54 +344,57 @@ const Engine = {
MainMenuLinks.DevMenu.classList.add("active");
},
loadLocationContent: function() {
loadLocationContent: function(initiallyInCity=true) {
Engine.hideAllContent();
Engine.Display.locationContent.style.display = "block";
try {
displayLocationContent();
} catch(e) {
exceptionAlert(e);
console.error(e);
}
MainMenuLinks.City.classList.add("active");
routing.navigateTo(Page.Location);
const rootComponent = <LocationRoot
initiallyInCity={initiallyInCity}
engine={Engine}
p={Player}
/>
ReactDOM.render(rootComponent, Engine.Display.locationContent);
},
loadTravelContent: function() {
switch(Player.city) {
case Locations.Aevum:
Player.location = Locations.AevumTravelAgency;
break;
case Locations.Chongqing:
Player.location = Locations.ChongqingTravelAgency;
break;
case Locations.Sector12:
Player.location = Locations.Sector12TravelAgency;
break;
case Locations.NewTokyo:
Player.location = Locations.NewTokyoTravelAgency;
break;
case Locations.Ishima:
Player.location = Locations.IshimaTravelAgency;
break;
case Locations.Volhaven:
Player.location = Locations.VolhavenTravelAgency;
break;
default:
dialogBoxCreate("ERROR: Invalid city. This is a bug please contact game dev");
break;
}
Engine.loadLocationContent();
// 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);
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() {
// 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 == "") {
dialogBoxCreate("You do not currently have a job! You can visit various companies " +
"in the city and try to find a job.");
return;
}
Player.location = Player.companyName;
Engine.loadLocationContent();
Engine.hideAllContent();
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() {
@ -503,14 +496,13 @@ const Engine = {
}
},
//Helper function that hides all content
// Helper function that hides all content
hideAllContent: function() {
Engine.Display.terminalContent.style.display = "none";
Engine.Display.characterContent.style.display = "none";
Engine.Display.scriptEditorContent.style.display = "none";
Engine.Display.activeScriptsContent.style.display = "none";
clearHacknetNodesUI();
Engine.Display.worldContent.style.display = "none";
Engine.Display.createProgramContent.style.display = "none";
Engine.Display.factionsContent.style.display = "none";
Engine.Display.factionContent.style.display = "none";
@ -518,6 +510,7 @@ const Engine = {
Engine.Display.augmentationsContent.style.display = "none";
Engine.Display.tutorialContent.style.display = "none";
Engine.Display.locationContent.style.display = "none";
ReactDOM.unmountComponentAtNode(Engine.Display.locationContent);
Engine.Display.workInProgressContent.style.display = "none";
Engine.Display.redPillContent.style.display = "none";
Engine.Display.cinematicTextContent.style.display = "none";
@ -542,15 +535,15 @@ const Engine = {
clearResleevesPage();
clearSleevesPage();
//Location lists
Engine.aevumLocationsList.style.display = "none";
Engine.chongqingLocationsList.style.display = "none";
Engine.sector12LocationsList.style.display = "none";
Engine.newTokyoLocationsList.style.display = "none";
Engine.ishimaLocationsList.style.display = "none";
Engine.volhavenLocationsList.style.display = "none";
// Make nav menu tabs inactive
Engine.inactivateMainMenuLinks();
//Make nav menu tabs inactive
// Close dev menu
closeDevMenu();
},
// Remove 'active' css class from all main menu links
inactivateMainMenuLinks: function() {
MainMenuLinks.Terminal.classList.remove("active");
MainMenuLinks.ScriptEditor.classList.remove("active");
MainMenuLinks.ActiveScripts.classList.remove("active");
@ -570,9 +563,6 @@ const Engine = {
MainMenuLinks.Tutorial.classList.remove("active");
MainMenuLinks.Options.classList.remove("active");
MainMenuLinks.DevMenu.classList.remove("active");
// Close dev menu
closeDevMenu();
},
displayCharacterOverviewInfo: function() {
@ -592,99 +582,6 @@ const Engine = {
displayCharacterInfo(Engine.Display.characterInfo, Player);
},
/* Display locations in the world*/
aevumLocationsList: null,
chongqingLocationsList: null,
sector12LocationsList: null,
newTokyoLocationsList: null,
ishimaLocationsList: null,
volhavenLocationsList: null,
displayWorldInfo: function() {
Engine.aevumLocationsList.style.display = "none";
Engine.chongqingLocationsList.style.display = "none";
Engine.sector12LocationsList.style.display = "none";
Engine.newTokyoLocationsList.style.display = "none";
Engine.ishimaLocationsList.style.display = "none";
Engine.volhavenLocationsList.style.display = "none";
document.getElementById("world-city-name").innerHTML = Player.city;
var cityDesc = document.getElementById("world-city-desc"); //TODO
switch(Player.city) {
case Locations.Aevum:
Engine.aevumLocationsList.style.display = "inline";
break;
case Locations.Chongqing:
Engine.chongqingLocationsList.style.display = "inline";
break;
case Locations.Sector12:
Engine.sector12LocationsList.style.display = "inline";
//City hall only in BitNode-3/with Source-File 3
if ((Player.bitNodeN === 3 || hasCorporationSF) && Player.bitNodeN !== 8) {
document.getElementById("sector12-cityhall-li").style.display = "block";
} else {
document.getElementById("sector12-cityhall-li").style.display = "none";
}
break;
case Locations.NewTokyo:
Engine.newTokyoLocationsList.style.display = "inline";
break;
case Locations.Ishima:
Engine.ishimaLocationsList.style.display = "inline";
break;
case Locations.Volhaven:
Engine.volhavenLocationsList.style.display = "inline";
break;
default:
console.log("Invalid city value in Player object!");
break;
}
//Generic Locations (common to every city):
// World Stock Exchange
// Corporation (if applicable)
// Bladeburner HQ (if applicable);
var genericLocationsList = document.getElementById("generic-locations-list");
genericLocationsList.style.display = "inline";
removeChildrenFromElement(genericLocationsList);
var li = createElement("li");
li.appendChild(createElement("a", {
innerText:"World Stock Exchange", class:"a-link-button",
clickListener:()=>{
Player.location = Locations.WorldStockExchange;
Engine.loadStockMarketContent();
return false;
}
}));
genericLocationsList.appendChild(li);
if (Player.corporation instanceof Corporation && document.getElementById("location-corporation-button") == null) {
var li = createElement("li");
li.appendChild(createElement("a", {
innerText:Player.corporation.name, id:"location-corporation-button",
class:"a-link-button",
clickListener:()=>{
Engine.loadCorporationContent();
return false;
}
}));
genericLocationsList.appendChild(li);
}
if (Player.bladeburner instanceof Bladeburner) {
var li = createElement("li");
li.appendChild(createElement("a", {
innerText:"Bladeburner Headquarters", class:"a-link-button",
clickListener:()=>{
Engine.loadBladeburnerContent();
return false;
}
}));
genericLocationsList.appendChild(li);
}
},
displayFactionsInfo: function() {
removeChildrenFromElement(Engine.Display.factionsContent);
@ -1343,9 +1240,6 @@ const Engine = {
Engine.Display.hacknetNodesContent = document.getElementById("hacknet-nodes-container");
Engine.Display.hacknetNodesContent.style.display = "none";
Engine.Display.worldContent = document.getElementById("world-container");
Engine.Display.worldContent.style.display = "none";
Engine.Display.createProgramContent = document.getElementById("create-program-container");
Engine.Display.createProgramContent.style.display = "none";
@ -1378,22 +1272,12 @@ const Engine = {
//Character info
Engine.Display.characterInfo = document.getElementById("character-content");
//Location lists
Engine.aevumLocationsList = document.getElementById("aevum-locations-list");
Engine.chongqingLocationsList = document.getElementById("chongqing-locations-list");
Engine.sector12LocationsList = document.getElementById("sector12-locations-list");
Engine.newTokyoLocationsList = document.getElementById("newtokyo-locations-list");
Engine.ishimaLocationsList = document.getElementById("ishima-locations-list");
Engine.volhavenLocationsList = document.getElementById("volhaven-locations-list");
//Location page (page that shows up when you visit a specific location in World)
Engine.Display.locationContent = document.getElementById("location-container");
//Engine.Display.locationContent.style.visibility = "hidden";
Engine.Display.locationContent.style.display = "none";
//Work In Progress
Engine.Display.workInProgressContent = document.getElementById("work-in-progress-container");
//Engine.Display.workInProgressContent.style.visibility = "hidden";
Engine.Display.workInProgressContent.style.display = "none";
//Red Pill / Hack World Daemon
@ -1404,9 +1288,6 @@ const Engine = {
Engine.Display.cinematicTextContent = document.getElementById("cinematic-text-container");
Engine.Display.cinematicTextContent.style.display = "none";
//Init Location buttons
initLocationButtons();
// Initialize references to main menu links
if (!initializeMainMenuLinks()) {
const errorMsg = "Failed to initialize Main Menu Links. Please try refreshing the page. " +
@ -1480,19 +1361,17 @@ const Engine = {
});
MainMenuLinks.City.addEventListener("click", function() {
Engine.loadWorldContent();
Engine.loadLocationContent();
return false;
});
MainMenuLinks.Travel.addEventListener("click", function() {
Engine.loadTravelContent();
MainMenuLinks.Travel.classList.add("active");
return false;
});
MainMenuLinks.Job.addEventListener("click", function() {
Engine.loadJobContent();
MainMenuLinks.Job.classList.add("active");
return false;
});

@ -206,226 +206,6 @@ if (htmlWebpackPlugin.options.googleAnalytics.trackingId) { %>
<!-- React Component -->
</div>
<!-- World -->
<div id="world-container" class="generic-menupage-container">
<h2 id="world-city-name"> </h2>
<p id="world-city-desc"> </p>
<ul id="aevum-locations-list">
<li id="aevum-travelagency-li">
<a id="aevum-travelagency" class="a-link-button"> Travel Agency </a>
</li>
<li id="aevum-hospital-li">
<a id="aevum-hospital" class="a-link-button">Hospital</a>
</li>
<li id="aevum-summituniversity-li">
<a id="aevum-summituniversity" class="a-link-button"> Summit University </a>
</li>
<li id="aevum-ecorp-li">
<a id="aevum-ecorp" class="a-link-button"> ECorp </a>
</li>
<li id="aevum-bachmanandassociates-li">
<a id="aevum-bachmanandassociates" class="a-link-button"> Bachman & Associates</a>
</li>
<li id="aevum-clarkeincorporated-li">
<a id="aevum-clarkeincorporated" class="a-link-button"> Clarke Incorporated </a>
</li>
<li id="aevum-fulcrumtechnologies-li">
<a id="aevum-fulcrumtechnologies" class="a-link-button"> Fulcrum Technologies </a>
</li>
<li id="aevum-aerocorp-li">
<a id="aevum-aerocorp" class="a-link-button"> AeroCorp </a>
</li>
<li id="aevum-galacticcybersystems-li">
<a id="aevum-galacticcybersystems" class="a-link-button"> Galactic Cybersystems </a>
</li>
<li id="aevum-watchdogsecurity-li">
<a id="aevum-watchdogsecurity" class="a-link-button">Watchdog Security </a>
</li>
<li id="aevum-rhoconstruction-li">
<a id="aevum-rhoconstruction" class="a-link-button">Rho Construction </a>
</li>
<li id="aevum-aevumpolice-li">
<a id="aevum-aevumpolice" class="a-link-button">Aevum Police</a>
</li>
<li id="aevum-netlinktechnologies-li">
<a id="aevum-netlinktechnologies" class="a-link-button">NetLink Technologies</a>
</li>
<li id="aevum-crushfitnessgym-li">
<a id="aevum-crushfitnessgym" class="a-link-button">Crush Fitness Gym </a>
</li>
<li id="aevum-snapfitnessgym-li">
<a id="aevum-snapfitnessgym" class="a-link-button">Snap Fitness Gym</a>
</li>
<li id="aevum-slums-li">
<a id="aevum-slums" class="a-link-button">The Slums</a>
</li>
</ul>
<ul id="chongqing-locations-list">
<li id="chongqing-travelagency-li">
<a id="chongqing-travelagency" class="a-link-button"> Travel Agency </a>
</li>
<li id="chongqing-hospital-li">
<a id="chongqing-hospital" class="a-link-button">Hospital</a>
</li>
<li id="chonqging-kuaigonginternational-li">
<a id="chongqing-kuaigonginternational" class="a-link-button">KuaiGong International </a>
</li>
<li id="chongqing-solarisspacesystems-li">
<a id="chongqing-solarisspacesystems" class="a-link-button">Solaris Space Systems</a>
</li>
<li id="chongqing-slums-li">
<a id="chongqing-slums" class="a-link-button">The Slums</a>
</li>
</ul>
<ul id="sector12-locations-list">
<li id="sector12-travelagency-li">
<a id="sector12-travelagency" class="a-link-button">Travel Agency </a>
</li>
<li id="sector12-hospital-li">
<a id="sector12-hospital" class="a-link-button">Hospital</a>
</li>
<li id="sector12-rothmanuniversity-li">
<a id="sector12-rothmanuniversity" class="a-link-button"> Rothman University</a>
</li>
<li id="sector12-megacorp-li">
<a id="sector12-megacorp" class="a-link-button">MegaCorp</a>
</li>
<li id="sector12-bladeindustries-li">
<a id="sector12-bladeindustries" class="a-link-button"> Blade Industries</a>
</li>
<li id="sector12-foursigma-li">
<a id="sector12-foursigma" class="a-link-button">Four Sigma</a>
</li>
<li id="sector12-icarusmicrosystems-li">
<a id="sector12-icarusmicrosystems" class="a-link-button"> Icarus Microsystems</a>
</li>
<li id="sector12-universalenergy-li">
<a id="sector12-universalenergy" class="a-link-button">Universal Energy </a>
</li>
<li id="sector12-deltaone-li">
<a id="sector12-deltaone" class="a-link-button">DeltaOne </a>
</li>
<li id="sector12-cia-li">
<a id="sector12-cia" class="a-link-button">Central Intelligence Agency </a>
</li>
<li id="sector12-nsa-li">
<a id="sector12-nsa" class="a-link-button">National Security Agency </a>
</li>
<li id="sector12-alphaenterprises-li">
<a id="sector12-alphaenterprises" class="a-link-button">Alpha Enterprises</a>
</li>
<li id="sector12-carmichaelsecurity-li">
<a id="sector12-carmichaelsecurity" class="a-link-button"> Carmichael Security</a>
</li>
<li id="sector12-foodnstuff-li">
<a id="sector12-foodnstuff" class="a-link-button">FoodNStuff</a>
</li>
<li id="sector12-joesguns-li">
<a id="sector12-joesguns" class="a-link-button"> Joe's Guns</a>
</li>
<li id="sector12-irongym-li">
<a id="sector12-irongym" class="a-link-button">Iron Gym </a>
</li>
<li id="sector12-powerhousegym-li">
<a id="sector12-powerhousegym" class="a-link-button">Powerhouse Gym</a>
</li>
<li id="sector12-slums-li">
<a id="sector12-slums" class="a-link-button">The Slums</a>
</li>
<li id="sector12-cityhall-li">
<a id="sector12-cityhall" class="a-link-button">City Hall</a>
</li>
</ul>
<ul id="newtokyo-locations-list">
<li id="newtokyo-travelagency-li">
<a id="newtokyo-travelagency" class="a-link-button"> Travel Agency</a>
</li>
<li id="newtokyo-hospital-li">
<a id="newtokyo-hospital" class="a-link-button">Hospital</a>
</li>
<li id="newtokyo-defcomm-li">
<a id="newtokyo-defcomm" class="a-link-button"> DefComm</a>
</li>
<li id="newtokyo-vitalife-li">
<a id="newtokyo-vitalife" class="a-link-button">VitaLife </a>
</li>
<li id="newtokyo-globalpharmaceuticals-li">
<a id="newtokyo-globalpharmaceuticals" class="a-link-button">Global Pharmaceuticals</a>
</li>
<li id="newtokyo-noodlebar-li">
<a id="newtokyo-noodlebar" class="a-link-button">Noodle Bar </a>
</li>
<li id="newtokyo-slums-li">
<a id="newtokyo-slums" class="a-link-button">The Slums</a>
</li>
</ul>
<ul id="ishima-locations-list">
<li id="ishima-travelagency-li">
<a id="ishima-travelagency" class="a-link-button">Travel Agency </a>
</li>
<li id="ishima-hospital-li">
<a id="ishima-hospital" class="a-link-button">Hospital</a>
</li>
<li id="ishima-stormtechnologies-li">
<a id="ishima-stormtechnologies" class="a-link-button">Storm Technologies</a>
</li>
<li id="ishima-novamedical-li">
<a id="ishima-novamedical" class="a-link-button">Nova Medical</a>
</li>
<li id="ishima-omegasoftware-li">
<a id="ishima-omegasoftware" class="a-link-button">Omega Software </a>
</li>
<li id="ishima-slums-li">
<a id="ishima-slums" class="a-link-button">The Slums</a>
</li>
</ul>
<ul id="volhaven-locations-list">
<li id="volhaven-travelagency-li">
<a id="volhaven-travelagency" class="a-link-button">Travel Agency </a>
</li>
<li id="volhaven-hospital-li">
<a id="volhaven-hospital" class="a-link-button">Hospital</a>
</li>
<li id="volhaven-zbinstituteoftechnology-li">
<a id="volhaven-zbinstituteoftechnology" class="a-link-button">ZB Insitute of Technology</a>
</li>
<li id="volhaven-omnitekincorporated-li">
<a id="volhaven-omnitekincorporated" class="a-link-button">OmniTek Incorporated </a>
</li>
<li id="volhaven-nwo-li">
<a id="volhaven-nwo" class="a-link-button">NWO</a>
</li>
<li id="volhaven-helislabs-li">
<a id="volhaven-helioslabs" class="a-link-button">Helios Labs</a>
</li>
<li id="volhaven-omniacybersystems-li">
<a id="volhaven-omniacybersystems" class="a-link-button">Omnia Cybersystems</a>
</li>
<li id="volhaven-lexocorp-li">
<a id="volhaven-lexocorp" class="a-link-button">LexoCorp</a>
</li>
<li id="volhaven-syscoresecurities-li">
<a id="volhaven-syscoresecurities" class="a-link-button">SysCore Securities</a>
</li>
<li id="volhaven-computek-li">
<a id="volhaven-computek" class="a-link-button">CompuTek</a>
</li>
<li id="volhaven-milleniumfitnessgym-li">
<a id="volhaven-milleniumfitnessgym" class="a-link-button">Millenium Fitness Gym</a>
</li>
<li id="volhaven-slums-li">
<a id="volhaven-slums" class="a-link-button">The Slums</a>
</li>
</ul>
<ul id="generic-locations-list"></ul>
</div>
<!-- Create a program(executable) -->
<div id="create-program-container" class="generic-menupage-container">
<p id="create-program-page-text">
@ -453,160 +233,41 @@ if (htmlWebpackPlugin.options.googleAnalytics.trackingId) { %>
<h1> Tutorial (AKA Links to Documentation) </h1>
<a id="tutorial-getting-started-link" class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/guidesandtips/gettingstartedguideforbeginnerprogrammers.html" >
Getting Started
</a><br><br>
Getting Started</a><br><br>
<a class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/servers.html">
Servers & Networking
</a><br><br>
Servers & Networking</a><br><br>
<a class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/hacking.html">
Hacking
</a><br><br>
Hacking</a><br><br>
<a class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/scripts.html">
Scripts
</a><br><br>
Scripts</a><br><br>
<a class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/netscript.html">
Netscript Programming Language
</a><br><br>
Netscript Programming Language</a><br><br>
<a class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/world.html">
Traveling
</a><br><br>
Traveling</a><br><br>
<a class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/companies.html">
Companies
</a><br><br>
Companies</a><br><br>
<a class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/infiltration.html">
Infiltration
</a><br><br>
Infiltration</a><br><br>
<a class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/factions.html">
Factions
</a><br><br>
Factions</a><br><br>
<a class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/augmentations.html">
Augmentations
</a><br><br>
Augmentations</a><br><br>
<a class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/shortcuts.html">
Keyboard Shortcuts
</a>
Keyboard Shortcuts</a>
</div>
<!-- Location (visiting a location in World) -->
<div id="location-container" class="generic-menupage-container">
<a id="location-return-to-world-button" class="a-link-button"> Return to World </a>
<h1 id="location-name"></h1>
<p id="location-info"> </p>
<p id="location-job-title"> </p>
<p id="location-text-divider-1"> --------------- </p>
<p id="location-job-reputation" class="tooltip"> </p>
<p id="location-text-divider-2"> --------------- </p>
<p id="location-company-favor" class="tooltip"> </p>
<p id="location-text-divider-3"> --------------- </p>
<!-- Jobs/Work at a company -->
<a id="location-software-job" class="a-link-button tooltip"> Apply for Software Job</a>
<a id="location-software-consultant-job" class="a-link-button tooltip"> Apply for Software Consultant Job</a>
<a id="location-it-job" class="a-link-button tooltip"> Apply for IT Job </a>
<a id="location-security-engineer-job" class="a-link-button tooltip"> Apply for Security Engineer Job</a>
<a id="location-network-engineer-job" class="a-link-button tooltip"> Apply for Network Engineer Job</a>
<a id="location-business-job" class="a-link-button tooltip"> Apply for Business Job</a>
<a id="location-business-consultant-job" class="a-link-button tooltip"> Apply for Business Consultant Job </a>
<a id="location-security-job" class="a-link-button tooltip"> Apply for Security Job</a>
<a id="location-agent-job" class="a-link-button tooltip"> Apply to be an Agent</a>
<a id="location-employee-job" class="a-link-button tooltip"> Apply to be an Employee </a>
<a id="location-parttime-employee-job" class="a-link-button tooltip"> Apply to be a Part-time Employee </a>
<a id="location-waiter-job" class="a-link-button tooltip"> Apply to be a Waiter</a>
<a id="location-parttime-waiter-job" class="a-link-button tooltip"> Apply to be a Part-time Waiter</a>
<a id="location-work" class="a-link-button"> Work </a>
<!-- Gym -->
<a id="location-gym-train-str" class="a-link-button">Train Strength</a>
<a id="location-gym-train-def" class="a-link-button">Train Defense </a>
<a id="location-gym-train-dex" class="a-link-button">Train Dexterity</a>
<a id="location-gym-train-agi" class="a-link-button">Train Agility</a>
<!-- Study/Take classes at a university -->
<a id="location-study-computer-science" class="a-link-button">Study Computer Science (free)</a>
<a id="location-data-structures-class" class="a-link-button">Take Data Structures course</a>
<a id="location-networks-class" class="a-link-button">Take Networks course</a>
<a id="location-algorithms-class" class="a-link-button">Take Algorithms course</a>
<a id="location-management-class" class="a-link-button">Take Management course</a>
<a id="location-leadership-class" class="a-link-button">Take Leadership course</a>
<!-- Purchase servers -->
<a id="location-purchase-2gb" class="a-link-button"> Purchase 2GB Server - $150,000</a>
<a id="location-purchase-4gb" class="a-link-button"> Purchase 4GB Server - $300,000</a>
<a id="location-purchase-8gb" class="a-link-button"> Purchase 8GB Server - $600,000</a>
<a id="location-purchase-16gb" class="a-link-button"> Purchase 16GB Server - $1,200,000</a>
<a id="location-purchase-32gb" class="a-link-button"> Purchase 32GB Server - $2,400,000</a>
<a id="location-purchase-64gb" class="a-link-button"> Purchase 64GB Server - $4,800,000</a>
<a id="location-purchase-128gb" class="a-link-button"> Purchase 128GB Server - $9,600,000</a>
<a id="location-purchase-256gb" class="a-link-button"> Purchase 256GB Server - $19,200,000</a>
<a id="location-purchase-512gb" class="a-link-button"> Purchase 512GB Server - $38,400,000</a>
<a id="location-purchase-1tb" class="a-link-button"> Purchase 1TB Server - $75,000,000</a>
<a id="location-purchase-tor" class="a-link-button"> Purchase TOR Router - $100,000</a>
<a id="location-purchase-home-ram" class="a-link-button"> Purchase additional RAM for Home computer </a>
<a id="location-purchase-home-cores" class="a-link-button"> Purchase additional Core for Home computer </a>
<!-- Infiltrate -->
<a id="location-infiltrate" class="a-link-button tooltip"> Infiltrate Company
<span class="tooltiptext">
Infiltrate this company's facility to try and steal their classified secrets!
Warning: You may end up hospitalized if you are unsuccessful!
</span>
</a>
<!-- Hospital -->
<a id="location-hospital-treatment" class="a-link-button"> Get Treatment for Wounds </a>
<!-- Travel agency -->
<p id="location-travel-agency-text">
From here, you can travel to any other city! A ticket costs $200,000.
</p>
<a id="location-travel-to-aevum" class="a-link-button"> Travel to Aevum </a>
<a id="location-travel-to-chongqing" class="a-link-button"> Travel to Chongqing</a>
<a id="location-travel-to-sector12" class="a-link-button"> Travel to Sector-12</a>
<a id="location-travel-to-newtokyo" class="a-link-button"> Travel to New Tokyo</a>
<a id="location-travel-to-ishima" class="a-link-button"> Travel to Ishima</a>
<a id="location-travel-to-volhaven" class="a-link-button"> Travel to Volhaven</a>
<!-- Slums -->
<p id="location-slums-description">
You have entered the Slums, a poverty-ridden district filled with gangs, criminals, and
other shadowy entities. The city's government and police have neglected this area for years...
<br /><br /><br />
In the Slums, you can commit crimes to earn money and experience. Crime attempts are not always
successful. Your chance at successfully committing a crime is determined by your stats.
</p>
<a class="a-link-button tooltip" id="location-slums-shoplift"> Shoplift </a>
<a id="location-slums-rob-store" class="a-link-button tooltip"> Rob a store </a>
<a id="location-slums-mug" class="a-link-button tooltip"> Mug someone </a>
<a id="location-slums-larceny" class="a-link-button tooltip"> Commit Larceny </a>
<a id="location-slums-deal-drugs" class="a-link-button tooltip"> Deal Drugs </a>
<a id="location-slums-bond-forgery" class="a-link-button tooltip">Bond Forgery</a>
<a id="location-slums-traffic-arms" class="a-link-button tooltip">Traffick Illegal Arms</a>
<a id="location-slums-homicide" class="a-link-button tooltip">Homicide</a>
<a id="location-slums-gta" class="a-link-button tooltip"> Grand Theft Auto </a>
<a id="location-slums-kidnap" class="a-link-button tooltip"> Kidnap and Ransom </a>
<a id="location-slums-assassinate" class="a-link-button tooltip"> Assassinate </a>
<a id="location-slums-heist" class="a-link-button tooltip"> Heist </a>
<!-- City Hall -->
<a id="location-cityhall-create-corporation" class="a-link-button">Create a Corporation</a>
<!-- Bladeburner @ NSA -->
<a id="location-nsa-bladeburner" class="a-link-button">Bladeburner Division</a>
<!-- Re-sleeving @ VitaLife -->
<a id="location-vitalife-resleeve" class="a-link-button">Re-Sleeve</a>
</div>
<div id="infiltration-container" class="generic-menupage-container">

@ -0,0 +1,80 @@
/**
* Basic stateless button that automatically re-renders itself every X seconds
* Uses the 'std-button' css class
*
* NOT recommended for usage - only if you really have to
*/
import * as React from "react";
interface IProps {
disabled?: boolean;
intervalTime?: number;
onClick?: (e: React.MouseEvent<HTMLElement>) => any;
style?: object;
text: string;
tooltip?: string;
}
interface IState {
i: number;
}
type IInnerHTMLMarkup = {
__html: string;
}
export class AutoupdatingStdButton extends React.Component<IProps, IState> {
/**
* Timer ID for auto-updating implementation (returned value from setInterval())
*/
interval: number = 0;
constructor(props: IProps) {
super(props);
this.state = {
i: 0,
}
}
componentDidMount() {
const time = this.props.intervalTime ? this.props.intervalTime : 1000;
this.interval = setInterval(() => this.tick(), time);
}
componentWillUnmount() {
clearInterval(this.interval);
}
tick() {
this.setState(prevState => ({
i: prevState.i + 1
}));
}
render() {
const hasTooltip = this.props.tooltip != null && this.props.tooltip !== "";
let className = this.props.disabled ? "std-button-disabled" : "std-button";
if (hasTooltip) {
className += " tooltip"
}
// Tooltip will eb set using inner HTML
let tooltipMarkup: IInnerHTMLMarkup | null;
if (hasTooltip) {
tooltipMarkup = {
__html: this.props.tooltip!
}
}
return (
<button className={className} onClick={this.props.onClick} style={this.props.style}>
{this.props.text}
{
hasTooltip &&
<span className={"tooltiptext"} dangerouslySetInnerHTML={tooltipMarkup!}></span>
}
</button>
)
}
}

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

@ -0,0 +1,20 @@
/**
* Stateless button that represents something that has been purchased.
*/
import * as React from "react";
interface IStdButtonPurchasedProps {
onClick?: (e: React.MouseEvent<HTMLElement>) => any;
style?: object;
text: string;
}
export class StdButtonPurchased extends React.Component<IStdButtonPurchasedProps, any> {
render() {
return (
<button className={"std-button-bought"} onClick={this.props.onClick} style={this.props.style}>
{this.props.text}
</button>
)
}
}

@ -28,11 +28,6 @@ export enum Page {
*/
HacknetNodes = "HacknetNodes",
/**
* View the city the player is currently in.
*/
World = "World",
/**
* The list of programs the player could potentially build.
*/
@ -64,7 +59,7 @@ export enum Page {
DevMenu = "Dev Menu",
/**
* Information about the specific location the player at (job, company, etc.);
* Visiting a location in the world
*/
Location = "Location",

@ -1,2 +1,2 @@
export function dialogBoxCreate(txt: string, preformatted: boolean): void;
export var dialogBoxOpened: boolean;
export function dialogBoxCreate(txt: string, preformatted?: boolean): void;
export var dialogBoxOpened: boolean;

@ -6,7 +6,8 @@
* 1. Just a Yes/No response from player
* 2. Popup also includes a text input field in addition to the Yes/No response
*/
import {clearEventListeners} from "./uiHelpers/clearEventListeners";
import { clearEventListeners } from "./uiHelpers/clearEventListeners";
import { KEY } from "./helpers/keyCodes";
export let yesNoBoxOpen: boolean = false;
@ -14,9 +15,9 @@ const yesNoBoxContainer: HTMLElement | null = document.getElementById("yes-no-bo
const yesNoBoxTextElement: HTMLElement | null = document.getElementById("yes-no-box-text");
export function yesNoBoxHotkeyHandler(e: KeyboardEvent) {
if (e.keyCode === 27) {
if (e.keyCode === KEY.ESC) {
yesNoBoxClose();
} else if (e.keyCode === 13) {
} else if (e.keyCode === KEY.ENTER) {
const yesBtn: HTMLElement | null = document.getElementById("yes-no-box-yes");
if (yesBtn) {
yesBtn.click();
@ -78,9 +79,9 @@ const yesNoTextInputBoxInput: HTMLInputElement | null = document.getElementById(
const yesNoTextInputBoxTextElement: HTMLElement | null = document.getElementById("yes-no-text-input-box-text");
export function yesNoTxtInpBoxHotkeyHandler(e: KeyboardEvent) {
if (e.keyCode === 27) {
if (e.keyCode === KEY.ESC) {
yesNoTxtInpBoxClose();
} else if (e.keyCode === 13) {
} else if (e.keyCode === KEY.ENTER) {
const yesBtn: HTMLElement | null = document.getElementById("yes-no-text-input-box-yes");
if (yesBtn) {
yesBtn.click();